├── updater ├── MODULE_LICENSE_APACHE2 ├── Android.mk ├── firmware.h ├── log_recovery.c ├── bootloader.h ├── recovery_updater.c ├── firmware.c ├── NOTICE └── bootloader.c ├── Android.mk ├── bravo_radio.mk ├── releasetools.pyc ├── fm_radio.mk ├── ecclist_for_mcc.conf ├── common_small.mk ├── common.mk ├── README.ecclist_for_mcc.conf ├── CleanSpec.mk ├── releasetools.py └── overlay └── frameworks └── base └── core └── res └── res └── values └── strings.xml /updater/MODULE_LICENSE_APACHE2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | include $(all-subdir-makefiles) 2 | -------------------------------------------------------------------------------- /bravo_radio.mk: -------------------------------------------------------------------------------- 1 | # Broadcom FM Radio 2 | PRODUCT_PACKAGES += \ 3 | FM \ 4 | hcitool -------------------------------------------------------------------------------- /releasetools.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_device_htc_common/master/releasetools.pyc -------------------------------------------------------------------------------- /fm_radio.mk: -------------------------------------------------------------------------------- 1 | # Broadcom FM Radio 2 | ifeq ($(BOARD_HAVE_FM_RADIO),true) 3 | PRODUCT_PACKAGES += \ 4 | FM \ 5 | hcitool 6 | endif 7 | -------------------------------------------------------------------------------- /ecclist_for_mcc.conf: -------------------------------------------------------------------------------- 1 | MCC ECClist 2 | 234 999,112,911 3 | 235 999,112,911 4 | 302 112,911 5 | 310 112,911 6 | 311 112,911 7 | 312 112,911 8 | 313 112,911 9 | 314 112,911 10 | 315 112,911 11 | 316 112,911 12 | 454 999,112,911 13 | 505 000,112,911 14 | 525 999,995,112,911 15 | -------------------------------------------------------------------------------- /updater/Android.mk: -------------------------------------------------------------------------------- 1 | ifneq ($(TARGET_SIMULATOR),true) 2 | ifeq ($(TARGET_ARCH),arm) 3 | 4 | LOCAL_PATH := $(call my-dir) 5 | include $(CLEAR_VARS) 6 | 7 | # librecovery_ui_htc is a static library included by all the recovery 8 | # UI libraries for specific devices (passion, sapphire, dream). It 9 | # knows how to recover the log stored in the cache partition when a 10 | # radio or hboot update is done. 11 | 12 | LOCAL_SRC_FILES := log_recovery.c 13 | LOCAL_C_INCLUDES += bootable/recovery 14 | LOCAL_MODULE := librecovery_ui_htc 15 | include $(BUILD_STATIC_LIBRARY) 16 | 17 | include $(CLEAR_VARS) 18 | 19 | # librecovery_update_htc is a set of edify extension functions for 20 | # doing radio and hboot updates on HTC devices. 21 | 22 | LOCAL_MODULE_TAGS := optional 23 | 24 | LOCAL_SRC_FILES := recovery_updater.c firmware.c bootloader.c 25 | LOCAL_STATIC_LIBRARIES += libmtdutils 26 | LOCAL_C_INCLUDES += bootable/recovery 27 | LOCAL_MODULE := librecovery_updater_htc 28 | include $(BUILD_STATIC_LIBRARY) 29 | 30 | endif # TARGET_ARCH == arm 31 | endif # !TARGET_SIMULATOR 32 | -------------------------------------------------------------------------------- /common_small.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2009 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # This lists the aspects that are unique to HTC but shared between all 18 | # HTC devices. These are specially fine-tuned for devices with a small 19 | # system partition. 20 | 21 | # Get additional product configuration from the non-open-source 22 | # counterpart to this file, if it exists. This is the most specific 23 | # inheritance, and therefore comes first 24 | $(call inherit-product-if-exists, vendor/htc/common/common_small-vendor.mk) 25 | 26 | # Inherit from the non-small variant of this file 27 | $(call inherit-product, device/htc/common/common.mk) 28 | -------------------------------------------------------------------------------- /common.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2009 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # This lists the aspects that are unique to HTC but shared between all 18 | # HTC devices 19 | 20 | # Sets an HTC-specific device-agnostic overlay 21 | DEVICE_PACKAGE_OVERLAYS := device/htc/common/overlay 22 | 23 | # Sets copy files for all HTC-specific device 24 | PRODUCT_COPY_FILES += device/htc/common/ecclist_for_mcc.conf:system/etc/ecclist_for_mcc.conf 25 | 26 | # Get additional product configuration from the non-open-source 27 | # counterpart to this file, if it exists 28 | $(call inherit-product-if-exists, vendor/htc/common/common-vendor.mk) 29 | 30 | # Override - we don't want to use any inherited value 31 | PRODUCT_MANUFACTURER := HTC 32 | -------------------------------------------------------------------------------- /README.ecclist_for_mcc.conf: -------------------------------------------------------------------------------- 1 | The following copyright and license information applies to ecclist_for_mcc.conf 2 | 3 | # Copyright (C) 2010 The Android Open Source Project 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | ecclist_for_mcc.conf contains emergency number of countries, which will be used to 18 | set the property of emergency numbers. 19 | 20 | The format of ecclist_for_mcc.conf is 21 | 22 | [MCC of a country] white space [Emergency number for that country, separated by comma] 23 | 24 | Note: 25 | 1. Use white space instead of TAB between MCC and emergency number list. 26 | 27 | 2. Emergency number 112 and 911 are included as default emergency numbers. But it is 28 | recommended to explicitly include those two numbers in the list. 29 | 30 | 3. It is recommended to sort the entries by MCC. 31 | -------------------------------------------------------------------------------- /updater/firmware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _RECOVERY_FIRMWARE_H 18 | #define _RECOVERY_FIRMWARE_H 19 | 20 | /* Reboot into the bootloader to install the given update. 21 | * Returns 0 if no radio image was defined, nonzero on error, 22 | * doesn't return at all on success... 23 | */ 24 | int install_firmware_update(const char *update_type, 25 | const char *update_data, 26 | size_t update_length, 27 | int width, int height, int bpp, 28 | const char* busy_image, 29 | const char* fail_image, 30 | const char *log_filename, 31 | const uint8_t* expected_sha1); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /CleanSpec.mk: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007 The Android Open Source Project 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | 16 | # If you don't need to do a full clean build but would like to touch 17 | # a file or delete some intermediate files, add a clean step to the end 18 | # of the list. These steps will only be run once, if they haven't been 19 | # run before. 20 | # 21 | # E.g.: 22 | # $(call add-clean-step, touch -c external/sqlite/sqlite3.h) 23 | # $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) 24 | # 25 | # Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with 26 | # files that are missing or have been moved. 27 | # 28 | # Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. 29 | # Use $(OUT_DIR) to refer to the "out" directory. 30 | # 31 | # If you need to re-do something that's already mentioned, just copy 32 | # the command and add it to the bottom of the list. E.g., if a change 33 | # that you made last week required touching a file and a change you 34 | # made today requires touching the same file, just copy the old 35 | # touch step and add it to the end of the list. 36 | # 37 | # ************************************************ 38 | # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST 39 | # ************************************************ 40 | 41 | # For example: 42 | #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) 43 | #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) 44 | #$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) 45 | #$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) 46 | 47 | # ************************************************ 48 | # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST 49 | # ************************************************ 50 | -------------------------------------------------------------------------------- /updater/log_recovery.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "bootloader.h" 22 | #include "mtdutils/mtdutils.h" 23 | 24 | #define LOGE(...) fprintf(stderr, "E:" __VA_ARGS__) 25 | 26 | void recover_firmware_update_log() { 27 | printf("recovering log from before firmware update\n"); 28 | 29 | mtd_scan_partitions(); 30 | const MtdPartition *part = mtd_find_partition_by_name(CACHE_NAME); 31 | if (part == NULL) { 32 | LOGE("Can't find %s\n", CACHE_NAME); 33 | return; 34 | } 35 | 36 | MtdReadContext* read = mtd_read_partition(part); 37 | 38 | size_t erase_size; 39 | if (mtd_partition_info(part, NULL, &erase_size, NULL) != 0) { 40 | LOGE("Error reading block size\n(%s)\n", strerror(errno)); 41 | mtd_read_close(read); 42 | return; 43 | } 44 | 45 | char* buffer = malloc(erase_size); 46 | if (mtd_read_data(read, buffer, erase_size) != erase_size) { 47 | LOGE("Error reading header block\n(%s)\n", strerror(errno)); 48 | mtd_read_close(read); 49 | free(buffer); 50 | return; 51 | } 52 | if (mtd_read_data(read, buffer, erase_size) != erase_size) { 53 | LOGE("Error reading log block\n(%s)\n", strerror(errno)); 54 | mtd_read_close(read); 55 | free(buffer); 56 | return; 57 | } 58 | mtd_read_close(read); 59 | 60 | if (memcmp(buffer, LOG_MAGIC, LOG_MAGIC_SIZE) != 0) { 61 | printf("no log to recover from cache partition\n"); 62 | free(buffer); 63 | return; 64 | } 65 | 66 | size_t log_size = *(size_t *)(buffer + LOG_MAGIC_SIZE); 67 | 68 | printf("\n###\n### START RECOVERED LOG\n###\n\n"); 69 | fwrite(buffer + sizeof(size_t) + LOG_MAGIC_SIZE, 1, log_size, stdout); 70 | printf("\n\n###\n### END RECOVERED LOG\n###\n\n"); 71 | 72 | free(buffer); 73 | } 74 | -------------------------------------------------------------------------------- /updater/bootloader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _RECOVERY_BOOTLOADER_H 18 | #define _RECOVERY_BOOTLOADER_H 19 | 20 | /* Bootloader Message 21 | * 22 | * This structure describes the content of a block in flash 23 | * that is used for recovery and the bootloader to talk to 24 | * each other. 25 | * 26 | * The command field is updated by linux when it wants to 27 | * reboot into recovery or to update radio or bootloader firmware. 28 | * It is also updated by the bootloader when firmware update 29 | * is complete (to boot into recovery for any final cleanup) 30 | * 31 | * The status field is written by the bootloader after the 32 | * completion of an "update-radio" or "update-hboot" command. 33 | * 34 | * The recovery field is only written by linux and used 35 | * for the system to send a message to recovery or the 36 | * other way around. 37 | */ 38 | struct bootloader_message { 39 | char command[32]; 40 | char status[32]; 41 | char recovery[1024]; 42 | }; 43 | 44 | /* Read and write the bootloader command from the "misc" partition. 45 | * These return zero on success. 46 | */ 47 | int get_bootloader_message(struct bootloader_message *out); 48 | int set_bootloader_message(const struct bootloader_message *in); 49 | 50 | /* Write an update to the cache partition for update-radio or update-hboot. 51 | * Note, this destroys any filesystem on the cache partition! 52 | * The expected bitmap format is 240x320, 16bpp (2Bpp), RGB 5:6:5. 53 | */ 54 | int write_update_for_bootloader( 55 | const char *update, int update_len, 56 | int bitmap_width, int bitmap_height, int bitmap_bpp, 57 | const char *busy_bitmap, const char *error_bitmap, 58 | const char *log_filename); 59 | 60 | /* Look for a log stored in the cache partition in the block after the 61 | * firmware update header. If we can read such a log, copy it to 62 | * stdout (ie, the current log). 63 | */ 64 | void recover_firmware_update_log(); 65 | 66 | #define CACHE_NAME "cache" 67 | #define MISC_NAME "misc" 68 | 69 | #define UPDATE_MAGIC "MSM-RADIO-UPDATE" 70 | #define UPDATE_MAGIC_SIZE 16 71 | #define UPDATE_VERSION 0x00010000 72 | 73 | #define LOG_MAGIC "LOGmagic" 74 | #define LOG_MAGIC_SIZE 8 75 | 76 | 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /releasetools.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 The Android Open Source Project 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Emit commands needed for HTC devices during OTA installation 16 | (installing the radio image).""" 17 | 18 | import common 19 | import re 20 | import sha 21 | 22 | def FullOTA_Assertions(info): 23 | AddBootloaderAssertion(info, info.input_zip) 24 | 25 | 26 | def IncrementalOTA_Assertions(info): 27 | AddBootloaderAssertion(info, info.target_zip) 28 | 29 | 30 | def AddBootloaderAssertion(info, input_zip): 31 | android_info = input_zip.read("OTA/android-info.txt") 32 | m = re.search(r"require\s+version-bootloader\s*=\s*(\S+)", android_info) 33 | if m: 34 | bootloaders = m.group(1).split("|") 35 | if "*" not in bootloaders: 36 | info.script.AssertSomeBootloader(*bootloaders) 37 | info.metadata["pre-bootloader"] = m.group(1) 38 | 39 | 40 | def InstallRadio(radio_img, api_version, input_zip, info): 41 | common.ZipWriteStr(info.output_zip, "radio.img", radio_img) 42 | 43 | if api_version >= 3: 44 | bitmap_txt = input_zip.read("RADIO/bitmap_size.txt") 45 | install_img = input_zip.read("RADIO/firmware_install.565") 46 | error_img = input_zip.read("RADIO/firmware_error.565") 47 | width, height, bpp = bitmap_txt.split() 48 | 49 | radio_sha = sha.sha(radio_img).hexdigest() 50 | 51 | info.script.UnmountAll() 52 | info.script.AppendExtra((''' 53 | assert(htc.install_radio(package_extract_file("radio.img"), 54 | %(width)s, %(height)s, %(bpp)s, 55 | package_extract_file("install.565"), 56 | package_extract_file("error.565"), 57 | %(radio_sha)s)); 58 | ''' % locals()).lstrip()) 59 | 60 | common.ZipWriteStr(info.output_zip, "install.565", install_img) 61 | common.ZipWriteStr(info.output_zip, "error.565", error_img) 62 | elif info.input_version >= 2: 63 | info.script.AppendExtra( 64 | 'write_firmware_image("PACKAGE:radio.img", "radio");') 65 | else: 66 | info.script.AppendExtra( 67 | ('assert(package_extract_file("radio.img", "/tmp/radio.img"),\n' 68 | ' write_firmware_image("/tmp/radio.img", "radio"));\n')) 69 | 70 | 71 | def FullOTA_InstallEnd(info): 72 | try: 73 | radio_img = info.input_zip.read("RADIO/radio.img") 74 | except KeyError: 75 | print "warning: no radio image in input target_files; not flashing radio" 76 | return 77 | 78 | info.script.Print("Writing radio image...") 79 | 80 | InstallRadio(radio_img, info.input_version, info.input_zip, info) 81 | 82 | 83 | def IncrementalOTA_InstallEnd(info): 84 | try: 85 | target_radio = info.target_zip.read("RADIO/radio.img") 86 | except KeyError: 87 | print "warning: radio image missing from target; not flashing radio" 88 | return 89 | 90 | try: 91 | source_radio = info.source_zip.read("RADIO/radio.img") 92 | except KeyError: 93 | source_radio = None 94 | 95 | if source_radio == target_radio: 96 | print "Radio image unchanged; skipping" 97 | return 98 | 99 | InstallRadio(target_radio, info.target_version, info.target_zip, info) 100 | -------------------------------------------------------------------------------- /overlay/frameworks/base/core/res/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 22 | 23 | 24 | 25 | AirTel-India 26 | en_IN 27 | 28 | Chunghwa-Taiwan 29 | zh_TW 30 | 31 | DCM 32 | ja_JP 33 | 14 34 | Era 35 | pl_PL 36 | 37 | H3G-Italy 38 | it_IT 39 | 40 | Hutch-Australia 41 | en_AU 42 | 11 43 | iTELEF-Spain 44 | es_ES 45 | 46 | OPTUS-Australia 47 | en_AU 48 | 11 49 | ORANGE-French 50 | fr_FR 51 | 52 | SMC-Voda-HK 53 | zh_HK 54 | 55 | StarHub-Singapore 56 | en_SG 57 | 11 58 | TIM-Italy 59 | it_IT 60 | 61 | TMA 62 | de_AT 63 | 13 64 | TMCZ 65 | cs_CZ 66 | 13 67 | TMD 68 | de_DE 69 | 13 70 | TMHR 71 | hr_HR 72 | 73 | TMMK 74 | mk_MK 75 | 76 | TMNL 77 | nl_NL 78 | 13 79 | TMSK 80 | sk_SK 81 | 82 | TMUK 83 | en_GB 84 | 13 85 | TMUS 86 | en_US 87 | 11 88 | VODA-Africa-South 89 | en_ZA 90 | 91 | VODA-Australia 92 | en_AU 93 | 11 94 | VODA-Germany 95 | de_DE 96 | 13 97 | VODA-Greece 98 | el_GR 99 | 100 | VODA-Ireland 101 | en_IE 102 | 103 | VODA-Italy 104 | it_IT 105 | 106 | VODA-Mobilkom 107 | de_AT 108 | 13 109 | VODA-Netherland 110 | nl_NL 111 | 13 112 | VODA-New-Zealand 113 | en_NZ 114 | 115 | VODA-Portugal 116 | pt_PT 117 | 118 | VODA-SFR 119 | fr_FR 120 | 121 | VODA-Spain 122 | es_ES 123 | 124 | VODA-Swisscom-DE 125 | de_CH 126 | 13 127 | VODA-Swisscom-FR 128 | fr_CH 129 | 130 | VODA-Swisscom-IT 131 | it_CH 132 | 133 | VODA-Swisscom-WWE 134 | en_CH 135 | 136 | VODA-UK 137 | en_GB 138 | 13 139 | 140 | 141 | -------------------------------------------------------------------------------- /updater/recovery_updater.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "edify/expr.h" 26 | #include "firmware.h" 27 | #include "mincrypt/sha.h" 28 | #include "minzip/Zip.h" 29 | #include "mounts.h" 30 | #include "updater/updater.h" 31 | 32 | Value* UpdateFn(const char* name, State* state, int argc, Expr* argv[]) { 33 | if (argc != 7) { 34 | return ErrorAbort(state, "%s() expects 7 args, got %d", name, argc); 35 | } 36 | 37 | char* type = strrchr(name, '_'); 38 | if (type == NULL || *(type+1) == '\0') { 39 | return ErrorAbort(state, "%s() couldn't get type from function name", 40 | name); 41 | } 42 | ++type; 43 | 44 | Value* image; 45 | Value* width_string; 46 | Value* height_string; 47 | Value* bpp_string; 48 | Value* busy; 49 | Value* fail; 50 | Value* expected_sha1_string; 51 | if (ReadValueArgs(state, argv, 7, &image, 52 | &width_string, &height_string, &bpp_string, 53 | &busy, &fail, &expected_sha1_string) < 0) { 54 | return NULL; 55 | } 56 | 57 | // close the package 58 | ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; 59 | mzCloseZipArchive(za); 60 | ((UpdaterInfo*)(state->cookie))->package_zip = NULL; 61 | 62 | // Try to unmount /cache. If we fail (because we're running in an 63 | // older recovery that still has the package file open), try to 64 | // remount it read-only. If that fails, abort. 65 | sync(); 66 | scan_mounted_volumes(); 67 | MountedVolume* vol = find_mounted_volume_by_mount_point("/cache"); 68 | int result = unmount_mounted_volume(vol); 69 | if (result != 0) { 70 | printf("%s(): failed to unmount cache (%d: %s)\n", 71 | name, result, strerror(errno)); 72 | 73 | result = remount_read_only(vol); 74 | if (result != 0) { 75 | printf("%s(): failed to remount cache (%d: %s)\n", 76 | name, result, strerror(errno)); 77 | return StringValue(strdup("")); 78 | } else { 79 | printf("%s(): remounted cache\n", name); 80 | } 81 | sync(); 82 | } else { 83 | printf("%s(): unmounted cache\n", name); 84 | } 85 | 86 | int width = 0, height = 0, bpp = 0; 87 | 88 | if (width_string->type != VAL_STRING || 89 | (width = strtol(width_string->data, NULL, 10)) == 0) { 90 | printf("%s(): bad width argument", name); 91 | } 92 | if (height_string->type != VAL_STRING || 93 | (height = strtol(height_string->data, NULL, 10)) == 0) { 94 | printf("%s(): bad height argument", name); 95 | } 96 | if (bpp_string->type != VAL_STRING || 97 | (bpp = strtol(bpp_string->data, NULL, 10)) == 0) { 98 | printf("%s(): bad bpp argument", name); 99 | } 100 | 101 | if (image->type != VAL_BLOB) { 102 | printf("image argument is not blob (is type %d)\n", image->type); 103 | goto done; 104 | } 105 | 106 | uint8_t expected_sha1[SHA_DIGEST_SIZE]; 107 | char* data = expected_sha1_string->data; 108 | if (expected_sha1_string->type != VAL_STRING || 109 | strlen(data) != SHA_DIGEST_SIZE*2) { 110 | printf("%s(): bad expected_sha1 argument", name); 111 | goto done; 112 | } 113 | printf("expected sha1 is: "); 114 | int i; 115 | for (i = 0; i < SHA_DIGEST_SIZE; ++i) { 116 | char temp = data[i*2+2]; 117 | data[i*2+2] = '\0'; 118 | expected_sha1[i] = strtol(data+i*2, NULL, 16); 119 | data[i*2+2] = temp; 120 | printf("%02x", expected_sha1[i]); 121 | } 122 | printf("\n"); 123 | 124 | install_firmware_update( 125 | type, 126 | image->data, 127 | image->size, 128 | width, height, bpp, 129 | busy->size > 0 ? busy->data : NULL, 130 | fail->size > 0 ? fail->data : NULL, 131 | "/tmp/recovery.log", 132 | expected_sha1); 133 | printf("%s: install_firmware_update returned!\n", name); 134 | 135 | done: 136 | FreeValue(image); 137 | FreeValue(width_string); 138 | FreeValue(height_string); 139 | FreeValue(bpp_string); 140 | FreeValue(busy); 141 | FreeValue(fail); 142 | // install_firmware_update should reboot. If it returns, it failed. 143 | return StringValue(strdup("")); 144 | } 145 | 146 | void Register_librecovery_updater_htc() { 147 | fprintf(stderr, "installing HTC updater extensions\n"); 148 | 149 | RegisterFunction("htc.install_radio", UpdateFn); 150 | RegisterFunction("htc.install_hboot", UpdateFn); 151 | } 152 | -------------------------------------------------------------------------------- /updater/firmware.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "bootloader.h" 18 | #include "common.h" 19 | #include "firmware.h" 20 | #include "mtdutils/mtdutils.h" 21 | #include "mincrypt/sha.h" 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | /* Bootloader / Recovery Flow 28 | * 29 | * On every boot, the bootloader will read the bootloader_message 30 | * from flash and check the command field. The bootloader should 31 | * deal with the command field not having a 0 terminator correctly 32 | * (so as to not crash if the block is invalid or corrupt). 33 | * 34 | * The bootloader will have to publish the partition that contains 35 | * the bootloader_message to the linux kernel so it can update it. 36 | * 37 | * if command == "boot-recovery" -> boot recovery.img 38 | * else if command == "update-radio" -> update radio image (below) 39 | * else if command == "update-hboot" -> update hboot image (below) 40 | * else -> boot boot.img (normal boot) 41 | * 42 | * Radio/Hboot Update Flow 43 | * 1. the bootloader will attempt to load and validate the header 44 | * 2. if the header is invalid, status="invalid-update", goto #8 45 | * 3. display the busy image on-screen 46 | * 4. if the update image is invalid, status="invalid-radio-image", goto #8 47 | * 5. attempt to update the firmware (depending on the command) 48 | * 6. if successful, status="okay", goto #8 49 | * 7. if failed, and the old image can still boot, status="failed-update" 50 | * 8. write the bootloader_message, leaving the recovery field 51 | * unchanged, updating status, and setting command to 52 | * "boot-recovery" 53 | * 9. reboot 54 | * 55 | * The bootloader will not modify or erase the cache partition. 56 | * It is recovery's responsibility to clean up the mess afterwards. 57 | */ 58 | 59 | #undef LOGE 60 | #define LOGE(...) fprintf(stderr, "E:" __VA_ARGS__) 61 | 62 | 63 | int verify_image(const uint8_t* expected_sha1) { 64 | MtdPartition* part = mtd_find_partition_by_name(CACHE_NAME); 65 | if (part == NULL) { 66 | printf("verify image: failed to find cache partition\n"); 67 | return -1; 68 | } 69 | 70 | size_t block_size; 71 | if (mtd_partition_info(part, NULL, &block_size, NULL) != 0) { 72 | printf("verify image: failed to get cache partition block size\n"); 73 | return -1; 74 | } 75 | printf("block size is 0x%x\n", block_size); 76 | 77 | char* buffer = malloc(block_size); 78 | if (buffer == NULL) { 79 | printf("verify image: failed to allocate memory\n"); 80 | return -1; 81 | } 82 | 83 | MtdReadContext* ctx = mtd_read_partition(part); 84 | if (ctx == NULL) { 85 | printf("verify image: failed to init read context\n"); 86 | return -1; 87 | } 88 | 89 | size_t pos = 0; 90 | if (mtd_read_data(ctx, buffer, block_size) != block_size) { 91 | printf("verify image: failed to read header\n"); 92 | return -1; 93 | } 94 | pos += block_size; 95 | 96 | if (strncmp(buffer, "MSM-RADIO-UPDATE", 16) != 0) { 97 | printf("verify image: header missing magic\n"); 98 | return -1; 99 | } 100 | 101 | unsigned image_offset = *(unsigned*)(buffer+24); 102 | unsigned image_length = *(unsigned*)(buffer+28); 103 | printf("image offset 0x%x length 0x%x\n", image_offset, image_length); 104 | mtd_read_skip_to(ctx, image_offset); 105 | 106 | FILE* f = fopen("/tmp/read-radio.dat", "wb"); 107 | if (f == NULL) { 108 | printf("verify image: failed to open temp file\n"); 109 | } 110 | 111 | SHA_CTX sha_ctx; 112 | SHA_init(&sha_ctx); 113 | 114 | size_t total = 0; 115 | while (total < image_length) { 116 | size_t to_read = image_length - total; 117 | if (to_read > block_size) to_read = block_size; 118 | ssize_t read = mtd_read_data(ctx, buffer, to_read); 119 | if (read < 0) { 120 | printf("verify image: failed reading image (read 0x%x so far)\n", 121 | total); 122 | return -1; 123 | } 124 | if (f) { 125 | fwrite(buffer, 1, read, f); 126 | } 127 | SHA_update(&sha_ctx, buffer, read); 128 | total += read; 129 | } 130 | 131 | if (f) fclose(f); 132 | 133 | free(buffer); 134 | mtd_read_close(ctx); 135 | 136 | const uint8_t* sha1 = SHA_final(&sha_ctx); 137 | if (memcmp(sha1, expected_sha1, SHA_DIGEST_SIZE) != 0) { 138 | printf("verify image: sha1 doesn't match\n"); 139 | return -1; 140 | } 141 | 142 | printf("verify image: verification succeeded\n"); 143 | 144 | return 0; 145 | } 146 | 147 | int install_firmware_update(const char *update_type, 148 | const char *update_data, 149 | size_t update_length, 150 | int width, int height, int bpp, 151 | const char* busy_image, 152 | const char* fail_image, 153 | const char *log_filename, 154 | const uint8_t* expected_sha1) { 155 | if (update_data == NULL || update_length == 0) return 0; 156 | 157 | mtd_scan_partitions(); 158 | 159 | /* We destroy the cache partition to pass the update image to the 160 | * bootloader, so all we can really do afterwards is wipe cache and reboot. 161 | * Set up this instruction now, in case we're interrupted while writing. 162 | */ 163 | 164 | struct bootloader_message boot; 165 | memset(&boot, 0, sizeof(boot)); 166 | strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); 167 | strlcpy(boot.recovery, "recovery\n--wipe_cache\n", sizeof(boot.command)); 168 | if (set_bootloader_message(&boot)) return -1; 169 | 170 | if (write_update_for_bootloader( 171 | update_data, update_length, 172 | width, height, bpp, busy_image, fail_image, log_filename)) { 173 | LOGE("Can't write %s image\n(%s)\n", update_type, strerror(errno)); 174 | return -1; 175 | } 176 | 177 | if (verify_image(expected_sha1) == 0) { 178 | /* The update image is fully written, so now we can instruct 179 | * the bootloader to install it. (After doing so, it will 180 | * come back here, and we will wipe the cache and reboot into 181 | * the system.) 182 | */ 183 | snprintf(boot.command, sizeof(boot.command), "update-%s", update_type); 184 | if (set_bootloader_message(&boot)) { 185 | return -1; 186 | } 187 | 188 | reboot(RB_AUTOBOOT); 189 | 190 | // Can't reboot? WTF? 191 | LOGE("Can't reboot\n"); 192 | } 193 | return -1; 194 | } 195 | -------------------------------------------------------------------------------- /updater/NOTICE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2009, The Android Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | 13 | 14 | Apache License 15 | Version 2.0, January 2004 16 | http://www.apache.org/licenses/ 17 | 18 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 19 | 20 | 1. Definitions. 21 | 22 | "License" shall mean the terms and conditions for use, reproduction, 23 | and distribution as defined by Sections 1 through 9 of this document. 24 | 25 | "Licensor" shall mean the copyright owner or entity authorized by 26 | the copyright owner that is granting the License. 27 | 28 | "Legal Entity" shall mean the union of the acting entity and all 29 | other entities that control, are controlled by, or are under common 30 | control with that entity. For the purposes of this definition, 31 | "control" means (i) the power, direct or indirect, to cause the 32 | direction or management of such entity, whether by contract or 33 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 34 | outstanding shares, or (iii) beneficial ownership of such entity. 35 | 36 | "You" (or "Your") shall mean an individual or Legal Entity 37 | exercising permissions granted by this License. 38 | 39 | "Source" form shall mean the preferred form for making modifications, 40 | including but not limited to software source code, documentation 41 | source, and configuration files. 42 | 43 | "Object" form shall mean any form resulting from mechanical 44 | transformation or translation of a Source form, including but 45 | not limited to compiled object code, generated documentation, 46 | and conversions to other media types. 47 | 48 | "Work" shall mean the work of authorship, whether in Source or 49 | Object form, made available under the License, as indicated by a 50 | copyright notice that is included in or attached to the work 51 | (an example is provided in the Appendix below). 52 | 53 | "Derivative Works" shall mean any work, whether in Source or Object 54 | form, that is based on (or derived from) the Work and for which the 55 | editorial revisions, annotations, elaborations, or other modifications 56 | represent, as a whole, an original work of authorship. For the purposes 57 | of this License, Derivative Works shall not include works that remain 58 | separable from, or merely link (or bind by name) to the interfaces of, 59 | the Work and Derivative Works thereof. 60 | 61 | "Contribution" shall mean any work of authorship, including 62 | the original version of the Work and any modifications or additions 63 | to that Work or Derivative Works thereof, that is intentionally 64 | submitted to Licensor for inclusion in the Work by the copyright owner 65 | or by an individual or Legal Entity authorized to submit on behalf of 66 | the copyright owner. For the purposes of this definition, "submitted" 67 | means any form of electronic, verbal, or written communication sent 68 | to the Licensor or its representatives, including but not limited to 69 | communication on electronic mailing lists, source code control systems, 70 | and issue tracking systems that are managed by, or on behalf of, the 71 | Licensor for the purpose of discussing and improving the Work, but 72 | excluding communication that is conspicuously marked or otherwise 73 | designated in writing by the copyright owner as "Not a Contribution." 74 | 75 | "Contributor" shall mean Licensor and any individual or Legal Entity 76 | on behalf of whom a Contribution has been received by Licensor and 77 | subsequently incorporated within the Work. 78 | 79 | 2. Grant of Copyright License. Subject to the terms and conditions of 80 | this License, each Contributor hereby grants to You a perpetual, 81 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 82 | copyright license to reproduce, prepare Derivative Works of, 83 | publicly display, publicly perform, sublicense, and distribute the 84 | Work and such Derivative Works in Source or Object form. 85 | 86 | 3. Grant of Patent License. Subject to the terms and conditions of 87 | this License, each Contributor hereby grants to You a perpetual, 88 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 89 | (except as stated in this section) patent license to make, have made, 90 | use, offer to sell, sell, import, and otherwise transfer the Work, 91 | where such license applies only to those patent claims licensable 92 | by such Contributor that are necessarily infringed by their 93 | Contribution(s) alone or by combination of their Contribution(s) 94 | with the Work to which such Contribution(s) was submitted. If You 95 | institute patent litigation against any entity (including a 96 | cross-claim or counterclaim in a lawsuit) alleging that the Work 97 | or a Contribution incorporated within the Work constitutes direct 98 | or contributory patent infringement, then any patent licenses 99 | granted to You under this License for that Work shall terminate 100 | as of the date such litigation is filed. 101 | 102 | 4. Redistribution. You may reproduce and distribute copies of the 103 | Work or Derivative Works thereof in any medium, with or without 104 | modifications, and in Source or Object form, provided that You 105 | meet the following conditions: 106 | 107 | (a) You must give any other recipients of the Work or 108 | Derivative Works a copy of this License; and 109 | 110 | (b) You must cause any modified files to carry prominent notices 111 | stating that You changed the files; and 112 | 113 | (c) You must retain, in the Source form of any Derivative Works 114 | that You distribute, all copyright, patent, trademark, and 115 | attribution notices from the Source form of the Work, 116 | excluding those notices that do not pertain to any part of 117 | the Derivative Works; and 118 | 119 | (d) If the Work includes a "NOTICE" text file as part of its 120 | distribution, then any Derivative Works that You distribute must 121 | include a readable copy of the attribution notices contained 122 | within such NOTICE file, excluding those notices that do not 123 | pertain to any part of the Derivative Works, in at least one 124 | of the following places: within a NOTICE text file distributed 125 | as part of the Derivative Works; within the Source form or 126 | documentation, if provided along with the Derivative Works; or, 127 | within a display generated by the Derivative Works, if and 128 | wherever such third-party notices normally appear. The contents 129 | of the NOTICE file are for informational purposes only and 130 | do not modify the License. You may add Your own attribution 131 | notices within Derivative Works that You distribute, alongside 132 | or as an addendum to the NOTICE text from the Work, provided 133 | that such additional attribution notices cannot be construed 134 | as modifying the License. 135 | 136 | You may add Your own copyright statement to Your modifications and 137 | may provide additional or different license terms and conditions 138 | for use, reproduction, or distribution of Your modifications, or 139 | for any such Derivative Works as a whole, provided Your use, 140 | reproduction, and distribution of the Work otherwise complies with 141 | the conditions stated in this License. 142 | 143 | 5. Submission of Contributions. Unless You explicitly state otherwise, 144 | any Contribution intentionally submitted for inclusion in the Work 145 | by You to the Licensor shall be under the terms and conditions of 146 | this License, without any additional terms or conditions. 147 | Notwithstanding the above, nothing herein shall supersede or modify 148 | the terms of any separate license agreement you may have executed 149 | with Licensor regarding such Contributions. 150 | 151 | 6. Trademarks. This License does not grant permission to use the trade 152 | names, trademarks, service marks, or product names of the Licensor, 153 | except as required for reasonable and customary use in describing the 154 | origin of the Work and reproducing the content of the NOTICE file. 155 | 156 | 7. Disclaimer of Warranty. Unless required by applicable law or 157 | agreed to in writing, Licensor provides the Work (and each 158 | Contributor provides its Contributions) on an "AS IS" BASIS, 159 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 160 | implied, including, without limitation, any warranties or conditions 161 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 162 | PARTICULAR PURPOSE. You are solely responsible for determining the 163 | appropriateness of using or redistributing the Work and assume any 164 | risks associated with Your exercise of permissions under this License. 165 | 166 | 8. Limitation of Liability. In no event and under no legal theory, 167 | whether in tort (including negligence), contract, or otherwise, 168 | unless required by applicable law (such as deliberate and grossly 169 | negligent acts) or agreed to in writing, shall any Contributor be 170 | liable to You for damages, including any direct, indirect, special, 171 | incidental, or consequential damages of any character arising as a 172 | result of this License or out of the use or inability to use the 173 | Work (including but not limited to damages for loss of goodwill, 174 | work stoppage, computer failure or malfunction, or any and all 175 | other commercial damages or losses), even if such Contributor 176 | has been advised of the possibility of such damages. 177 | 178 | 9. Accepting Warranty or Additional Liability. While redistributing 179 | the Work or Derivative Works thereof, You may choose to offer, 180 | and charge a fee for, acceptance of support, warranty, indemnity, 181 | or other liability obligations and/or rights consistent with this 182 | License. However, in accepting such obligations, You may act only 183 | on Your own behalf and on Your sole responsibility, not on behalf 184 | of any other Contributor, and only if You agree to indemnify, 185 | defend, and hold each Contributor harmless for any liability 186 | incurred by, or claims asserted against, such Contributor by reason 187 | of your accepting any such warranty or additional liability. 188 | 189 | END OF TERMS AND CONDITIONS 190 | 191 | -------------------------------------------------------------------------------- /updater/bootloader.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "bootloader.h" 18 | #include "common.h" 19 | #include "mtdutils/mtdutils.h" 20 | #include "roots.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | static const int MISC_PAGES = 3; // number of pages to save 27 | static const int MISC_COMMAND_PAGE = 1; // bootloader command is this page 28 | 29 | #undef LOGE 30 | #define LOGE(...) fprintf(stderr, "E:" __VA_ARGS__) 31 | 32 | #ifdef LOG_VERBOSE 33 | static void dump_data(const char *data, int len) { 34 | int pos; 35 | for (pos = 0; pos < len; ) { 36 | printf("%05x: %02x", pos, data[pos]); 37 | for (++pos; pos < len && (pos % 24) != 0; ++pos) { 38 | printf(" %02x", data[pos]); 39 | } 40 | printf("\n"); 41 | } 42 | } 43 | #endif 44 | 45 | int get_bootloader_message(struct bootloader_message *out) { 46 | size_t write_size; 47 | const MtdPartition *part = mtd_find_partition_by_name(MISC_NAME); 48 | if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { 49 | LOGE("Can't find %s\n", MISC_NAME); 50 | return -1; 51 | } 52 | 53 | MtdReadContext *read = mtd_read_partition(part); 54 | if (read == NULL) { 55 | LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); 56 | return -1; 57 | } 58 | 59 | const ssize_t size = write_size * MISC_PAGES; 60 | char data[size]; 61 | ssize_t r = mtd_read_data(read, data, size); 62 | if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); 63 | mtd_read_close(read); 64 | if (r != size) return -1; 65 | 66 | #ifdef LOG_VERBOSE 67 | printf("\n--- get_bootloader_message ---\n"); 68 | dump_data(data, size); 69 | printf("\n"); 70 | #endif 71 | 72 | memcpy(out, &data[write_size * MISC_COMMAND_PAGE], sizeof(*out)); 73 | return 0; 74 | } 75 | 76 | int set_bootloader_message(const struct bootloader_message *in) { 77 | size_t write_size; 78 | const MtdPartition *part = mtd_find_partition_by_name(MISC_NAME); 79 | if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { 80 | LOGE("Can't find %s\n", MISC_NAME); 81 | return -1; 82 | } 83 | 84 | MtdReadContext *read = mtd_read_partition(part); 85 | if (read == NULL) { 86 | LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); 87 | return -1; 88 | } 89 | 90 | ssize_t size = write_size * MISC_PAGES; 91 | char data[size]; 92 | ssize_t r = mtd_read_data(read, data, size); 93 | if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); 94 | mtd_read_close(read); 95 | if (r != size) return -1; 96 | 97 | memcpy(&data[write_size * MISC_COMMAND_PAGE], in, sizeof(*in)); 98 | 99 | #ifdef LOG_VERBOSE 100 | printf("\n--- set_bootloader_message ---\n"); 101 | dump_data(data, size); 102 | printf("\n"); 103 | #endif 104 | 105 | MtdWriteContext *write = mtd_write_partition(part); 106 | if (write == NULL) { 107 | LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); 108 | return -1; 109 | } 110 | if (mtd_write_data(write, data, size) != size) { 111 | LOGE("Can't write %s\n(%s)\n", MISC_NAME, strerror(errno)); 112 | mtd_write_close(write); 113 | return -1; 114 | } 115 | if (mtd_write_close(write)) { 116 | LOGE("Can't finish %s\n(%s)\n", MISC_NAME, strerror(errno)); 117 | return -1; 118 | } 119 | 120 | LOGI("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : ""); 121 | return 0; 122 | } 123 | 124 | /* Update Image 125 | * 126 | * - will be stored in the "cache" partition 127 | * - bad blocks will be ignored, like boot.img and recovery.img 128 | * - the first block will be the image header (described below) 129 | * - the size is in BYTES, inclusive of the header 130 | * - offsets are in BYTES from the start of the update header 131 | * - two raw bitmaps will be included, the "busy" and "fail" bitmaps 132 | * - for dream, the bitmaps will be 320x480x16bpp RGB565 133 | */ 134 | 135 | struct update_header { 136 | unsigned char MAGIC[UPDATE_MAGIC_SIZE]; 137 | 138 | unsigned version; 139 | unsigned size; 140 | 141 | unsigned image_offset; 142 | unsigned image_length; 143 | 144 | unsigned bitmap_width; 145 | unsigned bitmap_height; 146 | unsigned bitmap_bpp; 147 | 148 | unsigned busy_bitmap_offset; 149 | unsigned busy_bitmap_length; 150 | 151 | unsigned fail_bitmap_offset; 152 | unsigned fail_bitmap_length; 153 | }; 154 | 155 | int write_update_for_bootloader( 156 | const char *update, int update_length, 157 | int bitmap_width, int bitmap_height, int bitmap_bpp, 158 | const char *busy_bitmap, const char *fail_bitmap, 159 | const char *log_filename) { 160 | const MtdPartition *part = mtd_find_partition_by_name(CACHE_NAME); 161 | if (part == NULL) { 162 | LOGE("Can't find %s\n", CACHE_NAME); 163 | return -1; 164 | } 165 | 166 | MtdWriteContext *write = mtd_write_partition(part); 167 | if (write == NULL) { 168 | LOGE("Can't open %s\n(%s)\n", CACHE_NAME, strerror(errno)); 169 | return -1; 170 | } 171 | 172 | /* Write an invalid (zero) header first, to disable any previous 173 | * update and any other structured contents (like a filesystem), 174 | * and as a placeholder for the amount of space required. 175 | */ 176 | 177 | struct update_header header; 178 | memset(&header, 0, sizeof(header)); 179 | const ssize_t header_size = sizeof(header); 180 | if (mtd_write_data(write, (char*) &header, header_size) != header_size) { 181 | LOGE("Can't write header to %s\n(%s)\n", CACHE_NAME, strerror(errno)); 182 | mtd_write_close(write); 183 | return -1; 184 | } 185 | 186 | /* Write each section individually block-aligned, so we can write 187 | * each block independently without complicated buffering. 188 | */ 189 | 190 | memcpy(&header.MAGIC, UPDATE_MAGIC, UPDATE_MAGIC_SIZE); 191 | header.version = UPDATE_VERSION; 192 | header.size = header_size; 193 | 194 | if (log_filename != NULL) { 195 | // Write 1 byte into the following block, then fill to the end 196 | // in order to reserve that block. We'll use the block to 197 | // send a copy of the log through to the next invocation of 198 | // recovery. We write the log as late as possible in order to 199 | // capture any messages emitted by this function. 200 | mtd_erase_blocks(write, 0); 201 | if (mtd_write_data(write, (char*) &header, 1) != 1) { 202 | LOGE("Can't write log block to %s\n(%s)\n", 203 | CACHE_NAME, strerror(errno)); 204 | mtd_write_close(write); 205 | return -1; 206 | } 207 | } 208 | 209 | off_t image_start_pos = mtd_erase_blocks(write, 0); 210 | header.image_length = update_length; 211 | if ((int) header.image_offset == -1 || 212 | mtd_write_data(write, update, update_length) != update_length) { 213 | LOGE("Can't write update to %s\n(%s)\n", CACHE_NAME, strerror(errno)); 214 | mtd_write_close(write); 215 | return -1; 216 | } 217 | off_t busy_start_pos = mtd_erase_blocks(write, 0); 218 | header.image_offset = mtd_find_write_start(write, image_start_pos); 219 | 220 | header.bitmap_width = bitmap_width; 221 | header.bitmap_height = bitmap_height; 222 | header.bitmap_bpp = bitmap_bpp; 223 | 224 | int bitmap_length = (bitmap_bpp + 7) / 8 * bitmap_width * bitmap_height; 225 | 226 | LOGE("writing busy bitmap\n"); 227 | header.busy_bitmap_length = busy_bitmap != NULL ? bitmap_length : 0; 228 | if ((int) header.busy_bitmap_offset == -1 || 229 | mtd_write_data(write, busy_bitmap, bitmap_length) != bitmap_length) { 230 | LOGE("Can't write bitmap to %s\n(%s)\n", CACHE_NAME, strerror(errno)); 231 | mtd_write_close(write); 232 | return -1; 233 | } 234 | LOGE("busy bitmap written\n"); 235 | off_t fail_start_pos = mtd_erase_blocks(write, 0); 236 | LOGE("block padded\n"); 237 | header.busy_bitmap_offset = mtd_find_write_start(write, busy_start_pos); 238 | 239 | header.fail_bitmap_length = fail_bitmap != NULL ? bitmap_length : 0; 240 | if ((int) header.fail_bitmap_offset == -1 || 241 | mtd_write_data(write, fail_bitmap, bitmap_length) != bitmap_length) { 242 | LOGE("Can't write bitmap to %s\n(%s)\n", CACHE_NAME, strerror(errno)); 243 | mtd_write_close(write); 244 | return -1; 245 | } 246 | LOGE("finishing block\n"); 247 | mtd_erase_blocks(write, 0); 248 | LOGE("finished block\n"); 249 | header.fail_bitmap_offset = mtd_find_write_start(write, fail_start_pos); 250 | 251 | /* Write the header last, after all the blocks it refers to, so that 252 | * when the magic number is installed everything is valid. 253 | */ 254 | 255 | if (mtd_write_close(write)) { 256 | LOGE("Can't finish writing %s\n(%s)\n", CACHE_NAME, strerror(errno)); 257 | return -1; 258 | } 259 | 260 | write = mtd_write_partition(part); 261 | if (write == NULL) { 262 | LOGE("Can't reopen %s\n(%s)\n", CACHE_NAME, strerror(errno)); 263 | return -1; 264 | } 265 | 266 | if (mtd_write_data(write, (char*) &header, header_size) != header_size) { 267 | LOGE("Can't rewrite header to %s\n(%s)\n", CACHE_NAME, strerror(errno)); 268 | mtd_write_close(write); 269 | return -1; 270 | } 271 | 272 | if (log_filename != NULL) { 273 | LOGE("writing log\n"); 274 | size_t erase_size; 275 | if (mtd_partition_info(part, NULL, &erase_size, NULL) != 0) { 276 | LOGE("Error reading block size\n(%s)\n", strerror(errno)); 277 | mtd_write_close(write); 278 | return -1; 279 | } 280 | mtd_erase_blocks(write, 0); 281 | 282 | if (erase_size > 0) { 283 | char* log = malloc(erase_size); 284 | FILE* f = fopen(log_filename, "rb"); 285 | // The fseek() may fail if it tries to go before the 286 | // beginning of the log, but that's okay because we want 287 | // to be positioned at the start anyway. 288 | fseek(f, -(erase_size-sizeof(size_t)-LOG_MAGIC_SIZE), SEEK_END); 289 | memcpy(log, LOG_MAGIC, LOG_MAGIC_SIZE); 290 | size_t read = fread(log+sizeof(size_t)+LOG_MAGIC_SIZE, 291 | 1, erase_size-sizeof(size_t)-LOG_MAGIC_SIZE, f); 292 | LOGI("read %d bytes from log\n", (int)read); 293 | *(size_t *)(log + LOG_MAGIC_SIZE) = read; 294 | fclose(f); 295 | if (mtd_write_data(write, log, erase_size) != erase_size) { 296 | LOGE("failed to store log in cache partition\n(%s)\n", 297 | strerror(errno)); 298 | mtd_write_close(write); 299 | } 300 | free(log); 301 | } 302 | } 303 | 304 | if (mtd_erase_blocks(write, 0) != image_start_pos) { 305 | LOGE("Misalignment rewriting %s\n(%s)\n", CACHE_NAME, strerror(errno)); 306 | mtd_write_close(write); 307 | return -1; 308 | } 309 | 310 | LOGE("closing partition\n"); 311 | if (mtd_write_close(write)) { 312 | LOGE("Can't finish header of %s\n(%s)\n", CACHE_NAME, strerror(errno)); 313 | return -1; 314 | } 315 | 316 | return 0; 317 | } 318 | --------------------------------------------------------------------------------