static int read_data(ZipArchive *zip, const ZipEntry *entry, char** ppData, int* pLength) { int len = (int)mzGetZipEntryUncompLen(entry); if (len <= 0) { LOGE("Bad data length %d\n", len); return -1; } char *data = malloc(len + 1); if (data == NULL) { LOGE("Can't allocate %d bytes for data\n", len + 1); return -2; } bool ok = mzReadZipEntry(zip, entry, data, len); if (!ok) { LOGE("Error while reading data\n"); free(data); return -3; } data[len] = '\0'; // not necessary, but just to be safe *ppData = data; if (pLength) { *pLength = len; } return 0; }
/* 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; }
// package_extract_file(package_path, destination_path) // or // package_extract_file(package_path) // to return the entire contents of the file as the result of this // function (the char* returned is actually a FileContents*). Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 1 && argc != 2) { return ErrorAbort(state, "%s() expects 1 or 2 args, got %d", name, argc); } bool success = false; if (argc == 2) { // The two-argument version extracts to a file. char* zip_path; char* dest_path; if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL; ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; const ZipEntry* entry = mzFindZipEntry(za, zip_path); if (entry == NULL) { fprintf(stderr, "%s: no %s in package\n", name, zip_path); goto done2; } FILE* f = fopen(dest_path, "wb"); if (f == NULL) { fprintf(stderr, "%s: can't open %s for write: %s\n", name, dest_path, strerror(errno)); goto done2; } success = mzExtractZipEntryToFile(za, entry, fileno(f)); fclose(f); done2: free(zip_path); free(dest_path); return StringValue(strdup(success ? "t" : "")); } else { // The one-argument version returns the contents of the file // as the result. char* zip_path; Value* v = malloc(sizeof(Value)); v->type = VAL_BLOB; v->size = -1; v->data = NULL; if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL; ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; const ZipEntry* entry = mzFindZipEntry(za, zip_path); if (entry == NULL) { fprintf(stderr, "%s: no %s in package\n", name, zip_path); goto done1; } v->size = mzGetZipEntryUncompLen(entry); v->data = malloc(v->size); if (v->data == NULL) { fprintf(stderr, "%s: failed to allocate %ld bytes for %s\n", name, (long)v->size, zip_path); goto done1; } success = mzExtractZipEntryToBuffer(za, entry, (unsigned char *)v->data); done1: free(zip_path); if (!success) { free(v->data); v->data = NULL; v->size = -1; } return v; } }
Value *FlashIfwiOrBomFn(enum flash_option_type flash_option, const char *name, State * state, int argc, Expr * argv[]) { Value *ret = NULL; char *filename = NULL; int err, i, num, buffsize; char ifwi_name[128]; ZipArchive ifwi_za; const ZipEntry *ifwi_entry; unsigned char *buffer; unsigned char *file_buf = NULL; size_t file_size; #ifdef TEE_FRAMEWORK char bom_token_name[128]; const ZipEntry *bom_token_entry; int bom_token_buffsize; unsigned char *bom_token_buffer; #endif if (ReadArgs(state, argv, 1, &filename) < 0) { return NULL; } if (filename == NULL || strlen(filename) == 0) { ErrorAbort(state, "filename argument to %s can't be empty", name); goto done; } err = file_read(filename, (void **)&file_buf, &file_size); if (err) { ErrorAbort(state, "Failed to open zip archive file %s\n", filename); goto done; } err = mzOpenZipArchive(file_buf, file_size, &ifwi_za); if (err) { ErrorAbort(state, "Failed to open zip archive\n"); goto done; } num = mzZipEntryCount(&ifwi_za); for (i = 0; i < num; i++) { ifwi_entry = mzGetZipEntryAt(&ifwi_za, i); if ((ifwi_entry->fileNameLen + 1) < sizeof(ifwi_name)) { strncpy(ifwi_name, ifwi_entry->fileName, ifwi_entry->fileNameLen); ifwi_name[ifwi_entry->fileNameLen] = '\0'; } else { ErrorAbort(state, "ifwi file name is too big. Size max is:%zd.\n", sizeof(ifwi_name)); goto error; } if (strncmp(ifwi_name, IFWI_NAME, strlen(IFWI_NAME))) continue; buffsize = mzGetZipEntryUncompLen(ifwi_entry); if (buffsize <= 0) { ErrorAbort(state, "Bad ifwi_entry size : %d.\n", buffsize); goto error; } buffer = (unsigned char *)malloc(sizeof(unsigned char) * buffsize); if (buffer == NULL) { ErrorAbort(state, "Unable to alloc ifwi buffer of %d bytes.\n", buffsize); goto error; } err = mzExtractZipEntryToBuffer(&ifwi_za, ifwi_entry, buffer); if (!err) { ErrorAbort(state, "Failed to unzip %s\n", IFWI_BIN_PATH); free(buffer); goto error; } if (check_ifwi_file(buffer, buffsize) < 1) { free(buffer); continue; } if (flash_option == FLASH_BOM_TOKEN_BINARY) { #ifdef TEE_FRAMEWORK strcpy(bom_token_name, BOM_TOKEN_NAME); strncat(bom_token_name, &(ifwi_name[strlen(IFWI_NAME)]), sizeof(bom_token_name) - strlen(BOM_TOKEN_NAME) - 1); bom_token_entry = mzFindZipEntry(&ifwi_za, bom_token_name); if (bom_token_entry != NULL) { bom_token_buffsize = mzGetZipEntryUncompLen(bom_token_entry); if (bom_token_buffsize <= 0) { ErrorAbort(state, "Bad bom_token_entry size : %d.\n", bom_token_buffsize); free(buffer); goto error; } bom_token_buffer = (unsigned char *)malloc(sizeof(unsigned char) * bom_token_buffsize); if (bom_token_buffer == NULL) { ErrorAbort(state, "Unable to alloc bom token buffer of %d bytes.\n", bom_token_buffsize); free(buffer); goto error; } err = mzExtractZipEntryToBuffer(&ifwi_za, bom_token_entry, bom_token_buffer); if (!err) { ErrorAbort(state, "Failed to unzip %s.\n", IFWI_BIN_PATH); free(bom_token_buffer); free(buffer); goto error; } if (write_token(bom_token_buffer, bom_token_buffsize) == 0) { printf("BOM token written\n"); } else { printf("Unable to write BOM token.\n"); cancel_update(0, NULL); free(bom_token_buffer); free(buffer); ret = StringValue(strdup("fail")); goto error; } free(bom_token_buffer); } #else printf("BOM token flashing not supported\n"); #endif } else if (flash_option == FLASH_IFWI_BINARY) { printf("Flashing IFWI\n"); update_ifwi_file(buffer, buffsize); } else { ErrorAbort(state, "Don't know what to do with option %d\n", flash_option); free(buffer); goto error; } free(buffer); } ret = StringValue(strdup("t")); error: mzCloseZipArchive(&ifwi_za); done: free(file_buf); if (filename) free(filename); return ret; }