VirtualBox

source: vbox/trunk/src/VBox/Additions/3D/mesa/mesa-24.0.2/.gitlab-ci/bare-metal/mkbootimg.py@ 105254

最後變更 在這個檔案從105254是 103996,由 vboxsync 提交於 12 月 前

Additions/3D/mesa: export mesa-24.0.2 to OSE. bugref:10606

檔案大小: 26.3 KB
 
1#!/usr/bin/env python3
2#
3# Copyright 2015, 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"""Creates the boot image."""
17from argparse import (ArgumentParser, ArgumentTypeError,
18 FileType, RawDescriptionHelpFormatter)
19from hashlib import sha1
20from os import fstat
21from struct import pack
22import array
23import collections
24import os
25import re
26import subprocess
27import tempfile
28# Constant and structure definition is in
29# system/tools/mkbootimg/include/bootimg/bootimg.h
30BOOT_MAGIC = 'ANDROID!'
31BOOT_MAGIC_SIZE = 8
32BOOT_NAME_SIZE = 16
33BOOT_ARGS_SIZE = 512
34BOOT_EXTRA_ARGS_SIZE = 1024
35BOOT_IMAGE_HEADER_V1_SIZE = 1648
36BOOT_IMAGE_HEADER_V2_SIZE = 1660
37BOOT_IMAGE_HEADER_V3_SIZE = 1580
38BOOT_IMAGE_HEADER_V3_PAGESIZE = 4096
39BOOT_IMAGE_HEADER_V4_SIZE = 1584
40BOOT_IMAGE_V4_SIGNATURE_SIZE = 4096
41VENDOR_BOOT_MAGIC = 'VNDRBOOT'
42VENDOR_BOOT_MAGIC_SIZE = 8
43VENDOR_BOOT_NAME_SIZE = BOOT_NAME_SIZE
44VENDOR_BOOT_ARGS_SIZE = 2048
45VENDOR_BOOT_IMAGE_HEADER_V3_SIZE = 2112
46VENDOR_BOOT_IMAGE_HEADER_V4_SIZE = 2128
47VENDOR_RAMDISK_TYPE_NONE = 0
48VENDOR_RAMDISK_TYPE_PLATFORM = 1
49VENDOR_RAMDISK_TYPE_RECOVERY = 2
50VENDOR_RAMDISK_TYPE_DLKM = 3
51VENDOR_RAMDISK_NAME_SIZE = 32
52VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE = 16
53VENDOR_RAMDISK_TABLE_ENTRY_V4_SIZE = 108
54# Names with special meaning, mustn't be specified in --ramdisk_name.
55VENDOR_RAMDISK_NAME_BLOCKLIST = {b'default'}
56PARSER_ARGUMENT_VENDOR_RAMDISK_FRAGMENT = '--vendor_ramdisk_fragment'
57def filesize(f):
58 if f is None:
59 return 0
60 try:
61 return fstat(f.fileno()).st_size
62 except OSError:
63 return 0
64def update_sha(sha, f):
65 if f:
66 sha.update(f.read())
67 f.seek(0)
68 sha.update(pack('I', filesize(f)))
69 else:
70 sha.update(pack('I', 0))
71def pad_file(f, padding):
72 pad = (padding - (f.tell() & (padding - 1))) & (padding - 1)
73 f.write(pack(str(pad) + 'x'))
74def get_number_of_pages(image_size, page_size):
75 """calculates the number of pages required for the image"""
76 return (image_size + page_size - 1) // page_size
77def get_recovery_dtbo_offset(args):
78 """calculates the offset of recovery_dtbo image in the boot image"""
79 num_header_pages = 1 # header occupies a page
80 num_kernel_pages = get_number_of_pages(filesize(args.kernel), args.pagesize)
81 num_ramdisk_pages = get_number_of_pages(filesize(args.ramdisk),
82 args.pagesize)
83 num_second_pages = get_number_of_pages(filesize(args.second), args.pagesize)
84 dtbo_offset = args.pagesize * (num_header_pages + num_kernel_pages +
85 num_ramdisk_pages + num_second_pages)
86 return dtbo_offset
87def write_header_v3_and_above(args):
88 if args.header_version > 3:
89 boot_header_size = BOOT_IMAGE_HEADER_V4_SIZE
90 else:
91 boot_header_size = BOOT_IMAGE_HEADER_V3_SIZE
92 args.output.write(pack(f'{BOOT_MAGIC_SIZE}s', BOOT_MAGIC.encode()))
93 # kernel size in bytes
94 args.output.write(pack('I', filesize(args.kernel)))
95 # ramdisk size in bytes
96 args.output.write(pack('I', filesize(args.ramdisk)))
97 # os version and patch level
98 args.output.write(pack('I', (args.os_version << 11) | args.os_patch_level))
99 args.output.write(pack('I', boot_header_size))
100 # reserved
101 args.output.write(pack('4I', 0, 0, 0, 0))
102 # version of boot image header
103 args.output.write(pack('I', args.header_version))
104 args.output.write(pack(f'{BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE}s',
105 args.cmdline))
106 if args.header_version >= 4:
107 # The signature used to verify boot image v4.
108 args.output.write(pack('I', BOOT_IMAGE_V4_SIGNATURE_SIZE))
109 pad_file(args.output, BOOT_IMAGE_HEADER_V3_PAGESIZE)
110def write_vendor_boot_header(args):
111 if filesize(args.dtb) == 0:
112 raise ValueError('DTB image must not be empty.')
113 if args.header_version > 3:
114 vendor_ramdisk_size = args.vendor_ramdisk_total_size
115 vendor_boot_header_size = VENDOR_BOOT_IMAGE_HEADER_V4_SIZE
116 else:
117 vendor_ramdisk_size = filesize(args.vendor_ramdisk)
118 vendor_boot_header_size = VENDOR_BOOT_IMAGE_HEADER_V3_SIZE
119 args.vendor_boot.write(pack(f'{VENDOR_BOOT_MAGIC_SIZE}s',
120 VENDOR_BOOT_MAGIC.encode()))
121 # version of boot image header
122 args.vendor_boot.write(pack('I', args.header_version))
123 # flash page size
124 args.vendor_boot.write(pack('I', args.pagesize))
125 # kernel physical load address
126 args.vendor_boot.write(pack('I', args.base + args.kernel_offset))
127 # ramdisk physical load address
128 args.vendor_boot.write(pack('I', args.base + args.ramdisk_offset))
129 # ramdisk size in bytes
130 args.vendor_boot.write(pack('I', vendor_ramdisk_size))
131 args.vendor_boot.write(pack(f'{VENDOR_BOOT_ARGS_SIZE}s',
132 args.vendor_cmdline))
133 # kernel tags physical load address
134 args.vendor_boot.write(pack('I', args.base + args.tags_offset))
135 # asciiz product name
136 args.vendor_boot.write(pack(f'{VENDOR_BOOT_NAME_SIZE}s', args.board))
137 # header size in bytes
138 args.vendor_boot.write(pack('I', vendor_boot_header_size))
139 # dtb size in bytes
140 args.vendor_boot.write(pack('I', filesize(args.dtb)))
141 # dtb physical load address
142 args.vendor_boot.write(pack('Q', args.base + args.dtb_offset))
143 if args.header_version > 3:
144 vendor_ramdisk_table_size = (args.vendor_ramdisk_table_entry_num *
145 VENDOR_RAMDISK_TABLE_ENTRY_V4_SIZE)
146 # vendor ramdisk table size in bytes
147 args.vendor_boot.write(pack('I', vendor_ramdisk_table_size))
148 # number of vendor ramdisk table entries
149 args.vendor_boot.write(pack('I', args.vendor_ramdisk_table_entry_num))
150 # vendor ramdisk table entry size in bytes
151 args.vendor_boot.write(pack('I', VENDOR_RAMDISK_TABLE_ENTRY_V4_SIZE))
152 # bootconfig section size in bytes
153 args.vendor_boot.write(pack('I', filesize(args.vendor_bootconfig)))
154 pad_file(args.vendor_boot, args.pagesize)
155def write_header(args):
156 if args.header_version > 4:
157 raise ValueError(
158 f'Boot header version {args.header_version} not supported')
159 if args.header_version in {3, 4}:
160 return write_header_v3_and_above(args)
161 ramdisk_load_address = ((args.base + args.ramdisk_offset)
162 if filesize(args.ramdisk) > 0 else 0)
163 second_load_address = ((args.base + args.second_offset)
164 if filesize(args.second) > 0 else 0)
165 args.output.write(pack(f'{BOOT_MAGIC_SIZE}s', BOOT_MAGIC.encode()))
166 # kernel size in bytes
167 args.output.write(pack('I', filesize(args.kernel)))
168 # kernel physical load address
169 args.output.write(pack('I', args.base + args.kernel_offset))
170 # ramdisk size in bytes
171 args.output.write(pack('I', filesize(args.ramdisk)))
172 # ramdisk physical load address
173 args.output.write(pack('I', ramdisk_load_address))
174 # second bootloader size in bytes
175 args.output.write(pack('I', filesize(args.second)))
176 # second bootloader physical load address
177 args.output.write(pack('I', second_load_address))
178 # kernel tags physical load address
179 args.output.write(pack('I', args.base + args.tags_offset))
180 # flash page size
181 args.output.write(pack('I', args.pagesize))
182 # version of boot image header
183 args.output.write(pack('I', args.header_version))
184 # os version and patch level
185 args.output.write(pack('I', (args.os_version << 11) | args.os_patch_level))
186 # asciiz product name
187 args.output.write(pack(f'{BOOT_NAME_SIZE}s', args.board))
188 args.output.write(pack(f'{BOOT_ARGS_SIZE}s', args.cmdline))
189 sha = sha1()
190 update_sha(sha, args.kernel)
191 update_sha(sha, args.ramdisk)
192 update_sha(sha, args.second)
193 if args.header_version > 0:
194 update_sha(sha, args.recovery_dtbo)
195 if args.header_version > 1:
196 update_sha(sha, args.dtb)
197 img_id = pack('32s', sha.digest())
198 args.output.write(img_id)
199 args.output.write(pack(f'{BOOT_EXTRA_ARGS_SIZE}s', args.extra_cmdline))
200 if args.header_version > 0:
201 if args.recovery_dtbo:
202 # recovery dtbo size in bytes
203 args.output.write(pack('I', filesize(args.recovery_dtbo)))
204 # recovert dtbo offset in the boot image
205 args.output.write(pack('Q', get_recovery_dtbo_offset(args)))
206 else:
207 # Set to zero if no recovery dtbo
208 args.output.write(pack('I', 0))
209 args.output.write(pack('Q', 0))
210 # Populate boot image header size for header versions 1 and 2.
211 if args.header_version == 1:
212 args.output.write(pack('I', BOOT_IMAGE_HEADER_V1_SIZE))
213 elif args.header_version == 2:
214 args.output.write(pack('I', BOOT_IMAGE_HEADER_V2_SIZE))
215 if args.header_version > 1:
216 if filesize(args.dtb) == 0:
217 raise ValueError('DTB image must not be empty.')
218 # dtb size in bytes
219 args.output.write(pack('I', filesize(args.dtb)))
220 # dtb physical load address
221 args.output.write(pack('Q', args.base + args.dtb_offset))
222 pad_file(args.output, args.pagesize)
223 return img_id
224class AsciizBytes:
225 """Parses a string and encodes it as an asciiz bytes object.
226 >>> AsciizBytes(bufsize=4)('foo')
227 b'foo\\x00'
228 >>> AsciizBytes(bufsize=4)('foob')
229 Traceback (most recent call last):
230 ...
231 argparse.ArgumentTypeError: Encoded asciiz length exceeded: max 4, got 5
232 """
233 def __init__(self, bufsize):
234 self.bufsize = bufsize
235 def __call__(self, arg):
236 arg_bytes = arg.encode() + b'\x00'
237 if len(arg_bytes) > self.bufsize:
238 raise ArgumentTypeError(
239 'Encoded asciiz length exceeded: '
240 f'max {self.bufsize}, got {len(arg_bytes)}')
241 return arg_bytes
242class VendorRamdiskTableBuilder:
243 """Vendor ramdisk table builder.
244 Attributes:
245 entries: A list of VendorRamdiskTableEntry namedtuple.
246 ramdisk_total_size: Total size in bytes of all ramdisks in the table.
247 """
248 VendorRamdiskTableEntry = collections.namedtuple( # pylint: disable=invalid-name
249 'VendorRamdiskTableEntry',
250 ['ramdisk_path', 'ramdisk_size', 'ramdisk_offset', 'ramdisk_type',
251 'ramdisk_name', 'board_id'])
252 def __init__(self):
253 self.entries = []
254 self.ramdisk_total_size = 0
255 self.ramdisk_names = set()
256 def add_entry(self, ramdisk_path, ramdisk_type, ramdisk_name, board_id):
257 # Strip any trailing null for simple comparison.
258 stripped_ramdisk_name = ramdisk_name.rstrip(b'\x00')
259 if stripped_ramdisk_name in VENDOR_RAMDISK_NAME_BLOCKLIST:
260 raise ValueError(
261 f'Banned vendor ramdisk name: {stripped_ramdisk_name}')
262 if stripped_ramdisk_name in self.ramdisk_names:
263 raise ValueError(
264 f'Duplicated vendor ramdisk name: {stripped_ramdisk_name}')
265 self.ramdisk_names.add(stripped_ramdisk_name)
266 if board_id is None:
267 board_id = array.array(
268 'I', [0] * VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE)
269 else:
270 board_id = array.array('I', board_id)
271 if len(board_id) != VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE:
272 raise ValueError('board_id size must be '
273 f'{VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE}')
274 with open(ramdisk_path, 'rb') as f:
275 ramdisk_size = filesize(f)
276 self.entries.append(self.VendorRamdiskTableEntry(
277 ramdisk_path, ramdisk_size, self.ramdisk_total_size, ramdisk_type,
278 ramdisk_name, board_id))
279 self.ramdisk_total_size += ramdisk_size
280 def write_ramdisks_padded(self, fout, alignment):
281 for entry in self.entries:
282 with open(entry.ramdisk_path, 'rb') as f:
283 fout.write(f.read())
284 pad_file(fout, alignment)
285 def write_entries_padded(self, fout, alignment):
286 for entry in self.entries:
287 fout.write(pack('I', entry.ramdisk_size))
288 fout.write(pack('I', entry.ramdisk_offset))
289 fout.write(pack('I', entry.ramdisk_type))
290 fout.write(pack(f'{VENDOR_RAMDISK_NAME_SIZE}s',
291 entry.ramdisk_name))
292 fout.write(entry.board_id)
293 pad_file(fout, alignment)
294def write_padded_file(f_out, f_in, padding):
295 if f_in is None:
296 return
297 f_out.write(f_in.read())
298 pad_file(f_out, padding)
299def parse_int(x):
300 return int(x, 0)
301def parse_os_version(x):
302 match = re.search(r'^(\d{1,3})(?:\.(\d{1,3})(?:\.(\d{1,3}))?)?', x)
303 if match:
304 a = int(match.group(1))
305 b = c = 0
306 if match.lastindex >= 2:
307 b = int(match.group(2))
308 if match.lastindex == 3:
309 c = int(match.group(3))
310 # 7 bits allocated for each field
311 assert a < 128
312 assert b < 128
313 assert c < 128
314 return (a << 14) | (b << 7) | c
315 return 0
316def parse_os_patch_level(x):
317 match = re.search(r'^(\d{4})-(\d{2})(?:-(\d{2}))?', x)
318 if match:
319 y = int(match.group(1)) - 2000
320 m = int(match.group(2))
321 # 7 bits allocated for the year, 4 bits for the month
322 assert 0 <= y < 128
323 assert 0 < m <= 12
324 return (y << 4) | m
325 return 0
326def parse_vendor_ramdisk_type(x):
327 type_dict = {
328 'none': VENDOR_RAMDISK_TYPE_NONE,
329 'platform': VENDOR_RAMDISK_TYPE_PLATFORM,
330 'recovery': VENDOR_RAMDISK_TYPE_RECOVERY,
331 'dlkm': VENDOR_RAMDISK_TYPE_DLKM,
332 }
333 if x.lower() in type_dict:
334 return type_dict[x.lower()]
335 return parse_int(x)
336def get_vendor_boot_v4_usage():
337 return """vendor boot version 4 arguments:
338 --ramdisk_type {none,platform,recovery,dlkm}
339 specify the type of the ramdisk
340 --ramdisk_name NAME
341 specify the name of the ramdisk
342 --board_id{0..15} NUMBER
343 specify the value of the board_id vector, defaults to 0
344 --vendor_ramdisk_fragment VENDOR_RAMDISK_FILE
345 path to the vendor ramdisk file
346 These options can be specified multiple times, where each vendor ramdisk
347 option group ends with a --vendor_ramdisk_fragment option.
348 Each option group appends an additional ramdisk to the vendor boot image.
349"""
350def parse_vendor_ramdisk_args(args, args_list):
351 """Parses vendor ramdisk specific arguments.
352 Args:
353 args: An argparse.Namespace object. Parsed results are stored into this
354 object.
355 args_list: A list of argument strings to be parsed.
356 Returns:
357 A list argument strings that are not parsed by this method.
358 """
359 parser = ArgumentParser(add_help=False)
360 parser.add_argument('--ramdisk_type', type=parse_vendor_ramdisk_type,
361 default=VENDOR_RAMDISK_TYPE_NONE)
362 parser.add_argument('--ramdisk_name',
363 type=AsciizBytes(bufsize=VENDOR_RAMDISK_NAME_SIZE),
364 required=True)
365 for i in range(VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE):
366 parser.add_argument(f'--board_id{i}', type=parse_int, default=0)
367 parser.add_argument(PARSER_ARGUMENT_VENDOR_RAMDISK_FRAGMENT, required=True)
368 unknown_args = []
369 vendor_ramdisk_table_builder = VendorRamdiskTableBuilder()
370 if args.vendor_ramdisk is not None:
371 vendor_ramdisk_table_builder.add_entry(
372 args.vendor_ramdisk.name, VENDOR_RAMDISK_TYPE_PLATFORM, b'', None)
373 while PARSER_ARGUMENT_VENDOR_RAMDISK_FRAGMENT in args_list:
374 idx = args_list.index(PARSER_ARGUMENT_VENDOR_RAMDISK_FRAGMENT) + 2
375 vendor_ramdisk_args = args_list[:idx]
376 args_list = args_list[idx:]
377 ramdisk_args, extra_args = parser.parse_known_args(vendor_ramdisk_args)
378 ramdisk_args_dict = vars(ramdisk_args)
379 unknown_args.extend(extra_args)
380 ramdisk_path = ramdisk_args.vendor_ramdisk_fragment
381 ramdisk_type = ramdisk_args.ramdisk_type
382 ramdisk_name = ramdisk_args.ramdisk_name
383 board_id = [ramdisk_args_dict[f'board_id{i}']
384 for i in range(VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE)]
385 vendor_ramdisk_table_builder.add_entry(ramdisk_path, ramdisk_type,
386 ramdisk_name, board_id)
387 if len(args_list) > 0:
388 unknown_args.extend(args_list)
389 args.vendor_ramdisk_total_size = (vendor_ramdisk_table_builder
390 .ramdisk_total_size)
391 args.vendor_ramdisk_table_entry_num = len(vendor_ramdisk_table_builder
392 .entries)
393 args.vendor_ramdisk_table_builder = vendor_ramdisk_table_builder
394 return unknown_args
395def parse_cmdline():
396 version_parser = ArgumentParser(add_help=False)
397 version_parser.add_argument('--header_version', type=parse_int, default=0)
398 if version_parser.parse_known_args()[0].header_version < 3:
399 # For boot header v0 to v2, the kernel commandline field is split into
400 # two fields, cmdline and extra_cmdline. Both fields are asciiz strings,
401 # so we minus one here to ensure the encoded string plus the
402 # null-terminator can fit in the buffer size.
403 cmdline_size = BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE - 1
404 else:
405 cmdline_size = BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE
406 parser = ArgumentParser(formatter_class=RawDescriptionHelpFormatter,
407 epilog=get_vendor_boot_v4_usage())
408 parser.add_argument('--kernel', type=FileType('rb'),
409 help='path to the kernel')
410 parser.add_argument('--ramdisk', type=FileType('rb'),
411 help='path to the ramdisk')
412 parser.add_argument('--second', type=FileType('rb'),
413 help='path to the second bootloader')
414 parser.add_argument('--dtb', type=FileType('rb'), help='path to the dtb')
415 dtbo_group = parser.add_mutually_exclusive_group()
416 dtbo_group.add_argument('--recovery_dtbo', type=FileType('rb'),
417 help='path to the recovery DTBO')
418 dtbo_group.add_argument('--recovery_acpio', type=FileType('rb'),
419 metavar='RECOVERY_ACPIO', dest='recovery_dtbo',
420 help='path to the recovery ACPIO')
421 parser.add_argument('--cmdline', type=AsciizBytes(bufsize=cmdline_size),
422 default='', help='kernel command line arguments')
423 parser.add_argument('--vendor_cmdline',
424 type=AsciizBytes(bufsize=VENDOR_BOOT_ARGS_SIZE),
425 default='',
426 help='vendor boot kernel command line arguments')
427 parser.add_argument('--base', type=parse_int, default=0x10000000,
428 help='base address')
429 parser.add_argument('--kernel_offset', type=parse_int, default=0x00008000,
430 help='kernel offset')
431 parser.add_argument('--ramdisk_offset', type=parse_int, default=0x01000000,
432 help='ramdisk offset')
433 parser.add_argument('--second_offset', type=parse_int, default=0x00f00000,
434 help='second bootloader offset')
435 parser.add_argument('--dtb_offset', type=parse_int, default=0x01f00000,
436 help='dtb offset')
437 parser.add_argument('--os_version', type=parse_os_version, default=0,
438 help='operating system version')
439 parser.add_argument('--os_patch_level', type=parse_os_patch_level,
440 default=0, help='operating system patch level')
441 parser.add_argument('--tags_offset', type=parse_int, default=0x00000100,
442 help='tags offset')
443 parser.add_argument('--board', type=AsciizBytes(bufsize=BOOT_NAME_SIZE),
444 default='', help='board name')
445 parser.add_argument('--pagesize', type=parse_int,
446 choices=[2**i for i in range(11, 15)], default=2048,
447 help='page size')
448 parser.add_argument('--id', action='store_true',
449 help='print the image ID on standard output')
450 parser.add_argument('--header_version', type=parse_int, default=0,
451 help='boot image header version')
452 parser.add_argument('-o', '--output', type=FileType('wb'),
453 help='output file name')
454 parser.add_argument('--gki_signing_algorithm',
455 help='GKI signing algorithm to use')
456 parser.add_argument('--gki_signing_key',
457 help='path to RSA private key file')
458 parser.add_argument('--gki_signing_signature_args',
459 help='other hash arguments passed to avbtool')
460 parser.add_argument('--gki_signing_avbtool_path',
461 help='path to avbtool for boot signature generation')
462 parser.add_argument('--vendor_boot', type=FileType('wb'),
463 help='vendor boot output file name')
464 parser.add_argument('--vendor_ramdisk', type=FileType('rb'),
465 help='path to the vendor ramdisk')
466 parser.add_argument('--vendor_bootconfig', type=FileType('rb'),
467 help='path to the vendor bootconfig file')
468 args, extra_args = parser.parse_known_args()
469 if args.vendor_boot is not None and args.header_version > 3:
470 extra_args = parse_vendor_ramdisk_args(args, extra_args)
471 if len(extra_args) > 0:
472 raise ValueError(f'Unrecognized arguments: {extra_args}')
473 if args.header_version < 3:
474 args.extra_cmdline = args.cmdline[BOOT_ARGS_SIZE-1:]
475 args.cmdline = args.cmdline[:BOOT_ARGS_SIZE-1] + b'\x00'
476 assert len(args.cmdline) <= BOOT_ARGS_SIZE
477 assert len(args.extra_cmdline) <= BOOT_EXTRA_ARGS_SIZE
478 return args
479def add_boot_image_signature(args, pagesize):
480 """Adds the boot image signature.
481 Note that the signature will only be verified in VTS to ensure a
482 generic boot.img is used. It will not be used by the device
483 bootloader at boot time. The bootloader should only verify
484 the boot vbmeta at the end of the boot partition (or in the top-level
485 vbmeta partition) via the Android Verified Boot process, when the
486 device boots.
487 """
488 args.output.flush() # Flush the buffer for signature calculation.
489 # Appends zeros if the signing key is not specified.
490 if not args.gki_signing_key or not args.gki_signing_algorithm:
491 zeros = b'\x00' * BOOT_IMAGE_V4_SIGNATURE_SIZE
492 args.output.write(zeros)
493 pad_file(args.output, pagesize)
494 return
495 avbtool = 'avbtool' # Used from otatools.zip or Android build env.
496 # We need to specify the path of avbtool in build/core/Makefile.
497 # Because avbtool is not guaranteed to be in $PATH there.
498 if args.gki_signing_avbtool_path:
499 avbtool = args.gki_signing_avbtool_path
500 # Need to specify a value of --partition_size for avbtool to work.
501 # We use 64 MB below, but avbtool will not resize the boot image to
502 # this size because --do_not_append_vbmeta_image is also specified.
503 avbtool_cmd = [
504 avbtool, 'add_hash_footer',
505 '--partition_name', 'boot',
506 '--partition_size', str(64 * 1024 * 1024),
507 '--image', args.output.name,
508 '--algorithm', args.gki_signing_algorithm,
509 '--key', args.gki_signing_key,
510 '--salt', 'd00df00d'] # TODO: use a hash of kernel/ramdisk as the salt.
511 # Additional arguments passed to avbtool.
512 if args.gki_signing_signature_args:
513 avbtool_cmd += args.gki_signing_signature_args.split()
514 # Outputs the signed vbmeta to a separate file, then append to boot.img
515 # as the boot signature.
516 with tempfile.TemporaryDirectory() as temp_out_dir:
517 boot_signature_output = os.path.join(temp_out_dir, 'boot_signature')
518 avbtool_cmd += ['--do_not_append_vbmeta_image',
519 '--output_vbmeta_image', boot_signature_output]
520 subprocess.check_call(avbtool_cmd)
521 with open(boot_signature_output, 'rb') as boot_signature:
522 if filesize(boot_signature) > BOOT_IMAGE_V4_SIGNATURE_SIZE:
523 raise ValueError(
524 f'boot sigature size is > {BOOT_IMAGE_V4_SIGNATURE_SIZE}')
525 write_padded_file(args.output, boot_signature, pagesize)
526def write_data(args, pagesize):
527 write_padded_file(args.output, args.kernel, pagesize)
528 write_padded_file(args.output, args.ramdisk, pagesize)
529 write_padded_file(args.output, args.second, pagesize)
530 if args.header_version > 0 and args.header_version < 3:
531 write_padded_file(args.output, args.recovery_dtbo, pagesize)
532 if args.header_version == 2:
533 write_padded_file(args.output, args.dtb, pagesize)
534 if args.header_version >= 4:
535 add_boot_image_signature(args, pagesize)
536def write_vendor_boot_data(args):
537 if args.header_version > 3:
538 builder = args.vendor_ramdisk_table_builder
539 builder.write_ramdisks_padded(args.vendor_boot, args.pagesize)
540 write_padded_file(args.vendor_boot, args.dtb, args.pagesize)
541 builder.write_entries_padded(args.vendor_boot, args.pagesize)
542 write_padded_file(args.vendor_boot, args.vendor_bootconfig,
543 args.pagesize)
544 else:
545 write_padded_file(args.vendor_boot, args.vendor_ramdisk, args.pagesize)
546 write_padded_file(args.vendor_boot, args.dtb, args.pagesize)
547def main():
548 args = parse_cmdline()
549 if args.vendor_boot is not None:
550 if args.header_version not in {3, 4}:
551 raise ValueError(
552 '--vendor_boot not compatible with given header version')
553 if args.header_version == 3 and args.vendor_ramdisk is None:
554 raise ValueError('--vendor_ramdisk missing or invalid')
555 write_vendor_boot_header(args)
556 write_vendor_boot_data(args)
557 if args.output is not None:
558 if args.second is not None and args.header_version > 2:
559 raise ValueError(
560 '--second not compatible with given header version')
561 img_id = write_header(args)
562 if args.header_version > 2:
563 write_data(args, BOOT_IMAGE_HEADER_V3_PAGESIZE)
564 else:
565 write_data(args, args.pagesize)
566 if args.id and img_id is not None:
567 print('0x' + ''.join(f'{octet:02x}' for octet in img_id))
568if __name__ == '__main__':
569 main()
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette