Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 4088f38

Browse files
committed
Add script for mixing shared system images with a super image
Bug: 289369510 Test: ./development/gsi/repack_super_image/mix_ssi_with_device_image.py \ --device-image-files aosp_cf_arm64_phone-img.zip \ --ssi-files ssi-target_files.zip \ --misc-info misc_info.txt \ --ota-tools otatools.zip \ --output-dir output_dir Change-Id: I0c16f2e13036a5d66e96309c268214231d56d90b
1 parent e1e7e3f commit 4088f38

File tree

2 files changed

+180
-3
lines changed

2 files changed

+180
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright 2023 - The Android Open Source Project
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
"""Mix shared system images with a super image and disable vbmeta.
18+
19+
Example:
20+
./development/gsi/repack_super_image/mix_ssi_with_device_image.py \
21+
--device-image-files aosp_cf_arm64_phone-img.zip \
22+
--ssi-files ssi-target_files.zip \
23+
--misc-info misc_info.txt \
24+
--ota-tools otatools.zip \
25+
--output-dir ./output
26+
27+
or
28+
29+
ANDROID_PRODUCT_OUT=out/target/product/vsoc_arm64 \
30+
ANDROID_HOST_OUT=out/host/linux-x86/ \
31+
./development/gsi/repack_super_image/mix_ssi_with_device_image.py \
32+
--ssi-files out/target/product/ssi/IMAGES/ \
33+
--output-dir ./output
34+
"""
35+
36+
import argparse
37+
import os
38+
import shutil
39+
import subprocess
40+
import tempfile
41+
import zipfile
42+
43+
import repack_super_image
44+
45+
46+
SSI_PARTITIONS = ["system", "system_ext", "product"]
47+
48+
49+
def add_arguments(parser):
50+
parser.add_argument("--device-image-files",
51+
default=os.getenv("ANDROID_PRODUCT_OUT"),
52+
help="The path to the img zip or directory containing "
53+
"device images to be mixed with the given SSI. "
54+
"Caution: If this is a directory, super.img and "
55+
"vbmeta.img under this directory will be modified. "
56+
"Default: $ANDROID_PRODUCT_OUT")
57+
parser.add_argument("--ssi-files", required=True,
58+
help="The path to the target_files zip or directory "
59+
"containing shared system images for mixing.")
60+
parser.add_argument("--ota-tools",
61+
default=os.getenv("ANDROID_HOST_OUT"),
62+
help="The path to the device OTA tools zip or directory "
63+
"for mixing images. "
64+
"Default: $ANDROID_HOST_OUT")
65+
parser.add_argument("--misc-info",
66+
help="The device misc_info.txt for mixing images. "
67+
"Default: {args.device_image_files}/misc_info.txt.")
68+
parser.add_argument("--output-dir",
69+
help="The output directory for the mixed image. "
70+
"Default: {args.device_image_files}.")
71+
72+
73+
def unzip_ssi_images(ssi_target_files, output_dir):
74+
"""Unzip shared system images from the target files zipfile."""
75+
if not os.path.exists(ssi_target_files):
76+
raise FileNotFoundError(f"{ssi_target_files} does not exist.")
77+
with zipfile.ZipFile(ssi_target_files) as ssi_zip:
78+
for part_img in SSI_PARTITIONS:
79+
try:
80+
ssi_zip.extract(f"IMAGES/{part_img}.img", output_dir)
81+
except KeyError:
82+
pass
83+
return os.path.join(output_dir, "IMAGES")
84+
85+
86+
def unzip_super_images(device_img_artifact, output_dir):
87+
"""Unzip super.img from the device image artifact zipfile."""
88+
if not os.path.exists(device_img_artifact):
89+
raise FileNotFoundError(f"{device_img_artifact} does not exist.")
90+
with zipfile.ZipFile(device_img_artifact) as device_img_zip:
91+
device_img_zip.extract("super.img", output_dir)
92+
return os.path.join(output_dir, "super.img")
93+
94+
95+
def collect_ssi(ssi_dir):
96+
"""Collect system, system_ext and product images for mixing."""
97+
ssi_imgs = dict()
98+
for part_img in SSI_PARTITIONS:
99+
img_path = os.path.join(ssi_dir, f"{part_img}.img")
100+
if os.path.exists(img_path):
101+
ssi_imgs[part_img] = img_path
102+
else:
103+
# system.img is mandatory, while other images are optional in SSI
104+
if part_img == "system":
105+
raise FileNotFoundError(f"{img_path} does not exist.")
106+
else:
107+
print(f"No {part_img}.img")
108+
ssi_imgs[part_img] = ""
109+
return ssi_imgs
110+
111+
112+
def main():
113+
parser = argparse.ArgumentParser()
114+
add_arguments(parser)
115+
args = parser.parse_args()
116+
117+
if not args.device_image_files:
118+
raise ValueError("device image path is not set.")
119+
120+
output_dir = args.output_dir if args.output_dir else args.device_image_files
121+
if not os.path.isdir(output_dir):
122+
raise ValueError(f"output directory {output_dir} is not valid.")
123+
print(f"Output directory {output_dir}")
124+
125+
temp_dirs = []
126+
try:
127+
if os.path.isdir(args.ssi_files):
128+
ssi_dir = args.ssi_files
129+
else:
130+
temp_dir = tempfile.mkdtemp(prefix="ssi_")
131+
temp_dirs.append(temp_dir)
132+
ssi_dir = unzip_ssi_images(args.ssi_files, temp_dir)
133+
134+
device_misc_info = args.misc_info
135+
if os.path.isdir(args.device_image_files):
136+
device_image_dir = args.device_image_files
137+
super_img = os.path.join(device_image_dir, "super.img")
138+
if not device_misc_info:
139+
device_misc_info = os.path.join(device_image_dir, "misc_info.txt")
140+
else:
141+
super_img = unzip_super_images(args.device_image_files, output_dir)
142+
143+
if not device_misc_info or not os.path.exists(device_misc_info):
144+
raise FileNotFoundError(f"misc_info {device_misc_info} does not exist.")
145+
if not os.path.exists(super_img):
146+
raise FileNotFoundError(f"{super_img} does not exist.")
147+
148+
if not args.ota_tools or not os.path.exists(args.ota_tools):
149+
raise FileNotFoundError(f"otatools {args.ota_tools} does not exist.")
150+
if os.path.isdir(args.ota_tools):
151+
ota_tools_dir = args.ota_tools
152+
else:
153+
print("Unzip OTA tools.")
154+
ota_tools_dir = tempfile.mkdtemp(prefix="ota_tools")
155+
temp_dirs.append(ota_tools_dir)
156+
with zipfile.ZipFile(args.ota_tools) as ota_tools_zip:
157+
repack_super_image.unzip_ota_tools(ota_tools_zip, ota_tools_dir)
158+
159+
mix_part_imgs = collect_ssi(ssi_dir)
160+
output_super_img = os.path.join(output_dir, "super.img")
161+
repack_super_image.repack_super_image(ota_tools_dir, device_misc_info,
162+
super_img, mix_part_imgs,
163+
output_super_img)
164+
print(f"Created mixed super.img at {output_super_img}")
165+
166+
avbtool_path = os.path.join(ota_tools_dir, "bin", "avbtool")
167+
vbmeta_img = os.path.join(output_dir, "vbmeta.img")
168+
subprocess.check_call([avbtool_path, "make_vbmeta_image",
169+
"--flag", "2", "--output", vbmeta_img])
170+
print(f"Created vbmeta.img at {vbmeta_img}")
171+
finally:
172+
for temp_dir in temp_dirs:
173+
shutil.rmtree(temp_dir, ignore_errors=True)
174+
175+
176+
if __name__ == "__main__":
177+
main()

