blob: 90688a306ece5b1148f48e2ef7b1b4cfc715bed8 [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
Jerome Forissier2338a972019-11-22 17:29:24 -080065def get_name(obj):
66 # Symbol or section .name might be a byte array or a string, we want a
67 # string
68 try:
69 name = obj.name.decode()
70 except (UnicodeDecodeError, AttributeError):
71 name = obj.name
72 return name
73
74
Jens Wiklander3c519662019-10-18 16:01:17 +020075def get_symbol(elffile, name):
76 global elffile_symbols
Jens Wiklanderf77987a2019-11-21 17:29:48 +010077 global lsyms_def
Jens Wiklander3c519662019-10-18 16:01:17 +020078 if elffile_symbols is None:
79 elffile_symbols = dict()
Jens Wiklanderf77987a2019-11-21 17:29:48 +010080 lsyms_def = dict()
Jens Wiklander3c519662019-10-18 16:01:17 +020081 symbol_tables = [s for s in elffile.iter_sections()
82 if isinstance(s, SymbolTableSection)]
83 for section in symbol_tables:
84 for symbol in section.iter_symbols():
Jerome Forissier2338a972019-11-22 17:29:24 -080085 symbol_name = get_name(symbol)
Jens Wiklander3c519662019-10-18 16:01:17 +020086 if symbol['st_info']['bind'] == 'STB_GLOBAL':
Jerome Forissier2338a972019-11-22 17:29:24 -080087 elffile_symbols[symbol_name] = symbol
Jens Wiklanderf77987a2019-11-21 17:29:48 +010088 elif symbol['st_info']['bind'] == 'STB_LOCAL':
Jerome Forissier2338a972019-11-22 17:29:24 -080089 if symbol_name not in elffile_symbols.keys():
90 elffile_symbols[symbol_name] = symbol
91 if symbol_name not in lsyms_def.keys():
92 lsyms_def[symbol_name] = 1
Jens Wiklanderf77987a2019-11-21 17:29:48 +010093 else:
Jerome Forissier2338a972019-11-22 17:29:24 -080094 lsyms_def[symbol_name] += 1
Jens Wiklander3c519662019-10-18 16:01:17 +020095
Jens Wiklanderf77987a2019-11-21 17:29:48 +010096 if name in lsyms_def.keys() and lsyms_def[name] > 1:
97 eprint("Multiple definitions of local symbol %s" % name)
98 sys.exit(1)
99 if name not in elffile_symbols.keys():
Jens Wiklander3c519662019-10-18 16:01:17 +0200100 eprint("Cannot find symbol %s" % name)
101 sys.exit(1)
102
Jens Wiklanderf77987a2019-11-21 17:29:48 +0100103 return elffile_symbols[name]
104
Jens Wiklander3c519662019-10-18 16:01:17 +0200105
Jens Wiklander5dd15702019-10-21 23:17:43 +0200106def get_sections(elffile, pad_to, dump_names):
Jens Wiklander3c519662019-10-18 16:01:17 +0200107 last_end = 0
108 bin_data = bytearray()
109
110 for section in elffile.iter_sections():
Jerome Forissier2338a972019-11-22 17:29:24 -0800111 section_name = get_name(section)
Jens Wiklander3c519662019-10-18 16:01:17 +0200112 if (section['sh_type'] == 'SHT_NOBITS' or
113 not (section['sh_flags'] & SH_FLAGS.SHF_ALLOC) or
Jerome Forissier2338a972019-11-22 17:29:24 -0800114 not dump_names.match(section_name)):
Jens Wiklander3c519662019-10-18 16:01:17 +0200115 continue
116
117 if last_end == 0:
118 bin_data = section.data()
119 else:
120 if section['sh_addr'] > last_end:
121 bin_data += bytearray(section['sh_addr'] - last_end)
122 bin_data += section.data()
123
124 last_end = section['sh_addr'] + section['sh_size']
125
126 if pad_to > last_end:
127 bin_data += bytearray(pad_to - last_end)
128 last_end = pad_to
129
130 return bin_data
131
132
133def get_pageable_bin(elffile):
134 global tee_pageable_bin
135 if tee_pageable_bin is None:
136 pad_to = 0
Jens Wiklander3c519662019-10-18 16:01:17 +0200137 dump_names = re.compile(r'^\..*_(pageable|init)$')
Jens Wiklander5dd15702019-10-21 23:17:43 +0200138 tee_pageable_bin = get_sections(elffile, pad_to, dump_names)
Jens Wiklander3c519662019-10-18 16:01:17 +0200139 return tee_pageable_bin
140
141
142def get_pager_bin(elffile):
143 global tee_pager_bin
144 if tee_pager_bin is None:
145 pad_to = get_symbol(elffile, '__data_end')['st_value']
Jens Wiklander5dd15702019-10-21 23:17:43 +0200146 dump_names = re.compile(
Volodymyr Babchuk4b2d8942020-01-23 19:05:38 +0200147 r'^\.(text|nex_data|rodata|got|data|ARM\.exidx|ARM\.extab)$')
Jens Wiklander5dd15702019-10-21 23:17:43 +0200148 tee_pager_bin = get_sections(elffile, pad_to, dump_names)
Jens Wiklander3c519662019-10-18 16:01:17 +0200149
150 return tee_pager_bin
151
152
Jens Wiklander59666602019-10-21 23:17:43 +0200153def get_reloc_bin(elffile):
154 if get_arch_id(elffile) == 0:
155 exp_rel_type = ENUM_RELOC_TYPE_ARM['R_ARM_RELATIVE']
156 else:
157 exp_rel_type = ENUM_RELOC_TYPE_AARCH64['R_AARCH64_RELATIVE']
158
159 link_address = get_symbol(elffile, '__text_start')['st_value']
160
161 addrs = []
162 for section in elffile.iter_sections():
163 if not isinstance(section, RelocationSection):
164 continue
165 for rel in section.iter_relocations():
166 if rel['r_info_type'] == 0:
167 continue
168 if rel['r_info_type'] != exp_rel_type:
169 eprint("Unexpected relocation type 0x%x" %
170 rel['r_info_type'])
171 sys.exit(1)
172 addrs.append(rel['r_offset'] - link_address)
173
174 addrs.sort()
175 data = bytearray()
176 for a in addrs:
177 data += struct.pack('<I', a)
178
179 # Relocations has been reduced to only become the relative type with
180 # addend at the address (r_offset) of relocation, that is, increase by
181 # load_offset. The addresses (r_offset) are also sorted. The format is
182 # then:
183 # uint32_t: relocation #1
184 # uint32_t: relocation #2
185 # ...
186 # uint32_t: relocation #n
187
188 return data
189
190
Jens Wiklander5dd15702019-10-21 23:17:43 +0200191def get_hashes_bin(elffile):
192 pageable_bin = get_pageable_bin(elffile)
193 if len(pageable_bin) % small_page_size != 0:
194 eprint("pageable size not a multiple of 4K: "
195 "{}".format(paged_area_size))
196 sys.exit(1)
197
198 data = bytearray()
199 for n in range(0, len(pageable_bin), small_page_size):
200 page = pageable_bin[n:n + small_page_size]
201 data += hashlib.sha256(page).digest()
202
203 return data
204
205
206def get_embdata_bin(elffile):
207 global tee_embdata_bin
208 if tee_embdata_bin is None:
209 hashes_bin = get_hashes_bin(elffile)
Jens Wiklander59666602019-10-21 23:17:43 +0200210 reloc_bin = get_reloc_bin(elffile)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200211
Jens Wiklander59666602019-10-21 23:17:43 +0200212 num_entries = 2
Jens Wiklander5dd15702019-10-21 23:17:43 +0200213 hash_offs = 2 * 4 + num_entries * (2 * 4)
214 hash_pad = round_up(len(hashes_bin), 8) - len(hashes_bin)
Jens Wiklander59666602019-10-21 23:17:43 +0200215 reloc_offs = hash_offs + len(hashes_bin) + hash_pad
216 reloc_pad = round_up(len(reloc_bin), 8) - len(reloc_bin)
217 total_len = reloc_offs + len(reloc_bin) + reloc_pad
Jens Wiklander5dd15702019-10-21 23:17:43 +0200218
Jens Wiklander59666602019-10-21 23:17:43 +0200219 tee_embdata_bin = struct.pack('<IIIIII', total_len, num_entries,
220 hash_offs, len(hashes_bin),
221 reloc_offs, len(reloc_bin))
Jens Wiklander5dd15702019-10-21 23:17:43 +0200222 tee_embdata_bin += hashes_bin + bytearray(hash_pad)
Jens Wiklander59666602019-10-21 23:17:43 +0200223 tee_embdata_bin += reloc_bin + bytearray(reloc_pad)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200224
225 # The embedded data region is designed to be easy to extend when
226 # needed, it's formatted as:
Jens Wiklander59666602019-10-21 23:17:43 +0200227 # +---------------------------------------------------------+
228 # | uint32_t: Length of entire area including this field |
229 # +---------------------------------------------------------+
230 # | uint32_t: Number of entries "2" |
231 # +---------------------------------------------------------+
232 # | uint32_t: Offset of hashes from beginning of table |
233 # +---------------------------------------------------------+
234 # | uint32_t: Length of hashes |
235 # +---------------------------------------------------------+
236 # | uint32_t: Offset of relocations from beginning of table |
237 # +---------------------------------------------------------+
238 # | uint32_t: Length of relocations |
239 # +---------------------------------------------------------+
240 # | Data of hashes + eventual padding |
241 # +---------------------------------------------------------+
242 # | Data of relocations + eventual padding |
243 # +---------------------------------------------------------+
Jens Wiklander5dd15702019-10-21 23:17:43 +0200244
245 return tee_embdata_bin
246
247
Jens Wiklander3c519662019-10-18 16:01:17 +0200248def output_pager_bin(elffile, outf):
249 outf.write(get_pager_bin(elffile))
250
251
252def output_pageable_bin(elffile, outf):
253 outf.write(get_pageable_bin(elffile))
254
255
Jens Wiklander3c519662019-10-18 16:01:17 +0200256def get_init_load_addr(elffile):
257 init_load_addr = get_symbol(elffile, '_start')['st_value']
258 init_load_addr_hi = init_load_addr >> 32
259 init_load_addr_lo = init_load_addr & 0xffffffff
260 return init_load_addr_hi, init_load_addr_lo
261
262
Volodymyr Babchuk82fa8062020-01-22 19:17:40 +0200263def output_raw_bin(elffile, outf):
264 pager_bin = get_pager_bin(elffile)
265 pageable_bin = get_pageable_bin(elffile)
266 embdata_bin = get_embdata_bin(elffile)
267 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
268
269 outf.write(pager_bin)
270 outf.write(pageable_bin[:init_bin_size])
271 outf.write(embdata_bin)
272 outf.write(pageable_bin[init_bin_size:])
273
274
Jens Wiklander3c519662019-10-18 16:01:17 +0200275def output_header_v1(elffile, outf):
276 arch_id = get_arch_id(elffile)
277 pager_bin = get_pager_bin(elffile)
278 pageable_bin = get_pageable_bin(elffile)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200279 embdata_bin = get_embdata_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200280 init_load_addr = get_init_load_addr(elffile)
281 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
282 pager_bin_size = len(pager_bin)
283 paged_area_size = len(pageable_bin)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200284
Jens Wiklander55c1b942019-12-10 10:17:00 +0100285 init_mem_usage = (get_symbol(elffile, '__get_tee_init_end')['st_value'] -
Jens Wiklander5dd15702019-10-21 23:17:43 +0200286 get_symbol(elffile, '__text_start')['st_value'] +
287 len(embdata_bin))
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 len(embdata_bin))
Jens Wiklander3c519662019-10-18 16:01:17 +0200291 paged_size = paged_area_size - min(init_bin_size, paged_area_size)
292
Jens Wiklander3c519662019-10-18 16:01:17 +0200293 magic = 0x4554504f # 'OPTE'
294 version = 1
295 flags = 0
296 outf.write(struct.pack('<IBBHIIIII', magic, version, arch_id, flags,
297 init_size, init_load_addr[0], init_load_addr[1],
298 init_mem_usage, paged_size))
299 outf.write(pager_bin)
300 outf.write(pageable_bin[:init_bin_size])
Jens Wiklander5dd15702019-10-21 23:17:43 +0200301 outf.write(embdata_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200302 outf.write(pageable_bin[init_bin_size:])
303
304
305def output_header_v2(elffile, outf):
306 arch_id = get_arch_id(elffile)
307 init_load_addr = get_init_load_addr(elffile)
308 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
309 pager_bin_size = len(get_pager_bin(elffile))
310 paged_area_size = len(get_pageable_bin(elffile))
Jens Wiklander5dd15702019-10-21 23:17:43 +0200311 embdata_bin_size = len(get_embdata_bin(elffile))
Jens Wiklander3c519662019-10-18 16:01:17 +0200312
313 init_size = (pager_bin_size + min(init_bin_size, paged_area_size) +
Jens Wiklander5dd15702019-10-21 23:17:43 +0200314 embdata_bin_size)
Jens Wiklander3c519662019-10-18 16:01:17 +0200315 paged_size = paged_area_size - min(init_bin_size, paged_area_size)
316
317 magic = 0x4554504f # 'OPTE'
318 version = 2
319 flags = 0
320 nb_images = 1 if paged_size == 0 else 2
321 outf.write(struct.pack('<IBBHI', magic, version, arch_id, flags,
322 nb_images))
323 outf.write(struct.pack('<IIII', init_load_addr[0], init_load_addr[1],
324 0, init_size))
325 if nb_images == 2:
326 outf.write(struct.pack('<IIII', 0xffffffff, 0xffffffff, 1, paged_size))
327
328
329def output_pager_v2(elffile, outf):
330 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
Jens Wiklander5dd15702019-10-21 23:17:43 +0200331 pager_bin = get_pager_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200332 pageable_bin = get_pageable_bin(elffile)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200333 embdata_bin = get_embdata_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200334
Jens Wiklander5dd15702019-10-21 23:17:43 +0200335 outf.write(pager_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200336 outf.write(pageable_bin[:init_bin_size])
Jens Wiklander5dd15702019-10-21 23:17:43 +0200337 outf.write(embdata_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200338
339
340def output_pageable_v2(elffile, outf):
341 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
342 outf.write(get_pageable_bin(elffile)[init_bin_size:])
343
344
345def get_args():
346 parser = argparse.ArgumentParser()
347
348 parser.add_argument('--input',
349 required=True, type=argparse.FileType('rb'),
350 help='The input tee.elf')
351
352 parser.add_argument('--out_tee_bin',
353 required=False, type=argparse.FileType('wb'),
354 help='The output tee.bin')
355
Volodymyr Babchuk82fa8062020-01-22 19:17:40 +0200356 parser.add_argument('--out_tee_raw_bin',
357 required=False, type=argparse.FileType('wb'),
358 help='The output tee_raw.bin')
359
Jens Wiklander3c519662019-10-18 16:01:17 +0200360 parser.add_argument('--out_tee_pager_bin',
361 required=False, type=argparse.FileType('wb'),
362 help='The output tee_pager.bin')
363
364 parser.add_argument('--out_tee_pageable_bin',
365 required=False, type=argparse.FileType('wb'),
366 help='The output tee_pageable.bin')
367
368 parser.add_argument('--out_header_v2',
369 required=False, type=argparse.FileType('wb'),
370 help='The output tee_header_v2.bin')
371
372 parser.add_argument('--out_pager_v2',
373 required=False, type=argparse.FileType('wb'),
374 help='The output tee_pager_v2.bin')
375
376 parser.add_argument('--out_pageable_v2',
377 required=False, type=argparse.FileType('wb'),
378 help='The output tee_pageable_v2.bin')
379
380 return parser.parse_args()
381
382
383def main():
384 args = get_args()
385
386 elffile = ELFFile(args.input)
387
Volodymyr Babchuk82fa8062020-01-22 19:17:40 +0200388 if args.out_tee_raw_bin:
389 output_raw_bin(elffile, args.out_tee_raw_bin)
390
Jens Wiklander3c519662019-10-18 16:01:17 +0200391 if args.out_tee_bin:
392 output_header_v1(elffile, args.out_tee_bin)
393
394 if args.out_tee_pager_bin:
395 output_pager_bin(elffile, args.out_tee_pager_bin)
396
397 if args.out_tee_pageable_bin:
398 output_pageable_bin(elffile, args.out_tee_pageable_bin)
399
400 if args.out_header_v2:
401 output_header_v2(elffile, args.out_header_v2)
402
403 if args.out_pager_v2:
404 output_pager_v2(elffile, args.out_pager_v2)
405
406 if args.out_pageable_v2:
407 output_pageable_v2(elffile, args.out_pageable_v2)
408
409
410if __name__ == "__main__":
411 main()