Add care_map to target_files package
Generate a new file containing care_data of system (and vendor)
partition, and add it under META/ of target file package. For
A/B update, copy this file to OTA package for later use by
update_verifier.
Bug: 27175949
Change-Id: I90bb972703afaeb94bc3efe718fd81b1cfbcabcc
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index ddc0d0b..6acc69d 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -37,6 +37,7 @@
import build_image
import common
+import sparse_img
OPTIONS = common.OPTIONS
@@ -46,6 +47,19 @@
OPTIONS.replace_verity_private_key = False
OPTIONS.verity_signer_path = None
+def GetCareMap(which, imgname):
+ """Generate care_map of system (or vendor) partition"""
+
+ assert which in ("system", "vendor")
+ _, blk_device = common.GetTypeAndDevice("/" + which, OPTIONS.info_dict)
+
+ simg = sparse_img.SparseImage(imgname)
+ care_map_list = []
+ care_map_list.append(blk_device)
+ care_map_list.append(simg.care_map.to_string_raw())
+ return care_map_list
+
+
def AddSystem(output_zip, prefix="IMAGES/", recovery_img=None, boot_img=None):
"""Turn the contents of SYSTEM into a system image and store it in
output_zip."""
@@ -53,7 +67,7 @@
prebuilt_path = os.path.join(OPTIONS.input_tmp, prefix, "system.img")
if os.path.exists(prebuilt_path):
print "system.img already exists in %s, no need to rebuild..." % (prefix,)
- return
+ return prebuilt_path
def output_sink(fn, data):
ofile = open(os.path.join(OPTIONS.input_tmp, "SYSTEM", fn), "w")
@@ -70,6 +84,7 @@
block_list=block_list)
common.ZipWrite(output_zip, imgname, prefix + "system.img")
common.ZipWrite(output_zip, block_list, prefix + "system.map")
+ return imgname
def BuildSystem(input_dir, info_dict, block_list=None):
@@ -103,13 +118,14 @@
prebuilt_path = os.path.join(OPTIONS.input_tmp, prefix, "vendor.img")
if os.path.exists(prebuilt_path):
print "vendor.img already exists in %s, no need to rebuild..." % (prefix,)
- return
+ return prebuilt_path
block_list = common.MakeTempFile(prefix="vendor-blocklist-", suffix=".map")
imgname = BuildVendor(OPTIONS.input_tmp, OPTIONS.info_dict,
block_list=block_list)
common.ZipWrite(output_zip, imgname, prefix + "vendor.img")
common.ZipWrite(output_zip, block_list, prefix + "vendor.map")
+ return imgname
def BuildVendor(input_dir, info_dict, block_list=None):
@@ -139,8 +155,9 @@
image_props = build_image.ImagePropFromGlobalDict(info_dict, what)
fstab = info_dict["fstab"]
- if fstab:
- image_props["fs_type"] = fstab["/" + what].fs_type
+ mount_point = "/" + what
+ if fstab and mount_point in fstab:
+ image_props["fs_type"] = fstab[mount_point].fs_type
# Use a fixed timestamp (01/01/2009) when packaging the image.
# Bug: 24377993
@@ -330,10 +347,12 @@
recovery_image.AddToZip(output_zip)
banner("system")
- AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image)
+ system_imgname = AddSystem(output_zip, recovery_img=recovery_image,
+ boot_img=boot_image)
+ vendor_imgname = None
if has_vendor:
banner("vendor")
- AddVendor(output_zip)
+ vendor_imgname = AddVendor(output_zip)
if has_system_other:
banner("system_other")
AddSystemOther(output_zip)
@@ -348,7 +367,19 @@
if os.path.exists(ab_partitions):
with open(ab_partitions, 'r') as f:
lines = f.readlines()
+ # For devices using A/B update, generate care_map for system and vendor
+ # partitions (if present), then write this file to target_files package.
+ care_map_list = []
for line in lines:
+ if line.strip() == "system" and OPTIONS.info_dict.get(
+ "system_verity_block_device", None) is not None:
+ assert os.path.exists(system_imgname)
+ care_map_list += GetCareMap("system", system_imgname)
+ if line.strip() == "vendor" and OPTIONS.info_dict.get(
+ "vendor_verity_block_device", None) is not None:
+ assert os.path.exists(vendor_imgname)
+ care_map_list += GetCareMap("vendor", vendor_imgname)
+
img_name = line.strip() + ".img"
img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
if os.path.exists(img_radio_path):
@@ -359,6 +390,10 @@
img_path = 'IMAGES/' + img_name
assert img_path in output_zip.namelist(), "cannot find " + img_name
+ if care_map_list:
+ file_path = "META/care_map.txt"
+ common.ZipWriteStr(output_zip, file_path, '\n'.join(care_map_list))
+
common.ZipClose(output_zip)
def main(argv):
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 422ba43..d7f8b16 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -259,11 +259,18 @@
makeint("boot_size")
makeint("fstab_version")
- if d.get("no_recovery", False) == "true":
- d["fstab"] = None
- else:
+ system_root_image = d.get("system_root_image", None) == "true"
+ if d.get("no_recovery", None) != "true":
+ recovery_fstab_path = "RECOVERY/RAMDISK/etc/recovery.fstab"
d["fstab"] = LoadRecoveryFSTab(read_helper, d["fstab_version"],
- d.get("system_root_image", False))
+ recovery_fstab_path, system_root_image)
+ elif d.get("recovery_as_boot", None) == "true":
+ recovery_fstab_path = "BOOT/RAMDISK/etc/recovery.fstab"
+ d["fstab"] = LoadRecoveryFSTab(read_helper, d["fstab_version"],
+ recovery_fstab_path, system_root_image)
+ else:
+ d["fstab"] = None
+
d["build.prop"] = LoadBuildProp(read_helper)
return d
@@ -286,7 +293,8 @@
d[name] = value
return d
-def LoadRecoveryFSTab(read_helper, fstab_version, system_root_image=False):
+def LoadRecoveryFSTab(read_helper, fstab_version, recovery_fstab_path,
+ system_root_image=False):
class Partition(object):
def __init__(self, mount_point, fs_type, device, length, device2, context):
self.mount_point = mount_point
@@ -297,9 +305,9 @@
self.context = context
try:
- data = read_helper("RECOVERY/RAMDISK/etc/recovery.fstab")
+ data = read_helper(recovery_fstab_path)
except KeyError:
- print "Warning: could not find RECOVERY/RAMDISK/etc/recovery.fstab"
+ print "Warning: could not find {}".format(recovery_fstab_path)
data = ""
if fstab_version == 1:
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index b29ba69..d3d4974 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -1314,6 +1314,19 @@
compress_type=zipfile.ZIP_STORED)
WriteMetadata(metadata, output_zip)
+ # If dm-verity is supported for the device, copy contents of care_map
+ # into A/B OTA package.
+ if OPTIONS.info_dict.get("verity") == "true":
+ target_zip = zipfile.ZipFile(target_file, "r")
+ care_map_path = "META/care_map.txt"
+ namelist = target_zip.namelist()
+ if care_map_path in namelist:
+ care_map_data = target_zip.read(care_map_path)
+ common.ZipWriteStr(output_zip, "care_map.txt", care_map_data)
+ else:
+ print "Warning: cannot find care map file in target_file package"
+ common.ZipClose(target_zip)
+
# Sign the whole package to comply with the Android OTA package format.
common.ZipClose(output_zip)
SignOutput(temp_zip_file.name, output_file)