blob: 5d1d2acfb826681789b607d0aa918460c8853f38 [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(
Jens Wiklander59666602019-10-21 23:17:43 +0200147 r'^\.(text|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
263def output_header_v1(elffile, outf):
264 arch_id = get_arch_id(elffile)
265 pager_bin = get_pager_bin(elffile)
266 pageable_bin = get_pageable_bin(elffile)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200267 embdata_bin = get_embdata_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200268 init_load_addr = get_init_load_addr(elffile)
269 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
270 pager_bin_size = len(pager_bin)
271 paged_area_size = len(pageable_bin)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200272
Jens Wiklander55c1b942019-12-10 10:17:00 +0100273 init_mem_usage = (get_symbol(elffile, '__get_tee_init_end')['st_value'] -
Jens Wiklander5dd15702019-10-21 23:17:43 +0200274 get_symbol(elffile, '__text_start')['st_value'] +
275 len(embdata_bin))
Jens Wiklander3c519662019-10-18 16:01:17 +0200276
277 init_size = (pager_bin_size + min(init_bin_size, paged_area_size) +
Jens Wiklander5dd15702019-10-21 23:17:43 +0200278 len(embdata_bin))
Jens Wiklander3c519662019-10-18 16:01:17 +0200279 paged_size = paged_area_size - min(init_bin_size, paged_area_size)
280
Jens Wiklander3c519662019-10-18 16:01:17 +0200281 magic = 0x4554504f # 'OPTE'
282 version = 1
283 flags = 0
284 outf.write(struct.pack('<IBBHIIIII', magic, version, arch_id, flags,
285 init_size, init_load_addr[0], init_load_addr[1],
286 init_mem_usage, paged_size))
287 outf.write(pager_bin)
288 outf.write(pageable_bin[:init_bin_size])
Jens Wiklander5dd15702019-10-21 23:17:43 +0200289 outf.write(embdata_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200290 outf.write(pageable_bin[init_bin_size:])
291
292
293def output_header_v2(elffile, outf):
294 arch_id = get_arch_id(elffile)
295 init_load_addr = get_init_load_addr(elffile)
296 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
297 pager_bin_size = len(get_pager_bin(elffile))
298 paged_area_size = len(get_pageable_bin(elffile))
Jens Wiklander5dd15702019-10-21 23:17:43 +0200299 embdata_bin_size = len(get_embdata_bin(elffile))
Jens Wiklander3c519662019-10-18 16:01:17 +0200300
301 init_size = (pager_bin_size + min(init_bin_size, paged_area_size) +
Jens Wiklander5dd15702019-10-21 23:17:43 +0200302 embdata_bin_size)
Jens Wiklander3c519662019-10-18 16:01:17 +0200303 paged_size = paged_area_size - min(init_bin_size, paged_area_size)
304
305 magic = 0x4554504f # 'OPTE'
306 version = 2
307 flags = 0
308 nb_images = 1 if paged_size == 0 else 2
309 outf.write(struct.pack('<IBBHI', magic, version, arch_id, flags,
310 nb_images))
311 outf.write(struct.pack('<IIII', init_load_addr[0], init_load_addr[1],
312 0, init_size))
313 if nb_images == 2:
314 outf.write(struct.pack('<IIII', 0xffffffff, 0xffffffff, 1, paged_size))
315
316
317def output_pager_v2(elffile, outf):
318 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
Jens Wiklander5dd15702019-10-21 23:17:43 +0200319 pager_bin = get_pager_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200320 pageable_bin = get_pageable_bin(elffile)
Jens Wiklander5dd15702019-10-21 23:17:43 +0200321 embdata_bin = get_embdata_bin(elffile)
Jens Wiklander3c519662019-10-18 16:01:17 +0200322
Jens Wiklander5dd15702019-10-21 23:17:43 +0200323 outf.write(pager_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200324 outf.write(pageable_bin[:init_bin_size])
Jens Wiklander5dd15702019-10-21 23:17:43 +0200325 outf.write(embdata_bin)
Jens Wiklander3c519662019-10-18 16:01:17 +0200326
327
328def output_pageable_v2(elffile, outf):
329 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
330 outf.write(get_pageable_bin(elffile)[init_bin_size:])
331
332
333def get_args():
334 parser = argparse.ArgumentParser()
335
336 parser.add_argument('--input',
337 required=True, type=argparse.FileType('rb'),
338 help='The input tee.elf')
339
340 parser.add_argument('--out_tee_bin',
341 required=False, type=argparse.FileType('wb'),
342 help='The output tee.bin')
343
344 parser.add_argument('--out_tee_pager_bin',
345 required=False, type=argparse.FileType('wb'),
346 help='The output tee_pager.bin')
347
348 parser.add_argument('--out_tee_pageable_bin',
349 required=False, type=argparse.FileType('wb'),
350 help='The output tee_pageable.bin')
351
352 parser.add_argument('--out_header_v2',
353 required=False, type=argparse.FileType('wb'),
354 help='The output tee_header_v2.bin')
355
356 parser.add_argument('--out_pager_v2',
357 required=False, type=argparse.FileType('wb'),
358 help='The output tee_pager_v2.bin')
359
360 parser.add_argument('--out_pageable_v2',
361 required=False, type=argparse.FileType('wb'),
362 help='The output tee_pageable_v2.bin')
363
364 return parser.parse_args()
365
366
367def main():
368 args = get_args()
369
370 elffile = ELFFile(args.input)
371
372 if args.out_tee_bin:
373 output_header_v1(elffile, args.out_tee_bin)
374
375 if args.out_tee_pager_bin:
376 output_pager_bin(elffile, args.out_tee_pager_bin)
377
378 if args.out_tee_pageable_bin:
379 output_pageable_bin(elffile, args.out_tee_pageable_bin)
380
381 if args.out_header_v2:
382 output_header_v2(elffile, args.out_header_v2)
383
384 if args.out_pager_v2:
385 output_pager_v2(elffile, args.out_pager_v2)
386
387 if args.out_pageable_v2:
388 output_pageable_v2(elffile, args.out_pageable_v2)
389
390
391if __name__ == "__main__":
392 main()