aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Song <denniscy@google.com>2024-01-16 09:44:09 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2024-01-16 09:44:09 +0000
commit4348857df08e8997634a82abab1e0e6b9b657420 (patch)
treea7a4c7ef8964a242ac969f6f3d3abf815a19a1c6
parente8b9dee2e4330e293983020ad1ac132693a22d81 (diff)
parent12bb05a136eadcce1d546be820bce4163c6892e2 (diff)
downloadtreble-4348857df08e8997634a82abab1e0e6b9b657420.tar.gz
Build vendor_boot-chd_debug.img to add CHD debug ramdisk am: 12bb05a136
Original change: https://android-review.googlesource.com/c/platform/tools/treble/+/2908078 Change-Id: Ib2abf7972313545cf92b9111dc847b72d37801d1 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--cuttlefish/build_chd_debug_ramdisk.py194
-rw-r--r--cuttlefish/build_chd_utils.py12
2 files changed, 204 insertions, 2 deletions
diff --git a/cuttlefish/build_chd_debug_ramdisk.py b/cuttlefish/build_chd_debug_ramdisk.py
new file mode 100644
index 0000000..da16a5d
--- /dev/null
+++ b/cuttlefish/build_chd_debug_ramdisk.py
@@ -0,0 +1,194 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2024 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.
+
+import argparse
+import os
+import shlex
+import subprocess
+import tempfile
+
+from build_chd_utils import copy_files, unzip_otatools
+
+"""Builds a vendor_boot-chd_debug.img.
+
+The vendor_boot-chd_debug.img is built by adding those CHD specific debugging
+files to a Cuttlefish's vendor_boot-debug.img, using a new ramdisk fragment.
+
+Test command:
+python3 tools/treble/cuttlefish/build_chd_debug_ramdisk.py \
+ $ANDROID_PRODUCT_OUT/vendor_boot-debug.img \
+ -o $ANDROID_PRODUCT_OUT/vendor_boot-chd_debug.img \
+ --otatools_zip $ANDROID_PRODUCT_OUT/otatools.zip \
+ --add_file chd_debug.prop:adb_debug.prop
+"""
+
+# The value of ramdisk type needs to be synchronized with
+# `system/tools/mkbootimg/mkbootimg.py`. We choose `_PLATFORM` here because the
+# CHD debug ramdisk will be used in normal boot (not for _RECOVERY or _DLKM).
+_VENDOR_RAMDISK_TYPE_PLATFORM = '1'
+
+
+def _parse_args():
+ """Parse the arguments for building the chd debug ramdisk.
+
+ Returns:
+ An object of argparse.Namespace.
+ """
+ parser = argparse.ArgumentParser()
+ parser.add_argument('input_img',
+ help='The input Cuttlefish vendor boot debug image.')
+ parser.add_argument('--output_img', '-o', required=True,
+ help='The output CHD vendor boot debug image.')
+ parser.add_argument('--otatools_zip', required=True,
+ help='Path to the otatools.zip.')
+ parser.add_argument('--add_file', action='append', default=[],
+ help='The file to be added to the CHD debug ramdisk. '
+ 'The format is <src path>:<dst path>.')
+ return parser.parse_args()
+
+
+class BootImage:
+ """A class that supports adding a new ramdisk fragment into a boot.img."""
+
+ def __init__(self, bootimg, bootimg_dir, unpack_bootimg_bin, mkbootfs_bin,
+ mkbootimg_bin, lz4_bin):
+ self._bootimg = bootimg
+ self._bootimg_dir = bootimg_dir
+ self._unpack_bootimg_bin = unpack_bootimg_bin
+ self._mkbootfs_bin = mkbootfs_bin
+ self._mkbootimg_bin = mkbootimg_bin
+ self._lz4_bin = lz4_bin
+ self._bootimg_args = []
+
+ def unpack(self):
+ """Unpacks the boot.img and capture the bootimg arguments."""
+ if self._bootimg_args:
+ raise RuntimeError(f'cannot unpack {self._bootimg} twice')
+ print(f'Unpacking {self._bootimg} to {self._bootimg_dir}')
+ unpack_cmd = [
+ self._unpack_bootimg_bin,
+ '--boot_img', self._bootimg,
+ '--out', self._bootimg_dir,
+ '--format', 'mkbootimg'
+ ]
+ unpack_result = subprocess.run(unpack_cmd, check=True,
+ capture_output=True, encoding='utf-8')
+ self._bootimg_args = shlex.split(unpack_result.stdout)
+
+ def add_ramdisk(self, ramdisk_root):
+ """Adds a new ramdisk fragment and update the bootimg arguments."""
+ # Name the new ramdisk using the smallest unused index.
+ ramdisk_files = [file for file in os.listdir(self._bootimg_dir)
+ if file.startswith('vendor_ramdisk')]
+ new_ramdisk_name = f'vendor_ramdisk{len(ramdisk_files):02d}'
+ new_ramdisk_file = os.path.join(self._bootimg_dir, new_ramdisk_name)
+ if os.path.exists(new_ramdisk_file):
+ raise FileExistsError(f'{new_ramdisk_file} already exists')
+
+ print(f'Adding a new vendor ramdisk fragment {new_ramdisk_file}')
+ mkbootfs_cmd = [self._mkbootfs_bin, ramdisk_root]
+ mkbootfs_result = subprocess.run(mkbootfs_cmd, check=True,
+ capture_output=True)
+
+ compress_cmd = [self._lz4_bin, '-l', '-12', '--favor-decSpeed']
+ with open(new_ramdisk_file, 'w') as o:
+ subprocess.run(compress_cmd, check=True,
+ input=mkbootfs_result.stdout, stdout=o)
+
+ # Update the bootimg arguments to include the new ramdisk file.
+ self._bootimg_args.extend([
+ '--ramdisk_type', _VENDOR_RAMDISK_TYPE_PLATFORM,
+ '--ramdisk_name', 'chd',
+ '--vendor_ramdisk_fragment', new_ramdisk_file
+ ])
+
+ def pack(self, output_img):
+ """Packs the boot.img."""
+ print(f'Packing {output_img} with args: {self._bootimg_args}')
+ mkbootimg_cmd = [
+ self._mkbootimg_bin, '--vendor_boot', output_img
+ ] + self._bootimg_args
+ subprocess.check_call(mkbootimg_cmd)
+
+
+def _prepare_env(otatools_dir):
+ """Get the executable path of the required otatools.
+
+ We need `unpack_bootimg`, `mkbootfs`, `mkbootimg` and `lz4` for building CHD
+ debug ramdisk. This function returns the path to the above tools in order.
+
+ Args:
+ otatools_dir: The path to the otatools directory.
+
+ Raises:
+ FileNotFoundError if any required otatool does not exist.
+ """
+ tools_path = []
+ for tool_name in ['unpack_bootimg', 'mkbootfs', 'mkbootimg', 'lz4']:
+ tool_path = os.path.join(otatools_dir, 'bin', tool_name)
+ if not os.path.exists(tool_path):
+ raise FileNotFoundError(f'otatool {tool_path} does not exist')
+ tools_path.append(tool_path)
+ return tools_path
+
+
+def add_debug_ramdisk_files(input_image, files_to_add, otatools_dir, temp_dir,
+ output_image):
+ """Add files to a vendor boot debug image.
+
+ This function creates a new ramdisk fragment, add this fragment into the
+ input vendor boot debug image, and generate an output image.
+
+ Args:
+ input_image: The path to the input vendor boot debug image.
+ files_to_add: A list of files to be added in the debug ramdisk, where a
+ pair defines the src and dst path of each file.
+ otatools_dir: The path to the otatools directory.
+ temp_dir: The path to the temporary directory for ramdisk filesystem.
+ output_img: The path to the output vendor boot debug image.
+
+ Raises:
+ FileExistsError if having duplicated ramdisk fragments.
+ FileNotFoundError if any required otatool does not exist.
+ """
+ print(f'Adding {files_to_add} to {input_image}')
+ ramdisk_root = os.path.join(temp_dir, 'ramdisk_root')
+ os.mkdir(ramdisk_root)
+ copy_files(files_to_add, ramdisk_root)
+
+ bootimg_dir = os.path.join(temp_dir, 'bootimg')
+ unpack_bootimg, mkbootfs, mkbootimg, lz4 = _prepare_env(otatools_dir)
+ bootimg = BootImage(input_image, bootimg_dir, unpack_bootimg, mkbootfs,
+ mkbootimg, lz4)
+ bootimg.unpack()
+ bootimg.add_ramdisk(ramdisk_root)
+ bootimg.pack(output_image)
+
+
+def main(temp_dir):
+ args = _parse_args()
+ otatools_dir = os.path.join(temp_dir, 'otatools')
+ unzip_otatools(args.otatools_zip, otatools_dir, [
+ 'bin/unpack_bootimg', 'bin/mkbootfs', 'bin/mkbootimg', 'bin/lz4',
+ 'lib64/*'
+ ])
+ add_debug_ramdisk_files(args.input_img, args.add_file, otatools_dir,
+ temp_dir, args.output_img)
+
+
+if __name__ == '__main__':
+ with tempfile.TemporaryDirectory() as temp_dir:
+ main(temp_dir)
diff --git a/cuttlefish/build_chd_utils.py b/cuttlefish/build_chd_utils.py
index 39f0352..47c70e7 100644
--- a/cuttlefish/build_chd_utils.py
+++ b/cuttlefish/build_chd_utils.py
@@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations under
# the License.
+import fnmatch
import glob
import os
import shutil
@@ -22,15 +23,22 @@ import tempfile
import zipfile
-def unzip_otatools(otatools_zip_path, output_dir):
+def unzip_otatools(otatools_zip_path, output_dir, patterns=None):
"""Unzip otatools to a directory and set the permissions for execution.
Args:
otatools_zip_path: The path to otatools zip archive.
output_dir: The root directory of the unzip output.
+ patterns: If provided, only extract files matching any of these patterns
+ from the otatools zip archive; otherwise, extract all files.
"""
with zipfile.ZipFile(otatools_zip_path, 'r') as zf:
- zf.extractall(path=output_dir)
+ if patterns is None:
+ zf.extractall(path=output_dir)
+ else:
+ for file in zf.namelist():
+ if any(fnmatch.fnmatch(file, p) for p in patterns):
+ zf.extract(file, output_dir)
for f in glob.glob(os.path.join(output_dir, 'bin', '*')):
os.chmod(f, 0o777)