blob: 675ae247d7d3c1a21c626b54cd9e85f040040673 [file] [log] [blame]
Jens Wiklander3c519662019-10-18 16:01:17 +02001#!/usr/bin/env python3
2# SPDX-License-Identifier: BSD-2-Clause
3#
4# Copyright (c) 2019, Linaro Limited
5#
6
7from __future__ import print_function
8from __future__ import division
9
10import argparse
11import sys
12import struct
13import re
14import hashlib
15try:
16 from elftools.elf.elffile import ELFFile
17 from elftools.elf.constants import SH_FLAGS
18 from elftools.elf.sections import SymbolTableSection
19
20except ImportError:
21 print("""
22***
23Can't find elftools module. Probably it is not installed on your system.
24You can install this module with
25
26$ apt install python3-pyelftools
27
28if you are using Ubuntu. Or try to search for "pyelftools" or "elftools" in
29your package manager if you are using some other distribution.
30***
31""")
32 raise
33
34small_page_size = 4 * 1024
35elffile_symbols = None
36tee_pageable_bin = None
37tee_pager_bin = None
Jens Wiklander5dd15702019-10-21 23:17:43 +020038tee_embdata_bin = None
Jens Wiklander3c519662019-10-18 16:01:17 +020039
40
41def eprint(*args, **kwargs):
42 print(*args, file=sys.stderr, **kwargs)
43
44
Jens Wiklander5dd15702019-10-21 23:17:43 +020045def round_up(n, m):
46 if n == 0:
47 return 0
48 else:
49 return (((n - 1) // m) + 1) * m
50
51
52def get_arch_id(elffile):
53 e_machine = elffile.header['e_machine']
54 if e_machine == 'EM_ARM':
55 return 0
56 if e_machine == 'EM_AARCH64':
57 return 1
58 eprint('Unknown e_machine "%s"' % e_machine)
59 sys.exit(1)
60
61
Jens Wiklander3c519662019-10-18 16:01:17 +020062def get_symbol(elffile, name):
63 global elffile_symbols
64 if elffile_symbols is None:
65 elffile_symbols = dict()
66 symbol_tables = [s for s in elffile.iter_sections()
67 if isinstance(s, SymbolTableSection)]
68 for section in symbol_tables:
69 for symbol in section.iter_symbols():
70 if symbol['st_info']['bind'] == 'STB_GLOBAL':
71 elffile_symbols[symbol.name] = symbol
72
73 try:
74 return elffile_symbols[name]
75 except (KeyError):
76 eprint("Cannot find symbol %s" % name)
77 sys.exit(1)
78
79
Jens Wiklander5dd15702019-10-21 23:17:43 +020080def get_sections(elffile, pad_to, dump_names):
Jens Wiklander3c519662019-10-18 16:01:17 +020081 last_end = 0
82 bin_data = bytearray()
83
84 for section in elffile.iter_sections():
85 if (section['sh_type'] == 'SHT_NOBITS' or
86 not (section['sh_flags'] & SH_FLAGS.SHF_ALLOC) or
Jens Wiklander3c519662019-10-18 16:01:17 +020087 not dump_names.match(section.name)):
88 continue
89
90 if last_end == 0:
91 bin_data = section.data()
92 else:
93 if section['sh_addr'] > last_end:
94 bin_data += bytearray(section['sh_addr'] - last_end)
95 bin_data += section.data()
96
97 last_end = section['sh_addr'] + section['sh_size']
98
99 if pad_to > last_end:
100 bin_data += bytearray(pad_to - last_end)
101 last_end = pad_to
102
103 return bin_data
104
105
106def get_pageable_bin(elffile):
107 global tee_pageable_bin
108 if tee_pageable_bin is None:
109 pad_to = 0
Jens Wiklander3c519662019-10-18 16:01:17 +0200110 dump_names = re.compile(r'^\..*_(pageable|init)$')
Jens Wiklander5dd15702019-10-21 23:17:43 +0200111 tee_pageable_bin = get_sections(elffile, pad_to, dump_names)
Jens Wiklander3c519662019-10-18 16:01:17 +0200112 return tee_pageable_bin
113
114
115def get_pager_bin(elffile):
116 global tee_pager_bin
117 if tee_pager_bin is None:
118 pad_to = get_symbol(elffile, '__data_end')['st_value']
Jens Wiklander5dd15702019-10-21 23:17:43 +0200119 dump_names = re.compile(
120 r'^\.(text|rodata|got|data|ARM\.exidx|ARM\.extab|rel|rela)$')
121 tee_pager_bin = get_sections(elffile, pad_to, dump_names)
Jens Wiklander3c519662019-10-18 16:01:17 +0200122
123 return tee_pager_bin
124
125
Jens Wiklander5dd15702019-10-21 23:17:43 +0200126def get_hashes_bin(elffile):
127 pageable_bin = get_pageable_bin(elffile)
128 if len(pageable_bin) % small_page_size != 0:
129 eprint("pageable size not a multiple of 4K: "
130 "{}".format(paged_area_size))
131 sys.exit(1)
132
133 data = bytearray()
134 for n in range(0, len(pageable_bin), small_page_size):
135 page = pageable_bin[n:n + small_page_size]
136 data += hashlib.sha256(page).digest()
137
138 return data
139
140
141def get_embdata_bin(elffile):
142 global tee_embdata_bin
143 if tee_embdata_bin is None:
144 hashes_bin = get_hashes_bin(elffile)
145
146 num_entries = 1
147 hash_offs = 2 * 4 + num_entries * (2 * 4)
148 hash_pad = round_up(len(hashes_bin), 8) - len(hashes_bin)
149 total_len = hash_offs + len(hashes_bin) + hash_pad
150
151 tee_embdata_bin = struct.pack('<IIII', total_len, num_entries,
152 hash_offs, len(hashes_bin))
153 tee_embdata_bin += hashes_bin + bytearray(hash_pad)
154
155 # The embedded data region is designed to be easy to extend when
156 # needed, it's formatted as:
157 # +--------------------------------------------------------+
158 # | uint32_t: Length of entire area including this field |
159 # +--------------------------------------------------------+
160 # | uint32_t: Number of entries "1" |
161 # +--------------------------------------------------------+
162 # | uint32_t: Offset of hashes from beginning of table |
163 # +--------------------------------------------------------+
164 # | uint32_t: Length of hashes |
165 # +--------------------------------------------------------+
166 # | Data of hashes + eventual padding |
167 # +--------------------------------------------------------+
168
169 return tee_embdata_bin
170
171
Jens Wiklander3c519662019-10-18 16:01:17 +0200172def output_pager_bin(elffile, outf):
173 outf.write(get_pager_bin(elffile))
174
175
176def output_pageable_bin(elffile, outf):
177 outf.write(get_pageable_bin(elffile))
178
179
Jens Wiklander3c519662019-10-18 16:01:17 +0200180def get_init_load_addr(elffile):
181 init_load_addr = get_symbol(elffile, '_start')['st_value']
182 init_load_addr_hi = init_load_addr >> 32
183 init_load_addr_lo = init_load_addr & 0xffffffff
184 return init_load_addr_hi, init_load_addr_lo
185
186
187def output_header_v1(elffile, outf):
188 arch_id = get_arch_id(elffile)
189 pager_bin = get_pager_bin(elffile)
190 pageable_bin = get_pageable_bin(elffile)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200191 embdata_bin = get_embdata_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200192 init_load_addr = get_init_load_addr(elffile)
193 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
194 pager_bin_size = len(pager_bin)
195 paged_area_size = len(pageable_bin)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200196
197 init_mem_usage = (get_symbol(elffile, '__init_end')['st_value'] -
198 get_symbol(elffile, '__text_start')['st_value'] +
199 len(embdata_bin))
Jens Wiklander3c519662019-10-18 16:01:17 +0200200
201 init_size = (pager_bin_size + min(init_bin_size, paged_area_size) +
Jens Wiklander5dd15702019-10-21 23:17:43 +0200202 len(embdata_bin))
Jens Wiklander3c519662019-10-18 16:01:17 +0200203 paged_size = paged_area_size - min(init_bin_size, paged_area_size)
204
Jens Wiklander3c519662019-10-18 16:01:17 +0200205 magic = 0x4554504f # 'OPTE'
206 version = 1
207 flags = 0
208 outf.write(struct.pack('<IBBHIIIII', magic, version, arch_id, flags,
209 init_size, init_load_addr[0], init_load_addr[1],
210 init_mem_usage, paged_size))
211 outf.write(pager_bin)
212 outf.write(pageable_bin[:init_bin_size])
Jens Wiklander5dd15702019-10-21 23:17:43 +0200213 outf.write(embdata_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200214 outf.write(pageable_bin[init_bin_size:])
215
216
217def output_header_v2(elffile, outf):
218 arch_id = get_arch_id(elffile)
219 init_load_addr = get_init_load_addr(elffile)
220 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
221 pager_bin_size = len(get_pager_bin(elffile))
222 paged_area_size = len(get_pageable_bin(elffile))
Jens Wiklander5dd15702019-10-21 23:17:43 +0200223 embdata_bin_size = len(get_embdata_bin(elffile))
Jens Wiklander3c519662019-10-18 16:01:17 +0200224
225 init_size = (pager_bin_size + min(init_bin_size, paged_area_size) +
Jens Wiklander5dd15702019-10-21 23:17:43 +0200226 embdata_bin_size)
Jens Wiklander3c519662019-10-18 16:01:17 +0200227 paged_size = paged_area_size - min(init_bin_size, paged_area_size)
228
229 magic = 0x4554504f # 'OPTE'
230 version = 2
231 flags = 0
232 nb_images = 1 if paged_size == 0 else 2
233 outf.write(struct.pack('<IBBHI', magic, version, arch_id, flags,
234 nb_images))
235 outf.write(struct.pack('<IIII', init_load_addr[0], init_load_addr[1],
236 0, init_size))
237 if nb_images == 2:
238 outf.write(struct.pack('<IIII', 0xffffffff, 0xffffffff, 1, paged_size))
239
240
241def output_pager_v2(elffile, outf):
242 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
Jens Wiklander5dd15702019-10-21 23:17:43 +0200243 pager_bin = get_pager_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200244 pageable_bin = get_pageable_bin(elffile)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200245 embdata_bin = get_embdata_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200246
Jens Wiklander5dd15702019-10-21 23:17:43 +0200247 outf.write(pager_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200248 outf.write(pageable_bin[:init_bin_size])
Jens Wiklander5dd15702019-10-21 23:17:43 +0200249 outf.write(embdata_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200250
251
252def output_pageable_v2(elffile, outf):
253 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
254 outf.write(get_pageable_bin(elffile)[init_bin_size:])
255
256
257def get_args():
258 parser = argparse.ArgumentParser()
259
260 parser.add_argument('--input',
261 required=True, type=argparse.FileType('rb'),
262 help='The input tee.elf')
263
264 parser.add_argument('--out_tee_bin',
265 required=False, type=argparse.FileType('wb'),
266 help='The output tee.bin')
267
268 parser.add_argument('--out_tee_pager_bin',
269 required=False, type=argparse.FileType('wb'),
270 help='The output tee_pager.bin')
271
272 parser.add_argument('--out_tee_pageable_bin',
273 required=False, type=argparse.FileType('wb'),
274 help='The output tee_pageable.bin')
275
276 parser.add_argument('--out_header_v2',
277 required=False, type=argparse.FileType('wb'),
278 help='The output tee_header_v2.bin')
279
280 parser.add_argument('--out_pager_v2',
281 required=False, type=argparse.FileType('wb'),
282 help='The output tee_pager_v2.bin')
283
284 parser.add_argument('--out_pageable_v2',
285 required=False, type=argparse.FileType('wb'),
286 help='The output tee_pageable_v2.bin')
287
288 return parser.parse_args()
289
290
291def main():
292 args = get_args()
293
294 elffile = ELFFile(args.input)
295
296 if args.out_tee_bin:
297 output_header_v1(elffile, args.out_tee_bin)
298
299 if args.out_tee_pager_bin:
300 output_pager_bin(elffile, args.out_tee_pager_bin)
301
302 if args.out_tee_pageable_bin:
303 output_pageable_bin(elffile, args.out_tee_pageable_bin)
304
305 if args.out_header_v2:
306 output_header_v2(elffile, args.out_header_v2)
307
308 if args.out_pager_v2:
309 output_pager_v2(elffile, args.out_pager_v2)
310
311 if args.out_pageable_v2:
312 output_pageable_v2(elffile, args.out_pageable_v2)
313
314
315if __name__ == "__main__":
316 main()