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