source: mainline/tools/deploy/hikey960/mkfastboot

Last change on this file was c21cc26, checked in by Martin Decky <martin@…>, 4 years ago

Fastboot deployment script for HiKey 960

Convenience script to deploy HelenOS to the HiKey 960 board using the
fastboot mechanism.

  • Property mode set to 100755
File size: 6.8 KB
Line 
1#!/usr/bin/env python
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
17from __future__ import print_function
18from sys import argv, exit, stderr
19from argparse import ArgumentParser, FileType, Action
20from os import fstat
21from struct import pack
22from hashlib import sha1
23import sys
24import re
25
26def 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
33
34def 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))
41
42def pad_file(f, padding):
43 pad = (padding - (f.tell() & (padding - 1))) & (padding - 1)
44 f.write(pack(str(pad) + 'x'))
45
46def write_header(args):
47 BOOT_MAGIC = 'ANDROID!'.encode()
48 dt_addr = args.tags_addr
49
50 if 0 == dt_addr:
51 dt_addr = args.base + args.tags_offset
52
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()))
67
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())
73
74 args.output.write(img_id)
75 args.output.write(pack('1024s', args.cmdline[512:].encode()))
76 pad_file(args.output, args.pagesize)
77
78 return img_id
79
80class 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')
84
85 self.maxlen = int(kwargs['maxlen'])
86 del kwargs['maxlen']
87 super(ValidateStrLenAction, self).__init__(option_strings, dest, **kwargs)
88
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)
94
95def write_padded_file(f_out, f_in, padding):
96 if f_in is None:
97 return
98
99 f_out.write(f_in.read())
100 pad_file(f_out, padding)
101
102def parse_int(x):
103 return int(x, 0)
104
105def 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
111
112 if match.lastindex >= 2:
113 b = int(match.group(2))
114
115 if match.lastindex == 3:
116 c = int(match.group(3))
117
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
123
124 return 0
125
126def 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))
131
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
136
137 return 0
138
139def 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()
167
168def 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)
172
173def 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]
181
182 print('0x' + ''.join('{:02x}'.format(c) for c in img_id))
183
184if __name__ == '__main__':
185 main()
Note: See TracBrowser for help on using the repository browser.