gsi/repack_super_image/repack_super_image.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def rewrite_misc_info(args_part_imgs, unpacked_part_imgs, lpmake_path,
118118

119119

120120
def repack_super_image(ota_tools_dir, misc_info_path, super_img_path,
121-
part_imgs):
121+
part_imgs, output_path):
122122
temp_dirs = []
123123
temp_files = []
124124

@@ -168,7 +168,7 @@ def repack_super_image(ota_tools_dir, misc_info_path, super_img_path,
168168
build_super_image_path = os.path.join(ota_tools_dir, BIN_DIR_NAME,
169169
"build_super_image")
170170
subprocess.check_call([build_super_image_path, misc_info_file_path,
171-
super_img_path])
171+
output_path])
172172
finally:
173173
for temp_dir in temp_dirs:
174174
shutil.rmtree(temp_dir, ignore_errors=True)
@@ -232,7 +232,7 @@ def main():
232232
ota_tools_dir = temp_ota_tools_dir
233233

234234
repack_super_image(ota_tools_dir, args.misc_info, args.super_img,
235-
args_part_imgs)
235+
args_part_imgs, args.super_img)
236236
finally:
237237
if temp_ota_tools_dir:
238238
shutil.rmtree(temp_ota_tools_dir)

0 commit comments

Comments
 (0)