diff options
-rw-r--r-- | Android.mk | 3 | ||||
-rw-r--r-- | common.h | 3 | ||||
-rw-r--r-- | install.c | 66 | ||||
-rw-r--r-- | recovery.c | 22 | ||||
-rw-r--r-- | updater/updater.c | 7 |
5 files changed, 74 insertions, 27 deletions
diff --git a/Android.mk b/Android.mk index ba38ebe56..f04f7ddcc 100644 --- a/Android.mk +++ b/Android.mk @@ -22,6 +22,9 @@ LOCAL_MODULE := recovery LOCAL_FORCE_STATIC_EXECUTABLE := true +RECOVERY_API_VERSION := 2 +LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) + # This binary is in the recovery ramdisk, which is otherwise a copy of root. # It gets copied there in config/Makefile. LOCAL_MODULE_TAGS suppresses # a (redundant) copy of the binary in /system/bin for user builds. @@ -90,4 +90,7 @@ void ui_reset_progress(); #define LOGD(...) do {} while (0) #endif +#define STRINGIFY(x) #x +#define EXPAND(x) STRINGIFY(x) + #endif // RECOVERY_COMMON_H @@ -117,34 +117,54 @@ handle_update_script(ZipArchive *zip, const ZipEntry *update_script_entry) // The update binary ask us to install a firmware file on reboot. Set // that up. Takes ownership of type and filename. static int -handle_firmware_update(char* type, char* filename) { - struct stat st_data; - if (stat(filename, &st_data) < 0) { - LOGE("Error stat'ing %s: %s\n", filename, strerror(errno)); - return INSTALL_ERROR; +handle_firmware_update(char* type, char* filename, ZipArchive* zip) { + unsigned int data_size; + const ZipEntry* entry = NULL; + + if (strncmp(filename, "PACKAGE:", 8) == 0) { + entry = mzFindZipEntry(zip, filename+8); + if (entry == NULL) { + LOGE("Failed to find \"%s\" in package", filename+8); + return INSTALL_ERROR; + } + data_size = entry->uncompLen; + } else { + struct stat st_data; + if (stat(filename, &st_data) < 0) { + LOGE("Error stat'ing %s: %s\n", filename, strerror(errno)); + return INSTALL_ERROR; + } + data_size = st_data.st_size; } LOGI("type is %s; size is %d; file is %s\n", - type, (int)st_data.st_size, filename); + type, data_size, filename); - char* data = malloc(st_data.st_size); + char* data = malloc(data_size); if (data == NULL) { - LOGE("Can't allocate %d bytes for firmware data\n", st_data.st_size); + LOGI("Can't allocate %d bytes for firmware data\n", data_size); return INSTALL_ERROR; } - FILE* f = fopen(filename, "rb"); - if (f == NULL) { - LOGE("Failed to open %s: %s\n", filename, strerror(errno)); - return INSTALL_ERROR; - } - if (fread(data, 1, st_data.st_size, f) != st_data.st_size) { - LOGE("Failed to read firmware data: %s\n", strerror(errno)); - return INSTALL_ERROR; + if (entry) { + if (mzReadZipEntry(zip, entry, data, data_size) == false) { + LOGE("Failed to read \"%s\" from package", filename+8); + return INSTALL_ERROR; + } + } else { + FILE* f = fopen(filename, "rb"); + if (f == NULL) { + LOGE("Failed to open %s: %s\n", filename, strerror(errno)); + return INSTALL_ERROR; + } + if (fread(data, 1, data_size, f) != data_size) { + LOGE("Failed to read firmware data: %s\n", strerror(errno)); + return INSTALL_ERROR; + } + fclose(f); } - fclose(f); - if (remember_firmware_update(type, data, st_data.st_size)) { + if (remember_firmware_update(type, data, data_size)) { LOGE("Can't store %s image\n", type); free(data); return INSTALL_ERROR; @@ -184,7 +204,7 @@ try_update_binary(const char *path, ZipArchive *zip) { // When executing the update binary contained in the package, the // arguments passed are: // - // - the version number for this interface (currently 1) + // - the version number for this interface // // - an fd to which the program can write in order to update the // progress bar. The program can write single-line commands: @@ -194,7 +214,9 @@ try_update_binary(const char *path, ZipArchive *zip) { // // firmware <"hboot"|"radio"> <filename> // arrange to install the contents of <filename> in the - // given partition on reboot. + // given partition on reboot. (API v2: <filename> may + // start with "PACKAGE:" to indicate taking a file from + // the OTA package.) // // ui_print <string> // display <string> on the screen. @@ -204,7 +226,7 @@ try_update_binary(const char *path, ZipArchive *zip) { char** args = malloc(sizeof(char*) * 5); args[0] = binary; - args[1] = "1"; + args[1] = EXPAND(RECOVERY_API_VERSION); // defined in Android.mk args[2] = malloc(10); sprintf(args[2], "%d", pipefd[1]); args[3] = (char*)path; @@ -272,7 +294,7 @@ try_update_binary(const char *path, ZipArchive *zip) { } if (firmware_type != NULL) { - return handle_firmware_update(firmware_type, firmware_filename); + return handle_firmware_update(firmware_type, firmware_filename, zip); } else { return INSTALL_SUCCESS; } diff --git a/recovery.c b/recovery.c index 6c13b9f31..8ad133948 100644 --- a/recovery.c +++ b/recovery.c @@ -288,7 +288,25 @@ erase_root(const char *root) static void prompt_and_wait() { - ui_start_menu(MENU_HEADERS, MENU_ITEMS); + char* title[] = { "Android system recovery <" + EXPAND(RECOVERY_API_VERSION) ">", + "", + NULL }; + + // count the number of lines in our title, plus the + // product-provided headers. + int count = 0; + char** p; + for (p = title; *p; ++p, ++count); + for (p = MENU_HEADERS; *p; ++p, ++count); + + char** headers = malloc((count+1) * sizeof(char*)); + char** h = headers; + for (p = title; *p; ++p, ++h) *h = *p; + for (p = MENU_HEADERS; *p; ++p, ++h) *h = *p; + *h = NULL; + + ui_start_menu(headers, MENU_ITEMS); int selected = 0; int chosen_item = -1; @@ -370,7 +388,7 @@ prompt_and_wait() // if we didn't return from this function to reboot, show // the menu again. - ui_start_menu(MENU_HEADERS, MENU_ITEMS); + ui_start_menu(headers, MENU_ITEMS); selected = 0; chosen_item = -1; diff --git a/updater/updater.c b/updater/updater.c index 5a2ed2ccf..31d93ae96 100644 --- a/updater/updater.c +++ b/updater/updater.c @@ -34,9 +34,10 @@ int main(int argc, char** argv) { } char* version = argv[1]; - if (version[0] != '1' || version[1] != '\0') { - fprintf(stderr, "wrong updater binary API; expected 1, got %s\n", - version); + if ((version[0] != '1' && version[0] != '2') || version[1] != '\0') { + // We support version "1" or "2". + fprintf(stderr, "wrong updater binary API; expected 1 or 2, got %s\n", + argv[1]); return 2; } |