/* write_radio_image <src-image> * write_hboot_image <src-image> * Doesn't actually take effect until the rest of installation finishes. */ static int cmd_write_firmware_image(const char *name, void *cookie, int argc, const char *argv[]) { UNUSED(cookie); CHECK_WORDS(); if (argc != 1) { LOGE("Command %s requires exactly one argument\n", name); return 1; } const char *type; if (!strcmp(name, "write_radio_image")) { type = "radio"; } else if (!strcmp(name, "write_hboot_image")) { type = "hboot"; } else { LOGE("Unknown firmware update command %s\n", name); return 1; } if (!is_package_root_path(argv[0])) { LOGE("Command %s: non-package image file \"%s\" not supported\n", name, argv[0]); return 1; } ui_print("Extracting %s image...\n", type); char path[PATH_MAX]; const ZipArchive *package; if (!translate_package_root_path(argv[0], path, sizeof(path), &package)) { LOGE("Command %s: bad source path \"%s\"\n", name, argv[0]); return 1; } const ZipEntry *entry = mzFindZipEntry(package, path); if (entry == NULL) { LOGE("Can't find %s\n", path); return 1; } // Load the update image into RAM. struct FirmwareContext context; context.total_bytes = mzGetZipEntryUncompLen(entry); context.done_bytes = 0; context.data = malloc(context.total_bytes); if (context.data == NULL) { LOGE("Can't allocate %d bytes for %s\n", context.total_bytes, argv[0]); return 1; } if (!mzProcessZipEntryContents(package, entry, firmware_fn, &context) || context.done_bytes != context.total_bytes) { LOGE("Can't read %s\n", argv[0]); free(context.data); return 1; } if (remember_firmware_update(type, context.data, context.total_bytes)) { LOGE("Can't store %s image\n", type); free(context.data); return 1; } return 0; }
/* write_raw_image <src-image> <dest-root> */ static int cmd_write_raw_image(const char *name, void *cookie, int argc, const char *argv[]) { UNUSED(cookie); CHECK_WORDS(); if (argc != 2) { LOGE("Command %s requires exactly two arguments\n", name); return 1; } // Use 10% of the progress bar (20% post-verification) by default const char *src_root_path = argv[0]; const char *dst_root_path = argv[1]; ui_print("Writing %s...\n", dst_root_path); if (!gDidShowProgress) ui_show_progress(DEFAULT_IMAGE_PROGRESS_FRACTION, 0); /* Find the source image, which is probably in a package. */ if (!is_package_root_path(src_root_path)) { LOGE("Command %s: non-package source path \"%s\" not yet supported\n", name, src_root_path); return 255; } /* Get the package. */ char srcpathbuf[PATH_MAX]; const char *src_path; const ZipArchive *package; src_path = translate_package_root_path(src_root_path, srcpathbuf, sizeof(srcpathbuf), &package); if (src_path == NULL) { LOGE("Command %s: bad source path \"%s\"\n", name, src_root_path); return 1; } /* Get the entry. */ const ZipEntry *entry = mzFindZipEntry(package, src_path); if (entry == NULL) { LOGE("Missing file %s\n", src_path); return 1; } /* Unmount the destination root if it isn't already. */ int ret = ensure_root_path_unmounted(dst_root_path); if (ret < 0) { LOGE("Can't unmount %s\n", dst_root_path); return 1; } /* Open the partition for writing. */ const MtdPartition *partition = get_root_mtd_partition(dst_root_path); if (partition == NULL) { LOGE("Can't find %s\n", dst_root_path); return 1; } MtdWriteContext *context = mtd_write_partition(partition); if (context == NULL) { LOGE("Can't open %s\n", dst_root_path); return 1; } /* Extract and write the image. */ bool ok = mzProcessZipEntryContents(package, entry, write_raw_image_process_fn, context); if (!ok) { LOGE("Error writing %s\n", dst_root_path); mtd_write_close(context); return 1; } if (mtd_erase_blocks(context, -1) == (off_t) -1) { LOGE("Error finishing %s\n", dst_root_path); mtd_write_close(context); return -1; } if (mtd_write_close(context)) { LOGE("Error closing %s\n", dst_root_path); return -1; } return 0; }
static void* unzip_new_data(void* cookie) { NewThreadInfo* nti = (NewThreadInfo*) cookie; mzProcessZipEntryContents(nti->za, nti->entry, receive_new_data, nti); return NULL; }