Skip to content

Commit 3e2e3e5

Browse files
committed
rk: scripts: update mkbootimg/repack-bootimg/unpack_bootimg
AOSP 9f28439ba714 ("fix size of v3 boot header") Revert 7261bb083a97 ("Check DTB image size for boot image header version 2 and above") which failed to repack image without dtb. Change-Id: I591c0c548229e16482352c94651740de3e0e8b76 Signed-off-by: Tao Huang <huangtao@rock-chips.com>
1 parent 6fd73ce commit 3e2e3e5

3 files changed

Lines changed: 244 additions & 79 deletions

File tree

scripts/mkbootimg

Lines changed: 116 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
# limitations under the License.
1515

1616
from __future__ import print_function
17-
from sys import argv, exit, stderr
17+
1818
from argparse import ArgumentParser, FileType, Action
19-
from os import fstat
20-
from struct import pack
2119
from hashlib import sha1
22-
import sys
20+
from os import fstat
2321
import re
22+
from struct import pack
23+
24+
25+
BOOT_IMAGE_HEADER_V3_PAGESIZE = 4096
2426

2527
def filesize(f):
2628
if f is None:
@@ -61,18 +63,61 @@ def get_recovery_dtbo_offset(args):
6163
return dtbo_offset
6264

6365

66+
def write_header_v3(args):
67+
BOOT_IMAGE_HEADER_V3_SIZE = 1580
68+
BOOT_MAGIC = 'ANDROID!'.encode()
69+
70+
args.output.write(pack('8s', BOOT_MAGIC))
71+
args.output.write(pack(
72+
'4I',
73+
filesize(args.kernel), # kernel size in bytes
74+
filesize(args.ramdisk), # ramdisk size in bytes
75+
(args.os_version << 11) | args.os_patch_level, # os version and patch level
76+
BOOT_IMAGE_HEADER_V3_SIZE))
77+
78+
args.output.write(pack('4I', 0, 0, 0, 0)) # reserved
79+
80+
args.output.write(pack('I', args.header_version)) # version of bootimage header
81+
args.output.write(pack('1536s', args.cmdline.encode()))
82+
pad_file(args.output, BOOT_IMAGE_HEADER_V3_PAGESIZE)
83+
84+
def write_vendor_boot_header(args):
85+
VENDOR_BOOT_IMAGE_HEADER_V3_SIZE = 2112
86+
BOOT_MAGIC = 'VNDRBOOT'.encode()
87+
88+
args.vendor_boot.write(pack('8s', BOOT_MAGIC))
89+
args.vendor_boot.write(pack(
90+
'5I',
91+
args.header_version, # version of header
92+
args.pagesize, # flash page size we assume
93+
args.base + args.kernel_offset, # kernel physical load addr
94+
args.base + args.ramdisk_offset, # ramdisk physical load addr
95+
filesize(args.vendor_ramdisk))) # vendor ramdisk size in bytes
96+
args.vendor_boot.write(pack('2048s', args.vendor_cmdline.encode()))
97+
args.vendor_boot.write(pack('I', args.base + args.tags_offset)) # physical addr for kernel tags
98+
args.vendor_boot.write(pack('16s', args.board.encode())) # asciiz product name
99+
args.vendor_boot.write(pack('I', VENDOR_BOOT_IMAGE_HEADER_V3_SIZE)) # header size in bytes
100+
if filesize(args.dtb) == 0:
101+
raise ValueError("DTB image must not be empty.")
102+
args.vendor_boot.write(pack('I', filesize(args.dtb))) # size in bytes
103+
args.vendor_boot.write(pack('Q', args.base + args.dtb_offset)) # dtb physical load address
104+
pad_file(args.vendor_boot, args.pagesize)
105+
64106
def write_header(args):
65107
BOOT_IMAGE_HEADER_V1_SIZE = 1648
66108
BOOT_IMAGE_HEADER_V2_SIZE = 1660
67109
BOOT_MAGIC = 'ANDROID!'.encode()
68110

69-
if (args.header_version > 2):
111+
if args.header_version > 3:
70112
raise ValueError('Boot header version %d not supported' % args.header_version)
113+
elif args.header_version == 3:
114+
return write_header_v3(args)
71115

