source: mainline/tools/deploy/hikey960/mkfastboot@ 1bf25cc

Last change on this file since 1bf25cc was 1bf25cc, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Update mkfastboot and add license files for Apache-2.0 and BSD-2-Clause

  • Property mode set to 100755
File size: 6.3 KB
Line 
1#!/usr/bin/env python
2#
3# SPDX-FileCopyrightText: 2015 The Android Open Source Project
4#
5# SPDX-License-Identifier: Apache-2.0
6#
7
8from __future__ import print_function
9from sys import argv, exit, stderr
10from argparse import ArgumentParser, FileType, Action
11from os import fstat
12from struct import pack
13from hashlib import sha1
14import sys
15import re
16
17def filesize(f):
18 if f is None:
19 return 0
20 try:
21 return fstat(f.fileno()).st_size
22 except OSError:
23 return 0
24
25def update_sha(sha, f):
26 if f:
27 sha.update(f.read())
28 f.seek(0)
29 sha.update(pack('I', filesize(f)))
30 else:
31 sha.update(pack('I', 0))
32
33def pad_file(f, padding):
34 pad = (padding - (f.tell() & (padding - 1))) & (padding - 1)
35 f.write(pack(str(pad) + 'x'))
36
37def write_header(args):
38 BOOT_MAGIC = 'ANDROID!'.encode()
39 dt_addr = args.tags_addr
40
41 if 0 == dt_addr:
42 dt_addr = args.base + args.tags_offset
43
44 args.output.write(pack('8s', BOOT_MAGIC))
45 args.output.write(pack('10I',
46 filesize(args.kernel), # size in bytes
47 args.base + args.kernel_offset, # physical load addr
48 filesize(args.ramdisk), # size in bytes
49 args.base + args.ramdisk_offset, # physical load addr
50 filesize(args.second), # size in bytes
51 args.base + args.second_offset, # physical load addr
52 dt_addr, # physical addr for kernel tags
53 args.pagesize, # flash page size we assume
54 0, # future expansion: MUST be 0
55 (args.os_version << 11) | args.os_patch_level)) # os version and patch level
56 args.output.write(pack('16s', args.board.encode())) # asciiz product name
57 args.output.write(pack('512s', args.cmdline[:512].encode()))
58
59 sha = sha1()
60 update_sha(sha, args.kernel)
61 update_sha(sha, args.ramdisk)
62 update_sha(sha, args.second)
63 img_id = pack('32s', sha.digest())
64
65 args.output.write(img_id)
66 args.output.write(pack('1024s', args.cmdline[512:].encode()))
67 pad_file(args.output, args.pagesize)
68
69 return img_id
70
71class ValidateStrLenAction(Action):
72 def __init__(self, option_strings, dest, nargs=None, **kwargs):
73 if 'maxlen' not in kwargs:
74 raise ValueError('maxlen must be set')
75
76 self.maxlen = int(kwargs['maxlen'])
77 del kwargs['maxlen']
78 super(ValidateStrLenAction, self).__init__(option_strings, dest, **kwargs)
79
80 def __call__(self, parser, namespace, values, option_string=None):
81 if len(values) > self.maxlen:
82 raise ValueError('String argument too long: max {0:d}, got {1:d}'.
83 format(self.maxlen, len(values)))
84 setattr(namespace, self.dest, values)
85
86def write_padded_file(f_out, f_in, padding):
87 if f_in is None:
88 return
89
90 f_out.write(f_in.read())
91 pad_file(f_out, padding)
92
93def parse_int(x):
94 return int(x, 0)
95
96def parse_os_version(x):
97 match = re.search(r'^(\d{1,3})(?:\.(\d{1,3})(?:\.(\d{1,3}))?)?', x)
98 if match:
99 a = int(match.group(1))
100 b = 0
101 c = 0
102
103 if match.lastindex >= 2:
104 b = int(match.group(2))
105
106 if match.lastindex == 3:
107 c = int(match.group(3))
108
109 # 7 bits allocated for each field
110 assert a < 128
111 assert b < 128
112 assert c < 128
113 return (a << 14) | (b << 7) | c
114
115 return 0
116
117def parse_os_patch_level(x):
118 match = re.search(r'^(\d{4})-(\d{2})-(\d{2})', x)
119 if match:
120 y = int(match.group(1)) - 2000
121 m = int(match.group(2))
122
123 # 7 bits allocated for the year, 4 bits for the month
124 assert y >= 0 and y < 128
125 assert m > 0 and m <= 12
126 return (y << 4) | m
127
128 return 0
129
130def parse_cmdline():
131 parser = ArgumentParser()
132 parser.add_argument('--kernel', help='path to the kernel', type=FileType('rb'),
133 required=True)
134 parser.add_argument('--ramdisk', help='path to the ramdisk', type=FileType('rb'))
135 parser.add_argument('--second', help='path to the 2nd bootloader', type=FileType('rb'))
136 parser.add_argument('--cmdline', help='extra arguments to be passed on the '
137 'kernel command line', default='', action=ValidateStrLenAction, maxlen=1536)
138 parser.add_argument('--base', help='base address', type=parse_int, default=0x10000000)
139 parser.add_argument('--tags-addr', help='tags addr', type=parse_int, default=0x0)
140 parser.add_argument('--kernel_offset', help='kernel offset', type=parse_int, default=0x00008000)
141 parser.add_argument('--ramdisk_offset', help='ramdisk offset', type=parse_int, default=0x01000000)
142 parser.add_argument('--second_offset', help='2nd bootloader offset', type=parse_int,
143 default=0x00f00000)
144 parser.add_argument('--os_version', help='operating system version', type=parse_os_version,
145 default=0)
146 parser.add_argument('--os_patch_level', help='operating system patch level',
147 type=parse_os_patch_level, default=0)
148 parser.add_argument('--tags_offset', help='tags offset', type=parse_int, default=0x00000100)
149 parser.add_argument('--board', help='board name', default='', action=ValidateStrLenAction,
150 maxlen=16)
151 parser.add_argument('--pagesize', help='page size', type=parse_int,
152 choices=[2**i for i in range(11,15)], default=2048)
153 parser.add_argument('--id', help='print the image ID on standard output',
154 action='store_true')
155 parser.add_argument('-o', '--output', help='output file name', type=FileType('wb'),
156 required=True)
157 return parser.parse_args()
158
159def write_data(args):
160 write_padded_file(args.output, args.kernel, args.pagesize)
161 write_padded_file(args.output, args.ramdisk, args.pagesize)
162 write_padded_file(args.output, args.second, args.pagesize)
163
164def main():
165 args = parse_cmdline()
166 img_id = write_header(args)
167 write_data(args)
168 if args.id:
169 if isinstance(img_id, str):
170 # Python 2's struct.pack returns a string, but py3 returns bytes.
171 img_id = [ord(x) for x in img_id]
172
173 print('0x' + ''.join('{:02x}'.format(c) for c in img_id))
174
175if __name__ == '__main__':
176 main()
Note: See TracBrowser for help on using the repository browser.