2014-07-31 20:06:30 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
|
|
|
# Copyright (C) 2014 The Android Open Source Project
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
|
|
|
|
"""
|
|
|
|
Given a target-files zipfile that does not contain images (ie, does
|
|
|
|
not have an IMAGES/ top-level subdirectory), produce the images and
|
|
|
|
add them to the zipfile.
|
|
|
|
|
2016-08-04 04:21:52 +02:00
|
|
|
Usage: add_img_to_target_files [flag] target_files
|
|
|
|
|
|
|
|
-a (--add_missing)
|
|
|
|
Build and add missing images to "IMAGES/". If this option is
|
|
|
|
not specified, this script will simply exit when "IMAGES/"
|
|
|
|
directory exists in the target file.
|
|
|
|
|
|
|
|
-r (--rebuild_recovery)
|
|
|
|
Rebuild the recovery patch and write it to the system image. Only
|
2019-06-05 01:26:45 +02:00
|
|
|
meaningful when system image needs to be rebuilt and there're separate
|
|
|
|
boot / recovery images.
|
2016-08-04 04:21:52 +02:00
|
|
|
|
|
|
|
--replace_verity_private_key
|
|
|
|
Replace the private key used for verity signing. (same as the option
|
|
|
|
in sign_target_files_apks)
|
|
|
|
|
|
|
|
--replace_verity_public_key
|
|
|
|
Replace the certificate (public key) used for verity verification. (same
|
|
|
|
as the option in sign_target_files_apks)
|
|
|
|
|
|
|
|
--is_signing
|
|
|
|
Skip building & adding the images for "userdata" and "cache" if we
|
|
|
|
are signing the target files.
|
2014-07-31 20:06:30 +02:00
|
|
|
"""
|
|
|
|
|
2017-01-10 19:47:58 +01:00
|
|
|
from __future__ import print_function
|
|
|
|
|
2015-10-01 01:01:14 +02:00
|
|
|
import datetime
|
2018-10-12 19:30:39 +02:00
|
|
|
import logging
|
2014-07-31 20:06:30 +02:00
|
|
|
import os
|
2016-01-29 22:59:17 +01:00
|
|
|
import shlex
|
2015-06-25 22:56:53 +02:00
|
|
|
import shutil
|
2020-12-08 07:18:35 +01:00
|
|
|
import stat
|
releasetools: Address pylint warnings in add_img_to_target_files.py.
C:661, 0: Wrong hanging indentation (add 2 spaces).
OPTIONS.input_tmp, "VENDOR_IMAGES")
^ | (bad-continuation)
C:673, 0: Wrong continued indentation (add 14 spaces).
os.path.join("IMAGES", img_name))
^ | (bad-continuation)
C: 54, 0: Import "import datetime" should be placed at the top of the module (wrong-import-position)
C: 55, 0: Import "import hashlib" should be placed at the top of the module (wrong-import-position)
C: 56, 0: Import "import os" should be placed at the top of the module (wrong-import-position)
C: 57, 0: Import "import shlex" should be placed at the top of the module (wrong-import-position)
C: 58, 0: Import "import shutil" should be placed at the top of the module (wrong-import-position)
C: 59, 0: Import "import subprocess" should be placed at the top of the module (wrong-import-position)
C: 60, 0: Import "import tempfile" should be placed at the top of the module (wrong-import-position)
C: 61, 0: Import "import uuid" should be placed at the top of the module (wrong-import-position)
C: 62, 0: Import "import zipfile" should be placed at the top of the module (wrong-import-position)
C: 64, 0: Import "import build_image" should be placed at the top of the module (wrong-import-position)
C: 65, 0: Import "import common" should be placed at the top of the module (wrong-import-position)
C: 66, 0: Import "import rangelib" should be placed at the top of the module (wrong-import-position)
C: 67, 0: Import "import sparse_img" should be placed at the top of the module (wrong-import-position)
W:391,12: Redefining built-in 'dir' (redefined-builtin)
After this CL, it still gives the warning below, which is to be
addressed with follow-ups.
R:635, 2: Too many nested blocks (6/5) (too-many-nested-blocks)
Test: `m dist`
Test: pylint --rcfile=pylintrc add_img_to_target_files.py
Change-Id: I64da184b6b69e93449dbfc989a5d7f46d5223f42
2017-12-02 01:13:22 +01:00
|
|
|
import sys
|
2017-09-23 00:45:33 +02:00
|
|
|
import uuid
|
2014-07-31 20:06:30 +02:00
|
|
|
import zipfile
|
|
|
|
|
|
|
|
import build_image
|
2018-11-29 22:51:48 +01:00
|
|
|
import build_super_image
|
2014-07-31 20:06:30 +02:00
|
|
|
import common
|
Add options to sign the prebuilt custom images.
The custom images are any images owned by OEMs and SoCs, oem images
mounted on /oem is an example. The oem images can be used to customize
devices for different carriers, like wallpaper, ringtones, and
carrier-specific apks. OEMs can generate multiple oem images, like
oem.img, oem-carrier1.img and oem-carrier2.img and flash different oem
images for different carriers. The oem images are only one case, OEMs
and SoCs can add more custom images and mount them to custom partitions.
This change enables custom images to be vbmeta.img chained partitions.
The following configuration in BoardConfig.mk is an exmaple. It has two
custom partitions: oem and test. They will be signed by different keys.
And they will be chained by vbmeta.img. The custom images here are
prebuilts, which can be built by `make custom_images` separately.
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST should include all custom images
to apply AVB signing. And to every custom partition, one image whose
name is partition name must be added in its
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST.
BOARD_CUSTOMIMAGES_PARTITION_LIST := oem test
BOARD_AVB_OEM_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
BOARD_AVB_OEM_ALGORITHM := SHA256_RSA4096
BOARD_AVB_OEM_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_OEM_ROLLBACK_INDEX_LOCATION := 1
BOARD_AVB_OEM_PARTITION_SIZE := 5242880
BOARD_AVB_OEM_IMAGE_LIST := \
device/xxxx/yyyy/oem/oem.img \
device/xxxx/yyyy/oem/oem1.img
BOARD_AVB_TEST_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_TEST_ALGORITHM := SHA256_RSA2048
BOARD_AVB_TEST_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_TEST_ROLLBACK_INDEX_LOCATION := 2
BOARD_AVB_TEST_PARTITION_SIZE := 10485760
BOARD_AVB_TEST_IMAGE_LIST := \
device/xxxx/yyyy/test/test.img \
device/xxxx/yyyy/test/test1.img
To resign the custom images in the target zip file, the
avb_extra_custom_image_key, avb_extra_custom_image_algorithms and
avb_extra_custom_image_extra_args options are added to the
sign_target_files_apks tool too. The following test cases list some
examples about how to use them.
BUG: 154171021
Test: 1) "atest --host releasetools_test releasetools_py3_test -c"
2) Build images by 'make dist', sign and validate target files.
a) Test on dist w/ chained vbmeta_system and ome custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the oem images and vbmeta images in OUT and target zips by
avbtool.
b) Test on dist w/ chained vbmeta_system and oem and test custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
--avb_extra_custom_image_extra_args oem=--do_not_generate_fec \
--avb_extra_custom_image_key test=test_rsa4096.pem \
--avb_extra_custom_image_algorithm test=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Verify the oem, test images and vbmeta images in OUT and target zips
by avbtool.
c) Test on dist w/o chained partition.
sign_target_files_apks -d certs xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the vbmeta images in OUT and target zips by avbtool.
Change-Id: Ifccfee5e8909697eef6ccda0cc352fa16a9f6db6
2020-04-28 03:36:36 +02:00
|
|
|
import verity_utils
|
2021-01-19 21:30:46 +01:00
|
|
|
import ota_metadata_pb2
|
|
|
|
|
2021-04-16 01:39:22 +02:00
|
|
|
from apex_utils import GetApexInfoFromTargetFiles
|
2021-03-22 20:38:38 +01:00
|
|
|
from common import AddCareMapForAbOta
|
2014-07-31 20:06:30 +02:00
|
|
|
|
releasetools: Address pylint warnings in add_img_to_target_files.py.
C:661, 0: Wrong hanging indentation (add 2 spaces).
OPTIONS.input_tmp, "VENDOR_IMAGES")
^ | (bad-continuation)
C:673, 0: Wrong continued indentation (add 14 spaces).
os.path.join("IMAGES", img_name))
^ | (bad-continuation)
C: 54, 0: Import "import datetime" should be placed at the top of the module (wrong-import-position)
C: 55, 0: Import "import hashlib" should be placed at the top of the module (wrong-import-position)
C: 56, 0: Import "import os" should be placed at the top of the module (wrong-import-position)
C: 57, 0: Import "import shlex" should be placed at the top of the module (wrong-import-position)
C: 58, 0: Import "import shutil" should be placed at the top of the module (wrong-import-position)
C: 59, 0: Import "import subprocess" should be placed at the top of the module (wrong-import-position)
C: 60, 0: Import "import tempfile" should be placed at the top of the module (wrong-import-position)
C: 61, 0: Import "import uuid" should be placed at the top of the module (wrong-import-position)
C: 62, 0: Import "import zipfile" should be placed at the top of the module (wrong-import-position)
C: 64, 0: Import "import build_image" should be placed at the top of the module (wrong-import-position)
C: 65, 0: Import "import common" should be placed at the top of the module (wrong-import-position)
C: 66, 0: Import "import rangelib" should be placed at the top of the module (wrong-import-position)
C: 67, 0: Import "import sparse_img" should be placed at the top of the module (wrong-import-position)
W:391,12: Redefining built-in 'dir' (redefined-builtin)
After this CL, it still gives the warning below, which is to be
addressed with follow-ups.
R:635, 2: Too many nested blocks (6/5) (too-many-nested-blocks)
Test: `m dist`
Test: pylint --rcfile=pylintrc add_img_to_target_files.py
Change-Id: I64da184b6b69e93449dbfc989a5d7f46d5223f42
2017-12-02 01:13:22 +01:00
|
|
|
if sys.hexversion < 0x02070000:
|
|
|
|
print("Python 2.7 or newer is required.", file=sys.stderr)
|
|
|
|
sys.exit(1)
|
|
|
|
|
2018-10-12 19:30:39 +02:00
|
|
|
logger = logging.getLogger(__name__)
|
2014-07-31 20:06:30 +02:00
|
|
|
|
2018-10-12 19:30:39 +02:00
|
|
|
OPTIONS = common.OPTIONS
|
2014-11-14 06:41:08 +01:00
|
|
|
OPTIONS.add_missing = False
|
|
|
|
OPTIONS.rebuild_recovery = False
|
2017-06-10 01:58:03 +02:00
|
|
|
OPTIONS.replace_updated_files_list = []
|
2015-09-17 06:20:30 +02:00
|
|
|
OPTIONS.replace_verity_public_key = False
|
|
|
|
OPTIONS.replace_verity_private_key = False
|
2016-08-04 04:21:52 +02:00
|
|
|
OPTIONS.is_signing = False
|
2014-07-31 20:06:30 +02:00
|
|
|
|
2018-08-01 03:32:00 +02:00
|
|
|
# Use a fixed timestamp (01/01/2009 00:00:00 UTC) for files when packaging
|
|
|
|
# images. (b/24377993, b/80600931)
|
2018-08-27 19:57:19 +02:00
|
|
|
FIXED_FILE_TIMESTAMP = int((
|
|
|
|
datetime.datetime(2009, 1, 1, 0, 0, 0, 0, None) -
|
|
|
|
datetime.datetime.utcfromtimestamp(0)).total_seconds())
|
2018-01-17 21:14:43 +01:00
|
|
|
|
2017-11-14 16:42:30 +01:00
|
|
|
|
2017-03-06 04:51:56 +01:00
|
|
|
class OutputFile(object):
|
2019-01-14 08:23:01 +01:00
|
|
|
"""A helper class to write a generated file to the given dir or zip.
|
|
|
|
|
|
|
|
When generating images, we want the outputs to go into the given zip file, or
|
|
|
|
the given dir.
|
|
|
|
|
|
|
|
Attributes:
|
|
|
|
name: The name of the output file, regardless of the final destination.
|
|
|
|
"""
|
|
|
|
|
2021-01-19 21:30:46 +01:00
|
|
|
def __init__(self, output_zip, input_dir, *args):
|
2019-01-14 08:23:01 +01:00
|
|
|
# We write the intermediate output file under the given input_dir, even if
|
|
|
|
# the final destination is a zip archive.
|
2021-01-19 21:30:46 +01:00
|
|
|
self.name = os.path.join(input_dir, *args)
|
2017-03-06 04:51:56 +01:00
|
|
|
self._output_zip = output_zip
|
|
|
|
if self._output_zip:
|
2021-01-19 21:30:46 +01:00
|
|
|
self._zip_name = os.path.join(*args)
|
2017-03-06 04:51:56 +01:00
|
|
|
|
|
|
|
def Write(self):
|
|
|
|
if self._output_zip:
|
|
|
|
common.ZipWrite(self._output_zip, self.name, self._zip_name)
|
|
|
|
|
2018-08-27 19:57:19 +02:00
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
def AddSystem(output_zip, recovery_img=None, boot_img=None):
|
2014-07-31 20:06:30 +02:00
|
|
|
"""Turn the contents of SYSTEM into a system image and store it in
|
2016-01-29 22:59:17 +01:00
|
|
|
output_zip. Returns the name of the system image file."""
|
2014-11-14 06:41:08 +01:00
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system.img")
|
2019-01-14 08:23:01 +01:00
|
|
|
if os.path.exists(img.name):
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("system.img already exists; no need to rebuild...")
|
2019-01-14 08:23:01 +01:00
|
|
|
return img.name
|
2014-11-14 06:41:08 +01:00
|
|
|
|
|
|
|
def output_sink(fn, data):
|
2019-06-25 00:33:41 +02:00
|
|
|
output_file = os.path.join(OPTIONS.input_tmp, "SYSTEM", fn)
|
|
|
|
with open(output_file, "wb") as ofile:
|
|
|
|
ofile.write(data)
|
2014-11-14 06:41:08 +01:00
|
|
|
|
2019-03-15 22:36:21 +01:00
|
|
|
if output_zip:
|
|
|
|
arc_name = "SYSTEM/" + fn
|
|
|
|
if arc_name in output_zip.namelist():
|
|
|
|
OPTIONS.replace_updated_files_list.append(arc_name)
|
|
|
|
else:
|
2019-06-25 00:33:41 +02:00
|
|
|
common.ZipWrite(output_zip, output_file, arc_name)
|
2017-05-26 02:38:53 +02:00
|
|
|
|
Moving recovery resources from /system to /vendor
This change is part of a topic that moves the recovery resources from the
system partition to the vendor partition, if it exists, or the vendor directory
on the system partition otherwise. The recovery resources are moving from the
system image to the vendor partition so that a single system image may be used
with either an A/B or a non-A/B vendor image. The topic removes a delta in the
system image that prevented such reuse in the past.
The recovery resources that are moving are involved with updating the recovery
partition after an update. In a non-A/B configuration, the system boots from
the recovery partition, updates the other partitions (system, vendor, etc.)
Then, the next time the system boots normally, a script updates the recovery
partition (if necessary). This script, the executables it invokes, and the data
files that it uses were previously on the system partition. The resources that
are moving include the following.
* install-recovery.sh
* applypatch
* recovery-resource.dat (if present)
* recovery-from-boot.p (if present)
This change includes the platform build system and release tools changes to
move the recovery resources from system to vendor (or /system/vendor). The
release tools need to know where to generate the recovery patch, and they
discover this from misc_info.txt variable board_uses_vendorimage, which the
platform build system generates.
We remove applypatch from PRODUCT_PACKAGES, but it is added back as a required
module in target/product/base_vendor.mk.
Several release tools rely on the misc_info.txt board_uses_vendorimage variable
to know how to generate and detect the recovery patch.
This change partially removes the --rebuild_recovery flag from the
merge_target_files.py script. The flag will be fully removed in a follow-on
change.
Bug: 68319577
Test: Ensure that recovery partition is updated correctly.
Change-Id: Ia4045bd67ffb3d899efa8d20dab4c4299b87ee5f
2019-09-18 02:06:47 +02:00
|
|
|
board_uses_vendorimage = OPTIONS.info_dict.get(
|
|
|
|
"board_uses_vendorimage") == "true"
|
|
|
|
|
|
|
|
if (OPTIONS.rebuild_recovery and not board_uses_vendorimage and
|
2021-04-05 19:40:47 +02:00
|
|
|
recovery_img is not None and boot_img is not None):
|
Moving recovery resources from /system to /vendor
This change is part of a topic that moves the recovery resources from the
system partition to the vendor partition, if it exists, or the vendor directory
on the system partition otherwise. The recovery resources are moving from the
system image to the vendor partition so that a single system image may be used
with either an A/B or a non-A/B vendor image. The topic removes a delta in the
system image that prevented such reuse in the past.
The recovery resources that are moving are involved with updating the recovery
partition after an update. In a non-A/B configuration, the system boots from
the recovery partition, updates the other partitions (system, vendor, etc.)
Then, the next time the system boots normally, a script updates the recovery
partition (if necessary). This script, the executables it invokes, and the data
files that it uses were previously on the system partition. The resources that
are moving include the following.
* install-recovery.sh
* applypatch
* recovery-resource.dat (if present)
* recovery-from-boot.p (if present)
This change includes the platform build system and release tools changes to
move the recovery resources from system to vendor (or /system/vendor). The
release tools need to know where to generate the recovery patch, and they
discover this from misc_info.txt variable board_uses_vendorimage, which the
platform build system generates.
We remove applypatch from PRODUCT_PACKAGES, but it is added back as a required
module in target/product/base_vendor.mk.
Several release tools rely on the misc_info.txt board_uses_vendorimage variable
to know how to generate and detect the recovery patch.
This change partially removes the --rebuild_recovery flag from the
merge_target_files.py script. The flag will be fully removed in a follow-on
change.
Bug: 68319577
Test: Ensure that recovery partition is updated correctly.
Change-Id: Ia4045bd67ffb3d899efa8d20dab4c4299b87ee5f
2019-09-18 02:06:47 +02:00
|
|
|
logger.info("Building new recovery patch on system at system/vendor")
|
2015-03-24 03:13:21 +01:00
|
|
|
common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, recovery_img,
|
|
|
|
boot_img, info_dict=OPTIONS.info_dict)
|
2014-11-14 06:41:08 +01:00
|
|
|
|
2021-04-05 19:40:47 +02:00
|
|
|
block_list = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system.map")
|
2017-03-06 04:51:56 +01:00
|
|
|
CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "system", img,
|
|
|
|
block_list=block_list)
|
|
|
|
return img.name
|
2014-08-26 22:10:25 +02:00
|
|
|
|
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
def AddSystemOther(output_zip):
|
2016-06-16 23:47:10 +02:00
|
|
|
"""Turn the contents of SYSTEM_OTHER into a system_other image
|
|
|
|
and store it in output_zip."""
|
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system_other.img")
|
2019-01-14 08:23:01 +01:00
|
|
|
if os.path.exists(img.name):
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("system_other.img already exists; no need to rebuild...")
|
2016-06-16 23:47:10 +02:00
|
|
|
return
|
|
|
|
|
2017-03-06 04:51:56 +01:00
|
|
|
CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "system_other", img)
|
2016-06-16 23:47:10 +02:00
|
|
|
|
|
|
|
|
Moving recovery resources from /system to /vendor
This change is part of a topic that moves the recovery resources from the
system partition to the vendor partition, if it exists, or the vendor directory
on the system partition otherwise. The recovery resources are moving from the
system image to the vendor partition so that a single system image may be used
with either an A/B or a non-A/B vendor image. The topic removes a delta in the
system image that prevented such reuse in the past.
The recovery resources that are moving are involved with updating the recovery
partition after an update. In a non-A/B configuration, the system boots from
the recovery partition, updates the other partitions (system, vendor, etc.)
Then, the next time the system boots normally, a script updates the recovery
partition (if necessary). This script, the executables it invokes, and the data
files that it uses were previously on the system partition. The resources that
are moving include the following.
* install-recovery.sh
* applypatch
* recovery-resource.dat (if present)
* recovery-from-boot.p (if present)
This change includes the platform build system and release tools changes to
move the recovery resources from system to vendor (or /system/vendor). The
release tools need to know where to generate the recovery patch, and they
discover this from misc_info.txt variable board_uses_vendorimage, which the
platform build system generates.
We remove applypatch from PRODUCT_PACKAGES, but it is added back as a required
module in target/product/base_vendor.mk.
Several release tools rely on the misc_info.txt board_uses_vendorimage variable
to know how to generate and detect the recovery patch.
This change partially removes the --rebuild_recovery flag from the
merge_target_files.py script. The flag will be fully removed in a follow-on
change.
Bug: 68319577
Test: Ensure that recovery partition is updated correctly.
Change-Id: Ia4045bd67ffb3d899efa8d20dab4c4299b87ee5f
2019-09-18 02:06:47 +02:00
|
|
|
def AddVendor(output_zip, recovery_img=None, boot_img=None):
|
2014-08-26 22:10:25 +02:00
|
|
|
"""Turn the contents of VENDOR into a vendor image and store in it
|
|
|
|
output_zip."""
|
2014-11-14 06:41:08 +01:00
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor.img")
|
2019-01-14 08:23:01 +01:00
|
|
|
if os.path.exists(img.name):
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("vendor.img already exists; no need to rebuild...")
|
2019-01-14 08:23:01 +01:00
|
|
|
return img.name
|
2014-07-31 20:06:30 +02:00
|
|
|
|
Moving recovery resources from /system to /vendor
This change is part of a topic that moves the recovery resources from the
system partition to the vendor partition, if it exists, or the vendor directory
on the system partition otherwise. The recovery resources are moving from the
system image to the vendor partition so that a single system image may be used
with either an A/B or a non-A/B vendor image. The topic removes a delta in the
system image that prevented such reuse in the past.
The recovery resources that are moving are involved with updating the recovery
partition after an update. In a non-A/B configuration, the system boots from
the recovery partition, updates the other partitions (system, vendor, etc.)
Then, the next time the system boots normally, a script updates the recovery
partition (if necessary). This script, the executables it invokes, and the data
files that it uses were previously on the system partition. The resources that
are moving include the following.
* install-recovery.sh
* applypatch
* recovery-resource.dat (if present)
* recovery-from-boot.p (if present)
This change includes the platform build system and release tools changes to
move the recovery resources from system to vendor (or /system/vendor). The
release tools need to know where to generate the recovery patch, and they
discover this from misc_info.txt variable board_uses_vendorimage, which the
platform build system generates.
We remove applypatch from PRODUCT_PACKAGES, but it is added back as a required
module in target/product/base_vendor.mk.
Several release tools rely on the misc_info.txt board_uses_vendorimage variable
to know how to generate and detect the recovery patch.
This change partially removes the --rebuild_recovery flag from the
merge_target_files.py script. The flag will be fully removed in a follow-on
change.
Bug: 68319577
Test: Ensure that recovery partition is updated correctly.
Change-Id: Ia4045bd67ffb3d899efa8d20dab4c4299b87ee5f
2019-09-18 02:06:47 +02:00
|
|
|
def output_sink(fn, data):
|
|
|
|
ofile = open(os.path.join(OPTIONS.input_tmp, "VENDOR", fn), "w")
|
|
|
|
ofile.write(data)
|
|
|
|
ofile.close()
|
|
|
|
|
|
|
|
if output_zip:
|
|
|
|
arc_name = "VENDOR/" + fn
|
|
|
|
if arc_name in output_zip.namelist():
|
|
|
|
OPTIONS.replace_updated_files_list.append(arc_name)
|
|
|
|
else:
|
|
|
|
common.ZipWrite(output_zip, ofile.name, arc_name)
|
|
|
|
|
|
|
|
board_uses_vendorimage = OPTIONS.info_dict.get(
|
|
|
|
"board_uses_vendorimage") == "true"
|
|
|
|
|
|
|
|
if (OPTIONS.rebuild_recovery and board_uses_vendorimage and
|
2021-04-05 19:40:47 +02:00
|
|
|
recovery_img is not None and boot_img is not None):
|
Moving recovery resources from /system to /vendor
This change is part of a topic that moves the recovery resources from the
system partition to the vendor partition, if it exists, or the vendor directory
on the system partition otherwise. The recovery resources are moving from the
system image to the vendor partition so that a single system image may be used
with either an A/B or a non-A/B vendor image. The topic removes a delta in the
system image that prevented such reuse in the past.
The recovery resources that are moving are involved with updating the recovery
partition after an update. In a non-A/B configuration, the system boots from
the recovery partition, updates the other partitions (system, vendor, etc.)
Then, the next time the system boots normally, a script updates the recovery
partition (if necessary). This script, the executables it invokes, and the data
files that it uses were previously on the system partition. The resources that
are moving include the following.
* install-recovery.sh
* applypatch
* recovery-resource.dat (if present)
* recovery-from-boot.p (if present)
This change includes the platform build system and release tools changes to
move the recovery resources from system to vendor (or /system/vendor). The
release tools need to know where to generate the recovery patch, and they
discover this from misc_info.txt variable board_uses_vendorimage, which the
platform build system generates.
We remove applypatch from PRODUCT_PACKAGES, but it is added back as a required
module in target/product/base_vendor.mk.
Several release tools rely on the misc_info.txt board_uses_vendorimage variable
to know how to generate and detect the recovery patch.
This change partially removes the --rebuild_recovery flag from the
merge_target_files.py script. The flag will be fully removed in a follow-on
change.
Bug: 68319577
Test: Ensure that recovery partition is updated correctly.
Change-Id: Ia4045bd67ffb3d899efa8d20dab4c4299b87ee5f
2019-09-18 02:06:47 +02:00
|
|
|
logger.info("Building new recovery patch on vendor")
|
|
|
|
common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, recovery_img,
|
|
|
|
boot_img, info_dict=OPTIONS.info_dict)
|
|
|
|
|
2021-04-05 19:40:47 +02:00
|
|
|
block_list = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor.map")
|
2017-03-06 04:51:56 +01:00
|
|
|
CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "vendor", img,
|
|
|
|
block_list=block_list)
|
|
|
|
return img.name
|
2014-07-31 20:06:30 +02:00
|
|
|
|
2017-05-13 02:50:46 +02:00
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
def AddProduct(output_zip):
|
|
|
|
"""Turn the contents of PRODUCT into a product image and store it in
|
|
|
|
output_zip."""
|
2017-11-27 09:04:47 +01:00
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "product.img")
|
2019-01-14 08:23:01 +01:00
|
|
|
if os.path.exists(img.name):
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("product.img already exists; no need to rebuild...")
|
2019-01-14 08:23:01 +01:00
|
|
|
return img.name
|
2017-11-27 09:04:47 +01:00
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
block_list = OutputFile(
|
|
|
|
output_zip, OPTIONS.input_tmp, "IMAGES", "product.map")
|
|
|
|
CreateImage(
|
|
|
|
OPTIONS.input_tmp, OPTIONS.info_dict, "product", img,
|
|
|
|
block_list=block_list)
|
2017-11-27 09:04:47 +01:00
|
|
|
return img.name
|
|
|
|
|
|
|
|
|
2019-06-25 08:58:13 +02:00
|
|
|
def AddSystemExt(output_zip):
|
|
|
|
"""Turn the contents of SYSTEM_EXT into a system_ext image and store it in
|
|
|
|
output_zip."""
|
2018-05-29 14:09:01 +02:00
|
|
|
|
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES",
|
2019-06-25 08:58:13 +02:00
|
|
|
"system_ext.img")
|
2019-01-14 08:23:01 +01:00
|
|
|
if os.path.exists(img.name):
|
2019-06-25 08:58:13 +02:00
|
|
|
logger.info("system_ext.img already exists; no need to rebuild...")
|
2019-01-14 08:23:01 +01:00
|
|
|
return img.name
|
2018-05-29 14:09:01 +02:00
|
|
|
|
|
|
|
block_list = OutputFile(
|
2019-06-25 08:58:13 +02:00
|
|
|
output_zip, OPTIONS.input_tmp, "IMAGES", "system_ext.map")
|
2018-05-29 14:09:01 +02:00
|
|
|
CreateImage(
|
2019-06-25 08:58:13 +02:00
|
|
|
OPTIONS.input_tmp, OPTIONS.info_dict, "system_ext", img,
|
2018-05-29 14:09:01 +02:00
|
|
|
block_list=block_list)
|
|
|
|
return img.name
|
|
|
|
|
|
|
|
|
2017-11-14 16:42:30 +01:00
|
|
|
def AddOdm(output_zip):
|
|
|
|
"""Turn the contents of ODM into an odm image and store it in output_zip."""
|
|
|
|
|
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "odm.img")
|
2019-01-14 08:23:01 +01:00
|
|
|
if os.path.exists(img.name):
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("odm.img already exists; no need to rebuild...")
|
2019-01-14 08:23:01 +01:00
|
|
|
return img.name
|
2017-11-14 16:42:30 +01:00
|
|
|
|
|
|
|
block_list = OutputFile(
|
|
|
|
output_zip, OPTIONS.input_tmp, "IMAGES", "odm.map")
|
|
|
|
CreateImage(
|
|
|
|
OPTIONS.input_tmp, OPTIONS.info_dict, "odm", img,
|
|
|
|
block_list=block_list)
|
|
|
|
return img.name
|
|
|
|
|
|
|
|
|
2020-05-07 23:58:20 +02:00
|
|
|
def AddVendorDlkm(output_zip):
|
|
|
|
"""Turn the contents of VENDOR_DLKM into an vendor_dlkm image and store it in output_zip."""
|
|
|
|
|
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor_dlkm.img")
|
|
|
|
if os.path.exists(img.name):
|
|
|
|
logger.info("vendor_dlkm.img already exists; no need to rebuild...")
|
|
|
|
return img.name
|
|
|
|
|
|
|
|
block_list = OutputFile(
|
|
|
|
output_zip, OPTIONS.input_tmp, "IMAGES", "vendor_dlkm.map")
|
|
|
|
CreateImage(
|
|
|
|
OPTIONS.input_tmp, OPTIONS.info_dict, "vendor_dlkm", img,
|
|
|
|
block_list=block_list)
|
|
|
|
return img.name
|
|
|
|
|
2020-07-16 01:52:59 +02:00
|
|
|
def AddOdmDlkm(output_zip):
|
|
|
|
"""Turn the contents of OdmDlkm into an odm_dlkm image and store it in output_zip."""
|
|
|
|
|
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "odm_dlkm.img")
|
|
|
|
if os.path.exists(img.name):
|
|
|
|
logger.info("odm_dlkm.img already exists; no need to rebuild...")
|
|
|
|
return img.name
|
|
|
|
|
|
|
|
block_list = OutputFile(
|
|
|
|
output_zip, OPTIONS.input_tmp, "IMAGES", "odm_dlkm.map")
|
|
|
|
CreateImage(
|
|
|
|
OPTIONS.input_tmp, OPTIONS.info_dict, "odm_dlkm", img,
|
|
|
|
block_list=block_list)
|
|
|
|
return img.name
|
|
|
|
|
2020-05-07 23:58:20 +02:00
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
def AddDtbo(output_zip):
|
2017-05-31 06:46:33 +02:00
|
|
|
"""Adds the DTBO image.
|
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
Uses the image under IMAGES/ if it already exists. Otherwise looks for the
|
2017-05-31 06:46:33 +02:00
|
|
|
image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
|
|
|
|
"""
|
2018-02-27 20:46:19 +01:00
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "dtbo.img")
|
2019-01-14 08:23:01 +01:00
|
|
|
if os.path.exists(img.name):
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("dtbo.img already exists; no need to rebuild...")
|
2019-01-14 08:23:01 +01:00
|
|
|
return img.name
|
2017-05-31 06:46:33 +02:00
|
|
|
|
|
|
|
dtbo_prebuilt_path = os.path.join(
|
|
|
|
OPTIONS.input_tmp, "PREBUILT_IMAGES", "dtbo.img")
|
|
|
|
assert os.path.exists(dtbo_prebuilt_path)
|
|
|
|
shutil.copy(dtbo_prebuilt_path, img.name)
|
|
|
|
|
|
|
|
# AVB-sign the image as needed.
|
2017-05-26 12:30:04 +02:00
|
|
|
if OPTIONS.info_dict.get("avb_enable") == "true":
|
2020-12-08 07:18:35 +01:00
|
|
|
# Signing requires +w
|
|
|
|
os.chmod(img.name, os.stat(img.name).st_mode | stat.S_IWUSR)
|
|
|
|
|
2019-03-18 22:01:38 +01:00
|
|
|
avbtool = OPTIONS.info_dict["avb_avbtool"]
|
2017-05-24 08:06:55 +02:00
|
|
|
part_size = OPTIONS.info_dict["dtbo_size"]
|
2017-05-31 06:46:33 +02:00
|
|
|
# The AVB hash footer will be replaced if already present.
|
|
|
|
cmd = [avbtool, "add_hash_footer", "--image", img.name,
|
|
|
|
"--partition_size", str(part_size), "--partition_name", "dtbo"]
|
2017-05-26 12:30:04 +02:00
|
|
|
common.AppendAVBSigningArgs(cmd, "dtbo")
|
|
|
|
args = OPTIONS.info_dict.get("avb_dtbo_add_hash_footer_args")
|
2017-05-31 06:46:33 +02:00
|
|
|
if args and args.strip():
|
|
|
|
cmd.extend(shlex.split(args))
|
2018-11-21 20:02:48 +01:00
|
|
|
common.RunAndCheckOutput(cmd)
|
2017-05-31 06:46:33 +02:00
|
|
|
|
|
|
|
img.Write()
|
|
|
|
return img.name
|
|
|
|
|
2021-02-18 11:27:29 +01:00
|
|
|
def AddPvmfw(output_zip):
|
|
|
|
"""Adds the pvmfw image.
|
|
|
|
|
|
|
|
Uses the image under IMAGES/ if it already exists. Otherwise looks for the
|
|
|
|
image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
|
|
|
|
"""
|
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "pvmfw.img")
|
|
|
|
if os.path.exists(img.name):
|
|
|
|
logger.info("pvmfw.img already exists; no need to rebuild...")
|
|
|
|
return img.name
|
|
|
|
|
|
|
|
pvmfw_prebuilt_path = os.path.join(
|
|
|
|
OPTIONS.input_tmp, "PREBUILT_IMAGES", "pvmfw.img")
|
|
|
|
assert os.path.exists(pvmfw_prebuilt_path)
|
|
|
|
shutil.copy(pvmfw_prebuilt_path, img.name)
|
|
|
|
|
|
|
|
# AVB-sign the image as needed.
|
|
|
|
if OPTIONS.info_dict.get("avb_enable") == "true":
|
|
|
|
# Signing requires +w
|
|
|
|
os.chmod(img.name, os.stat(img.name).st_mode | stat.S_IWUSR)
|
|
|
|
|
|
|
|
avbtool = OPTIONS.info_dict["avb_avbtool"]
|
|
|
|
part_size = OPTIONS.info_dict["pvmfw_size"]
|
|
|
|
# The AVB hash footer will be replaced if already present.
|
|
|
|
cmd = [avbtool, "add_hash_footer", "--image", img.name,
|
|
|
|
"--partition_size", str(part_size), "--partition_name", "pvmfw"]
|
|
|
|
common.AppendAVBSigningArgs(cmd, "pvmfw")
|
|
|
|
args = OPTIONS.info_dict.get("avb_pvmfw_add_hash_footer_args")
|
|
|
|
if args and args.strip():
|
|
|
|
cmd.extend(shlex.split(args))
|
|
|
|
common.RunAndCheckOutput(cmd)
|
|
|
|
|
|
|
|
img.Write()
|
|
|
|
return img.name
|
|
|
|
|
Add options to sign the prebuilt custom images.
The custom images are any images owned by OEMs and SoCs, oem images
mounted on /oem is an example. The oem images can be used to customize
devices for different carriers, like wallpaper, ringtones, and
carrier-specific apks. OEMs can generate multiple oem images, like
oem.img, oem-carrier1.img and oem-carrier2.img and flash different oem
images for different carriers. The oem images are only one case, OEMs
and SoCs can add more custom images and mount them to custom partitions.
This change enables custom images to be vbmeta.img chained partitions.
The following configuration in BoardConfig.mk is an exmaple. It has two
custom partitions: oem and test. They will be signed by different keys.
And they will be chained by vbmeta.img. The custom images here are
prebuilts, which can be built by `make custom_images` separately.
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST should include all custom images
to apply AVB signing. And to every custom partition, one image whose
name is partition name must be added in its
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST.
BOARD_CUSTOMIMAGES_PARTITION_LIST := oem test
BOARD_AVB_OEM_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
BOARD_AVB_OEM_ALGORITHM := SHA256_RSA4096
BOARD_AVB_OEM_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_OEM_ROLLBACK_INDEX_LOCATION := 1
BOARD_AVB_OEM_PARTITION_SIZE := 5242880
BOARD_AVB_OEM_IMAGE_LIST := \
device/xxxx/yyyy/oem/oem.img \
device/xxxx/yyyy/oem/oem1.img
BOARD_AVB_TEST_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_TEST_ALGORITHM := SHA256_RSA2048
BOARD_AVB_TEST_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_TEST_ROLLBACK_INDEX_LOCATION := 2
BOARD_AVB_TEST_PARTITION_SIZE := 10485760
BOARD_AVB_TEST_IMAGE_LIST := \
device/xxxx/yyyy/test/test.img \
device/xxxx/yyyy/test/test1.img
To resign the custom images in the target zip file, the
avb_extra_custom_image_key, avb_extra_custom_image_algorithms and
avb_extra_custom_image_extra_args options are added to the
sign_target_files_apks tool too. The following test cases list some
examples about how to use them.
BUG: 154171021
Test: 1) "atest --host releasetools_test releasetools_py3_test -c"
2) Build images by 'make dist', sign and validate target files.
a) Test on dist w/ chained vbmeta_system and ome custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the oem images and vbmeta images in OUT and target zips by
avbtool.
b) Test on dist w/ chained vbmeta_system and oem and test custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
--avb_extra_custom_image_extra_args oem=--do_not_generate_fec \
--avb_extra_custom_image_key test=test_rsa4096.pem \
--avb_extra_custom_image_algorithm test=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Verify the oem, test images and vbmeta images in OUT and target zips
by avbtool.
c) Test on dist w/o chained partition.
sign_target_files_apks -d certs xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the vbmeta images in OUT and target zips by avbtool.
Change-Id: Ifccfee5e8909697eef6ccda0cc352fa16a9f6db6
2020-04-28 03:36:36 +02:00
|
|
|
def AddCustomImages(output_zip, partition_name):
|
|
|
|
"""Adds and signs custom images in IMAGES/.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
output_zip: The output zip file (needs to be already open), or None to
|
|
|
|
write images to OPTIONS.input_tmp/.
|
|
|
|
|
|
|
|
Uses the image under IMAGES/ if it already exists. Otherwise looks for the
|
|
|
|
image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
AssertionError: If image can't be found.
|
|
|
|
"""
|
|
|
|
|
|
|
|
partition_size = OPTIONS.info_dict.get(
|
|
|
|
"avb_{}_partition_size".format(partition_name))
|
|
|
|
key_path = OPTIONS.info_dict.get("avb_{}_key_path".format(partition_name))
|
|
|
|
algorithm = OPTIONS.info_dict.get("avb_{}_algorithm".format(partition_name))
|
|
|
|
extra_args = OPTIONS.info_dict.get(
|
|
|
|
"avb_{}_add_hashtree_footer_args".format(partition_name))
|
|
|
|
partition_size = OPTIONS.info_dict.get(
|
|
|
|
"avb_{}_partition_size".format(partition_name))
|
|
|
|
|
|
|
|
builder = verity_utils.CreateCustomImageBuilder(
|
|
|
|
OPTIONS.info_dict, partition_name, partition_size,
|
|
|
|
key_path, algorithm, extra_args)
|
|
|
|
|
|
|
|
for img_name in OPTIONS.info_dict.get(
|
2021-04-05 19:40:47 +02:00
|
|
|
"avb_{}_image_list".format(partition_name)).split():
|
|
|
|
custom_image = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", img_name)
|
Add options to sign the prebuilt custom images.
The custom images are any images owned by OEMs and SoCs, oem images
mounted on /oem is an example. The oem images can be used to customize
devices for different carriers, like wallpaper, ringtones, and
carrier-specific apks. OEMs can generate multiple oem images, like
oem.img, oem-carrier1.img and oem-carrier2.img and flash different oem
images for different carriers. The oem images are only one case, OEMs
and SoCs can add more custom images and mount them to custom partitions.
This change enables custom images to be vbmeta.img chained partitions.
The following configuration in BoardConfig.mk is an exmaple. It has two
custom partitions: oem and test. They will be signed by different keys.
And they will be chained by vbmeta.img. The custom images here are
prebuilts, which can be built by `make custom_images` separately.
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST should include all custom images
to apply AVB signing. And to every custom partition, one image whose
name is partition name must be added in its
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST.
BOARD_CUSTOMIMAGES_PARTITION_LIST := oem test
BOARD_AVB_OEM_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
BOARD_AVB_OEM_ALGORITHM := SHA256_RSA4096
BOARD_AVB_OEM_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_OEM_ROLLBACK_INDEX_LOCATION := 1
BOARD_AVB_OEM_PARTITION_SIZE := 5242880
BOARD_AVB_OEM_IMAGE_LIST := \
device/xxxx/yyyy/oem/oem.img \
device/xxxx/yyyy/oem/oem1.img
BOARD_AVB_TEST_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_TEST_ALGORITHM := SHA256_RSA2048
BOARD_AVB_TEST_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_TEST_ROLLBACK_INDEX_LOCATION := 2
BOARD_AVB_TEST_PARTITION_SIZE := 10485760
BOARD_AVB_TEST_IMAGE_LIST := \
device/xxxx/yyyy/test/test.img \
device/xxxx/yyyy/test/test1.img
To resign the custom images in the target zip file, the
avb_extra_custom_image_key, avb_extra_custom_image_algorithms and
avb_extra_custom_image_extra_args options are added to the
sign_target_files_apks tool too. The following test cases list some
examples about how to use them.
BUG: 154171021
Test: 1) "atest --host releasetools_test releasetools_py3_test -c"
2) Build images by 'make dist', sign and validate target files.
a) Test on dist w/ chained vbmeta_system and ome custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the oem images and vbmeta images in OUT and target zips by
avbtool.
b) Test on dist w/ chained vbmeta_system and oem and test custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
--avb_extra_custom_image_extra_args oem=--do_not_generate_fec \
--avb_extra_custom_image_key test=test_rsa4096.pem \
--avb_extra_custom_image_algorithm test=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Verify the oem, test images and vbmeta images in OUT and target zips
by avbtool.
c) Test on dist w/o chained partition.
sign_target_files_apks -d certs xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the vbmeta images in OUT and target zips by avbtool.
Change-Id: Ifccfee5e8909697eef6ccda0cc352fa16a9f6db6
2020-04-28 03:36:36 +02:00
|
|
|
if os.path.exists(custom_image.name):
|
|
|
|
continue
|
|
|
|
|
|
|
|
custom_image_prebuilt_path = os.path.join(
|
|
|
|
OPTIONS.input_tmp, "PREBUILT_IMAGES", img_name)
|
|
|
|
assert os.path.exists(custom_image_prebuilt_path), \
|
2021-04-05 19:40:47 +02:00
|
|
|
"Failed to find %s at %s" % (img_name, custom_image_prebuilt_path)
|
Add options to sign the prebuilt custom images.
The custom images are any images owned by OEMs and SoCs, oem images
mounted on /oem is an example. The oem images can be used to customize
devices for different carriers, like wallpaper, ringtones, and
carrier-specific apks. OEMs can generate multiple oem images, like
oem.img, oem-carrier1.img and oem-carrier2.img and flash different oem
images for different carriers. The oem images are only one case, OEMs
and SoCs can add more custom images and mount them to custom partitions.
This change enables custom images to be vbmeta.img chained partitions.
The following configuration in BoardConfig.mk is an exmaple. It has two
custom partitions: oem and test. They will be signed by different keys.
And they will be chained by vbmeta.img. The custom images here are
prebuilts, which can be built by `make custom_images` separately.
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST should include all custom images
to apply AVB signing. And to every custom partition, one image whose
name is partition name must be added in its
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST.
BOARD_CUSTOMIMAGES_PARTITION_LIST := oem test
BOARD_AVB_OEM_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
BOARD_AVB_OEM_ALGORITHM := SHA256_RSA4096
BOARD_AVB_OEM_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_OEM_ROLLBACK_INDEX_LOCATION := 1
BOARD_AVB_OEM_PARTITION_SIZE := 5242880
BOARD_AVB_OEM_IMAGE_LIST := \
device/xxxx/yyyy/oem/oem.img \
device/xxxx/yyyy/oem/oem1.img
BOARD_AVB_TEST_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_TEST_ALGORITHM := SHA256_RSA2048
BOARD_AVB_TEST_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_TEST_ROLLBACK_INDEX_LOCATION := 2
BOARD_AVB_TEST_PARTITION_SIZE := 10485760
BOARD_AVB_TEST_IMAGE_LIST := \
device/xxxx/yyyy/test/test.img \
device/xxxx/yyyy/test/test1.img
To resign the custom images in the target zip file, the
avb_extra_custom_image_key, avb_extra_custom_image_algorithms and
avb_extra_custom_image_extra_args options are added to the
sign_target_files_apks tool too. The following test cases list some
examples about how to use them.
BUG: 154171021
Test: 1) "atest --host releasetools_test releasetools_py3_test -c"
2) Build images by 'make dist', sign and validate target files.
a) Test on dist w/ chained vbmeta_system and ome custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the oem images and vbmeta images in OUT and target zips by
avbtool.
b) Test on dist w/ chained vbmeta_system and oem and test custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
--avb_extra_custom_image_extra_args oem=--do_not_generate_fec \
--avb_extra_custom_image_key test=test_rsa4096.pem \
--avb_extra_custom_image_algorithm test=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Verify the oem, test images and vbmeta images in OUT and target zips
by avbtool.
c) Test on dist w/o chained partition.
sign_target_files_apks -d certs xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the vbmeta images in OUT and target zips by avbtool.
Change-Id: Ifccfee5e8909697eef6ccda0cc352fa16a9f6db6
2020-04-28 03:36:36 +02:00
|
|
|
|
|
|
|
shutil.copy(custom_image_prebuilt_path, custom_image.name)
|
|
|
|
|
|
|
|
if builder is not None:
|
|
|
|
builder.Build(custom_image.name)
|
|
|
|
|
|
|
|
custom_image.Write()
|
|
|
|
|
|
|
|
default = os.path.join(OPTIONS.input_tmp, "IMAGES", partition_name + ".img")
|
|
|
|
assert os.path.exists(default), \
|
|
|
|
"There should be one %s.img" % (partition_name)
|
|
|
|
return default
|
|
|
|
|
2014-08-26 22:10:25 +02:00
|
|
|
|
2017-03-06 04:51:56 +01:00
|
|
|
def CreateImage(input_dir, info_dict, what, output_file, block_list=None):
|
2019-06-25 00:33:41 +02:00
|
|
|
logger.info("creating %s.img...", what)
|
2014-07-31 20:06:30 +02:00
|
|
|
|
|
|
|
image_props = build_image.ImagePropFromGlobalDict(info_dict, what)
|
2018-08-01 03:32:00 +02:00
|
|
|
image_props["timestamp"] = FIXED_FILE_TIMESTAMP
|
2015-10-01 01:01:14 +02:00
|
|
|
|
2014-07-31 20:06:30 +02:00
|
|
|
if what == "system":
|
|
|
|
fs_config_prefix = ""
|
|
|
|
else:
|
|
|
|
fs_config_prefix = what + "_"
|
|
|
|
|
|
|
|
fs_config = os.path.join(
|
|
|
|
input_dir, "META/" + fs_config_prefix + "filesystem_config.txt")
|
2015-03-24 03:13:21 +01:00
|
|
|
if not os.path.exists(fs_config):
|
|
|
|
fs_config = None
|
2014-07-31 20:06:30 +02:00
|
|
|
|
2015-03-25 03:07:40 +01:00
|
|
|
# Override values loaded from info_dict.
|
|
|
|
if fs_config:
|
|
|
|
image_props["fs_config"] = fs_config
|
|
|
|
if block_list:
|
2017-03-06 04:51:56 +01:00
|
|
|
image_props["block_list"] = block_list.name
|
2015-03-25 03:07:40 +01:00
|
|
|
|
2017-09-23 00:45:33 +02:00
|
|
|
# Use repeatable ext4 FS UUID and hash_seed UUID (based on partition name and
|
|
|
|
# build fingerprint).
|
2019-10-08 05:48:48 +02:00
|
|
|
build_info = common.BuildInfo(info_dict)
|
2020-09-15 21:07:39 +02:00
|
|
|
uuid_seed = what + "-" + build_info.GetPartitionFingerprint(what)
|
2017-09-23 00:45:33 +02:00
|
|
|
image_props["uuid"] = str(uuid.uuid5(uuid.NAMESPACE_URL, uuid_seed))
|
|
|
|
hash_seed = "hash_seed-" + uuid_seed
|
|
|
|
image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))
|
|
|
|
|
2018-09-28 01:58:00 +02:00
|
|
|
build_image.BuildImage(
|
|
|
|
os.path.join(input_dir, what.upper()), image_props, output_file.name)
|
2014-07-31 20:06:30 +02:00
|
|
|
|
2017-03-06 04:51:56 +01:00
|
|
|
output_file.Write()
|
|
|
|
if block_list:
|
|
|
|
block_list.Write()
|
|
|
|
|
2019-02-07 02:57:21 +01:00
|
|
|
# Set the '_image_size' for given image size.
|
2017-01-20 02:39:30 +01:00
|
|
|
is_verity_partition = "verity_block_device" in image_props
|
2017-06-01 20:32:32 +02:00
|
|
|
verity_supported = (image_props.get("verity") == "true" or
|
2017-05-26 12:30:04 +02:00
|
|
|
image_props.get("avb_enable") == "true")
|
2017-06-01 20:32:32 +02:00
|
|
|
is_avb_enable = image_props.get("avb_hashtree_enable") == "true"
|
|
|
|
if verity_supported and (is_verity_partition or is_avb_enable):
|
2018-09-28 00:31:11 +02:00
|
|
|
image_size = image_props.get("image_size")
|
|
|
|
if image_size:
|
2019-02-07 02:57:21 +01:00
|
|
|
image_size_key = what + "_image_size"
|
|
|
|
info_dict[image_size_key] = int(image_size)
|
2017-01-20 02:39:30 +01:00
|
|
|
|
2018-11-09 00:41:24 +01:00
|
|
|
use_dynamic_size = (
|
2018-11-21 20:02:48 +01:00
|
|
|
info_dict.get("use_dynamic_partition_size") == "true" and
|
|
|
|
what in shlex.split(info_dict.get("dynamic_partition_list", "").strip()))
|
2018-11-09 00:41:24 +01:00
|
|
|
if use_dynamic_size:
|
|
|
|
info_dict.update(build_image.GlobalDictFromImageProp(image_props, what))
|
|
|
|
|
2014-07-31 20:06:30 +02:00
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
def AddUserdata(output_zip):
|
2015-06-25 22:56:53 +02:00
|
|
|
"""Create a userdata image and store it in output_zip.
|
|
|
|
|
|
|
|
In most case we just create and store an empty userdata.img;
|
|
|
|
But the invoker can also request to create userdata.img with real
|
|
|
|
data from the target files, by setting "userdata_img_with_data=true"
|
|
|
|
in OPTIONS.info_dict.
|
|
|
|
"""
|
2014-07-31 20:06:30 +02:00
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "userdata.img")
|
2019-01-14 08:23:01 +01:00
|
|
|
if os.path.exists(img.name):
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("userdata.img already exists; no need to rebuild...")
|
2014-11-14 06:41:08 +01:00
|
|
|
return
|
|
|
|
|
2016-06-16 02:04:54 +02:00
|
|
|
# Skip userdata.img if no size.
|
2015-07-09 20:51:16 +02:00
|
|
|
image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, "data")
|
2016-06-16 02:04:54 +02:00
|
|
|
if not image_props.get("partition_size"):
|
2014-07-31 20:06:30 +02:00
|
|
|
return
|
|
|
|
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("creating userdata.img...")
|
2014-07-31 20:06:30 +02:00
|
|
|
|
2018-08-01 03:32:00 +02:00
|
|
|
image_props["timestamp"] = FIXED_FILE_TIMESTAMP
|
2015-10-01 01:01:14 +02:00
|
|
|
|
2017-05-24 08:49:03 +02:00
|
|
|
if OPTIONS.info_dict.get("userdata_img_with_data") == "true":
|
|
|
|
user_dir = os.path.join(OPTIONS.input_tmp, "DATA")
|
2015-06-25 22:56:53 +02:00
|
|
|
else:
|
2017-12-25 19:43:47 +01:00
|
|
|
user_dir = common.MakeTempDir()
|
2015-06-25 22:56:53 +02:00
|
|
|
|
2018-09-28 01:58:00 +02:00
|
|
|
build_image.BuildImage(user_dir, image_props, img.name)
|
2014-07-31 20:06:30 +02:00
|
|
|
|
|
|
|
common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict)
|
2017-03-06 04:51:56 +01:00
|
|
|
img.Write()
|
2014-07-31 20:06:30 +02:00
|
|
|
|
|
|
|
|
2018-08-21 06:09:07 +02:00
|
|
|
def AddVBMeta(output_zip, partitions, name, needed_partitions):
|
|
|
|
"""Creates a VBMeta image and stores it in output_zip.
|
|
|
|
|
|
|
|
It generates the requested VBMeta image. The requested image could be for
|
|
|
|
top-level or chained VBMeta image, which is determined based on the name.
|
2017-07-12 02:27:55 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
output_zip: The output zip file, which needs to be already open.
|
|
|
|
partitions: A dict that's keyed by partition names with image paths as
|
Add options to sign the prebuilt custom images.
The custom images are any images owned by OEMs and SoCs, oem images
mounted on /oem is an example. The oem images can be used to customize
devices for different carriers, like wallpaper, ringtones, and
carrier-specific apks. OEMs can generate multiple oem images, like
oem.img, oem-carrier1.img and oem-carrier2.img and flash different oem
images for different carriers. The oem images are only one case, OEMs
and SoCs can add more custom images and mount them to custom partitions.
This change enables custom images to be vbmeta.img chained partitions.
The following configuration in BoardConfig.mk is an exmaple. It has two
custom partitions: oem and test. They will be signed by different keys.
And they will be chained by vbmeta.img. The custom images here are
prebuilts, which can be built by `make custom_images` separately.
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST should include all custom images
to apply AVB signing. And to every custom partition, one image whose
name is partition name must be added in its
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST.
BOARD_CUSTOMIMAGES_PARTITION_LIST := oem test
BOARD_AVB_OEM_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
BOARD_AVB_OEM_ALGORITHM := SHA256_RSA4096
BOARD_AVB_OEM_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_OEM_ROLLBACK_INDEX_LOCATION := 1
BOARD_AVB_OEM_PARTITION_SIZE := 5242880
BOARD_AVB_OEM_IMAGE_LIST := \
device/xxxx/yyyy/oem/oem.img \
device/xxxx/yyyy/oem/oem1.img
BOARD_AVB_TEST_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_TEST_ALGORITHM := SHA256_RSA2048
BOARD_AVB_TEST_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_TEST_ROLLBACK_INDEX_LOCATION := 2
BOARD_AVB_TEST_PARTITION_SIZE := 10485760
BOARD_AVB_TEST_IMAGE_LIST := \
device/xxxx/yyyy/test/test.img \
device/xxxx/yyyy/test/test1.img
To resign the custom images in the target zip file, the
avb_extra_custom_image_key, avb_extra_custom_image_algorithms and
avb_extra_custom_image_extra_args options are added to the
sign_target_files_apks tool too. The following test cases list some
examples about how to use them.
BUG: 154171021
Test: 1) "atest --host releasetools_test releasetools_py3_test -c"
2) Build images by 'make dist', sign and validate target files.
a) Test on dist w/ chained vbmeta_system and ome custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the oem images and vbmeta images in OUT and target zips by
avbtool.
b) Test on dist w/ chained vbmeta_system and oem and test custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
--avb_extra_custom_image_extra_args oem=--do_not_generate_fec \
--avb_extra_custom_image_key test=test_rsa4096.pem \
--avb_extra_custom_image_algorithm test=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Verify the oem, test images and vbmeta images in OUT and target zips
by avbtool.
c) Test on dist w/o chained partition.
sign_target_files_apks -d certs xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the vbmeta images in OUT and target zips by avbtool.
Change-Id: Ifccfee5e8909697eef6ccda0cc352fa16a9f6db6
2020-04-28 03:36:36 +02:00
|
|
|
values. Only valid partition names are accepted, as partitions listed
|
|
|
|
in common.AVB_PARTITIONS and custom partitions listed in
|
|
|
|
OPTIONS.info_dict.get("avb_custom_images_partition_list")
|
2018-10-15 23:41:34 +02:00
|
|
|
name: Name of the VBMeta partition, e.g. 'vbmeta', 'vbmeta_system'.
|
2018-08-21 06:09:07 +02:00
|
|
|
needed_partitions: Partitions whose descriptors should be included into the
|
|
|
|
generated VBMeta image.
|
|
|
|
|
2018-10-23 00:08:02 +02:00
|
|
|
Returns:
|
|
|
|
Path to the created image.
|
|
|
|
|
2018-08-21 06:09:07 +02:00
|
|
|
Raises:
|
|
|
|
AssertionError: On invalid input args.
|
2017-07-12 02:27:55 +02:00
|
|
|
"""
|
2018-08-21 06:09:07 +02:00
|
|
|
assert needed_partitions, "Needed partitions must be specified"
|
|
|
|
|
|
|
|
img = OutputFile(
|
|
|
|
output_zip, OPTIONS.input_tmp, "IMAGES", "{}.img".format(name))
|
2019-01-14 08:23:01 +01:00
|
|
|
if os.path.exists(img.name):
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("%s.img already exists; not rebuilding...", name)
|
2019-01-14 08:23:01 +01:00
|
|
|
return img.name
|
2017-07-12 02:27:55 +02:00
|
|
|
|
2019-07-26 23:13:51 +02:00
|
|
|
common.BuildVBMeta(img.name, partitions, name, needed_partitions)
|
2017-03-06 04:51:56 +01:00
|
|
|
img.Write()
|
2018-10-23 00:08:02 +02:00
|
|
|
return img.name
|
Update for new Android Verified Boot (AVB).
This updates the build system for the new Android Verified Boot
codebase. As this is based on Brillo Verified Boot, this change replaces
the existing BVB support.
Android Verified Boot is enabled by the BOARD_AVB_ENABLE variable
BOARD_AVB_ENABLE := true
This will make the build system create vbmeta.img which will contain a
hash descriptor for boot.img, a hashtree descriptor for system.img, a
kernel-cmdline descriptor for setting up dm-verity for system.img and
append a hash-tree to system.img.
Additionally, the descriptors are left in boot.img and system.img so a
third party can create their own vbmeta.img file linking - using the
option --chain_partition - to these images. If this is not needed
footers can be erased using the 'avbtool erase_footer' command. It's
also harmless to just leave them in the images.
By default, the algorithm SHA256_RSA4096 is used with a test key from
the AVB source directory. This can be overriden by the
BOARD_AVB_ALGORITHM and BOARD_AVB_KEY_PATH variables to use e.g. a
4096-bit RSA key and SHA-512:
BOARD_AVB_ALGORITHM := SHA512_RSA4096
BOARD_AVB_KEY_PATH := /path/to/rsa_key_4096bits.pem
To prevent rollback attacks, the rollback index should be increased on a
regular basis. The rollback index can be set with the
BOARD_AVB_ROLLBACK_INDEX variable:
BOARD_AVB_ROLLBACK_INDEX := 5
If this is not set, the rollback index defaults to 0.
The variable BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS can be used to specify
additional options passed to 'avbtool make_vbmeta_image'. Typical
options to be used here include '--prop', '--prop_from_file', and
'--chain_partition'.
The variable BOARD_AVBTOOL_BOOT_ADD_HASH_FOOTER_ARGS can be used to
specify additional options passed to 'avbtool add_hash_footer' for
boot.img. Typical options to be used here include '--hash_algorithm' and
'--salt'.
The variable BOARD_AVBTOOL_SYSTEM_ADD_HASHTREE_FOOTER_ARGS can be used
to specify additional options passed to 'avbtool add_hashtree_footer'
for systems.img. Typical options to be used here include
'--hash_algorithm', '--salt', and '--block_size'.
BUG=31264226
TEST=Manually tested on edison-eng by inspecting {boot, system,
vbmeta}.img in out/ directory as well as their counterparts in
the IMAGES/ directory of edision-target_files-eng.zeuthen.zip
Merged-In: Ic9a61cfc65c148b12996e57f04da5432eef6b982
Change-Id: I97042655bca15e7eac899f12c5bada2f6184d307
2016-09-15 19:43:54 +02:00
|
|
|
|
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
def AddPartitionTable(output_zip):
|
2016-04-08 21:08:03 +02:00
|
|
|
"""Create a partition table image and store it in output_zip."""
|
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
img = OutputFile(
|
|
|
|
output_zip, OPTIONS.input_tmp, "IMAGES", "partition-table.img")
|
|
|
|
bpt = OutputFile(
|
2018-04-26 20:59:33 +02:00
|
|
|
output_zip, OPTIONS.input_tmp, "META", "partition-table.bpt")
|
2016-04-08 21:08:03 +02:00
|
|
|
|
|
|
|
# use BPTTOOL from environ, or "bpttool" if empty or not set.
|
|
|
|
bpttool = os.getenv("BPTTOOL") or "bpttool"
|
2017-03-06 04:51:56 +01:00
|
|
|
cmd = [bpttool, "make_table", "--output_json", bpt.name,
|
|
|
|
"--output_gpt", img.name]
|
2016-04-08 21:08:03 +02:00
|
|
|
input_files_str = OPTIONS.info_dict["board_bpt_input_files"]
|
|
|
|
input_files = input_files_str.split(" ")
|
|
|
|
for i in input_files:
|
|
|
|
cmd.extend(["--input", i])
|
|
|
|
disk_size = OPTIONS.info_dict.get("board_bpt_disk_size")
|
|
|
|
if disk_size:
|
|
|
|
cmd.extend(["--disk_size", disk_size])
|
|
|
|
args = OPTIONS.info_dict.get("board_bpt_make_table_args")
|
|
|
|
if args:
|
|
|
|
cmd.extend(shlex.split(args))
|
2018-11-21 20:02:48 +01:00
|
|
|
common.RunAndCheckOutput(cmd)
|
2016-04-08 21:08:03 +02:00
|
|
|
|
2017-03-06 04:51:56 +01:00
|
|
|
img.Write()
|
|
|
|
bpt.Write()
|
2016-04-08 21:08:03 +02:00
|
|
|
|
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
def AddCache(output_zip):
|
2014-07-31 20:06:30 +02:00
|
|
|
"""Create an empty cache image and store it in output_zip."""
|
|
|
|
|
2018-02-27 20:46:19 +01:00
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "cache.img")
|
2019-01-14 08:23:01 +01:00
|
|
|
if os.path.exists(img.name):
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("cache.img already exists; no need to rebuild...")
|
2014-11-14 06:41:08 +01:00
|
|
|
return
|
|
|
|
|
2015-07-09 20:51:16 +02:00
|
|
|
image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, "cache")
|
2014-07-31 20:06:30 +02:00
|
|
|
# The build system has to explicitly request for cache.img.
|
|
|
|
if "fs_type" not in image_props:
|
|
|
|
return
|
|
|
|
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("creating cache.img...")
|
2014-07-31 20:06:30 +02:00
|
|
|
|
2018-08-01 03:32:00 +02:00
|
|
|
image_props["timestamp"] = FIXED_FILE_TIMESTAMP
|
2015-10-01 01:01:14 +02:00
|
|
|
|
2017-12-25 19:43:47 +01:00
|
|
|
user_dir = common.MakeTempDir()
|
2018-09-28 01:58:00 +02:00
|
|
|
build_image.BuildImage(user_dir, image_props, img.name)
|
2014-07-31 20:06:30 +02:00
|
|
|
|
|
|
|
common.CheckSize(img.name, "cache.img", OPTIONS.info_dict)
|
2017-03-06 04:51:56 +01:00
|
|
|
img.Write()
|
2014-07-31 20:06:30 +02:00
|
|
|
|
|
|
|
|
2018-04-18 08:47:21 +02:00
|
|
|
def CheckAbOtaImages(output_zip, ab_partitions):
|
|
|
|
"""Checks that all the listed A/B partitions have their images available.
|
2018-01-18 02:57:49 +01:00
|
|
|
|
2018-04-18 08:47:21 +02:00
|
|
|
The images need to be available under IMAGES/ or RADIO/, with the former takes
|
|
|
|
a priority.
|
2018-01-18 02:57:49 +01:00
|
|
|
|
|
|
|
Args:
|
|
|
|
output_zip: The output zip file (needs to be already open), or None to
|
2018-04-18 08:47:21 +02:00
|
|
|
find images in OPTIONS.input_tmp/.
|
2018-01-18 02:57:49 +01:00
|
|
|
ab_partitions: The list of A/B partitions.
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
AssertionError: If it can't find an image.
|
|
|
|
"""
|
|
|
|
for partition in ab_partitions:
|
|
|
|
img_name = partition.strip() + ".img"
|
|
|
|
|
2018-01-17 21:14:43 +01:00
|
|
|
# Assert that the image is present under IMAGES/ now.
|
2018-01-18 02:57:49 +01:00
|
|
|
if output_zip:
|
|
|
|
# Zip spec says: All slashes MUST be forward slashes.
|
2018-04-18 08:47:21 +02:00
|
|
|
images_path = "IMAGES/" + img_name
|
|
|
|
radio_path = "RADIO/" + img_name
|
|
|
|
available = (images_path in output_zip.namelist() or
|
|
|
|
radio_path in output_zip.namelist())
|
2018-01-18 02:57:49 +01:00
|
|
|
else:
|
2018-04-18 08:47:21 +02:00
|
|
|
images_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
|
|
|
|
radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
|
|
|
|
available = os.path.exists(images_path) or os.path.exists(radio_path)
|
|
|
|
|
|
|
|
assert available, "Failed to find " + img_name
|
2018-01-18 02:57:49 +01:00
|
|
|
|
|
|
|
|
|
|
|
def AddPackRadioImages(output_zip, images):
|
|
|
|
"""Copies images listed in META/pack_radioimages.txt from RADIO/ to IMAGES/.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
output_zip: The output zip file (needs to be already open), or None to
|
|
|
|
write images to OPTIONS.input_tmp/.
|
|
|
|
images: A list of image names.
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
AssertionError: If a listed image can't be found.
|
|
|
|
"""
|
|
|
|
for image in images:
|
|
|
|
img_name = image.strip()
|
|
|
|
_, ext = os.path.splitext(img_name)
|
|
|
|
if not ext:
|
|
|
|
img_name += ".img"
|
2018-01-17 21:14:43 +01:00
|
|
|
|
2018-01-18 02:57:49 +01:00
|
|
|
prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
|
|
|
|
if os.path.exists(prebuilt_path):
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("%s already exists, no need to overwrite...", img_name)
|
2018-01-18 02:57:49 +01:00
|
|
|
continue
|
|
|
|
|
|
|
|
img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
|
|
|
|
assert os.path.exists(img_radio_path), \
|
|
|
|
"Failed to find %s at %s" % (img_name, img_radio_path)
|
2018-01-17 21:14:43 +01:00
|
|
|
|
2018-01-18 02:57:49 +01:00
|
|
|
if output_zip:
|
2018-01-17 21:14:43 +01:00
|
|
|
common.ZipWrite(output_zip, img_radio_path, "IMAGES/" + img_name)
|
2018-01-18 02:57:49 +01:00
|
|
|
else:
|
|
|
|
shutil.copy(img_radio_path, prebuilt_path)
|
|
|
|
|
|
|
|
|
2018-08-30 22:11:47 +02:00
|
|
|
def AddSuperEmpty(output_zip):
|
|
|
|
"""Create a super_empty.img and store it in output_zip."""
|
|
|
|
|
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "super_empty.img")
|
2018-11-29 22:51:48 +01:00
|
|
|
build_super_image.BuildSuperImage(OPTIONS.info_dict, img.name)
|
2018-08-30 22:11:47 +02:00
|
|
|
img.Write()
|
|
|
|
|
|
|
|
|
2018-11-09 00:41:24 +01:00
|
|
|
def AddSuperSplit(output_zip):
|
|
|
|
"""Create split super_*.img and store it in output_zip."""
|
|
|
|
|
2018-11-29 22:51:48 +01:00
|
|
|
outdir = os.path.join(OPTIONS.input_tmp, "OTA")
|
2018-12-07 19:08:27 +01:00
|
|
|
built = build_super_image.BuildSuperImage(OPTIONS.input_tmp, outdir)
|
2018-11-09 00:41:24 +01:00
|
|
|
|
2018-12-07 19:08:27 +01:00
|
|
|
if built:
|
|
|
|
for dev in OPTIONS.info_dict['super_block_devices'].strip().split():
|
|
|
|
img = OutputFile(output_zip, OPTIONS.input_tmp, "OTA",
|
|
|
|
"super_" + dev + ".img")
|
|
|
|
img.Write()
|
2018-11-09 00:41:24 +01:00
|
|
|
|
|
|
|
|
2017-06-10 01:58:03 +02:00
|
|
|
def ReplaceUpdatedFiles(zip_filename, files_list):
|
2017-12-15 02:05:33 +01:00
|
|
|
"""Updates all the ZIP entries listed in files_list.
|
2017-05-26 02:38:53 +02:00
|
|
|
|
2018-09-15 01:24:41 +02:00
|
|
|
For now the list includes META/care_map.pb, and the related files under
|
2017-06-10 01:58:03 +02:00
|
|
|
SYSTEM/ after rebuilding recovery.
|
|
|
|
"""
|
2017-12-15 02:05:33 +01:00
|
|
|
common.ZipDelete(zip_filename, files_list)
|
2017-05-26 02:38:53 +02:00
|
|
|
output_zip = zipfile.ZipFile(zip_filename, "a",
|
|
|
|
compression=zipfile.ZIP_DEFLATED,
|
|
|
|
allowZip64=True)
|
2017-06-10 01:58:03 +02:00
|
|
|
for item in files_list:
|
2017-05-26 02:38:53 +02:00
|
|
|
file_path = os.path.join(OPTIONS.input_tmp, item)
|
|
|
|
assert os.path.exists(file_path)
|
|
|
|
common.ZipWrite(output_zip, file_path, arcname=item)
|
|
|
|
common.ZipClose(output_zip)
|
|
|
|
|
|
|
|
|
2020-09-15 18:53:44 +02:00
|
|
|
def HasPartition(partition_name):
|
|
|
|
"""Determines if the target files archive should build a given partition."""
|
|
|
|
|
|
|
|
return ((os.path.isdir(
|
|
|
|
os.path.join(OPTIONS.input_tmp, partition_name.upper())) and
|
2021-04-05 19:40:47 +02:00
|
|
|
OPTIONS.info_dict.get(
|
|
|
|
"building_{}_image".format(partition_name)) == "true") or
|
|
|
|
os.path.exists(
|
|
|
|
os.path.join(OPTIONS.input_tmp, "IMAGES",
|
|
|
|
"{}.img".format(partition_name))))
|
2020-09-15 18:53:44 +02:00
|
|
|
|
2021-01-19 21:30:46 +01:00
|
|
|
def AddApexInfo(output_zip):
|
2021-04-16 01:39:22 +02:00
|
|
|
apex_infos = GetApexInfoFromTargetFiles(OPTIONS.input_tmp, 'system')
|
2021-01-19 21:30:46 +01:00
|
|
|
apex_metadata_proto = ota_metadata_pb2.ApexMetadata()
|
|
|
|
apex_metadata_proto.apex_info.extend(apex_infos)
|
|
|
|
apex_info_bytes = apex_metadata_proto.SerializeToString()
|
|
|
|
|
|
|
|
output_file = os.path.join(OPTIONS.input_tmp, "META", "apex_info.pb")
|
|
|
|
with open(output_file, "wb") as ofile:
|
|
|
|
ofile.write(apex_info_bytes)
|
|
|
|
if output_zip:
|
|
|
|
arc_name = "META/apex_info.pb"
|
|
|
|
if arc_name in output_zip.namelist():
|
|
|
|
OPTIONS.replace_updated_files_list.append(arc_name)
|
|
|
|
else:
|
|
|
|
common.ZipWrite(output_zip, output_file, arc_name)
|
|
|
|
|
2020-09-15 18:53:44 +02:00
|
|
|
|
2014-07-31 20:06:30 +02:00
|
|
|
def AddImagesToTargetFiles(filename):
|
2017-11-20 20:56:43 +01:00
|
|
|
"""Creates and adds images (boot/recovery/system/...) to a target_files.zip.
|
|
|
|
|
|
|
|
It works with either a zip file (zip mode), or a directory that contains the
|
|
|
|
files to be packed into a target_files.zip (dir mode). The latter is used when
|
|
|
|
being called from build/make/core/Makefile.
|
|
|
|
|
|
|
|
The images will be created under IMAGES/ in the input target_files.zip.
|
|
|
|
|
|
|
|
Args:
|
2018-01-09 22:21:02 +01:00
|
|
|
filename: the target_files.zip, or the zip root directory.
|
2017-11-20 20:56:43 +01:00
|
|
|
"""
|
2017-03-06 04:51:56 +01:00
|
|
|
if os.path.isdir(filename):
|
|
|
|
OPTIONS.input_tmp = os.path.abspath(filename)
|
|
|
|
else:
|
2018-01-09 22:21:02 +01:00
|
|
|
OPTIONS.input_tmp = common.UnzipTemp(filename)
|
2014-07-31 20:06:30 +02:00
|
|
|
|
2014-11-14 06:41:08 +01:00
|
|
|
if not OPTIONS.add_missing:
|
2017-03-06 04:51:56 +01:00
|
|
|
if os.path.isdir(os.path.join(OPTIONS.input_tmp, "IMAGES")):
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.warning("target_files appears to already contain images.")
|
2017-03-06 04:51:56 +01:00
|
|
|
sys.exit(1)
|
2014-08-26 22:10:25 +02:00
|
|
|
|
2018-08-24 21:08:38 +02:00
|
|
|
OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.input_tmp, repacking=True)
|
2018-01-09 22:21:02 +01:00
|
|
|
|
|
|
|
has_recovery = OPTIONS.info_dict.get("no_recovery") != "true"
|
2019-04-22 20:09:57 +02:00
|
|
|
has_boot = OPTIONS.info_dict.get("no_boot") != "true"
|
2019-07-10 19:49:37 +02:00
|
|
|
has_vendor_boot = OPTIONS.info_dict.get("vendor_boot") == "true"
|
2018-01-09 22:21:02 +01:00
|
|
|
|
2020-09-15 18:53:44 +02:00
|
|
|
# {vendor,odm,product,system_ext,vendor_dlkm,odm_dlkm, system, system_other}.img
|
|
|
|
# can be built from source, or dropped into target_files.zip as a prebuilt blob.
|
|
|
|
has_vendor = HasPartition("vendor")
|
|
|
|
has_odm = HasPartition("odm")
|
|
|
|
has_vendor_dlkm = HasPartition("vendor_dlkm")
|
|
|
|
has_odm_dlkm = HasPartition("odm_dlkm")
|
|
|
|
has_product = HasPartition("product")
|
|
|
|
has_system_ext = HasPartition("system_ext")
|
|
|
|
has_system = HasPartition("system")
|
|
|
|
has_system_other = HasPartition("system_other")
|
2020-05-30 04:39:12 +02:00
|
|
|
has_userdata = OPTIONS.info_dict.get("building_userdata_image") == "true"
|
|
|
|
has_cache = OPTIONS.info_dict.get("building_cache_image") == "true"
|
2016-06-16 23:47:10 +02:00
|
|
|
|
2018-01-09 22:21:02 +01:00
|
|
|
# Set up the output destination. It writes to the given directory for dir
|
|
|
|
# mode; otherwise appends to the given ZIP.
|
|
|
|
if os.path.isdir(filename):
|
|
|
|
output_zip = None
|
|
|
|
else:
|
2017-03-06 04:51:56 +01:00
|
|
|
output_zip = zipfile.ZipFile(filename, "a",
|
|
|
|
compression=zipfile.ZIP_DEFLATED,
|
|
|
|
allowZip64=True)
|
2017-11-20 20:56:43 +01:00
|
|
|
|
|
|
|
# Always make input_tmp/IMAGES available, since we may stage boot / recovery
|
|
|
|
# images there even under zip mode. The directory will be cleaned up as part
|
|
|
|
# of OPTIONS.input_tmp.
|
|
|
|
images_dir = os.path.join(OPTIONS.input_tmp, "IMAGES")
|
|
|
|
if not os.path.isdir(images_dir):
|
|
|
|
os.makedirs(images_dir)
|
2014-08-26 22:10:25 +02:00
|
|
|
|
2017-07-12 02:27:55 +02:00
|
|
|
# A map between partition names and their paths, which could be used when
|
|
|
|
# generating AVB vbmeta image.
|
2019-10-08 05:48:48 +02:00
|
|
|
partitions = {}
|
2017-07-12 02:27:55 +02:00
|
|
|
|
2014-08-26 22:10:25 +02:00
|
|
|
def banner(s):
|
2019-06-25 00:33:41 +02:00
|
|
|
logger.info("\n\n++++ %s ++++\n\n", s)
|
2014-08-26 22:10:25 +02:00
|
|
|
|
2019-04-22 20:09:57 +02:00
|
|
|
boot_image = None
|
|
|
|
if has_boot:
|
|
|
|
banner("boot")
|
2020-04-09 03:27:00 +02:00
|
|
|
boot_images = OPTIONS.info_dict.get("boot_images")
|
|
|
|
if boot_images is None:
|
|
|
|
boot_images = "boot.img"
|
2021-04-05 19:40:47 +02:00
|
|
|
for index,b in enumerate(boot_images.split()):
|
2020-04-09 03:27:00 +02:00
|
|
|
# common.GetBootableImage() returns the image directly if present.
|
|
|
|
boot_image = common.GetBootableImage(
|
|
|
|
"IMAGES/" + b, b, OPTIONS.input_tmp, "BOOT")
|
|
|
|
# boot.img may be unavailable in some targets (e.g. aosp_arm64).
|
|
|
|
if boot_image:
|
|
|
|
boot_image_path = os.path.join(OPTIONS.input_tmp, "IMAGES", b)
|
2020-06-09 04:54:13 +02:00
|
|
|
# Although multiple boot images can be generated, include the image
|
|
|
|
# descriptor of only the first boot image in vbmeta
|
|
|
|
if index == 0:
|
2020-04-09 03:27:00 +02:00
|
|
|
partitions['boot'] = boot_image_path
|
|
|
|
if not os.path.exists(boot_image_path):
|
|
|
|
boot_image.WriteToDir(OPTIONS.input_tmp)
|
|
|
|
if output_zip:
|
|
|
|
boot_image.AddToZip(output_zip)
|
2014-08-26 22:10:25 +02:00
|
|
|
|
2019-07-10 19:49:37 +02:00
|
|
|
if has_vendor_boot:
|
|
|
|
banner("vendor_boot")
|
|
|
|
vendor_boot_image = common.GetVendorBootImage(
|
|
|
|
"IMAGES/vendor_boot.img", "vendor_boot.img", OPTIONS.input_tmp,
|
|
|
|
"VENDOR_BOOT")
|
|
|
|
if vendor_boot_image:
|
|
|
|
partitions['vendor_boot'] = os.path.join(OPTIONS.input_tmp, "IMAGES",
|
|
|
|
"vendor_boot.img")
|
|
|
|
if not os.path.exists(partitions['vendor_boot']):
|
|
|
|
vendor_boot_image.WriteToDir(OPTIONS.input_tmp)
|
|
|
|
if output_zip:
|
|
|
|
vendor_boot_image.AddToZip(output_zip)
|
|
|
|
|
2014-11-14 06:41:08 +01:00
|
|
|
recovery_image = None
|
2015-10-28 03:25:18 +01:00
|
|
|
if has_recovery:
|
|
|
|
banner("recovery")
|
2017-07-12 02:27:55 +02:00
|
|
|
recovery_image = common.GetBootableImage(
|
|
|
|
"IMAGES/recovery.img", "recovery.img", OPTIONS.input_tmp, "RECOVERY")
|
|
|
|
assert recovery_image, "Failed to create recovery.img."
|
2017-07-12 02:27:55 +02:00
|
|
|
partitions['recovery'] = os.path.join(
|
2017-07-12 02:27:55 +02:00
|
|
|
OPTIONS.input_tmp, "IMAGES", "recovery.img")
|
2017-07-12 02:27:55 +02:00
|
|
|
if not os.path.exists(partitions['recovery']):
|
2017-07-12 02:27:55 +02:00
|
|
|
recovery_image.WriteToDir(OPTIONS.input_tmp)
|
|
|
|
if output_zip:
|
|
|
|
recovery_image.AddToZip(output_zip)
|
2014-08-26 22:10:25 +02:00
|
|
|
|
2016-11-30 21:11:57 +01:00
|
|
|
banner("recovery (two-step image)")
|
|
|
|
# The special recovery.img for two-step package use.
|
|
|
|
recovery_two_step_image = common.GetBootableImage(
|
2019-07-26 08:11:41 +02:00
|
|
|
"OTA/recovery-two-step.img", "recovery-two-step.img",
|
2016-11-30 21:11:57 +01:00
|
|
|
OPTIONS.input_tmp, "RECOVERY", two_step_image=True)
|
2017-07-12 02:27:55 +02:00
|
|
|
assert recovery_two_step_image, "Failed to create recovery-two-step.img."
|
|
|
|
recovery_two_step_image_path = os.path.join(
|
2019-07-26 08:11:41 +02:00
|
|
|
OPTIONS.input_tmp, "OTA", "recovery-two-step.img")
|
2017-07-12 02:27:55 +02:00
|
|
|
if not os.path.exists(recovery_two_step_image_path):
|
|
|
|
recovery_two_step_image.WriteToDir(OPTIONS.input_tmp)
|
2017-03-06 04:51:56 +01:00
|
|
|
if output_zip:
|
|
|
|
recovery_two_step_image.AddToZip(output_zip)
|
2016-11-30 21:11:57 +01:00
|
|
|
|
2019-01-29 20:01:46 +01:00
|
|
|
if has_system:
|
|
|
|
banner("system")
|
|
|
|
partitions['system'] = AddSystem(
|
|
|
|
output_zip, recovery_img=recovery_image, boot_img=boot_image)
|
2017-07-12 02:27:55 +02:00
|
|
|
|
2014-08-26 22:10:25 +02:00
|
|
|
if has_vendor:
|
|
|
|
banner("vendor")
|
Moving recovery resources from /system to /vendor
This change is part of a topic that moves the recovery resources from the
system partition to the vendor partition, if it exists, or the vendor directory
on the system partition otherwise. The recovery resources are moving from the
system image to the vendor partition so that a single system image may be used
with either an A/B or a non-A/B vendor image. The topic removes a delta in the
system image that prevented such reuse in the past.
The recovery resources that are moving are involved with updating the recovery
partition after an update. In a non-A/B configuration, the system boots from
the recovery partition, updates the other partitions (system, vendor, etc.)
Then, the next time the system boots normally, a script updates the recovery
partition (if necessary). This script, the executables it invokes, and the data
files that it uses were previously on the system partition. The resources that
are moving include the following.
* install-recovery.sh
* applypatch
* recovery-resource.dat (if present)
* recovery-from-boot.p (if present)
This change includes the platform build system and release tools changes to
move the recovery resources from system to vendor (or /system/vendor). The
release tools need to know where to generate the recovery patch, and they
discover this from misc_info.txt variable board_uses_vendorimage, which the
platform build system generates.
We remove applypatch from PRODUCT_PACKAGES, but it is added back as a required
module in target/product/base_vendor.mk.
Several release tools rely on the misc_info.txt board_uses_vendorimage variable
to know how to generate and detect the recovery patch.
This change partially removes the --rebuild_recovery flag from the
merge_target_files.py script. The flag will be fully removed in a follow-on
change.
Bug: 68319577
Test: Ensure that recovery partition is updated correctly.
Change-Id: Ia4045bd67ffb3d899efa8d20dab4c4299b87ee5f
2019-09-18 02:06:47 +02:00
|
|
|
partitions['vendor'] = AddVendor(
|
|
|
|
output_zip, recovery_img=recovery_image, boot_img=boot_image)
|
2017-07-12 02:27:55 +02:00
|
|
|
|
2017-11-27 09:04:47 +01:00
|
|
|
if has_product:
|
|
|
|
banner("product")
|
|
|
|
partitions['product'] = AddProduct(output_zip)
|
|
|
|
|
2019-06-25 08:58:13 +02:00
|
|
|
if has_system_ext:
|
|
|
|
banner("system_ext")
|
|
|
|
partitions['system_ext'] = AddSystemExt(output_zip)
|
2018-05-29 14:09:01 +02:00
|
|
|
|
2017-11-14 16:42:30 +01:00
|
|
|
if has_odm:
|
|
|
|
banner("odm")
|
|
|
|
partitions['odm'] = AddOdm(output_zip)
|
|
|
|
|
2020-05-07 23:58:20 +02:00
|
|
|
if has_vendor_dlkm:
|
|
|
|
banner("vendor_dlkm")
|
|
|
|
partitions['vendor_dlkm'] = AddVendorDlkm(output_zip)
|
|
|
|
|
2020-07-16 01:52:59 +02:00
|
|
|
if has_odm_dlkm:
|
|
|
|
banner("odm_dlkm")
|
|
|
|
partitions['odm_dlkm'] = AddOdmDlkm(output_zip)
|
|
|
|
|
2016-06-16 23:47:10 +02:00
|
|
|
if has_system_other:
|
|
|
|
banner("system_other")
|
|
|
|
AddSystemOther(output_zip)
|
2017-07-12 02:27:55 +02:00
|
|
|
|
2021-01-19 21:30:46 +01:00
|
|
|
AddApexInfo(output_zip)
|
|
|
|
|
2016-08-04 04:21:52 +02:00
|
|
|
if not OPTIONS.is_signing:
|
|
|
|
banner("userdata")
|
|
|
|
AddUserdata(output_zip)
|
|
|
|
banner("cache")
|
|
|
|
AddCache(output_zip)
|
2017-05-31 06:46:33 +02:00
|
|
|
|
|
|
|
if OPTIONS.info_dict.get("board_bpt_enable") == "true":
|
2016-04-08 21:08:03 +02:00
|
|
|
banner("partition-table")
|
|
|
|
AddPartitionTable(output_zip)
|
2017-05-31 06:46:33 +02:00
|
|
|
|
|
|
|
if OPTIONS.info_dict.get("has_dtbo") == "true":
|
|
|
|
banner("dtbo")
|
2017-07-12 02:27:55 +02:00
|
|
|
partitions['dtbo'] = AddDtbo(output_zip)
|
2017-05-31 06:46:33 +02:00
|
|
|
|
2021-02-18 11:27:29 +01:00
|
|
|
if OPTIONS.info_dict.get("has_pvmfw") == "true":
|
|
|
|
banner("pvmfw")
|
|
|
|
partitions['pvmfw'] = AddPvmfw(output_zip)
|
|
|
|
|
Add options to sign the prebuilt custom images.
The custom images are any images owned by OEMs and SoCs, oem images
mounted on /oem is an example. The oem images can be used to customize
devices for different carriers, like wallpaper, ringtones, and
carrier-specific apks. OEMs can generate multiple oem images, like
oem.img, oem-carrier1.img and oem-carrier2.img and flash different oem
images for different carriers. The oem images are only one case, OEMs
and SoCs can add more custom images and mount them to custom partitions.
This change enables custom images to be vbmeta.img chained partitions.
The following configuration in BoardConfig.mk is an exmaple. It has two
custom partitions: oem and test. They will be signed by different keys.
And they will be chained by vbmeta.img. The custom images here are
prebuilts, which can be built by `make custom_images` separately.
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST should include all custom images
to apply AVB signing. And to every custom partition, one image whose
name is partition name must be added in its
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST.
BOARD_CUSTOMIMAGES_PARTITION_LIST := oem test
BOARD_AVB_OEM_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
BOARD_AVB_OEM_ALGORITHM := SHA256_RSA4096
BOARD_AVB_OEM_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_OEM_ROLLBACK_INDEX_LOCATION := 1
BOARD_AVB_OEM_PARTITION_SIZE := 5242880
BOARD_AVB_OEM_IMAGE_LIST := \
device/xxxx/yyyy/oem/oem.img \
device/xxxx/yyyy/oem/oem1.img
BOARD_AVB_TEST_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_TEST_ALGORITHM := SHA256_RSA2048
BOARD_AVB_TEST_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_TEST_ROLLBACK_INDEX_LOCATION := 2
BOARD_AVB_TEST_PARTITION_SIZE := 10485760
BOARD_AVB_TEST_IMAGE_LIST := \
device/xxxx/yyyy/test/test.img \
device/xxxx/yyyy/test/test1.img
To resign the custom images in the target zip file, the
avb_extra_custom_image_key, avb_extra_custom_image_algorithms and
avb_extra_custom_image_extra_args options are added to the
sign_target_files_apks tool too. The following test cases list some
examples about how to use them.
BUG: 154171021
Test: 1) "atest --host releasetools_test releasetools_py3_test -c"
2) Build images by 'make dist', sign and validate target files.
a) Test on dist w/ chained vbmeta_system and ome custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the oem images and vbmeta images in OUT and target zips by
avbtool.
b) Test on dist w/ chained vbmeta_system and oem and test custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
--avb_extra_custom_image_extra_args oem=--do_not_generate_fec \
--avb_extra_custom_image_key test=test_rsa4096.pem \
--avb_extra_custom_image_algorithm test=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Verify the oem, test images and vbmeta images in OUT and target zips
by avbtool.
c) Test on dist w/o chained partition.
sign_target_files_apks -d certs xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the vbmeta images in OUT and target zips by avbtool.
Change-Id: Ifccfee5e8909697eef6ccda0cc352fa16a9f6db6
2020-04-28 03:36:36 +02:00
|
|
|
# Custom images.
|
|
|
|
custom_partitions = OPTIONS.info_dict.get(
|
|
|
|
"avb_custom_images_partition_list", "").strip().split()
|
|
|
|
for partition_name in custom_partitions:
|
|
|
|
partition_name = partition_name.strip()
|
|
|
|
banner("custom images for " + partition_name)
|
|
|
|
partitions[partition_name] = AddCustomImages(output_zip, partition_name)
|
|
|
|
|
2017-05-26 12:30:04 +02:00
|
|
|
if OPTIONS.info_dict.get("avb_enable") == "true":
|
2018-08-21 06:09:07 +02:00
|
|
|
# vbmeta_partitions includes the partitions that should be included into
|
|
|
|
# top-level vbmeta.img, which are the ones that are not included in any
|
|
|
|
# chained VBMeta image plus the chained VBMeta images themselves.
|
Add options to sign the prebuilt custom images.
The custom images are any images owned by OEMs and SoCs, oem images
mounted on /oem is an example. The oem images can be used to customize
devices for different carriers, like wallpaper, ringtones, and
carrier-specific apks. OEMs can generate multiple oem images, like
oem.img, oem-carrier1.img and oem-carrier2.img and flash different oem
images for different carriers. The oem images are only one case, OEMs
and SoCs can add more custom images and mount them to custom partitions.
This change enables custom images to be vbmeta.img chained partitions.
The following configuration in BoardConfig.mk is an exmaple. It has two
custom partitions: oem and test. They will be signed by different keys.
And they will be chained by vbmeta.img. The custom images here are
prebuilts, which can be built by `make custom_images` separately.
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST should include all custom images
to apply AVB signing. And to every custom partition, one image whose
name is partition name must be added in its
BOARD_AVB_<CUSTOM_PARTITION>_IMAGE_LIST.
BOARD_CUSTOMIMAGES_PARTITION_LIST := oem test
BOARD_AVB_OEM_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
BOARD_AVB_OEM_ALGORITHM := SHA256_RSA4096
BOARD_AVB_OEM_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_OEM_ROLLBACK_INDEX_LOCATION := 1
BOARD_AVB_OEM_PARTITION_SIZE := 5242880
BOARD_AVB_OEM_IMAGE_LIST := \
device/xxxx/yyyy/oem/oem.img \
device/xxxx/yyyy/oem/oem1.img
BOARD_AVB_TEST_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_TEST_ALGORITHM := SHA256_RSA2048
BOARD_AVB_TEST_ADD_HASHTREE_FOOTER_ARGS :=
BOARD_AVB_TEST_ROLLBACK_INDEX_LOCATION := 2
BOARD_AVB_TEST_PARTITION_SIZE := 10485760
BOARD_AVB_TEST_IMAGE_LIST := \
device/xxxx/yyyy/test/test.img \
device/xxxx/yyyy/test/test1.img
To resign the custom images in the target zip file, the
avb_extra_custom_image_key, avb_extra_custom_image_algorithms and
avb_extra_custom_image_extra_args options are added to the
sign_target_files_apks tool too. The following test cases list some
examples about how to use them.
BUG: 154171021
Test: 1) "atest --host releasetools_test releasetools_py3_test -c"
2) Build images by 'make dist', sign and validate target files.
a) Test on dist w/ chained vbmeta_system and ome custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the oem images and vbmeta images in OUT and target zips by
avbtool.
b) Test on dist w/ chained vbmeta_system and oem and test custom images
sign_target_files_apks -d certs \
--avb_extra_custom_image_key oem=oem_rsa4096.pem \
--avb_extra_custom_image_algorithm oem=SHA256_RSA4096 \
--avb_extra_custom_image_extra_args oem=--do_not_generate_fec \
--avb_extra_custom_image_key test=test_rsa4096.pem \
--avb_extra_custom_image_algorithm test=SHA256_RSA4096 \
xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Verify the oem, test images and vbmeta images in OUT and target zips
by avbtool.
c) Test on dist w/o chained partition.
sign_target_files_apks -d certs xxx-target_xxx.zip signed.zip
validate_target_files.py signed.zip
Flash image and boot up.
Verify the vbmeta images in OUT and target zips by avbtool.
Change-Id: Ifccfee5e8909697eef6ccda0cc352fa16a9f6db6
2020-04-28 03:36:36 +02:00
|
|
|
# Currently custom_partitions are all chained to VBMeta image.
|
|
|
|
vbmeta_partitions = common.AVB_PARTITIONS[:] + tuple(custom_partitions)
|
2018-08-21 06:09:07 +02:00
|
|
|
|
2018-10-15 23:41:34 +02:00
|
|
|
vbmeta_system = OPTIONS.info_dict.get("avb_vbmeta_system", "").strip()
|
|
|
|
if vbmeta_system:
|
|
|
|
banner("vbmeta_system")
|
2018-10-23 00:08:02 +02:00
|
|
|
partitions["vbmeta_system"] = AddVBMeta(
|
2018-10-15 23:41:34 +02:00
|
|
|
output_zip, partitions, "vbmeta_system", vbmeta_system.split())
|
2018-08-21 06:09:07 +02:00
|
|
|
vbmeta_partitions = [
|
|
|
|
item for item in vbmeta_partitions
|
2018-10-15 23:41:34 +02:00
|
|
|
if item not in vbmeta_system.split()]
|
|
|
|
vbmeta_partitions.append("vbmeta_system")
|
2018-08-21 06:09:07 +02:00
|
|
|
|
|
|
|
vbmeta_vendor = OPTIONS.info_dict.get("avb_vbmeta_vendor", "").strip()
|
|
|
|
if vbmeta_vendor:
|
|
|
|
banner("vbmeta_vendor")
|
2018-10-23 00:08:02 +02:00
|
|
|
partitions["vbmeta_vendor"] = AddVBMeta(
|
2018-08-21 06:09:07 +02:00
|
|
|
output_zip, partitions, "vbmeta_vendor", vbmeta_vendor.split())
|
|
|
|
vbmeta_partitions = [
|
|
|
|
item for item in vbmeta_partitions
|
|
|
|
if item not in vbmeta_vendor.split()]
|
|
|
|
vbmeta_partitions.append("vbmeta_vendor")
|
|
|
|
|
2020-11-13 04:28:17 +01:00
|
|
|
if OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true":
|
|
|
|
banner("vbmeta")
|
|
|
|
AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
|
2014-08-26 22:10:25 +02:00
|
|
|
|
2019-06-28 20:00:05 +02:00
|
|
|
if OPTIONS.info_dict.get("use_dynamic_partitions") == "true":
|
2021-03-25 11:12:28 +01:00
|
|
|
if OPTIONS.info_dict.get("build_super_empty_partition") == "true":
|
|
|
|
banner("super_empty")
|
|
|
|
AddSuperEmpty(output_zip)
|
2018-08-30 22:11:47 +02:00
|
|
|
|
2019-06-28 20:00:05 +02:00
|
|
|
if OPTIONS.info_dict.get("build_super_partition") == "true":
|
2018-12-27 21:47:23 +01:00
|
|
|
if OPTIONS.info_dict.get(
|
2021-04-05 19:40:47 +02:00
|
|
|
"build_retrofit_dynamic_partitions_ota_package") == "true":
|
2018-11-09 00:41:24 +01:00
|
|
|
banner("super split images")
|
|
|
|
AddSuperSplit(output_zip)
|
|
|
|
|
2016-06-28 23:34:03 +02:00
|
|
|
banner("radio")
|
2018-01-18 02:57:49 +01:00
|
|
|
ab_partitions_txt = os.path.join(OPTIONS.input_tmp, "META",
|
|
|
|
"ab_partitions.txt")
|
|
|
|
if os.path.exists(ab_partitions_txt):
|
2019-06-25 00:33:41 +02:00
|
|
|
with open(ab_partitions_txt) as f:
|
2018-01-18 02:57:49 +01:00
|
|
|
ab_partitions = f.readlines()
|
2015-11-17 01:32:27 +01:00
|
|
|
|
2018-04-18 08:47:21 +02:00
|
|
|
# For devices using A/B update, make sure we have all the needed images
|
|
|
|
# ready under IMAGES/ or RADIO/.
|
|
|
|
CheckAbOtaImages(output_zip, ab_partitions)
|
2015-11-17 01:32:27 +01:00
|
|
|
|
2018-09-12 20:49:33 +02:00
|
|
|
# Generate care_map.pb for ab_partitions, then write this file to
|
|
|
|
# target_files package.
|
2021-03-22 20:38:38 +01:00
|
|
|
output_care_map = os.path.join(OPTIONS.input_tmp, "META", "care_map.pb")
|
|
|
|
AddCareMapForAbOta(output_zip if output_zip else output_care_map,
|
|
|
|
ab_partitions, partitions)
|
2016-03-08 01:31:19 +01:00
|
|
|
|
2017-06-17 00:30:23 +02:00
|
|
|
# Radio images that need to be packed into IMAGES/, and product-img.zip.
|
2018-01-18 02:57:49 +01:00
|
|
|
pack_radioimages_txt = os.path.join(
|
2017-06-17 00:30:23 +02:00
|
|
|
OPTIONS.input_tmp, "META", "pack_radioimages.txt")
|
2018-01-18 02:57:49 +01:00
|
|
|
if os.path.exists(pack_radioimages_txt):
|
2019-06-25 00:33:41 +02:00
|
|
|
with open(pack_radioimages_txt) as f:
|
2018-01-18 02:57:49 +01:00
|
|
|
AddPackRadioImages(output_zip, f.readlines())
|
2017-06-17 00:30:23 +02:00
|
|
|
|
2017-03-06 04:51:56 +01:00
|
|
|
if output_zip:
|
|
|
|
common.ZipClose(output_zip)
|
2017-06-10 01:58:03 +02:00
|
|
|
if OPTIONS.replace_updated_files_list:
|
|
|
|
ReplaceUpdatedFiles(output_zip.filename,
|
|
|
|
OPTIONS.replace_updated_files_list)
|
2017-05-26 02:38:53 +02:00
|
|
|
|
2014-07-31 20:06:30 +02:00
|
|
|
|
|
|
|
def main(argv):
|
2015-09-17 06:20:30 +02:00
|
|
|
def option_handler(o, a):
|
2014-11-14 06:41:08 +01:00
|
|
|
if o in ("-a", "--add_missing"):
|
|
|
|
OPTIONS.add_missing = True
|
|
|
|
elif o in ("-r", "--rebuild_recovery",):
|
|
|
|
OPTIONS.rebuild_recovery = True
|
2015-09-17 06:20:30 +02:00
|
|
|
elif o == "--replace_verity_private_key":
|
|
|
|
OPTIONS.replace_verity_private_key = (True, a)
|
|
|
|
elif o == "--replace_verity_public_key":
|
|
|
|
OPTIONS.replace_verity_public_key = (True, a)
|
2016-08-04 04:21:52 +02:00
|
|
|
elif o == "--is_signing":
|
|
|
|
OPTIONS.is_signing = True
|
2014-11-14 06:41:08 +01:00
|
|
|
else:
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
2015-03-24 03:13:21 +01:00
|
|
|
args = common.ParseOptions(
|
|
|
|
argv, __doc__, extra_opts="ar",
|
2015-09-17 06:20:30 +02:00
|
|
|
extra_long_opts=["add_missing", "rebuild_recovery",
|
|
|
|
"replace_verity_public_key=",
|
|
|
|
"replace_verity_private_key=",
|
2016-10-18 01:20:12 +02:00
|
|
|
"is_signing"],
|
2015-03-24 03:13:21 +01:00
|
|
|
extra_option_handler=option_handler)
|
2014-11-14 06:41:08 +01:00
|
|
|
|
2014-07-31 20:06:30 +02:00
|
|
|
if len(args) != 1:
|
|
|
|
common.Usage(__doc__)
|
|
|
|
sys.exit(1)
|
|
|
|
|
2018-10-12 19:30:39 +02:00
|
|
|
common.InitLogging()
|
|
|
|
|
2014-07-31 20:06:30 +02:00
|
|
|
AddImagesToTargetFiles(args[0])
|
2018-10-12 19:30:39 +02:00
|
|
|
logger.info("done.")
|
2014-07-31 20:06:30 +02:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
try:
|
|
|
|
common.CloseInheritedPipes()
|
|
|
|
main(sys.argv[1:])
|
2018-10-12 19:30:39 +02:00
|
|
|
except common.ExternalError:
|
|
|
|
logger.exception("\n ERROR:\n")
|
2014-07-31 20:06:30 +02:00
|
|
|
sys.exit(1)
|
2014-08-26 22:10:25 +02:00
|
|
|
finally:
|
|
|
|
common.Cleanup()
|