From 4181f531c7991d4685040f642db725bc3f1fbe7d Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 28 Feb 2018 21:20:08 -0800 Subject: [PATCH 1/2] Conditionally generate META/boot_filesystem_config.txt. if BOARD_BUILD_SYSTEM_ROOT_IMAGE != true: # case A - BOOT/RAMDISK corresponds to the / under normal boot, with matching fs_config in META/boot_filesystem_config.txt. - RECOVERY/RAMDISK corresponds to the / under recovery, with fs_config in META/recovery_filesystem_config.txt. else: if BOARD_USES_RECOVERY_AS_BOOT == true: # case B - ROOT/ corresponds to the / under normal boot, with fs_config in META/root_filesystem_config.txt. - BOOT/RAMDISK corresponds to the / under recovery, with fs_config in META/boot_filesystem_config.txt. else: # case C - ROOT/ corresponds to the / under normal boot, with fs_config in META/root_filesystem_config.txt. - RECOVERY/RAMDISK corresponds to the / under recovery, with fs_config in META/recovery_filesystem_config.txt. - BOOT/RAMDISK doesn't exist. This CL fixes case C, where we shouldn't try to generate 'META/boot_filesystem_config.txt' for BOOT/RAMDISK. It wouldn't be fatal without this fix, but would wrongly scan the current directory and include a large fs_config output into target-files.zip. Bug: 72731506 Test: `lunch aosp_bullhead-userdebug` and `m dist`. (case A) Test: `lunch aosp_marlin-userdebug` and `m dist`. (case B) Test: Define 'BOARD_BUILD_SYSTEM_ROOT_IMAGE := true' for angler. `m dist` and check the generated target-files.zip. (case C) Change-Id: I5582ce8cca464d535af0718be0fd8e65791bd6c2 Merged-In: I5582ce8cca464d535af0718be0fd8e65791bd6c2 (cherry picked from commit da01b211f816cd63f7fb245012d67e654e625c3e) --- core/Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/Makefile b/core/Makefile index c03f21ffb5..9cf539deda 100644 --- a/core/Makefile +++ b/core/Makefile @@ -2781,9 +2781,15 @@ ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE $(hide) $(call fs_config,$(zip_root)/PRODUCT,product/) > $(zip_root)/META/product_filesystem_config.txt endif ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true) + @# When using BOARD_BUILD_SYSTEM_ROOT_IMAGE, ROOT always contains the files for the root under + @# normal boot. BOOT/RAMDISK exists only if additionally using BOARD_USES_RECOVERY_AS_BOOT. $(hide) $(call fs_config,$(zip_root)/ROOT,) > $(zip_root)/META/root_filesystem_config.txt -endif +ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true) $(hide) $(call fs_config,$(zip_root)/BOOT/RAMDISK,) > $(zip_root)/META/boot_filesystem_config.txt +endif +else # BOARD_BUILD_SYSTEM_ROOT_IMAGE != true + $(hide) $(call fs_config,$(zip_root)/BOOT/RAMDISK,) > $(zip_root)/META/boot_filesystem_config.txt +endif ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),) $(hide) $(call fs_config,$(zip_root)/RECOVERY/RAMDISK,) > $(zip_root)/META/recovery_filesystem_config.txt endif From 2d2ce7dd0295f51bb885f11ab967ff23ca397fa3 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Fri, 9 Mar 2018 17:04:42 -0800 Subject: [PATCH 2/2] Use bsdiff to generate recovery-from-boot.p for system-root-image. This CL handles a path that uses system-root-image on non-A/B device. For this path, we can't generate recovery-from-boot patch with imgdiff, because boot/recovery images contain different number of entries (only recovery iamge has ramdisk image now). Using BOARD_USES_FULL_RECOVERY_IMAGE can work around the issue, at the cost of extra size. Compared to carrying full recovery image, this CL saves the cost of the kernel size, by putting a patch that's roughly the size of the recovery ramdisk. The applypatch executable already detects and handles a bsdiff patch automatically. No change required to that end. Note that it won't further reduce the patch size by handling that ramdisk entry specially, because (a) that's the only difference between the two images; and (b) there's no corresponding data in boot image to be diff'd against. Bug: 72731506 Test: `m dist` with aosp_angler-userdebug. Check the device can install recovery image successfully (after intentionally corrupting the recovery image). Test: Build aosp_angler-userdebug with BOARD_BUILD_SYSTEM_ROOT_IMAGE set. Verify the generated patch files. Test: Run validate_target_files.py with the target_files.zips. Change-Id: I69c06f51ba8c39ae059c5e9a6872a9f10600cf17 Merged-In: I69c06f51ba8c39ae059c5e9a6872a9f10600cf17 (cherry picked from commit 6d5d623987c94411e7402401828c22dd5706315f) --- core/Makefile | 36 ++++++++++++++++++---------- tools/releasetools/common.py | 46 +++++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 30 deletions(-) diff --git a/core/Makefile b/core/Makefile index 9cf539deda..7911026044 100644 --- a/core/Makefile +++ b/core/Makefile @@ -1261,19 +1261,23 @@ else recovery_wipe := endif -# Prior to A/B update, we used to have: +# Traditionally with non-A/B OTA we have: # boot.img + recovery-from-boot.p + recovery-resource.dat = recovery.img. -# recovery-resource.dat is needed only if we carry a patch of the boot and -# recovery images and invoke install-recovery.sh on the first boot post an -# OTA update. +# recovery-resource.dat is needed only if we carry an imgdiff patch of the boot and recovery images +# and invoke install-recovery.sh on the first boot post an OTA update. # # We no longer need that if one of the following conditions holds: -# a) We carry a full copy of the recovery image +# a) We carry a full copy of the recovery image - no patching needed # (BOARD_USES_FULL_RECOVERY_IMAGE = true); -# b) We build a single image that contains boot and recovery both -# (BOARD_USES_RECOVERY_AS_BOOT = true). +# b) We build a single image that contains boot and recovery both - no recovery image to install +# (BOARD_USES_RECOVERY_AS_BOOT = true); +# c) We build the root into system image - not needing the resource file as we do bsdiff +# (BOARD_BUILD_SYSTEM_ROOT_IMAGE = true). +# Note that condition b) implies condition c), because of the earlier check in this file: +# "BOARD_USES_RECOVERY_AS_BOOT = true must have BOARD_BUILD_SYSTEM_ROOT_IMAGE = true" (not vice +# versa though). -ifeq (,$(filter true, $(BOARD_USES_FULL_RECOVERY_IMAGE) $(BOARD_USES_RECOVERY_AS_BOOT))) +ifeq (,$(filter true, $(BOARD_USES_FULL_RECOVERY_IMAGE) $(BOARD_BUILD_SYSTEM_ROOT_IMAGE))) # Named '.dat' so we don't attempt to use imgdiff for patching it. RECOVERY_RESOURCE_ZIP := $(TARGET_OUT)/etc/recovery-resource.dat else @@ -1560,15 +1564,21 @@ SYSTEMIMAGE_SOURCE_DIR := $(TARGET_OUT) # image size check calculation. ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),) ifneq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true) +ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true) +diff_tool := $(HOST_OUT_EXECUTABLES)/bsdiff +else +diff_tool := $(HOST_OUT_EXECUTABLES)/imgdiff +endif intermediates := $(call intermediates-dir-for,PACKAGING,recovery_patch) RECOVERY_FROM_BOOT_PATCH := $(intermediates)/recovery_from_boot.p -$(RECOVERY_FROM_BOOT_PATCH): $(INSTALLED_RECOVERYIMAGE_TARGET) \ - $(INSTALLED_BOOTIMAGE_TARGET) \ - $(HOST_OUT_EXECUTABLES)/imgdiff \ - $(HOST_OUT_EXECUTABLES)/bsdiff +$(RECOVERY_FROM_BOOT_PATCH): PRIVATE_DIFF_TOOL := $(diff_tool) +$(RECOVERY_FROM_BOOT_PATCH): \ + $(INSTALLED_RECOVERYIMAGE_TARGET) \ + $(INSTALLED_BOOTIMAGE_TARGET) \ + $(diff_tool) @echo "Construct recovery from boot" mkdir -p $(dir $@) - PATH=$(HOST_OUT_EXECUTABLES):$$PATH $(HOST_OUT_EXECUTABLES)/imgdiff $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_RECOVERYIMAGE_TARGET) $@ + $(PRIVATE_DIFF_TOOL) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_RECOVERYIMAGE_TARGET) $@ else # $(BOARD_USES_FULL_RECOVERY_IMAGE) == true RECOVERY_FROM_BOOT_PATCH := $(INSTALLED_RECOVERYIMAGE_TARGET) endif diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index 743c6a057e..787de98222 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -1828,35 +1828,47 @@ def ExtractPublicKey(cert): def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img, info_dict=None): - """Generate a binary patch that creates the recovery image starting - with the boot image. (Most of the space in these images is just the - kernel, which is identical for the two, so the resulting patch - should be efficient.) Add it to the output zip, along with a shell - script that is run from init.rc on first boot to actually do the - patching and install the new recovery image. + """Generates the recovery-from-boot patch and writes the script to output. - recovery_img and boot_img should be File objects for the - corresponding images. info should be the dictionary returned by - common.LoadInfoDict() on the input target_files. + Most of the space in the boot and recovery images is just the kernel, which is + identical for the two, so the resulting patch should be efficient. Add it to + the output zip, along with a shell script that is run from init.rc on first + boot to actually do the patching and install the new recovery image. + + Args: + input_dir: The top-level input directory of the target-files.zip. + output_sink: The callback function that writes the result. + recovery_img: File object for the recovery image. + boot_img: File objects for the boot image. + info_dict: A dict returned by common.LoadInfoDict() on the input + target_files. Will use OPTIONS.info_dict if None has been given. """ - if info_dict is None: info_dict = OPTIONS.info_dict - full_recovery_image = info_dict.get("full_recovery_image", None) == "true" + full_recovery_image = info_dict.get("full_recovery_image") == "true" if full_recovery_image: output_sink("etc/recovery.img", recovery_img.data) else: - diff_program = ["imgdiff"] + system_root_image = info_dict.get("system_root_image") == "true" path = os.path.join(input_dir, "SYSTEM", "etc", "recovery-resource.dat") - if os.path.exists(path): - diff_program.append("-b") - diff_program.append(path) - bonus_args = "-b /system/etc/recovery-resource.dat" - else: + # With system-root-image, boot and recovery images will have mismatching + # entries (only recovery has the ramdisk entry) (Bug: 72731506). Use bsdiff + # to handle such a case. + if system_root_image: + diff_program = ["bsdiff"] bonus_args = "" + assert not os.path.exists(path) + else: + diff_program = ["imgdiff"] + if os.path.exists(path): + diff_program.append("-b") + diff_program.append(path) + bonus_args = "-b /system/etc/recovery-resource.dat" + else: + bonus_args = "" d = Difference(recovery_img, boot_img, diff_program=diff_program) _, _, patch = d.ComputePatch()