72116
args.output.write(pack('8s', BOOT_MAGIC))
73117
final_ramdisk_offset = (args.base + args.ramdisk_offset) if filesize(args.ramdisk) > 0 else 0
74118
final_second_offset = (args.base + args.second_offset) if filesize(args.second) > 0 else 0
75-
args.output.write(pack('10I',
119+
args.output.write(pack(
120+
'10I',
76121
filesize(args.kernel), # size in bytes
77122
args.base + args.kernel_offset, # physical load addr
78123
filesize(args.ramdisk), # size in bytes
@@ -115,6 +160,10 @@ def write_header(args):
115160
args.output.write(pack('I', BOOT_IMAGE_HEADER_V2_SIZE))
116161

117162
if args.header_version > 1:
163+
164+
# if filesize(args.dtb) == 0:
165+
# raise ValueError("DTB image must not be empty.")
166+
118167
args.output.write(pack('I', filesize(args.dtb))) # size in bytes
119168
args.output.write(pack('Q', args.base + args.dtb_offset)) # dtb physical load address
120169
pad_file(args.output, args.pagesize)
@@ -131,8 +180,8 @@ class ValidateStrLenAction(Action):
131180

132181
def __call__(self, parser, namespace, values, option_string=None):
133182
if len(values) > self.maxlen:
134-
raise ValueError('String argument too long: max {0:d}, got {1:d}'.
135-
format(self.maxlen, len(values)))
183+
raise ValueError(
184+
'String argument too long: max {0:d}, got {1:d}'.format(self.maxlen, len(values)))
136185
setattr(namespace, self.dest, values)
137186

138187

@@ -146,6 +195,7 @@ def write_padded_file(f_out, f_in, padding):
146195
def parse_int(x):
147196
return int(x, 0)
148197

198+
149199
def parse_os_version(x):
150200
match = re.search(r'^(\d{1,3})(?:\.(\d{1,3})(?:\.(\d{1,3}))?)?', x)
151201
if match:
@@ -162,33 +212,40 @@ def parse_os_version(x):
162212
return (a << 14) | (b << 7) | c
163213
return 0
164214

215+
165216
def parse_os_patch_level(x):
166-
match = re.search(r'^(\d{4})-(\d{2})-(\d{2})', x)
217+
match = re.search(r'^(\d{4})-(\d{2})(?:-(\d{2}))?', x)
167218
if match:
168219
y = int(match.group(1)) - 2000
169220
m = int(match.group(2))
170221
# 7 bits allocated for the year, 4 bits for the month
171-
assert y >= 0 and y < 128
172-
assert m > 0 and m <= 12
222+
assert 0 <= y < 128
223+
assert 0 < m <= 12
173224
return (y << 4) | m
174225
return 0
175226

227+
176228
def parse_cmdline():
177229
parser = ArgumentParser()
178-
parser.add_argument('--kernel', help='path to the kernel', type=FileType('rb'),
179-
required=True)
230+
parser.add_argument('--kernel', help='path to the kernel', type=FileType('rb'))
180231
parser.add_argument('--ramdisk', help='path to the ramdisk', type=FileType('rb'))
181232
parser.add_argument('--second', help='path to the 2nd bootloader', type=FileType('rb'))
182233
parser.add_argument('--dtb', help='path to dtb', type=FileType('rb'))
183234
recovery_dtbo_group = parser.add_mutually_exclusive_group()
184-
recovery_dtbo_group.add_argument('--recovery_dtbo', help='path to the recovery DTBO', type=FileType('rb'))
235+
recovery_dtbo_group.add_argument('--recovery_dtbo', help='path to the recovery DTBO',
236+
type=FileType('rb'))
185237
recovery_dtbo_group.add_argument('--recovery_acpio', help='path to the recovery ACPIO',
186-
type=FileType('rb'), metavar='RECOVERY_ACPIO', dest='recovery_dtbo')
238+
type=FileType('rb'), metavar='RECOVERY_ACPIO',
239+
dest='recovery_dtbo')
187240
parser.add_argument('--cmdline', help='extra arguments to be passed on the '
188241
'kernel command line', default='', action=ValidateStrLenAction, maxlen=1536)
242+
parser.add_argument('--vendor_cmdline',
243+
help='kernel command line arguments contained in vendor boot',
244+
default='', action=ValidateStrLenAction, maxlen=2048)
189245
parser.add_argument('--base', help='base address', type=parse_int, default=0x10000000)
190246
parser.add_argument('--kernel_offset', help='kernel offset', type=parse_int, default=0x00008000)
191-
parser.add_argument('--ramdisk_offset', help='ramdisk offset', type=parse_int, default=0x01000000)
247+
parser.add_argument('--ramdisk_offset', help='ramdisk offset', type=parse_int,
248+
default=0x01000000)
192249
parser.add_argument('--second_offset', help='2nd bootloader offset', type=parse_int,
193250
default=0x00f00000)
194251
parser.add_argument('--dtb_offset', help='dtb offset', type=parse_int, default=0x01f00000)
@@ -201,34 +258,59 @@ def parse_cmdline():
201258
parser.add_argument('--board', help='board name', default='', action=ValidateStrLenAction,
202259
maxlen=16)
203260
parser.add_argument('--pagesize', help='page size', type=parse_int,
204-
choices=[2**i for i in range(11,15)], default=2048)
261+
choices=[2**i for i in range(11, 15)], default=2048)
205262
parser.add_argument('--id', help='print the image ID on standard output',
206263
action='store_true')
207-
parser.add_argument('--header_version', help='boot image header version', type=parse_int, default=0)
208-
parser.add_argument('-o', '--output', help='output file name', type=FileType('wb'),
209-
required=True)
264+
parser.add_argument('--header_version', help='boot image header version', type=parse_int,
265+
default=0)
266+
parser.add_argument('-o', '--output', help='output file name', type=FileType('wb'))
267+
parser.add_argument('--vendor_boot', help='vendor boot output file name', type=FileType('wb'))
268+
parser.add_argument('--vendor_ramdisk', help='path to the vendor ramdisk', type=FileType('rb'))
269+
210270
return parser.parse_args()
211271

212272

213-
def write_data(args):
214-
write_padded_file(args.output, args.kernel, args.pagesize)
215-
write_padded_file(args.output, args.ramdisk, args.pagesize)
216-
write_padded_file(args.output, args.second, args.pagesize)
273+
def write_data(args, pagesize):
274+
write_padded_file(args.output, args.kernel, pagesize)
275+
write_padded_file(args.output, args.ramdisk, pagesize)
276+
write_padded_file(args.output, args.second, pagesize)
277+
278+
if args.header_version > 0 and args.header_version < 3:
279+
write_padded_file(args.output, args.recovery_dtbo, pagesize)
280+
if args.header_version == 2:
281+
write_padded_file(args.output, args.dtb, pagesize)
282+
283+
284+
def write_vendor_boot_data(args):
285+
write_padded_file(args.vendor_boot, args.vendor_ramdisk, args.pagesize)
286+
write_padded_file(args.vendor_boot, args.dtb, args.pagesize)
217287

218-
if args.header_version > 0:
219-
write_padded_file(args.output, args.recovery_dtbo, args.pagesize)
220-
if args.header_version > 1:
221-
write_padded_file(args.output, args.dtb, args.pagesize)
222288

223289
def main():
224290
args = parse_cmdline()
225-
img_id = write_header(args)
226-
write_data(args)
227-
if args.id:
228-
if isinstance(img_id, str):
291+
if args.vendor_boot is not None:
292+
if args.header_version < 3:
293+
raise ValueError('--vendor_boot not compatible with given header version')
294+
if args.vendor_ramdisk is None:
295+
raise ValueError('--vendor_ramdisk missing or invalid')
296+
write_vendor_boot_header(args)
297+
write_vendor_boot_data(args)
298+
if args.output is not None:
299+
if args.kernel is None:
300+
raise ValueError('kernel must be supplied when creating a boot image')
301+
if args.second is not None and args.header_version > 2:
302+
raise ValueError('--second not compatible with given header version')
303+
img_id = write_header(args)
304+
if args.header_version > 2:
305+
write_data(args, BOOT_IMAGE_HEADER_V3_PAGESIZE)
306+
else:
307+
write_data(args, args.pagesize)
308+
if args.id and img_id is not None:
229309
# Python 2's struct.pack returns a string, but py3 returns bytes.
230-
img_id = [ord(x) for x in img_id]
231-
print('0x' + ''.join('{:02x}'.format(c) for c in img_id))
310+
if isinstance(img_id, str):
311+
img_id = [ord(x) for x in img_id]
312+
print('0x' + ''.join('{:02x}'.format(c) for c in img_id))
313+
232314

233315
if __name__ == '__main__':
234316
main()

scripts/repack-bootimg

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -121,19 +121,8 @@ $srctree/scripts/unpack_bootimg --boot_img $boot_img --out $out > $log
121121
cmdline=$(grep -a "^command line args: " $log | tr '\0' '\n'| sed "s/^command line args: //")
122122
extra_cmdline=$(grep -a "^additional command line args: " $log | tr '\0' '\n'| sed "s/^additional command line args: //")
123123
version=$(grep -a "^boot image header version: " $log | sed "s/^boot image header version: //")
124-
125-
os_version_patch_level=$(grep -a "^os version and patch level: " $log | sed "s/^os version and patch level: //")
126-
127-
v=$(($os_version_patch_level >> 11))
128-
a=$(($v >> 14))
129-
b=$((($v >> 7) & 0x7f))
130-
c=$(($v & 0x7f))
131-
os_version=$(printf '%d.%d.%d' $a $b $c)
132-
133-
v=$(($os_version_patch_level & 0x7ff))
134-
y=$((($v >> 4) + 2000))
135-
m=$((($v & 15)))
136-
os_patch_level=$(printf '%d-%02d-01' $y $m)
124+
os_version=$(grep -a "^os version: " $log | sed "s/^os version: //")
125+
os_patch_level=$(grep -a "^os patch level: " $log | sed "s/^os patch level: //")
137126

138127
dtb_size=$(grep -a "^dtb size: " $log | sed "s/^dtb size: //")
139128
dtb_size=${dtb_size:-0}

0 commit comments

Comments
 (0)