blob: e4b46631682af61f4a3fc5ba7c425170f82b4c03 [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
Jens Wiklander59666602019-10-21 23:17:43 +020018 from elftools.elf.enums import ENUM_RELOC_TYPE_ARM
19 from elftools.elf.enums import ENUM_RELOC_TYPE_AARCH64
Jens Wiklander3c519662019-10-18 16:01:17 +020020 from elftools.elf.sections import SymbolTableSection
Jens Wiklander59666602019-10-21 23:17:43 +020021 from elftools.elf.relocation import RelocationSection
Jens Wiklander3c519662019-10-18 16:01:17 +020022
23except ImportError:
24 print("""
25***
26Can't find elftools module. Probably it is not installed on your system.
27You can install this module with
28
29$ apt install python3-pyelftools
30
31if you are using Ubuntu. Or try to search for "pyelftools" or "elftools" in
32your package manager if you are using some other distribution.
33***
34""")
35 raise
36
37small_page_size = 4 * 1024
38elffile_symbols = None
39tee_pageable_bin = None
40tee_pager_bin = None
Jens Wiklander5dd15702019-10-21 23:17:43 +020041tee_embdata_bin = None
Jens Wiklander3c519662019-10-18 16:01:17 +020042
43
44def eprint(*args, **kwargs):
45 print(*args, file=sys.stderr, **kwargs)
46
47
Jens Wiklander5dd15702019-10-21 23:17:43 +020048def round_up(n, m):
49 if n == 0:
50 return 0
51 else:
52 return (((n - 1) // m) + 1) * m
53
54
55def get_arch_id(elffile):
56 e_machine = elffile.header['e_machine']
57 if e_machine == 'EM_ARM':
58 return 0
59 if e_machine == 'EM_AARCH64':
60 return 1
61 eprint('Unknown e_machine "%s"' % e_machine)
62 sys.exit(1)
63
64
Jens Wiklander3c519662019-10-18 16:01:17 +020065def get_symbol(elffile, name):
66 global elffile_symbols
Jens Wiklanderf77987a2019-11-21 17:29:48 +010067 global lsyms_def
Jens Wiklander3c519662019-10-18 16:01:17 +020068 if elffile_symbols is None:
69 elffile_symbols = dict()
Jens Wiklanderf77987a2019-11-21 17:29:48 +010070 lsyms_def = dict()
Jens Wiklander3c519662019-10-18 16:01:17 +020071 symbol_tables = [s for s in elffile.iter_sections()
72 if isinstance(s, SymbolTableSection)]
73 for section in symbol_tables:
74 for symbol in section.iter_symbols():
75 if symbol['st_info']['bind'] == 'STB_GLOBAL':
76 elffile_symbols[symbol.name] = symbol
Jens Wiklanderf77987a2019-11-21 17:29:48 +010077 elif symbol['st_info']['bind'] == 'STB_LOCAL':
78 if symbol.name not in elffile_symbols.keys():
79 elffile_symbols[symbol.name] = symbol
80 if symbol.name not in lsyms_def.keys():
81 lsyms_def[symbol.name] = 1
82 else:
83 lsyms_def[symbol.name] += 1
Jens Wiklander3c519662019-10-18 16:01:17 +020084
Jens Wiklanderf77987a2019-11-21 17:29:48 +010085 if name in lsyms_def.keys() and lsyms_def[name] > 1:
86 eprint("Multiple definitions of local symbol %s" % name)
87 sys.exit(1)
88 if name not in elffile_symbols.keys():
Jens Wiklander3c519662019-10-18 16:01:17 +020089 eprint("Cannot find symbol %s" % name)
90 sys.exit(1)
91
Jens Wiklanderf77987a2019-11-21 17:29:48 +010092 return elffile_symbols[name]
93
Jens Wiklander3c519662019-10-18 16:01:17 +020094
Jens Wiklander5dd15702019-10-21 23:17:43 +020095def get_sections(elffile, pad_to, dump_names):
Jens Wiklander3c519662019-10-18 16:01:17 +020096 last_end = 0
97 bin_data = bytearray()
98
99 for section in elffile.iter_sections():
100 if (section['sh_type'] == 'SHT_NOBITS' or
101 not (section['sh_flags'] & SH_FLAGS.SHF_ALLOC) or
Jens Wiklander3c519662019-10-18 16:01:17 +0200102 not dump_names.match(section.name)):
103 continue
104
105 if last_end == 0:
106 bin_data = section.data()
107 else:
108 if section['sh_addr'] > last_end:
109 bin_data += bytearray(section['sh_addr'] - last_end)
110 bin_data += section.data()
111
112 last_end = section['sh_addr'] + section['sh_size']
113
114 if pad_to > last_end:
115 bin_data += bytearray(pad_to - last_end)
116 last_end = pad_to
117
118 return bin_data
119
120
121def get_pageable_bin(elffile):
122 global tee_pageable_bin
123 if tee_pageable_bin is None:
124 pad_to = 0
Jens Wiklander3c519662019-10-18 16:01:17 +0200125 dump_names = re.compile(r'^\..*_(pageable|init)$')
Jens Wiklander5dd15702019-10-21 23:17:43 +0200126 tee_pageable_bin = get_sections(elffile, pad_to, dump_names)
Jens Wiklander3c519662019-10-18 16:01:17 +0200127 return tee_pageable_bin
128
129
130def get_pager_bin(elffile):
131 global tee_pager_bin
132 if tee_pager_bin is None:
133 pad_to = get_symbol(elffile, '__data_end')['st_value']
Jens Wiklander5dd15702019-10-21 23:17:43 +0200134 dump_names = re.compile(
Jens Wiklander59666602019-10-21 23:17:43 +0200135 r'^\.(text|rodata|got|data|ARM\.exidx|ARM\.extab)$')
Jens Wiklander5dd15702019-10-21 23:17:43 +0200136 tee_pager_bin = get_sections(elffile, pad_to, dump_names)
Jens Wiklander3c519662019-10-18 16:01:17 +0200137
138 return tee_pager_bin
139
140
Jens Wiklander59666602019-10-21 23:17:43 +0200141def get_reloc_bin(elffile):
142 if get_arch_id(elffile) == 0:
143 exp_rel_type = ENUM_RELOC_TYPE_ARM['R_ARM_RELATIVE']
144 else:
145 exp_rel_type = ENUM_RELOC_TYPE_AARCH64['R_AARCH64_RELATIVE']
146
147 link_address = get_symbol(elffile, '__text_start')['st_value']
148
149 addrs = []
150 for section in elffile.iter_sections():
151 if not isinstance(section, RelocationSection):
152 continue
153 for rel in section.iter_relocations():
154 if rel['r_info_type'] == 0:
155 continue
156 if rel['r_info_type'] != exp_rel_type:
157 eprint("Unexpected relocation type 0x%x" %
158 rel['r_info_type'])
159 sys.exit(1)
160 addrs.append(rel['r_offset'] - link_address)
161
162 addrs.sort()
163 data = bytearray()
164 for a in addrs:
165 data += struct.pack('<I', a)
166
167 # Relocations has been reduced to only become the relative type with
168 # addend at the address (r_offset) of relocation, that is, increase by
169 # load_offset. The addresses (r_offset) are also sorted. The format is
170 # then:
171 # uint32_t: relocation #1
172 # uint32_t: relocation #2
173 # ...
174 # uint32_t: relocation #n
175
176 return data
177
178
Jens Wiklander5dd15702019-10-21 23:17:43 +0200179def get_hashes_bin(elffile):
180 pageable_bin = get_pageable_bin(elffile)
181 if len(pageable_bin) % small_page_size != 0:
182 eprint("pageable size not a multiple of 4K: "
183 "{}".format(paged_area_size))
184 sys.exit(1)
185
186 data = bytearray()
187 for n in range(0, len(pageable_bin), small_page_size):
188 page = pageable_bin[n:n + small_page_size]
189 data += hashlib.sha256(page).digest()
190
191 return data
192
193
194def get_embdata_bin(elffile):
195 global tee_embdata_bin
196 if tee_embdata_bin is None:
197 hashes_bin = get_hashes_bin(elffile)
Jens Wiklander59666602019-10-21 23:17:43 +0200198 reloc_bin = get_reloc_bin(elffile)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200199
Jens Wiklander59666602019-10-21 23:17:43 +0200200 num_entries = 2
Jens Wiklander5dd15702019-10-21 23:17:43 +0200201 hash_offs = 2 * 4 + num_entries * (2 * 4)
202 hash_pad = round_up(len(hashes_bin), 8) - len(hashes_bin)
Jens Wiklander59666602019-10-21 23:17:43 +0200203 reloc_offs = hash_offs + len(hashes_bin) + hash_pad
204 reloc_pad = round_up(len(reloc_bin), 8) - len(reloc_bin)
205 total_len = reloc_offs + len(reloc_bin) + reloc_pad
Jens Wiklander5dd15702019-10-21 23:17:43 +0200206
Jens Wiklander59666602019-10-21 23:17:43 +0200207 tee_embdata_bin = struct.pack('<IIIIII', total_len, num_entries,
208 hash_offs, len(hashes_bin),
209 reloc_offs, len(reloc_bin))
Jens Wiklander5dd15702019-10-21 23:17:43 +0200210 tee_embdata_bin += hashes_bin + bytearray(hash_pad)
Jens Wiklander59666602019-10-21 23:17:43 +0200211 tee_embdata_bin += reloc_bin + bytearray(reloc_pad)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200212
213 # The embedded data region is designed to be easy to extend when
214 # needed, it's formatted as:
Jens Wiklander59666602019-10-21 23:17:43 +0200215 # +---------------------------------------------------------+
216 # | uint32_t: Length of entire area including this field |
217 # +---------------------------------------------------------+
218 # | uint32_t: Number of entries "2" |
219 # +---------------------------------------------------------+
220 # | uint32_t: Offset of hashes from beginning of table |
221 # +---------------------------------------------------------+
222 # | uint32_t: Length of hashes |
223 # +---------------------------------------------------------+
224 # | uint32_t: Offset of relocations from beginning of table |
225 # +---------------------------------------------------------+
226 # | uint32_t: Length of relocations |
227 # +---------------------------------------------------------+
228 # | Data of hashes + eventual padding |
229 # +---------------------------------------------------------+
230 # | Data of relocations + eventual padding |
231 # +---------------------------------------------------------+
Jens Wiklander5dd15702019-10-21 23:17:43 +0200232
233 return tee_embdata_bin
234
235
Jens Wiklander3c519662019-10-18 16:01:17 +0200236def output_pager_bin(elffile, outf):
237 outf.write(get_pager_bin(elffile))
238
239
240def output_pageable_bin(elffile, outf):
241 outf.write(get_pageable_bin(elffile))
242
243
Jens Wiklander3c519662019-10-18 16:01:17 +0200244def get_init_load_addr(elffile):
245 init_load_addr = get_symbol(elffile, '_start')['st_value']
246 init_load_addr_hi = init_load_addr >> 32
247 init_load_addr_lo = init_load_addr & 0xffffffff
248 return init_load_addr_hi, init_load_addr_lo
249
250
251def output_header_v1(elffile, outf):
252 arch_id = get_arch_id(elffile)
253 pager_bin = get_pager_bin(elffile)
254 pageable_bin = get_pageable_bin(elffile)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200255 embdata_bin = get_embdata_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200256 init_load_addr = get_init_load_addr(elffile)
257 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
258 pager_bin_size = len(pager_bin)
259 paged_area_size = len(pageable_bin)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200260
261 init_mem_usage = (get_symbol(elffile, '__init_end')['st_value'] -
262 get_symbol(elffile, '__text_start')['st_value'] +
263 len(embdata_bin))
Jens Wiklander3c519662019-10-18 16:01:17 +0200264
265 init_size = (pager_bin_size + min(init_bin_size, paged_area_size) +
Jens Wiklander5dd15702019-10-21 23:17:43 +0200266 len(embdata_bin))
Jens Wiklander3c519662019-10-18 16:01:17 +0200267 paged_size = paged_area_size - min(init_bin_size, paged_area_size)
268
Jens Wiklander3c519662019-10-18 16:01:17 +0200269 magic = 0x4554504f # 'OPTE'
270 version = 1
271 flags = 0
272 outf.write(struct.pack('<IBBHIIIII', magic, version, arch_id, flags,
273 init_size, init_load_addr[0], init_load_addr[1],
274 init_mem_usage, paged_size))
275 outf.write(pager_bin)
276 outf.write(pageable_bin[:init_bin_size])
Jens Wiklander5dd15702019-10-21 23:17:43 +0200277 outf.write(embdata_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200278 outf.write(pageable_bin[init_bin_size:])
279
280
281def output_header_v2(elffile, outf):
282 arch_id = get_arch_id(elffile)
283 init_load_addr = get_init_load_addr(elffile)
284 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
285 pager_bin_size = len(get_pager_bin(elffile))
286 paged_area_size = len(get_pageable_bin(elffile))
Jens Wiklander5dd15702019-10-21 23:17:43 +0200287 embdata_bin_size = len(get_embdata_bin(elffile))
Jens Wiklander3c519662019-10-18 16:01:17 +0200288
289 init_size = (pager_bin_size + min(init_bin_size, paged_area_size) +
Jens Wiklander5dd15702019-10-21 23:17:43 +0200290 embdata_bin_size)
Jens Wiklander3c519662019-10-18 16:01:17 +0200291 paged_size = paged_area_size - min(init_bin_size, paged_area_size)
292
293 magic = 0x4554504f # 'OPTE'
294 version = 2
295 flags = 0
296 nb_images = 1 if paged_size == 0 else 2
297 outf.write(struct.pack('<IBBHI', magic, version, arch_id, flags,
298 nb_images))
299 outf.write(struct.pack('<IIII', init_load_addr[0], init_load_addr[1],
300 0, init_size))
301 if nb_images == 2:
302 outf.write(struct.pack('<IIII', 0xffffffff, 0xffffffff, 1, paged_size))
303
304
305def output_pager_v2(elffile, outf):
306 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
Jens Wiklander5dd15702019-10-21 23:17:43 +0200307 pager_bin = get_pager_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200308 pageable_bin = get_pageable_bin(elffile)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200309 embdata_bin = get_embdata_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200310
Jens Wiklander5dd15702019-10-21 23:17:43 +0200311 outf.write(pager_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200312 outf.write(pageable_bin[:init_bin_size])
Jens Wiklander5dd15702019-10-21 23:17:43 +0200313 outf.write(embdata_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200314
315
316def output_pageable_v2(elffile, outf):
317 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
318 outf.write(get_pageable_bin(elffile)[init_bin_size:])
319
320
321def get_args():
322 parser = argparse.ArgumentParser()
323
324 parser.add_argument('--input',
325 required=True, type=argparse.FileType('rb'),
326 help='The input tee.elf')
327
328 parser.add_argument('--out_tee_bin',
329 required=False, type=argparse.FileType('wb'),
330 help='The output tee.bin')
331
332 parser.add_argument('--out_tee_pager_bin',
333 required=False, type=argparse.FileType('wb'),
334 help='The output tee_pager.bin')
335
336 parser.add_argument('--out_tee_pageable_bin',
337 required=False, type=argparse.FileType('wb'),
338 help='The output tee_pageable.bin')
339
340 parser.add_argument('--out_header_v2',
341 required=False, type=argparse.FileType('wb'),
342 help='The output tee_header_v2.bin')
343
344 parser.add_argument('--out_pager_v2',
345 required=False, type=argparse.FileType('wb'),
346 help='The output tee_pager_v2.bin')
347
348 parser.add_argument('--out_pageable_v2',
349 required=False, type=argparse.FileType('wb'),
350 help='The output tee_pageable_v2.bin')
351
352 return parser.parse_args()
353
354
355def main():
356 args = get_args()
357
358 elffile = ELFFile(args.input)
359
360 if args.out_tee_bin:
361 output_header_v1(elffile, args.out_tee_bin)
362
363 if args.out_tee_pager_bin:
364 output_pager_bin(elffile, args.out_tee_pager_bin)
365
366 if args.out_tee_pageable_bin:
367 output_pageable_bin(elffile, args.out_tee_pageable_bin)
368
369 if args.out_header_v2:
370 output_header_v2(elffile, args.out_header_v2)
371
372 if args.out_pager_v2:
373 output_pager_v2(elffile, args.out_pager_v2)
374
375 if args.out_pageable_v2:
376 output_pageable_v2(elffile, args.out_pageable_v2)
377
378
379if __name__ == "__main__":
380 main()