android OTA package packing and extract to partition
1. 打包image并将写image到对应partition的命令写入OTA升级脚本里
device/google/dragon/releasetools.py
def FullOTA_InstallEnd(info): # copy the data into the package. try: bootloader_img = info.input_zip.read("RADIO/bootloader.img") ec_img = info.input_zip.read("RADIO/ec.bin") except KeyError: print "no firmware images in target_files; skipping install" return # copy the data into the package. common.ZipWriteStr(info.output_zip, "bootloader.img", bootloader_img) #应该是将bootloader.img打包到OTA package common.ZipWriteStr(info.output_zip, "ec.bin", ec_img) # emit the script code to trigger the firmware updater on the device info.script.AppendExtra( """dragon.firmware_update(package_extract_file("bootloader.img"), package_extract_file("ec.bin"));""")
build/tools/releasetools/edify_generator.py
def AppendExtra(self, extra): """Append text verbatim to the output script.""" self.script.append(extra)
self.script.append()应该是将package_extract_file命令写入一个OTA升级脚本里,这个脚本最终的样子类似于:
https://www.cnblogs.com/aspirs/p/13060333.html
在升级OTA package会执行这个命令将文件写入partition
build/tools/releasetools/edify_generator.py
def WriteRawImage(self, mount_point, fn, mapfn=None): """Write the given package file into the partition for the given mount point.""" fstab = self.fstab if fstab: p = fstab[mount_point] partition_type = common.PARTITION_TYPES[p.fs_type] args = {'device': p.device, 'fn': fn} if partition_type == "EMMC": if mapfn: args["map"] = mapfn self.script.append( 'package_extract_file("%(fn)s", "%(device)s", "%(map)s");' % args) else: self.script.append( 'package_extract_file("%(fn)s", "%(device)s");' % args) else: raise ValueError( "don't know how to write "%s" partitions" % p.fs_type)
2. 将image写到partition
bootable/recovery/updater/install.cpp
Value* PackageExtractFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { if (argv.size() < 1 || argv.size() > 2) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name, argv.size()); } if (argv.size() == 2) { // The two-argument version extracts to a file. std::vector<std::string> args; if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, argv.size()); } const std::string& zip_path = args[0]; //bin name const std::string& dest_path = args[1]; //device name ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip; ZipString zip_string_path(zip_path.c_str()); ZipEntry entry; if (FindEntry(za, zip_string_path, &entry) != 0) { LOG(ERROR) << name << ": no " << zip_path << " in package"; return StringValue(""); } unique_fd fd(TEMP_FAILURE_RETRY( ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR))); if (fd == -1) { PLOG(ERROR) << name << ": can't open " << dest_path << " for write"; return StringValue(""); } bool success = true; int32_t ret = ExtractEntryToFile(za, &entry, fd); //fd是device name对应的fd,从zip package za里抽取bin name对应的entry写到fd(device name) if (ret != 0) { LOG(ERROR) << name << ": Failed to extract entry "" << zip_path << "" (" << entry.uncompressed_length << " bytes) to "" << dest_path << "": " << ErrorCodeString(ret); success = false; } if (ota_fsync(fd) == -1) { PLOG(ERROR) << "fsync of "" << dest_path << "" failed"; success = false; } if (ota_close(fd) == -1) { PLOG(ERROR) << "close of "" << dest_path << "" failed"; success = false; } return StringValue(success ? "t" : ""); } else { // The one-argument version returns the contents of the file as the result. std::vector<std::string> args; if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, argv.size()); } const std::string& zip_path = args[0]; ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip; ZipString zip_string_path(zip_path.c_str()); ZipEntry entry; if (FindEntry(za, zip_string_path, &entry) != 0) { return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name, zip_path.c_str()); } std::string buffer; buffer.resize(entry.uncompressed_length); int32_t ret = ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&buffer[0]), buffer.size()); if (ret != 0) { return ErrorAbort(state, kPackageExtractFileFailure, "%s: Failed to extract entry "%s" (%zu bytes) to memory: %s", name, zip_path.c_str(), buffer.size(), ErrorCodeString(ret)); } return new Value(VAL_BLOB, buffer); } }
bootable/recovery/updater/install.cpp
void RegisterInstallFunctions() { RegisterFunction("mount", MountFn); RegisterFunction("is_mounted", IsMountedFn); RegisterFunction("unmount", UnmountFn); RegisterFunction("format", FormatFn); RegisterFunction("show_progress", ShowProgressFn); RegisterFunction("set_progress", SetProgressFn); RegisterFunction("package_extract_file", PackageExtractFileFn); RegisterFunction("getprop", GetPropFn); RegisterFunction("file_getprop", FileGetPropFn); RegisterFunction("apply_patch", ApplyPatchFn); RegisterFunction("apply_patch_check", ApplyPatchCheckFn); RegisterFunction("apply_patch_space", ApplyPatchSpaceFn); RegisterFunction("wipe_block_device", WipeBlockDeviceFn); RegisterFunction("read_file", ReadFileFn); RegisterFunction("sha1_check", Sha1CheckFn); RegisterFunction("write_value", WriteValueFn); RegisterFunction("wipe_cache", WipeCacheFn); RegisterFunction("ui_print", UIPrintFn); RegisterFunction("run_program", RunProgramFn); RegisterFunction("reboot_now", RebootNowFn); RegisterFunction("get_stage", GetStageFn); RegisterFunction("set_stage", SetStageFn); RegisterFunction("enable_reboot", EnableRebootFn); RegisterFunction("tune2fs", Tune2FsFn); }