From c19a8d5590a4ffd42b37ceaca2d779b48e481f99 Mon Sep 17 00:00:00 2001 From: Doug Zongker Date: Thu, 1 Jul 2010 15:30:11 -0700 Subject: [PATCH] support for ext4/EMMC in target_files and OTA generation Move the image sizes into a more generic key-value file. Make them optional. Add additional key/value pairs describing what kind of filesystem the device uses. Pass new fs-type-related arguments in edify scripts when mounting and reformatting partitions. Don't include all the init.*.rc files from the regular system in recovery -- they aren't needed, and break recovery on some devices. Change-Id: Ic1c651f754ed00ba1cffe8cf56c43f7f3b0ebfd7 --- core/Makefile | 31 +++++++++++----- tools/releasetools/common.py | 40 +++++++++++++++++++-- tools/releasetools/edify_generator.py | 46 ++++++++++++++++-------- tools/releasetools/img_from_target_files | 3 +- tools/releasetools/ota_from_target_files | 19 +++++----- 5 files changed, 104 insertions(+), 35 deletions(-) diff --git a/core/Makefile b/core/Makefile index 05498a191..8d1399a5a 100644 --- a/core/Makefile +++ b/core/Makefile @@ -656,6 +656,7 @@ $(INSTALLED_RECOVERYIMAGE_TARGET): $(MKBOOTFS) $(MKBOOTIMG) $(MINIGZIP) \ mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/tmp echo Copying baseline ramdisk... cp -R $(TARGET_ROOT_OUT) $(TARGET_RECOVERY_OUT) + rm $(TARGET_RECOVERY_ROOT_OUT)/init*.rc echo Modifying ramdisk contents... cp -f $(recovery_initrc) $(TARGET_RECOVERY_ROOT_OUT)/ cp -f $(recovery_binary) $(TARGET_RECOVERY_ROOT_OUT)/sbin/ @@ -995,15 +996,29 @@ endif $(hide) $(ACP) $(APKCERTS_FILE) $(zip_root)/META/apkcerts.txt $(hide) echo "$(PRODUCT_OTA_PUBLIC_KEYS)" > $(zip_root)/META/otakeys.txt $(hide) echo "$(PRIVATE_RECOVERY_API_VERSION)" > $(zip_root)/META/recovery-api-version.txt - $(hide) echo "blocksize $(BOARD_FLASH_BLOCK_SIZE)" > $(zip_root)/META/imagesizes.txt - $(hide) echo "boot $(call image-size-from-data-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt - $(hide) echo "recovery $(call image-size-from-data-size,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt -ifeq (true,$(INTERNAL_USERIMAGES_USE_EXT)) - $(hide) echo "system $(BOARD_SYSTEMIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/imagesizes.txt - $(hide) echo "userdata $(BOARD_USERDATAIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/imagesizes.txt +ifdef BOARD_FLASH_BLOCK_SIZE + $(hide) echo "blocksize=$(BOARD_FLASH_BLOCK_SIZE)" > $(zip_root)/META/misc_info.txt +endif +ifdef BOARD_BOOTIMAGE_PARTITION_SIZE + $(hide) echo "boot_size=$(BOARD_BOOTIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt +endif +ifdef BOARD_RECOVERYIMAGE_PARTITION_SIZE + $(hide) echo "recovery_size=$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt +endif +ifdef BOARD_SYSTEMIMAGE_PARTITION_SIZE + $(hide) echo "system_size=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt +endif +ifdef BOARD_USERDATAIMAGE_PARTITION_SIZE + $(hide) echo "userdata_size=$(BOARD_USERDATAIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt +endif +ifeq ($(TARGET_USERIMAGES_USE_EXT4), true) + $(hide) echo "fs_type=ext4" >> $(zip_root)/META/misc_info.txt + $(hide) echo "partition_type=EMMC" >> $(zip_root)/META/misc_info.txt + @# TODO: where is the right place to get this path from? BoardConfig.mk? + $(hide) echo "partition_path=/dev/block/platform/sdhci-tegra.3/by-name/" >> $(zip_root)/META/misc_info.txt else - $(hide) echo "system $(call image-size-from-data-size,$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt - $(hide) echo "userdata $(call image-size-from-data-size,$(BOARD_USERDATAIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt + $(hide) echo "fs_type=yaffs2" >> $(zip_root)/META/misc_info.txt + $(hide) echo "partition_type=MTD" >> $(zip_root)/META/misc_info.txt endif $(hide) echo "$(tool_extensions)" > $(zip_root)/META/tool-extensions.txt ifdef mkyaffs2_extra_flags diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index 46cef11d7..2a811330e 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -58,9 +58,35 @@ def Run(args, **kwargs): return subprocess.Popen(args, **kwargs) -def LoadMaxSizes(): +def LoadInfoDict(): + """Read and parse the META/misc_info.txt key/value pairs from the + input target files and return a dict.""" + + d = {} + try: + for line in open(os.path.join(OPTIONS.input_tmp, "META", "misc_info.txt")): + line = line.strip() + if not line or line.startswith("#"): continue + k, v = line.split("=", 1) + d[k] = v + except IOError, e: + if e.errno == errno.ENOENT: + # ok if misc_info.txt file doesn't exist + pass + else: + raise + + if "fs_type" not in d: info["fs_type"] = "yaffs2" + if "partition_type" not in d: info["partition_type"] = "MTD" + + return d + + +def LoadMaxSizes(info): """Load the maximum allowable images sizes from the input - target_files size.""" + target_files. Uses the imagesizes.txt file if it's available + (pre-honeycomb target_files), or the more general info dict (which + must be passed in) if not.""" OPTIONS.max_image_size = {} try: for line in open(os.path.join(OPTIONS.input_tmp, "META", "imagesizes.txt")): @@ -71,7 +97,15 @@ def LoadMaxSizes(): OPTIONS.max_image_size[image + ".img"] = size except IOError, e: if e.errno == errno.ENOENT: - pass + def copy(x, y): + if x in info: OPTIONS.max_image_size[x+".img"] = int(info[x+y]) + copy("blocksize", "") + copy("boot", "_size") + copy("recovery", "_size") + copy("system", "_size") + copy("userdata", "_size") + else: + raise def LoadMkyaffs2ExtraFlags(): diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py index 68b0850b7..3334b438f 100644 --- a/tools/releasetools/edify_generator.py +++ b/tools/releasetools/edify_generator.py @@ -21,10 +21,11 @@ class EdifyGenerator(object): """Class to generate scripts in the 'edify' recovery script language used from donut onwards.""" - def __init__(self, version): + def __init__(self, version, info): self.script = [] self.mounts = set() self.version = version + self.info = info def MakeTemporary(self): """Make a temporary script object whose commands can latter be @@ -130,12 +131,15 @@ class EdifyGenerator(object): available on /cache.""" self.script.append("assert(apply_patch_space(%d));" % (amount,)) - def Mount(self, kind, what, path): + def Mount(self, what, mount_point): """Mount the given 'what' at the given path. 'what' should be a - partition name if kind is "MTD", or a block device if kind is - "vfat". No other values of 'kind' are supported.""" - self.script.append('mount("%s", "%s", "%s");' % (kind, what, path)) - self.mounts.add(path) + partition name for an MTD partition, or a block device for + anything else.""" + what = self.info.get("partition_path", "") + what + self.script.append('mount("%s", "%s", "%s", "%s");' % + (self.info["fs_type"], self.info["partition_type"], + what, mount_point)) + self.mounts.add(mount_point) def UnpackPackageDir(self, src, dst): """Unpack a given directory from the OTA package into the given @@ -154,8 +158,11 @@ class EdifyGenerator(object): self.script.append('ui_print("%s");' % (message,)) def FormatPartition(self, partition): - """Format the given MTD partition.""" - self.script.append('format("MTD", "%s");' % (partition,)) + """Format the given partition.""" + partition = self.info.get("partition_path", "") + partition + self.script.append('format("%s", "%s", "%s");' % + (self.info["fs_type"], self.info["partition_type"], + partition)) def DeleteFiles(self, file_list): """Delete all files in file_list.""" @@ -190,12 +197,23 @@ class EdifyGenerator(object): 'write_firmware_image("PACKAGE:%s", "%s");' % (fn, kind)) def WriteRawImage(self, partition, fn): - """Write the given package file into the given MTD partition.""" - self.script.append( - ('assert(package_extract_file("%(fn)s", "/tmp/%(partition)s.img"),\n' - ' write_raw_image("/tmp/%(partition)s.img", "%(partition)s"),\n' - ' delete("/tmp/%(partition)s.img"));') - % {'partition': partition, 'fn': fn}) + """Write the given package file into the given partition.""" + + if self.info["partition_type"] == "MTD": + self.script.append( + ('assert(package_extract_file("%(fn)s", "/tmp/%(partition)s.img"),\n' + ' write_raw_image("/tmp/%(partition)s.img", "%(partition)s"),\n' + ' delete("/tmp/%(partition)s.img"));') + % {'partition': partition, 'fn': fn}) + elif self.info["partition_type"] == "EMMC": + self.script.append( + ('package_extract_file("%(fn)s", "%(dir)s%(partition)s");') + % {'partition': partition, 'fn': fn, + 'dir': self.info.get("partition_path", ""), + }) + else: + raise ValueError("don't know how to write \"%s\" partitions" % + (self.info["partition_type"],)) def SetPermissions(self, fn, uid, gid, mode): """Set file ownership and permissions.""" diff --git a/tools/releasetools/img_from_target_files b/tools/releasetools/img_from_target_files index 07eb6487c..46ac754bc 100755 --- a/tools/releasetools/img_from_target_files +++ b/tools/releasetools/img_from_target_files @@ -171,7 +171,8 @@ def main(argv): OPTIONS.input_tmp = common.UnzipTemp(args[0]) - common.LoadMaxSizes() + info = common.LoadInfoDict() + common.LoadMaxSizes(info) if not OPTIONS.max_image_size: print print " WARNING: Failed to load max image sizes; will not enforce" diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files index ad7e0e4bb..02f25085a 100755 --- a/tools/releasetools/ota_from_target_files +++ b/tools/releasetools/ota_from_target_files @@ -334,11 +334,11 @@ fi return Item.Get("system/etc/install-recovery.sh", dir=False) -def WriteFullOTAPackage(input_zip, output_zip): +def WriteFullOTAPackage(input_zip, output_zip, info): # TODO: how to determine this? We don't know what version it will # be installed on top of. For now, we expect the API just won't # change very often. - script = edify_generator.EdifyGenerator(3) + script = edify_generator.EdifyGenerator(3, info) metadata = {"post-build": GetBuildProp("ro.build.fingerprint", input_zip), "pre-device": GetBuildProp("ro.product.device", input_zip), @@ -366,7 +366,7 @@ def WriteFullOTAPackage(input_zip, output_zip): script.FormatPartition("userdata") script.FormatPartition("system") - script.Mount("MTD", "system", "/system") + script.Mount("system", "/system") script.UnpackPackageDir("recovery", "/system") script.UnpackPackageDir("system", "/system") @@ -448,14 +448,14 @@ def GetRecoveryAPIVersion(zip): return 0 -def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): +def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip, info): source_version = GetRecoveryAPIVersion(source_zip) target_version = GetRecoveryAPIVersion(target_zip) if source_version == 0: print ("WARNING: generating edify script for a source that " "can't install it.") - script = edify_generator.EdifyGenerator(source_version) + script = edify_generator.EdifyGenerator(source_version, info) metadata = {"pre-device": GetBuildProp("ro.product.device", source_zip), "post-timestamp": GetBuildProp("ro.build.date.utc", target_zip), @@ -516,7 +516,7 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): metadata["pre-build"] = source_fp metadata["post-build"] = target_fp - script.Mount("MTD", "system", "/system") + script.Mount("system", "/system") script.AssertSomeFingerprint(source_fp, target_fp) source_boot = common.File("/tmp/boot.img", @@ -755,7 +755,8 @@ def main(argv): else: raise - common.LoadMaxSizes() + info = common.LoadInfoDict() + common.LoadMaxSizes(info) if not OPTIONS.max_image_size: print print " WARNING: Failed to load max image sizes; will not enforce" @@ -773,12 +774,12 @@ def main(argv): compression=zipfile.ZIP_DEFLATED) if OPTIONS.incremental_source is None: - WriteFullOTAPackage(input_zip, output_zip) + WriteFullOTAPackage(input_zip, output_zip, info) else: print "unzipping source target-files..." OPTIONS.source_tmp = common.UnzipTemp(OPTIONS.incremental_source) source_zip = zipfile.ZipFile(OPTIONS.incremental_source, "r") - WriteIncrementalOTAPackage(input_zip, source_zip, output_zip) + WriteIncrementalOTAPackage(input_zip, source_zip, output_zip, info) output_zip.close() if OPTIONS.package_key: