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
This commit is contained in:
parent
671f5fb09f
commit
c19a8d5590
|
@ -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
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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."""
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue