blob: 23f4412ed08782fd39a0438d5e79dd70499dc875 [file] [log] [blame]
Doug Zongker3c84f562014-07-31 11:06:30 -07001#!/usr/bin/env python
2#
3# Copyright (C) 2014 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"""
18Given a target-files zipfile that does not contain images (ie, does
19not have an IMAGES/ top-level subdirectory), produce the images and
20add them to the zipfile.
21
Tianjie Xub48589a2016-08-03 19:21:52 -070022Usage: add_img_to_target_files [flag] target_files
23
24 -a (--add_missing)
25 Build and add missing images to "IMAGES/". If this option is
26 not specified, this script will simply exit when "IMAGES/"
27 directory exists in the target file.
28
29 -r (--rebuild_recovery)
30 Rebuild the recovery patch and write it to the system image. Only
Tao Bao4978fa92019-06-04 16:26:45 -070031 meaningful when system image needs to be rebuilt and there're separate
32 boot / recovery images.
Tianjie Xub48589a2016-08-03 19:21:52 -070033
34 --replace_verity_private_key
35 Replace the private key used for verity signing. (same as the option
36 in sign_target_files_apks)
37
38 --replace_verity_public_key
39 Replace the certificate (public key) used for verity verification. (same
40 as the option in sign_target_files_apks)
41
42 --is_signing
43 Skip building & adding the images for "userdata" and "cache" if we
44 are signing the target files.
Doug Zongker3c84f562014-07-31 11:06:30 -070045"""
46
Tao Bao89fbb0f2017-01-10 10:47:58 -080047from __future__ import print_function
48
Tao Bao822f5842015-09-30 16:01:14 -070049import datetime
Tao Bao32fcdab2018-10-12 10:30:39 -070050import logging
Doug Zongker3c84f562014-07-31 11:06:30 -070051import os
David Zeuthend995f4b2016-01-29 16:59:17 -050052import shlex
Ying Wang2a048392015-06-25 13:56:53 -070053import shutil
Rupert Shuttleworth72942742020-12-08 06:18:35 +000054import stat
Tao Bao6b9fef52017-12-01 16:13:22 -080055import sys
Tao Baod86e3112017-09-22 15:45:33 -070056import uuid
Kelvin Zhang834f5d42022-01-21 12:44:44 -080057import tempfile
Doug Zongker3c84f562014-07-31 11:06:30 -070058import zipfile
59
Doug Zongker3c84f562014-07-31 11:06:30 -070060import build_image
Yifan Hong055e6cf2018-11-29 13:51:48 -080061import build_super_image
Doug Zongker3c84f562014-07-31 11:06:30 -070062import common
Hongguang Chenf23364d2020-04-27 18:36:36 -070063import verity_utils
Kelvin Zhang5f0fcee2021-01-19 15:30:46 -050064import ota_metadata_pb2
65
Daniel Normane9af70a2021-04-15 16:39:22 -070066from apex_utils import GetApexInfoFromTargetFiles
Kelvin Zhang70876142022-02-09 16:05:29 -080067from common import AddCareMapForAbOta, ZipDelete
Doug Zongker3c84f562014-07-31 11:06:30 -070068
Tao Bao6b9fef52017-12-01 16:13:22 -080069if sys.hexversion < 0x02070000:
70 print("Python 2.7 or newer is required.", file=sys.stderr)
71 sys.exit(1)
72
Tao Bao32fcdab2018-10-12 10:30:39 -070073logger = logging.getLogger(__name__)
Doug Zongker3c84f562014-07-31 11:06:30 -070074
Tao Bao32fcdab2018-10-12 10:30:39 -070075OPTIONS = common.OPTIONS
Michael Runge2e0d8fc2014-11-13 21:41:08 -080076OPTIONS.add_missing = False
77OPTIONS.rebuild_recovery = False
Tianjie Xu9ac4cb02017-06-09 16:58:03 -070078OPTIONS.replace_updated_files_list = []
Tianjie Xub48589a2016-08-03 19:21:52 -070079OPTIONS.is_signing = False
Doug Zongker3c84f562014-07-31 11:06:30 -070080
Bryan Henrye6d547d2018-07-31 18:32:00 -070081# Use a fixed timestamp (01/01/2009 00:00:00 UTC) for files when packaging
82# images. (b/24377993, b/80600931)
Tao Baoe30a6a62018-08-27 10:57:19 -070083FIXED_FILE_TIMESTAMP = int((
84 datetime.datetime(2009, 1, 1, 0, 0, 0, 0, None) -
85 datetime.datetime.utcfromtimestamp(0)).total_seconds())
Tao Baoa2ff4c92018-01-17 12:14:43 -080086
Bowgo Tsaid624fa62017-11-14 23:42:30 +080087
Dan Willemsen2ee00d52017-03-05 19:51:56 -080088class OutputFile(object):
Tao Bao93e7ebe2019-01-13 23:23:01 -080089 """A helper class to write a generated file to the given dir or zip.
Dan Willemsen2ee00d52017-03-05 19:51:56 -080090
Tao Bao93e7ebe2019-01-13 23:23:01 -080091 When generating images, we want the outputs to go into the given zip file, or
92 the given dir.
93
94 Attributes:
95 name: The name of the output file, regardless of the final destination.
96 """
97
Kelvin Zhang5f0fcee2021-01-19 15:30:46 -050098 def __init__(self, output_zip, input_dir, *args):
Tao Bao93e7ebe2019-01-13 23:23:01 -080099 # We write the intermediate output file under the given input_dir, even if
100 # the final destination is a zip archive.
Kelvin Zhang5f0fcee2021-01-19 15:30:46 -0500101 self.name = os.path.join(input_dir, *args)
Tao Bao93e7ebe2019-01-13 23:23:01 -0800102 self._output_zip = output_zip
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800103 if self._output_zip:
Kelvin Zhang5f0fcee2021-01-19 15:30:46 -0500104 self._zip_name = os.path.join(*args)
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800105
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800106 def Write(self, compress_type=None):
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800107 if self._output_zip:
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800108 common.ZipWrite(self._output_zip, self.name,
109 self._zip_name, compress_type=compress_type)
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800110
Tao Baoe30a6a62018-08-27 10:57:19 -0700111
Tao Bao886d8832018-02-27 11:46:19 -0800112def AddSystem(output_zip, recovery_img=None, boot_img=None):
Doug Zongker3c84f562014-07-31 11:06:30 -0700113 """Turn the contents of SYSTEM into a system image and store it in
David Zeuthend995f4b2016-01-29 16:59:17 -0500114 output_zip. Returns the name of the system image file."""
Michael Runge2e0d8fc2014-11-13 21:41:08 -0800115
Tao Bao886d8832018-02-27 11:46:19 -0800116 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system.img")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800117 if os.path.exists(img.name):
Tao Bao32fcdab2018-10-12 10:30:39 -0700118 logger.info("system.img already exists; no need to rebuild...")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800119 return img.name
Michael Runge2e0d8fc2014-11-13 21:41:08 -0800120
121 def output_sink(fn, data):
Tao Baoa3705452019-06-24 15:33:41 -0700122 output_file = os.path.join(OPTIONS.input_tmp, "SYSTEM", fn)
123 with open(output_file, "wb") as ofile:
124 ofile.write(data)
Michael Runge2e0d8fc2014-11-13 21:41:08 -0800125
Daniel Normana4911da2019-03-15 14:36:21 -0700126 if output_zip:
127 arc_name = "SYSTEM/" + fn
128 if arc_name in output_zip.namelist():
129 OPTIONS.replace_updated_files_list.append(arc_name)
130 else:
Tao Baoa3705452019-06-24 15:33:41 -0700131 common.ZipWrite(output_zip, output_file, arc_name)
Tianjie Xu38af07f2017-05-25 17:38:53 -0700132
Bill Peckhame868aec2019-09-17 17:06:47 -0700133 board_uses_vendorimage = OPTIONS.info_dict.get(
134 "board_uses_vendorimage") == "true"
135
136 if (OPTIONS.rebuild_recovery and not board_uses_vendorimage and
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800137 recovery_img is not None and boot_img is not None):
Bill Peckhame868aec2019-09-17 17:06:47 -0700138 logger.info("Building new recovery patch on system at system/vendor")
Dan Albert8b72aef2015-03-23 19:13:21 -0700139 common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, recovery_img,
140 boot_img, info_dict=OPTIONS.info_dict)
Michael Runge2e0d8fc2014-11-13 21:41:08 -0800141
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800142 block_list = OutputFile(output_zip, OPTIONS.input_tmp,
143 "IMAGES", "system.map")
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800144 CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "system", img,
145 block_list=block_list)
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800146 return img.name
Doug Zongkerfc44a512014-08-26 13:10:25 -0700147
148
Tao Bao886d8832018-02-27 11:46:19 -0800149def AddSystemOther(output_zip):
Alex Light4e358ab2016-06-16 14:47:10 -0700150 """Turn the contents of SYSTEM_OTHER into a system_other image
151 and store it in output_zip."""
152
Tao Bao886d8832018-02-27 11:46:19 -0800153 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system_other.img")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800154 if os.path.exists(img.name):
Tao Bao32fcdab2018-10-12 10:30:39 -0700155 logger.info("system_other.img already exists; no need to rebuild...")
Alex Light4e358ab2016-06-16 14:47:10 -0700156 return
157
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800158 CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "system_other", img)
Alex Light4e358ab2016-06-16 14:47:10 -0700159
160
Bill Peckhame868aec2019-09-17 17:06:47 -0700161def AddVendor(output_zip, recovery_img=None, boot_img=None):
Doug Zongkerfc44a512014-08-26 13:10:25 -0700162 """Turn the contents of VENDOR into a vendor image and store in it
163 output_zip."""
Michael Runge2e0d8fc2014-11-13 21:41:08 -0800164
Tao Bao886d8832018-02-27 11:46:19 -0800165 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor.img")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800166 if os.path.exists(img.name):
Tao Bao32fcdab2018-10-12 10:30:39 -0700167 logger.info("vendor.img already exists; no need to rebuild...")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800168 return img.name
Michael Runge2e0d8fc2014-11-13 21:41:08 -0800169
Bill Peckhame868aec2019-09-17 17:06:47 -0700170 def output_sink(fn, data):
Iavor-Valentin Iftime756b5612022-02-09 15:56:14 +0000171 output_file = os.path.join(OPTIONS.input_tmp, "VENDOR", fn)
172 with open(output_file, "wb") as ofile:
173 ofile.write(data)
Bill Peckhame868aec2019-09-17 17:06:47 -0700174
175 if output_zip:
176 arc_name = "VENDOR/" + fn
177 if arc_name in output_zip.namelist():
178 OPTIONS.replace_updated_files_list.append(arc_name)
179 else:
Iavor-Valentin Iftime756b5612022-02-09 15:56:14 +0000180 common.ZipWrite(output_zip, output_file, arc_name)
Bill Peckhame868aec2019-09-17 17:06:47 -0700181
182 board_uses_vendorimage = OPTIONS.info_dict.get(
183 "board_uses_vendorimage") == "true"
184
185 if (OPTIONS.rebuild_recovery and board_uses_vendorimage and
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800186 recovery_img is not None and boot_img is not None):
Bill Peckhame868aec2019-09-17 17:06:47 -0700187 logger.info("Building new recovery patch on vendor")
188 common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, recovery_img,
189 boot_img, info_dict=OPTIONS.info_dict)
190
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800191 block_list = OutputFile(output_zip, OPTIONS.input_tmp,
192 "IMAGES", "vendor.map")
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800193 CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "vendor", img,
194 block_list=block_list)
195 return img.name
Doug Zongker3c84f562014-07-31 11:06:30 -0700196
Yueyao Zhu889ee5e2017-05-12 17:50:46 -0700197
Tao Bao886d8832018-02-27 11:46:19 -0800198def AddProduct(output_zip):
199 """Turn the contents of PRODUCT into a product image and store it in
200 output_zip."""
Jaekyun Seokb7735d82017-11-27 17:04:47 +0900201
Tao Bao886d8832018-02-27 11:46:19 -0800202 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "product.img")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800203 if os.path.exists(img.name):
Tao Bao32fcdab2018-10-12 10:30:39 -0700204 logger.info("product.img already exists; no need to rebuild...")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800205 return img.name
Jaekyun Seokb7735d82017-11-27 17:04:47 +0900206
Tao Bao886d8832018-02-27 11:46:19 -0800207 block_list = OutputFile(
208 output_zip, OPTIONS.input_tmp, "IMAGES", "product.map")
209 CreateImage(
210 OPTIONS.input_tmp, OPTIONS.info_dict, "product", img,
211 block_list=block_list)
Jaekyun Seokb7735d82017-11-27 17:04:47 +0900212 return img.name
213
214
Justin Yun6151e3f2019-06-25 15:58:13 +0900215def AddSystemExt(output_zip):
216 """Turn the contents of SYSTEM_EXT into a system_ext image and store it in
217 output_zip."""
Dario Freni5f681e12018-05-29 13:09:01 +0100218
219 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES",
Justin Yun6151e3f2019-06-25 15:58:13 +0900220 "system_ext.img")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800221 if os.path.exists(img.name):
Justin Yun6151e3f2019-06-25 15:58:13 +0900222 logger.info("system_ext.img already exists; no need to rebuild...")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800223 return img.name
Dario Freni5f681e12018-05-29 13:09:01 +0100224
225 block_list = OutputFile(
Justin Yun6151e3f2019-06-25 15:58:13 +0900226 output_zip, OPTIONS.input_tmp, "IMAGES", "system_ext.map")
Dario Freni5f681e12018-05-29 13:09:01 +0100227 CreateImage(
Justin Yun6151e3f2019-06-25 15:58:13 +0900228 OPTIONS.input_tmp, OPTIONS.info_dict, "system_ext", img,
Dario Freni5f681e12018-05-29 13:09:01 +0100229 block_list=block_list)
230 return img.name
231
232
Bowgo Tsaid624fa62017-11-14 23:42:30 +0800233def AddOdm(output_zip):
234 """Turn the contents of ODM into an odm image and store it in output_zip."""
235
236 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "odm.img")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800237 if os.path.exists(img.name):
Tao Bao32fcdab2018-10-12 10:30:39 -0700238 logger.info("odm.img already exists; no need to rebuild...")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800239 return img.name
Bowgo Tsaid624fa62017-11-14 23:42:30 +0800240
241 block_list = OutputFile(
242 output_zip, OPTIONS.input_tmp, "IMAGES", "odm.map")
243 CreateImage(
244 OPTIONS.input_tmp, OPTIONS.info_dict, "odm", img,
245 block_list=block_list)
246 return img.name
247
248
Yifan Hongcfb917a2020-05-07 14:58:20 -0700249def AddVendorDlkm(output_zip):
250 """Turn the contents of VENDOR_DLKM into an vendor_dlkm image and store it in output_zip."""
251
252 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor_dlkm.img")
253 if os.path.exists(img.name):
254 logger.info("vendor_dlkm.img already exists; no need to rebuild...")
255 return img.name
256
257 block_list = OutputFile(
258 output_zip, OPTIONS.input_tmp, "IMAGES", "vendor_dlkm.map")
259 CreateImage(
260 OPTIONS.input_tmp, OPTIONS.info_dict, "vendor_dlkm", img,
261 block_list=block_list)
262 return img.name
263
Tianjiebbde59f2021-05-03 21:18:56 -0700264
Yifan Hongf496f1b2020-07-15 16:52:59 -0700265def AddOdmDlkm(output_zip):
266 """Turn the contents of OdmDlkm into an odm_dlkm image and store it in output_zip."""
267
268 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "odm_dlkm.img")
269 if os.path.exists(img.name):
270 logger.info("odm_dlkm.img already exists; no need to rebuild...")
271 return img.name
272
273 block_list = OutputFile(
274 output_zip, OPTIONS.input_tmp, "IMAGES", "odm_dlkm.map")
275 CreateImage(
276 OPTIONS.input_tmp, OPTIONS.info_dict, "odm_dlkm", img,
277 block_list=block_list)
278 return img.name
279
Ramji Jiyani13a41372022-01-27 07:05:08 +0000280def AddSystemDlkm(output_zip):
281 """Turn the contents of SystemDlkm into an system_dlkm image and store it in output_zip."""
282
283 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system_dlkm.img")
284 if os.path.exists(img.name):
285 logger.info("system_dlkm.img already exists; no need to rebuild...")
286 return img.name
287
288 block_list = OutputFile(
289 output_zip, OPTIONS.input_tmp, "IMAGES", "system_dlkm.map")
290 CreateImage(
291 OPTIONS.input_tmp, OPTIONS.info_dict, "system_dlkm", img,
292 block_list=block_list)
293 return img.name
294
Yifan Hongcfb917a2020-05-07 14:58:20 -0700295
Tao Bao886d8832018-02-27 11:46:19 -0800296def AddDtbo(output_zip):
Tao Baoc633ed02017-05-30 21:46:33 -0700297 """Adds the DTBO image.
298
Tao Bao886d8832018-02-27 11:46:19 -0800299 Uses the image under IMAGES/ if it already exists. Otherwise looks for the
Tao Baoc633ed02017-05-30 21:46:33 -0700300 image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
301 """
Tao Bao886d8832018-02-27 11:46:19 -0800302 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "dtbo.img")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800303 if os.path.exists(img.name):
Tao Bao32fcdab2018-10-12 10:30:39 -0700304 logger.info("dtbo.img already exists; no need to rebuild...")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800305 return img.name
Tao Baoc633ed02017-05-30 21:46:33 -0700306
307 dtbo_prebuilt_path = os.path.join(
308 OPTIONS.input_tmp, "PREBUILT_IMAGES", "dtbo.img")
309 assert os.path.exists(dtbo_prebuilt_path)
310 shutil.copy(dtbo_prebuilt_path, img.name)
311
312 # AVB-sign the image as needed.
Bowgo Tsai3e599ea2017-05-26 18:30:04 +0800313 if OPTIONS.info_dict.get("avb_enable") == "true":
Rupert Shuttleworth72942742020-12-08 06:18:35 +0000314 # Signing requires +w
315 os.chmod(img.name, os.stat(img.name).st_mode | stat.S_IWUSR)
316
Tao Baof88e0ce2019-03-18 14:01:38 -0700317 avbtool = OPTIONS.info_dict["avb_avbtool"]
Tao Bao3ebfdde2017-05-23 23:06:55 -0700318 part_size = OPTIONS.info_dict["dtbo_size"]
Tao Baoc633ed02017-05-30 21:46:33 -0700319 # The AVB hash footer will be replaced if already present.
320 cmd = [avbtool, "add_hash_footer", "--image", img.name,
321 "--partition_size", str(part_size), "--partition_name", "dtbo"]
Bowgo Tsai3e599ea2017-05-26 18:30:04 +0800322 common.AppendAVBSigningArgs(cmd, "dtbo")
323 args = OPTIONS.info_dict.get("avb_dtbo_add_hash_footer_args")
Tao Baoc633ed02017-05-30 21:46:33 -0700324 if args and args.strip():
325 cmd.extend(shlex.split(args))
Tao Bao2764aee2018-11-21 11:02:48 -0800326 common.RunAndCheckOutput(cmd)
Tao Baoc633ed02017-05-30 21:46:33 -0700327
328 img.Write()
329 return img.name
330
Tianjiebbde59f2021-05-03 21:18:56 -0700331
Andrew Sculle077cf72021-02-18 10:27:29 +0000332def AddPvmfw(output_zip):
333 """Adds the pvmfw image.
334
335 Uses the image under IMAGES/ if it already exists. Otherwise looks for the
336 image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
337 """
338 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "pvmfw.img")
339 if os.path.exists(img.name):
340 logger.info("pvmfw.img already exists; no need to rebuild...")
341 return img.name
342
343 pvmfw_prebuilt_path = os.path.join(
344 OPTIONS.input_tmp, "PREBUILT_IMAGES", "pvmfw.img")
345 assert os.path.exists(pvmfw_prebuilt_path)
346 shutil.copy(pvmfw_prebuilt_path, img.name)
347
348 # AVB-sign the image as needed.
349 if OPTIONS.info_dict.get("avb_enable") == "true":
350 # Signing requires +w
351 os.chmod(img.name, os.stat(img.name).st_mode | stat.S_IWUSR)
352
353 avbtool = OPTIONS.info_dict["avb_avbtool"]
354 part_size = OPTIONS.info_dict["pvmfw_size"]
355 # The AVB hash footer will be replaced if already present.
356 cmd = [avbtool, "add_hash_footer", "--image", img.name,
357 "--partition_size", str(part_size), "--partition_name", "pvmfw"]
358 common.AppendAVBSigningArgs(cmd, "pvmfw")
359 args = OPTIONS.info_dict.get("avb_pvmfw_add_hash_footer_args")
360 if args and args.strip():
361 cmd.extend(shlex.split(args))
362 common.RunAndCheckOutput(cmd)
363
364 img.Write()
365 return img.name
366
Tianjiebbde59f2021-05-03 21:18:56 -0700367
Hongguang Chenf23364d2020-04-27 18:36:36 -0700368def AddCustomImages(output_zip, partition_name):
369 """Adds and signs custom images in IMAGES/.
370
371 Args:
372 output_zip: The output zip file (needs to be already open), or None to
373 write images to OPTIONS.input_tmp/.
374
375 Uses the image under IMAGES/ if it already exists. Otherwise looks for the
376 image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
377
378 Raises:
379 AssertionError: If image can't be found.
380 """
381
Hongguang Chenf23364d2020-04-27 18:36:36 -0700382 key_path = OPTIONS.info_dict.get("avb_{}_key_path".format(partition_name))
383 algorithm = OPTIONS.info_dict.get("avb_{}_algorithm".format(partition_name))
384 extra_args = OPTIONS.info_dict.get(
385 "avb_{}_add_hashtree_footer_args".format(partition_name))
386 partition_size = OPTIONS.info_dict.get(
387 "avb_{}_partition_size".format(partition_name))
388
389 builder = verity_utils.CreateCustomImageBuilder(
390 OPTIONS.info_dict, partition_name, partition_size,
391 key_path, algorithm, extra_args)
392
393 for img_name in OPTIONS.info_dict.get(
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800394 "avb_{}_image_list".format(partition_name)).split():
395 custom_image = OutputFile(
396 output_zip, OPTIONS.input_tmp, "IMAGES", img_name)
Hongguang Chenf23364d2020-04-27 18:36:36 -0700397 if os.path.exists(custom_image.name):
398 continue
399
400 custom_image_prebuilt_path = os.path.join(
401 OPTIONS.input_tmp, "PREBUILT_IMAGES", img_name)
402 assert os.path.exists(custom_image_prebuilt_path), \
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800403 "Failed to find %s at %s" % (img_name, custom_image_prebuilt_path)
Hongguang Chenf23364d2020-04-27 18:36:36 -0700404
405 shutil.copy(custom_image_prebuilt_path, custom_image.name)
406
407 if builder is not None:
408 builder.Build(custom_image.name)
409
410 custom_image.Write()
411
412 default = os.path.join(OPTIONS.input_tmp, "IMAGES", partition_name + ".img")
413 assert os.path.exists(default), \
414 "There should be one %s.img" % (partition_name)
415 return default
416
Doug Zongker3c84f562014-07-31 11:06:30 -0700417
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800418def CreateImage(input_dir, info_dict, what, output_file, block_list=None):
Tao Baoa3705452019-06-24 15:33:41 -0700419 logger.info("creating %s.img...", what)
Doug Zongker3c84f562014-07-31 11:06:30 -0700420
Doug Zongker3c84f562014-07-31 11:06:30 -0700421 image_props = build_image.ImagePropFromGlobalDict(info_dict, what)
Bryan Henrye6d547d2018-07-31 18:32:00 -0700422 image_props["timestamp"] = FIXED_FILE_TIMESTAMP
Tao Bao822f5842015-09-30 16:01:14 -0700423
Doug Zongker3c84f562014-07-31 11:06:30 -0700424 if what == "system":
425 fs_config_prefix = ""
426 else:
427 fs_config_prefix = what + "_"
428
429 fs_config = os.path.join(
430 input_dir, "META/" + fs_config_prefix + "filesystem_config.txt")
Dan Albert8b72aef2015-03-23 19:13:21 -0700431 if not os.path.exists(fs_config):
432 fs_config = None
Doug Zongker3c84f562014-07-31 11:06:30 -0700433
Ying Wanga2292c92015-03-24 19:07:40 -0700434 # Override values loaded from info_dict.
435 if fs_config:
436 image_props["fs_config"] = fs_config
Ying Wanga2292c92015-03-24 19:07:40 -0700437 if block_list:
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800438 image_props["block_list"] = block_list.name
Ying Wanga2292c92015-03-24 19:07:40 -0700439
Tao Baod86e3112017-09-22 15:45:33 -0700440 # Use repeatable ext4 FS UUID and hash_seed UUID (based on partition name and
Tianjiefdda51d2021-05-05 14:46:35 -0700441 # build fingerprint). Also use the legacy build id, because the vbmeta digest
442 # isn't available at this point.
443 build_info = common.BuildInfo(info_dict, use_legacy_id=True)
Yifan Hongc08cbf02020-09-15 19:07:39 +0000444 uuid_seed = what + "-" + build_info.GetPartitionFingerprint(what)
Tao Baod86e3112017-09-22 15:45:33 -0700445 image_props["uuid"] = str(uuid.uuid5(uuid.NAMESPACE_URL, uuid_seed))
446 hash_seed = "hash_seed-" + uuid_seed
447 image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))
448
Tao Baoc6bd70a2018-09-27 16:58:00 -0700449 build_image.BuildImage(
450 os.path.join(input_dir, what.upper()), image_props, output_file.name)
Doug Zongker3c84f562014-07-31 11:06:30 -0700451
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800452 output_file.Write()
453 if block_list:
454 block_list.Write()
455
Shashikant Baviskar16a73892019-02-07 10:57:21 +0900456 # Set the '_image_size' for given image size.
Tianjie Xuf1a13182017-01-19 17:39:30 -0800457 is_verity_partition = "verity_block_device" in image_props
hungweichen65ba3752022-08-17 10:14:01 +0000458 verity_supported = (image_props.get("avb_enable") == "true")
Tianjie Xu6b2e1552017-06-01 11:32:32 -0700459 is_avb_enable = image_props.get("avb_hashtree_enable") == "true"
460 if verity_supported and (is_verity_partition or is_avb_enable):
Tao Bao35f4ebc2018-09-27 15:31:11 -0700461 image_size = image_props.get("image_size")
462 if image_size:
Shashikant Baviskar16a73892019-02-07 10:57:21 +0900463 image_size_key = what + "_image_size"
464 info_dict[image_size_key] = int(image_size)
Tianjie Xuf1a13182017-01-19 17:39:30 -0800465
Yifan Hongc767f7c2018-11-08 15:41:24 -0800466 use_dynamic_size = (
Tao Bao2764aee2018-11-21 11:02:48 -0800467 info_dict.get("use_dynamic_partition_size") == "true" and
468 what in shlex.split(info_dict.get("dynamic_partition_list", "").strip()))
Yifan Hongc767f7c2018-11-08 15:41:24 -0800469 if use_dynamic_size:
470 info_dict.update(build_image.GlobalDictFromImageProp(image_props, what))
471
Doug Zongker3c84f562014-07-31 11:06:30 -0700472
Tao Bao886d8832018-02-27 11:46:19 -0800473def AddUserdata(output_zip):
Ying Wang2a048392015-06-25 13:56:53 -0700474 """Create a userdata image and store it in output_zip.
475
476 In most case we just create and store an empty userdata.img;
477 But the invoker can also request to create userdata.img with real
478 data from the target files, by setting "userdata_img_with_data=true"
479 in OPTIONS.info_dict.
480 """
Doug Zongker3c84f562014-07-31 11:06:30 -0700481
Tao Bao886d8832018-02-27 11:46:19 -0800482 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "userdata.img")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800483 if os.path.exists(img.name):
Tao Bao32fcdab2018-10-12 10:30:39 -0700484 logger.info("userdata.img already exists; no need to rebuild...")
Michael Runge2e0d8fc2014-11-13 21:41:08 -0800485 return
486
Elliott Hughes305b0882016-06-15 17:04:54 -0700487 # Skip userdata.img if no size.
Tao Bao2c15d9e2015-07-09 11:51:16 -0700488 image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, "data")
Elliott Hughes305b0882016-06-15 17:04:54 -0700489 if not image_props.get("partition_size"):
Doug Zongker3c84f562014-07-31 11:06:30 -0700490 return
491
Tao Bao32fcdab2018-10-12 10:30:39 -0700492 logger.info("creating userdata.img...")
Doug Zongker3c84f562014-07-31 11:06:30 -0700493
Bryan Henrye6d547d2018-07-31 18:32:00 -0700494 image_props["timestamp"] = FIXED_FILE_TIMESTAMP
Tao Bao822f5842015-09-30 16:01:14 -0700495
Tao Baofa863c82017-05-23 23:49:03 -0700496 if OPTIONS.info_dict.get("userdata_img_with_data") == "true":
497 user_dir = os.path.join(OPTIONS.input_tmp, "DATA")
Ying Wang2a048392015-06-25 13:56:53 -0700498 else:
Tao Bao1c830bf2017-12-25 10:43:47 -0800499 user_dir = common.MakeTempDir()
Ying Wang2a048392015-06-25 13:56:53 -0700500
Tao Baoc6bd70a2018-09-27 16:58:00 -0700501 build_image.BuildImage(user_dir, image_props, img.name)
Doug Zongker3c84f562014-07-31 11:06:30 -0700502
503 common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict)
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800504 # Always use compression for useradata image.
505 # As it's likely huge and consist of lots of 0s.
506 img.Write(zipfile.ZIP_DEFLATED)
Doug Zongker3c84f562014-07-31 11:06:30 -0700507
508
Tao Bao744c4c72018-08-20 21:09:07 -0700509def AddVBMeta(output_zip, partitions, name, needed_partitions):
510 """Creates a VBMeta image and stores it in output_zip.
511
512 It generates the requested VBMeta image. The requested image could be for
513 top-level or chained VBMeta image, which is determined based on the name.
Tao Baobf70c312017-07-11 17:27:55 -0700514
515 Args:
516 output_zip: The output zip file, which needs to be already open.
517 partitions: A dict that's keyed by partition names with image paths as
Hongguang Chenf23364d2020-04-27 18:36:36 -0700518 values. Only valid partition names are accepted, as partitions listed
519 in common.AVB_PARTITIONS and custom partitions listed in
520 OPTIONS.info_dict.get("avb_custom_images_partition_list")
David Anderson7709ab22018-10-15 14:41:34 -0700521 name: Name of the VBMeta partition, e.g. 'vbmeta', 'vbmeta_system'.
Tao Bao744c4c72018-08-20 21:09:07 -0700522 needed_partitions: Partitions whose descriptors should be included into the
523 generated VBMeta image.
524
Tao Bao71064202018-10-22 15:08:02 -0700525 Returns:
526 Path to the created image.
527
Tao Bao744c4c72018-08-20 21:09:07 -0700528 Raises:
529 AssertionError: On invalid input args.
Tao Baobf70c312017-07-11 17:27:55 -0700530 """
Tao Bao744c4c72018-08-20 21:09:07 -0700531 assert needed_partitions, "Needed partitions must be specified"
532
533 img = OutputFile(
534 output_zip, OPTIONS.input_tmp, "IMAGES", "{}.img".format(name))
Tao Bao93e7ebe2019-01-13 23:23:01 -0800535 if os.path.exists(img.name):
Tao Bao32fcdab2018-10-12 10:30:39 -0700536 logger.info("%s.img already exists; not rebuilding...", name)
Tao Bao93e7ebe2019-01-13 23:23:01 -0800537 return img.name
Tao Bao262bf3f2017-07-11 17:27:55 -0700538
Daniel Norman276f0622019-07-26 14:13:51 -0700539 common.BuildVBMeta(img.name, partitions, name, needed_partitions)
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800540 img.Write()
Tao Bao71064202018-10-22 15:08:02 -0700541 return img.name
David Zeuthen2ce63ed2016-09-15 13:43:54 -0400542
543
Tao Bao886d8832018-02-27 11:46:19 -0800544def AddPartitionTable(output_zip):
David Zeuthen25328622016-04-08 15:08:03 -0400545 """Create a partition table image and store it in output_zip."""
546
Tao Bao886d8832018-02-27 11:46:19 -0800547 img = OutputFile(
548 output_zip, OPTIONS.input_tmp, "IMAGES", "partition-table.img")
549 bpt = OutputFile(
Bryan Henryf130a232018-04-26 11:59:33 -0700550 output_zip, OPTIONS.input_tmp, "META", "partition-table.bpt")
David Zeuthen25328622016-04-08 15:08:03 -0400551
552 # use BPTTOOL from environ, or "bpttool" if empty or not set.
553 bpttool = os.getenv("BPTTOOL") or "bpttool"
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800554 cmd = [bpttool, "make_table", "--output_json", bpt.name,
555 "--output_gpt", img.name]
David Zeuthen25328622016-04-08 15:08:03 -0400556 input_files_str = OPTIONS.info_dict["board_bpt_input_files"]
jiajia tange5ddfcd2022-06-21 10:36:12 +0800557 input_files = input_files_str.split()
David Zeuthen25328622016-04-08 15:08:03 -0400558 for i in input_files:
559 cmd.extend(["--input", i])
560 disk_size = OPTIONS.info_dict.get("board_bpt_disk_size")
561 if disk_size:
562 cmd.extend(["--disk_size", disk_size])
563 args = OPTIONS.info_dict.get("board_bpt_make_table_args")
564 if args:
565 cmd.extend(shlex.split(args))
Tao Bao2764aee2018-11-21 11:02:48 -0800566 common.RunAndCheckOutput(cmd)
David Zeuthen25328622016-04-08 15:08:03 -0400567
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800568 img.Write()
569 bpt.Write()
David Zeuthen25328622016-04-08 15:08:03 -0400570
571
Tao Bao886d8832018-02-27 11:46:19 -0800572def AddCache(output_zip):
Doug Zongker3c84f562014-07-31 11:06:30 -0700573 """Create an empty cache image and store it in output_zip."""
574
Tao Bao886d8832018-02-27 11:46:19 -0800575 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "cache.img")
Tao Bao93e7ebe2019-01-13 23:23:01 -0800576 if os.path.exists(img.name):
Tao Bao32fcdab2018-10-12 10:30:39 -0700577 logger.info("cache.img already exists; no need to rebuild...")
Michael Runge2e0d8fc2014-11-13 21:41:08 -0800578 return
579
Tao Bao2c15d9e2015-07-09 11:51:16 -0700580 image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, "cache")
Doug Zongker3c84f562014-07-31 11:06:30 -0700581 # The build system has to explicitly request for cache.img.
582 if "fs_type" not in image_props:
583 return
584
Tao Bao32fcdab2018-10-12 10:30:39 -0700585 logger.info("creating cache.img...")
Doug Zongker3c84f562014-07-31 11:06:30 -0700586
Bryan Henrye6d547d2018-07-31 18:32:00 -0700587 image_props["timestamp"] = FIXED_FILE_TIMESTAMP
Tao Bao822f5842015-09-30 16:01:14 -0700588
Tao Bao1c830bf2017-12-25 10:43:47 -0800589 user_dir = common.MakeTempDir()
Tao Baoc6bd70a2018-09-27 16:58:00 -0700590 build_image.BuildImage(user_dir, image_props, img.name)
Doug Zongker3c84f562014-07-31 11:06:30 -0700591
592 common.CheckSize(img.name, "cache.img", OPTIONS.info_dict)
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800593 img.Write()
Doug Zongker3c84f562014-07-31 11:06:30 -0700594
595
Tao Bao5277d102018-04-17 23:47:21 -0700596def CheckAbOtaImages(output_zip, ab_partitions):
597 """Checks that all the listed A/B partitions have their images available.
Tao Baobea20ac2018-01-17 17:57:49 -0800598
Tao Bao5277d102018-04-17 23:47:21 -0700599 The images need to be available under IMAGES/ or RADIO/, with the former takes
600 a priority.
Tao Baobea20ac2018-01-17 17:57:49 -0800601
602 Args:
603 output_zip: The output zip file (needs to be already open), or None to
Tao Bao5277d102018-04-17 23:47:21 -0700604 find images in OPTIONS.input_tmp/.
Tao Baobea20ac2018-01-17 17:57:49 -0800605 ab_partitions: The list of A/B partitions.
606
607 Raises:
608 AssertionError: If it can't find an image.
609 """
610 for partition in ab_partitions:
Daniel Norman78554ea2021-09-14 10:29:38 -0700611 img_name = partition + ".img"
Tao Baobea20ac2018-01-17 17:57:49 -0800612
Tao Baoa2ff4c92018-01-17 12:14:43 -0800613 # Assert that the image is present under IMAGES/ now.
Tao Baobea20ac2018-01-17 17:57:49 -0800614 if output_zip:
615 # Zip spec says: All slashes MUST be forward slashes.
Tao Bao5277d102018-04-17 23:47:21 -0700616 images_path = "IMAGES/" + img_name
617 radio_path = "RADIO/" + img_name
618 available = (images_path in output_zip.namelist() or
619 radio_path in output_zip.namelist())
Tao Baobea20ac2018-01-17 17:57:49 -0800620 else:
Tao Bao5277d102018-04-17 23:47:21 -0700621 images_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
622 radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
623 available = os.path.exists(images_path) or os.path.exists(radio_path)
624
625 assert available, "Failed to find " + img_name
Tao Baobea20ac2018-01-17 17:57:49 -0800626
627
Tao Baobea20ac2018-01-17 17:57:49 -0800628def AddPackRadioImages(output_zip, images):
629 """Copies images listed in META/pack_radioimages.txt from RADIO/ to IMAGES/.
630
631 Args:
632 output_zip: The output zip file (needs to be already open), or None to
633 write images to OPTIONS.input_tmp/.
634 images: A list of image names.
635
636 Raises:
637 AssertionError: If a listed image can't be found.
638 """
639 for image in images:
640 img_name = image.strip()
641 _, ext = os.path.splitext(img_name)
642 if not ext:
643 img_name += ".img"
Tao Baoa2ff4c92018-01-17 12:14:43 -0800644
Tao Baobea20ac2018-01-17 17:57:49 -0800645 prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
646 if os.path.exists(prebuilt_path):
Tao Bao32fcdab2018-10-12 10:30:39 -0700647 logger.info("%s already exists, no need to overwrite...", img_name)
Tao Baobea20ac2018-01-17 17:57:49 -0800648 continue
649
650 img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
651 assert os.path.exists(img_radio_path), \
652 "Failed to find %s at %s" % (img_name, img_radio_path)
Tao Baoa2ff4c92018-01-17 12:14:43 -0800653
Tao Baobea20ac2018-01-17 17:57:49 -0800654 if output_zip:
Tao Baoa2ff4c92018-01-17 12:14:43 -0800655 common.ZipWrite(output_zip, img_radio_path, "IMAGES/" + img_name)
Tao Baobea20ac2018-01-17 17:57:49 -0800656 else:
657 shutil.copy(img_radio_path, prebuilt_path)
658
659
David Anderson1ef03e22018-08-30 13:11:47 -0700660def AddSuperEmpty(output_zip):
661 """Create a super_empty.img and store it in output_zip."""
662
663 img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "super_empty.img")
Yifan Hong055e6cf2018-11-29 13:51:48 -0800664 build_super_image.BuildSuperImage(OPTIONS.info_dict, img.name)
David Anderson1ef03e22018-08-30 13:11:47 -0700665 img.Write()
666
667
Yifan Hongc767f7c2018-11-08 15:41:24 -0800668def AddSuperSplit(output_zip):
669 """Create split super_*.img and store it in output_zip."""
670
Yifan Hong055e6cf2018-11-29 13:51:48 -0800671 outdir = os.path.join(OPTIONS.input_tmp, "OTA")
Yifan Honge98427a2018-12-07 10:08:27 -0800672 built = build_super_image.BuildSuperImage(OPTIONS.input_tmp, outdir)
Yifan Hongc767f7c2018-11-08 15:41:24 -0800673
Yifan Honge98427a2018-12-07 10:08:27 -0800674 if built:
675 for dev in OPTIONS.info_dict['super_block_devices'].strip().split():
676 img = OutputFile(output_zip, OPTIONS.input_tmp, "OTA",
677 "super_" + dev + ".img")
678 img.Write()
Yifan Hongc767f7c2018-11-08 15:41:24 -0800679
680
Tianjie Xu9ac4cb02017-06-09 16:58:03 -0700681def ReplaceUpdatedFiles(zip_filename, files_list):
Tao Bao89d7ab22017-12-14 17:05:33 -0800682 """Updates all the ZIP entries listed in files_list.
Tianjie Xu38af07f2017-05-25 17:38:53 -0700683
Tianjie Xu4c05f4a2018-09-14 16:24:41 -0700684 For now the list includes META/care_map.pb, and the related files under
Tianjie Xu9ac4cb02017-06-09 16:58:03 -0700685 SYSTEM/ after rebuilding recovery.
686 """
Tao Bao89d7ab22017-12-14 17:05:33 -0800687 common.ZipDelete(zip_filename, files_list)
Tianjie Xu38af07f2017-05-25 17:38:53 -0700688 output_zip = zipfile.ZipFile(zip_filename, "a",
689 compression=zipfile.ZIP_DEFLATED,
690 allowZip64=True)
Tianjie Xu9ac4cb02017-06-09 16:58:03 -0700691 for item in files_list:
Tianjie Xu38af07f2017-05-25 17:38:53 -0700692 file_path = os.path.join(OPTIONS.input_tmp, item)
693 assert os.path.exists(file_path)
694 common.ZipWrite(output_zip, file_path, arcname=item)
695 common.ZipClose(output_zip)
696
697
Chris Gross435b8fe2020-09-15 09:53:44 -0700698def HasPartition(partition_name):
699 """Determines if the target files archive should build a given partition."""
700
701 return ((os.path.isdir(
702 os.path.join(OPTIONS.input_tmp, partition_name.upper())) and
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800703 OPTIONS.info_dict.get(
704 "building_{}_image".format(partition_name)) == "true") or
705 os.path.exists(
706 os.path.join(OPTIONS.input_tmp, "IMAGES",
707 "{}.img".format(partition_name))))
Chris Gross435b8fe2020-09-15 09:53:44 -0700708
Tianjiea5fca032021-06-01 22:06:28 -0700709
Kelvin Zhang5f0fcee2021-01-19 15:30:46 -0500710def AddApexInfo(output_zip):
Tianjiea5fca032021-06-01 22:06:28 -0700711 apex_infos = GetApexInfoFromTargetFiles(OPTIONS.input_tmp, 'system',
712 compressed_only=False)
Kelvin Zhang5f0fcee2021-01-19 15:30:46 -0500713 apex_metadata_proto = ota_metadata_pb2.ApexMetadata()
714 apex_metadata_proto.apex_info.extend(apex_infos)
715 apex_info_bytes = apex_metadata_proto.SerializeToString()
716
717 output_file = os.path.join(OPTIONS.input_tmp, "META", "apex_info.pb")
718 with open(output_file, "wb") as ofile:
719 ofile.write(apex_info_bytes)
720 if output_zip:
721 arc_name = "META/apex_info.pb"
722 if arc_name in output_zip.namelist():
723 OPTIONS.replace_updated_files_list.append(arc_name)
724 else:
725 common.ZipWrite(output_zip, output_file, arc_name)
726
Chris Gross435b8fe2020-09-15 09:53:44 -0700727
Tianjiec3bf3d02021-07-14 15:56:37 -0700728def AddVbmetaDigest(output_zip):
729 """Write the vbmeta digest to the output dir and zipfile."""
730
731 # Calculate the vbmeta digest and put the result in to META/
732 boot_images = OPTIONS.info_dict.get("boot_images")
733 # Disable the digest calculation if the target_file is used as a container
Bowgo Tsaiaba5c9e2021-09-27 14:08:41 +0800734 # for boot images. A boot container might contain boot-5.4.img, boot-5.10.img
735 # etc., instead of just a boot.img and will fail in vbmeta digest calculation.
736 boot_container = boot_images and (
737 len(boot_images.split()) >= 2 or boot_images.split()[0] != 'boot.img')
Tianjiec3bf3d02021-07-14 15:56:37 -0700738 if (OPTIONS.info_dict.get("avb_enable") == "true" and not boot_container and
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800739 OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true"):
Tianjiec3bf3d02021-07-14 15:56:37 -0700740 avbtool = OPTIONS.info_dict["avb_avbtool"]
741 digest = verity_utils.CalculateVbmetaDigest(OPTIONS.input_tmp, avbtool)
742 vbmeta_digest_txt = os.path.join(OPTIONS.input_tmp, "META",
743 "vbmeta_digest.txt")
744 with open(vbmeta_digest_txt, 'w') as f:
745 f.write(digest)
746 # writes to the output zipfile
747 if output_zip:
748 arc_name = "META/vbmeta_digest.txt"
749 if arc_name in output_zip.namelist():
750 OPTIONS.replace_updated_files_list.append(arc_name)
751 else:
752 common.ZipWriteStr(output_zip, arc_name, digest)
753
754
Doug Zongker3c84f562014-07-31 11:06:30 -0700755def AddImagesToTargetFiles(filename):
Tao Baoae396d92017-11-20 11:56:43 -0800756 """Creates and adds images (boot/recovery/system/...) to a target_files.zip.
757
758 It works with either a zip file (zip mode), or a directory that contains the
759 files to be packed into a target_files.zip (dir mode). The latter is used when
760 being called from build/make/core/Makefile.
761
762 The images will be created under IMAGES/ in the input target_files.zip.
763
764 Args:
Tao Baodba59ee2018-01-09 13:21:02 -0800765 filename: the target_files.zip, or the zip root directory.
Tao Baoae396d92017-11-20 11:56:43 -0800766 """
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800767 if os.path.isdir(filename):
768 OPTIONS.input_tmp = os.path.abspath(filename)
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800769 else:
Tao Baodba59ee2018-01-09 13:21:02 -0800770 OPTIONS.input_tmp = common.UnzipTemp(filename)
Doug Zongkerfc44a512014-08-26 13:10:25 -0700771
Michael Runge2e0d8fc2014-11-13 21:41:08 -0800772 if not OPTIONS.add_missing:
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800773 if os.path.isdir(os.path.join(OPTIONS.input_tmp, "IMAGES")):
Tao Bao32fcdab2018-10-12 10:30:39 -0700774 logger.warning("target_files appears to already contain images.")
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800775 sys.exit(1)
Doug Zongkerfc44a512014-08-26 13:10:25 -0700776
Tao Bao410ad8b2018-08-24 12:08:38 -0700777 OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.input_tmp, repacking=True)
Tao Baodba59ee2018-01-09 13:21:02 -0800778
779 has_recovery = OPTIONS.info_dict.get("no_recovery") != "true"
Chris Grossa784ef12019-04-22 11:09:57 -0700780 has_boot = OPTIONS.info_dict.get("no_boot") != "true"
Devin Mooreafdd7c72021-12-13 22:04:08 +0000781 has_init_boot = OPTIONS.info_dict.get("init_boot") == "true"
Steve Mucklee1b10862019-07-10 10:49:37 -0700782 has_vendor_boot = OPTIONS.info_dict.get("vendor_boot") == "true"
Lucas Weif57333f2022-02-24 10:30:15 +0800783 has_vendor_kernel_boot = OPTIONS.info_dict.get("vendor_kernel_boot") == "true"
Tao Baodba59ee2018-01-09 13:21:02 -0800784
Ramji Jiyani13a41372022-01-27 07:05:08 +0000785 # {vendor,odm,product,system_ext,vendor_dlkm,odm_dlkm, system_dlkm, system, system_other}.img
Chris Gross435b8fe2020-09-15 09:53:44 -0700786 # can be built from source, or dropped into target_files.zip as a prebuilt blob.
787 has_vendor = HasPartition("vendor")
788 has_odm = HasPartition("odm")
789 has_vendor_dlkm = HasPartition("vendor_dlkm")
790 has_odm_dlkm = HasPartition("odm_dlkm")
Ramji Jiyani13a41372022-01-27 07:05:08 +0000791 has_system_dlkm = HasPartition("system_dlkm")
Chris Gross435b8fe2020-09-15 09:53:44 -0700792 has_product = HasPartition("product")
793 has_system_ext = HasPartition("system_ext")
794 has_system = HasPartition("system")
795 has_system_other = HasPartition("system_other")
Chris Gross203191b2020-05-30 02:39:12 +0000796 has_userdata = OPTIONS.info_dict.get("building_userdata_image") == "true"
797 has_cache = OPTIONS.info_dict.get("building_cache_image") == "true"
Doug Zongker3c84f562014-07-31 11:06:30 -0700798
Tao Baodba59ee2018-01-09 13:21:02 -0800799 # Set up the output destination. It writes to the given directory for dir
800 # mode; otherwise appends to the given ZIP.
801 if os.path.isdir(filename):
802 output_zip = None
803 else:
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800804 output_zip = zipfile.ZipFile(filename, "a",
805 compression=zipfile.ZIP_DEFLATED,
806 allowZip64=True)
Tao Baoae396d92017-11-20 11:56:43 -0800807
808 # Always make input_tmp/IMAGES available, since we may stage boot / recovery
809 # images there even under zip mode. The directory will be cleaned up as part
810 # of OPTIONS.input_tmp.
811 images_dir = os.path.join(OPTIONS.input_tmp, "IMAGES")
812 if not os.path.isdir(images_dir):
813 os.makedirs(images_dir)
Doug Zongker3c84f562014-07-31 11:06:30 -0700814
Tao Baobf70c312017-07-11 17:27:55 -0700815 # A map between partition names and their paths, which could be used when
816 # generating AVB vbmeta image.
Tao Bao3ed35d32019-10-07 20:48:48 -0700817 partitions = {}
Tao Baobf70c312017-07-11 17:27:55 -0700818
Doug Zongkerfc44a512014-08-26 13:10:25 -0700819 def banner(s):
Tao Baoa3705452019-06-24 15:33:41 -0700820 logger.info("\n\n++++ %s ++++\n\n", s)
Doug Zongker3c84f562014-07-31 11:06:30 -0700821
Chris Grossa784ef12019-04-22 11:09:57 -0700822 boot_image = None
Greg Kaisere086f722021-09-14 19:32:27 +0000823 if has_boot:
Chris Grossa784ef12019-04-22 11:09:57 -0700824 banner("boot")
Steve Muckle9793cf62020-04-08 18:27:00 -0700825 boot_images = OPTIONS.info_dict.get("boot_images")
826 if boot_images is None:
827 boot_images = "boot.img"
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800828 for index, b in enumerate(boot_images.split()):
Steve Muckle9793cf62020-04-08 18:27:00 -0700829 # common.GetBootableImage() returns the image directly if present.
830 boot_image = common.GetBootableImage(
831 "IMAGES/" + b, b, OPTIONS.input_tmp, "BOOT")
832 # boot.img may be unavailable in some targets (e.g. aosp_arm64).
833 if boot_image:
834 boot_image_path = os.path.join(OPTIONS.input_tmp, "IMAGES", b)
Roopesh Nataraja3e15f6e2020-06-08 19:54:13 -0700835 # Although multiple boot images can be generated, include the image
836 # descriptor of only the first boot image in vbmeta
837 if index == 0:
Steve Muckle9793cf62020-04-08 18:27:00 -0700838 partitions['boot'] = boot_image_path
839 if not os.path.exists(boot_image_path):
840 boot_image.WriteToDir(OPTIONS.input_tmp)
841 if output_zip:
842 boot_image.AddToZip(output_zip)
Doug Zongker3c84f562014-07-31 11:06:30 -0700843
Devin Mooreafdd7c72021-12-13 22:04:08 +0000844 if has_init_boot:
845 banner("init_boot")
846 init_boot_image = common.GetBootableImage(
847 "IMAGES/init_boot.img", "init_boot.img", OPTIONS.input_tmp, "INIT_BOOT")
848 if init_boot_image:
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800849 partitions['init_boot'] = os.path.join(
850 OPTIONS.input_tmp, "IMAGES", "init_boot.img")
Devin Mooreafdd7c72021-12-13 22:04:08 +0000851 if not os.path.exists(partitions['init_boot']):
852 init_boot_image.WriteToDir(OPTIONS.input_tmp)
853 if output_zip:
854 init_boot_image.AddToZip(output_zip)
855
Greg Kaisere086f722021-09-14 19:32:27 +0000856 if has_vendor_boot:
Steve Mucklee1b10862019-07-10 10:49:37 -0700857 banner("vendor_boot")
858 vendor_boot_image = common.GetVendorBootImage(
859 "IMAGES/vendor_boot.img", "vendor_boot.img", OPTIONS.input_tmp,
860 "VENDOR_BOOT")
861 if vendor_boot_image:
862 partitions['vendor_boot'] = os.path.join(OPTIONS.input_tmp, "IMAGES",
863 "vendor_boot.img")
864 if not os.path.exists(partitions['vendor_boot']):
865 vendor_boot_image.WriteToDir(OPTIONS.input_tmp)
866 if output_zip:
867 vendor_boot_image.AddToZip(output_zip)
868
Lucas Weif57333f2022-02-24 10:30:15 +0800869 if has_vendor_kernel_boot:
870 banner("vendor_kernel_boot")
Lucas Wei03230252022-04-18 16:00:40 +0800871 vendor_kernel_boot_image = common.GetVendorKernelBootImage(
Lucas Weif57333f2022-02-24 10:30:15 +0800872 "IMAGES/vendor_kernel_boot.img", "vendor_kernel_boot.img", OPTIONS.input_tmp,
873 "VENDOR_KERNEL_BOOT")
874 if vendor_kernel_boot_image:
875 partitions['vendor_kernel_boot'] = os.path.join(OPTIONS.input_tmp, "IMAGES",
876 "vendor_kernel_boot.img")
877 if not os.path.exists(partitions['vendor_kernel_boot']):
878 vendor_kernel_boot_image.WriteToDir(OPTIONS.input_tmp)
879 if output_zip:
880 vendor_kernel_boot_image.AddToZip(output_zip)
881
Michael Runge2e0d8fc2014-11-13 21:41:08 -0800882 recovery_image = None
Greg Kaisere086f722021-09-14 19:32:27 +0000883 if has_recovery:
Tao Baodb45efa2015-10-27 19:25:18 -0700884 banner("recovery")
Tao Bao262bf3f2017-07-11 17:27:55 -0700885 recovery_image = common.GetBootableImage(
886 "IMAGES/recovery.img", "recovery.img", OPTIONS.input_tmp, "RECOVERY")
887 assert recovery_image, "Failed to create recovery.img."
Tao Baobf70c312017-07-11 17:27:55 -0700888 partitions['recovery'] = os.path.join(
Tao Bao262bf3f2017-07-11 17:27:55 -0700889 OPTIONS.input_tmp, "IMAGES", "recovery.img")
Tao Baobf70c312017-07-11 17:27:55 -0700890 if not os.path.exists(partitions['recovery']):
Tao Bao262bf3f2017-07-11 17:27:55 -0700891 recovery_image.WriteToDir(OPTIONS.input_tmp)
892 if output_zip:
893 recovery_image.AddToZip(output_zip)
Doug Zongker3c84f562014-07-31 11:06:30 -0700894
Tao Baod42e97e2016-11-30 12:11:57 -0800895 banner("recovery (two-step image)")
896 # The special recovery.img for two-step package use.
897 recovery_two_step_image = common.GetBootableImage(
Tao Bao04808502019-07-25 23:11:41 -0700898 "OTA/recovery-two-step.img", "recovery-two-step.img",
Tao Baod42e97e2016-11-30 12:11:57 -0800899 OPTIONS.input_tmp, "RECOVERY", two_step_image=True)
Tao Bao262bf3f2017-07-11 17:27:55 -0700900 assert recovery_two_step_image, "Failed to create recovery-two-step.img."
901 recovery_two_step_image_path = os.path.join(
Tao Bao04808502019-07-25 23:11:41 -0700902 OPTIONS.input_tmp, "OTA", "recovery-two-step.img")
Tao Bao262bf3f2017-07-11 17:27:55 -0700903 if not os.path.exists(recovery_two_step_image_path):
904 recovery_two_step_image.WriteToDir(OPTIONS.input_tmp)
Dan Willemsen2ee00d52017-03-05 19:51:56 -0800905 if output_zip:
906 recovery_two_step_image.AddToZip(output_zip)
Tao Baod42e97e2016-11-30 12:11:57 -0800907
Daniel Norman78554ea2021-09-14 10:29:38 -0700908 def add_partition(partition, has_partition, add_func, add_args):
909 if has_partition:
910 banner(partition)
911 partitions[partition] = add_func(output_zip, *add_args)
Tao Baobf70c312017-07-11 17:27:55 -0700912
Daniel Norman78554ea2021-09-14 10:29:38 -0700913 add_partition_calls = (
914 ("system", has_system, AddSystem, [recovery_image, boot_image]),
915 ("vendor", has_vendor, AddVendor, [recovery_image, boot_image]),
916 ("product", has_product, AddProduct, []),
917 ("system_ext", has_system_ext, AddSystemExt, []),
918 ("odm", has_odm, AddOdm, []),
919 ("vendor_dlkm", has_vendor_dlkm, AddVendorDlkm, []),
920 ("odm_dlkm", has_odm_dlkm, AddOdmDlkm, []),
Ramji Jiyani13a41372022-01-27 07:05:08 +0000921 ("system_dlkm", has_system_dlkm, AddSystemDlkm, []),
Daniel Norman78554ea2021-09-14 10:29:38 -0700922 ("system_other", has_system_other, AddSystemOther, []),
923 )
924 for call in add_partition_calls:
925 add_partition(*call)
Tao Baobf70c312017-07-11 17:27:55 -0700926
Kelvin Zhang5f0fcee2021-01-19 15:30:46 -0500927 AddApexInfo(output_zip)
928
Tianjie Xub48589a2016-08-03 19:21:52 -0700929 if not OPTIONS.is_signing:
Greg Kaisere086f722021-09-14 19:32:27 +0000930 banner("userdata")
931 AddUserdata(output_zip)
932 banner("cache")
933 AddCache(output_zip)
Tao Baoc633ed02017-05-30 21:46:33 -0700934
935 if OPTIONS.info_dict.get("board_bpt_enable") == "true":
David Zeuthen25328622016-04-08 15:08:03 -0400936 banner("partition-table")
937 AddPartitionTable(output_zip)
Tao Baoc633ed02017-05-30 21:46:33 -0700938
Daniel Norman78554ea2021-09-14 10:29:38 -0700939 add_partition("dtbo",
940 OPTIONS.info_dict.get("has_dtbo") == "true", AddDtbo, [])
941 add_partition("pvmfw",
942 OPTIONS.info_dict.get("has_pvmfw") == "true", AddPvmfw, [])
Andrew Sculle077cf72021-02-18 10:27:29 +0000943
Hongguang Chenf23364d2020-04-27 18:36:36 -0700944 # Custom images.
945 custom_partitions = OPTIONS.info_dict.get(
946 "avb_custom_images_partition_list", "").strip().split()
947 for partition_name in custom_partitions:
948 partition_name = partition_name.strip()
949 banner("custom images for " + partition_name)
950 partitions[partition_name] = AddCustomImages(output_zip, partition_name)
951
Bowgo Tsai3e599ea2017-05-26 18:30:04 +0800952 if OPTIONS.info_dict.get("avb_enable") == "true":
Tao Bao744c4c72018-08-20 21:09:07 -0700953 # vbmeta_partitions includes the partitions that should be included into
954 # top-level vbmeta.img, which are the ones that are not included in any
955 # chained VBMeta image plus the chained VBMeta images themselves.
Hongguang Chenf23364d2020-04-27 18:36:36 -0700956 # Currently custom_partitions are all chained to VBMeta image.
957 vbmeta_partitions = common.AVB_PARTITIONS[:] + tuple(custom_partitions)
Tao Bao744c4c72018-08-20 21:09:07 -0700958
David Anderson7709ab22018-10-15 14:41:34 -0700959 vbmeta_system = OPTIONS.info_dict.get("avb_vbmeta_system", "").strip()
Greg Kaisere086f722021-09-14 19:32:27 +0000960 if vbmeta_system:
David Anderson7709ab22018-10-15 14:41:34 -0700961 banner("vbmeta_system")
Tao Bao71064202018-10-22 15:08:02 -0700962 partitions["vbmeta_system"] = AddVBMeta(
David Anderson7709ab22018-10-15 14:41:34 -0700963 output_zip, partitions, "vbmeta_system", vbmeta_system.split())
Tao Bao744c4c72018-08-20 21:09:07 -0700964 vbmeta_partitions = [
965 item for item in vbmeta_partitions
David Anderson7709ab22018-10-15 14:41:34 -0700966 if item not in vbmeta_system.split()]
967 vbmeta_partitions.append("vbmeta_system")
Tao Bao744c4c72018-08-20 21:09:07 -0700968
969 vbmeta_vendor = OPTIONS.info_dict.get("avb_vbmeta_vendor", "").strip()
Greg Kaisere086f722021-09-14 19:32:27 +0000970 if vbmeta_vendor:
Tao Bao744c4c72018-08-20 21:09:07 -0700971 banner("vbmeta_vendor")
Tao Bao71064202018-10-22 15:08:02 -0700972 partitions["vbmeta_vendor"] = AddVBMeta(
Tao Bao744c4c72018-08-20 21:09:07 -0700973 output_zip, partitions, "vbmeta_vendor", vbmeta_vendor.split())
974 vbmeta_partitions = [
975 item for item in vbmeta_partitions
976 if item not in vbmeta_vendor.split()]
977 vbmeta_partitions.append("vbmeta_vendor")
978
Greg Kaisere086f722021-09-14 19:32:27 +0000979 if OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true":
Bowgo Tsai82182252020-11-13 11:28:17 +0800980 banner("vbmeta")
981 AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
Doug Zongker3c84f562014-07-31 11:06:30 -0700982
Tao Bao48a2feb2019-06-28 11:00:05 -0700983 if OPTIONS.info_dict.get("use_dynamic_partitions") == "true":
Greg Kaisere086f722021-09-14 19:32:27 +0000984 if OPTIONS.info_dict.get("build_super_empty_partition") == "true":
Yo Chiange86bab42021-03-25 10:12:28 +0000985 banner("super_empty")
986 AddSuperEmpty(output_zip)
David Anderson1ef03e22018-08-30 13:11:47 -0700987
Greg Kaisere086f722021-09-14 19:32:27 +0000988 if OPTIONS.info_dict.get("build_super_partition") == "true":
Tao Bao519d1822018-12-27 12:47:23 -0800989 if OPTIONS.info_dict.get(
Kelvin Zhang834f5d42022-01-21 12:44:44 -0800990 "build_retrofit_dynamic_partitions_ota_package") == "true":
Yifan Hongc767f7c2018-11-08 15:41:24 -0800991 banner("super split images")
992 AddSuperSplit(output_zip)
Yifan Hongc767f7c2018-11-08 15:41:24 -0800993
Tianjie Xuaaca4212016-06-28 14:34:03 -0700994 banner("radio")
Tao Baobea20ac2018-01-17 17:57:49 -0800995 ab_partitions_txt = os.path.join(OPTIONS.input_tmp, "META",
996 "ab_partitions.txt")
997 if os.path.exists(ab_partitions_txt):
Tao Baoa3705452019-06-24 15:33:41 -0700998 with open(ab_partitions_txt) as f:
Daniel Norman78554ea2021-09-14 10:29:38 -0700999 ab_partitions = f.read().splitlines()
Tianjie Xucfa86222016-03-07 16:31:19 -08001000
Greg Kaisere086f722021-09-14 19:32:27 +00001001 # For devices using A/B update, make sure we have all the needed images
1002 # ready under IMAGES/ or RADIO/.
1003 CheckAbOtaImages(output_zip, ab_partitions)
Tianjie Xuaaca4212016-06-28 14:34:03 -07001004
Greg Kaisere086f722021-09-14 19:32:27 +00001005 # Generate care_map.pb for ab_partitions, then write this file to
1006 # target_files package.
1007 output_care_map = os.path.join(OPTIONS.input_tmp, "META", "care_map.pb")
1008 AddCareMapForAbOta(output_zip if output_zip else output_care_map,
1009 ab_partitions, partitions)
Tianjie Xucfa86222016-03-07 16:31:19 -08001010
Tao Bao95a95c32017-06-16 15:30:23 -07001011 # Radio images that need to be packed into IMAGES/, and product-img.zip.
Tao Baobea20ac2018-01-17 17:57:49 -08001012 pack_radioimages_txt = os.path.join(
Tao Bao95a95c32017-06-16 15:30:23 -07001013 OPTIONS.input_tmp, "META", "pack_radioimages.txt")
Tao Baobea20ac2018-01-17 17:57:49 -08001014 if os.path.exists(pack_radioimages_txt):
Tao Baoa3705452019-06-24 15:33:41 -07001015 with open(pack_radioimages_txt) as f:
Tao Baobea20ac2018-01-17 17:57:49 -08001016 AddPackRadioImages(output_zip, f.readlines())
Tao Bao95a95c32017-06-16 15:30:23 -07001017
Greg Kaisere086f722021-09-14 19:32:27 +00001018 AddVbmetaDigest(output_zip)
Tianjiebbde59f2021-05-03 21:18:56 -07001019
Dan Willemsen2ee00d52017-03-05 19:51:56 -08001020 if output_zip:
1021 common.ZipClose(output_zip)
Tianjie Xu9ac4cb02017-06-09 16:58:03 -07001022 if OPTIONS.replace_updated_files_list:
1023 ReplaceUpdatedFiles(output_zip.filename,
1024 OPTIONS.replace_updated_files_list)
Tianjie Xu38af07f2017-05-25 17:38:53 -07001025
Doug Zongker3c84f562014-07-31 11:06:30 -07001026
Kelvin Zhang834f5d42022-01-21 12:44:44 -08001027def OptimizeCompressedEntries(zipfile_path):
1028 """Convert files that do not compress well to uncompressed storage
1029
1030 EROFS images tend to be compressed already, so compressing them again
1031 yields little space savings. Leaving them uncompressed will make
1032 downstream tooling's job easier, and save compute time.
1033 """
1034 if not zipfile.is_zipfile(zipfile_path):
1035 return
1036 entries_to_store = []
1037 with tempfile.TemporaryDirectory() as tmpdir:
1038 with zipfile.ZipFile(zipfile_path, "r", allowZip64=True) as zfp:
1039 for zinfo in zfp.filelist:
1040 if not zinfo.filename.startswith("IMAGES/") and not zinfo.filename.startswith("META"):
Kelvin Zhang9d021e92022-02-07 16:37:15 -08001041 continue
Kelvin Zhang834f5d42022-01-21 12:44:44 -08001042 # Don't try to store userdata.img uncompressed, it's usually huge.
1043 if zinfo.filename.endswith("userdata.img"):
Kelvin Zhang9d021e92022-02-07 16:37:15 -08001044 continue
Kelvin Zhang834f5d42022-01-21 12:44:44 -08001045 if zinfo.compress_size > zinfo.file_size * 0.80 and zinfo.compress_type != zipfile.ZIP_STORED:
1046 entries_to_store.append(zinfo)
1047 zfp.extract(zinfo, tmpdir)
Kelvin Zhang70876142022-02-09 16:05:29 -08001048 if len(entries_to_store) == 0:
1049 return
Kelvin Zhang834f5d42022-01-21 12:44:44 -08001050 # Remove these entries, then re-add them as ZIP_STORED
Kelvin Zhang70876142022-02-09 16:05:29 -08001051 ZipDelete(zipfile_path, [entry.filename for entry in entries_to_store])
Kelvin Zhang834f5d42022-01-21 12:44:44 -08001052 with zipfile.ZipFile(zipfile_path, "a", allowZip64=True) as zfp:
1053 for entry in entries_to_store:
1054 zfp.write(os.path.join(tmpdir, entry.filename), entry.filename, compress_type=zipfile.ZIP_STORED)
1055
1056
Doug Zongker3c84f562014-07-31 11:06:30 -07001057def main(argv):
Baligh Uddin59f4ff12015-09-16 21:20:30 -07001058 def option_handler(o, a):
Michael Runge2e0d8fc2014-11-13 21:41:08 -08001059 if o in ("-a", "--add_missing"):
1060 OPTIONS.add_missing = True
1061 elif o in ("-r", "--rebuild_recovery",):
1062 OPTIONS.rebuild_recovery = True
Baligh Uddin59f4ff12015-09-16 21:20:30 -07001063 elif o == "--replace_verity_private_key":
hungweichendd3fca02022-08-19 06:33:25 +00001064 raise ValueError("--replace_verity_private_key is no longer supported,"
1065 " please switch to AVB")
Baligh Uddin59f4ff12015-09-16 21:20:30 -07001066 elif o == "--replace_verity_public_key":
hungweichendd3fca02022-08-19 06:33:25 +00001067 raise ValueError("--replace_verity_public_key is no longer supported,"
1068 " please switch to AVB")
Tianjie Xub48589a2016-08-03 19:21:52 -07001069 elif o == "--is_signing":
1070 OPTIONS.is_signing = True
Michael Runge2e0d8fc2014-11-13 21:41:08 -08001071 else:
1072 return False
1073 return True
1074
Dan Albert8b72aef2015-03-23 19:13:21 -07001075 args = common.ParseOptions(
1076 argv, __doc__, extra_opts="ar",
Baligh Uddin59f4ff12015-09-16 21:20:30 -07001077 extra_long_opts=["add_missing", "rebuild_recovery",
1078 "replace_verity_public_key=",
1079 "replace_verity_private_key=",
Greg Kaisere086f722021-09-14 19:32:27 +00001080 "is_signing"],
Dan Albert8b72aef2015-03-23 19:13:21 -07001081 extra_option_handler=option_handler)
Michael Runge2e0d8fc2014-11-13 21:41:08 -08001082
Doug Zongker3c84f562014-07-31 11:06:30 -07001083 if len(args) != 1:
1084 common.Usage(__doc__)
1085 sys.exit(1)
1086
Tao Bao32fcdab2018-10-12 10:30:39 -07001087 common.InitLogging()
1088
Doug Zongker3c84f562014-07-31 11:06:30 -07001089 AddImagesToTargetFiles(args[0])
Kelvin Zhang834f5d42022-01-21 12:44:44 -08001090 OptimizeCompressedEntries(args[0])
Tao Bao32fcdab2018-10-12 10:30:39 -07001091 logger.info("done.")
Doug Zongker3c84f562014-07-31 11:06:30 -07001092
Kelvin Zhang834f5d42022-01-21 12:44:44 -08001093
Doug Zongker3c84f562014-07-31 11:06:30 -07001094if __name__ == '__main__':
1095 try:
1096 common.CloseInheritedPipes()
1097 main(sys.argv[1:])
Doug Zongkerfc44a512014-08-26 13:10:25 -07001098 finally:
1099 common.Cleanup()