blob: 3afacf530dee9c23379cf9f5d62f2200e04f363d [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
38
39
40def eprint(*args, **kwargs):
41 print(*args, file=sys.stderr, **kwargs)
42
43
44def get_symbol(elffile, name):
45 global elffile_symbols
46 if elffile_symbols is None:
47 elffile_symbols = dict()
48 symbol_tables = [s for s in elffile.iter_sections()
49 if isinstance(s, SymbolTableSection)]
50 for section in symbol_tables:
51 for symbol in section.iter_symbols():
52 if symbol['st_info']['bind'] == 'STB_GLOBAL':
53 elffile_symbols[symbol.name] = symbol
54
55 try:
56 return elffile_symbols[name]
57 except (KeyError):
58 eprint("Cannot find symbol %s" % name)
59 sys.exit(1)
60
61
62def get_sections(elffile, pad_to, skip_names, dump_names):
63 last_end = 0
64 bin_data = bytearray()
65
66 for section in elffile.iter_sections():
67 if (section['sh_type'] == 'SHT_NOBITS' or
68 not (section['sh_flags'] & SH_FLAGS.SHF_ALLOC) or
69 skip_names.match(section.name) or
70 not dump_names.match(section.name)):
71 continue
72
73 if last_end == 0:
74 bin_data = section.data()
75 else:
76 if section['sh_addr'] > last_end:
77 bin_data += bytearray(section['sh_addr'] - last_end)
78 bin_data += section.data()
79
80 last_end = section['sh_addr'] + section['sh_size']
81
82 if pad_to > last_end:
83 bin_data += bytearray(pad_to - last_end)
84 last_end = pad_to
85
86 return bin_data
87
88
89def get_pageable_bin(elffile):
90 global tee_pageable_bin
91 if tee_pageable_bin is None:
92 pad_to = 0
93 skip_names = re.compile(r'^$')
94 dump_names = re.compile(r'^\..*_(pageable|init)$')
95 tee_pageable_bin = get_sections(elffile, pad_to, skip_names,
96 dump_names)
97 return tee_pageable_bin
98
99
100def get_pager_bin(elffile):
101 global tee_pager_bin
102 if tee_pager_bin is None:
103 pad_to = get_symbol(elffile, '__data_end')['st_value']
104 skip_names = re.compile(r'^\..*_(pageable|init)$')
105 dump_names = re.compile(r'')
106 tee_pager_bin = get_sections(elffile, pad_to, skip_names, dump_names)
107
108 return tee_pager_bin
109
110
111def output_pager_bin(elffile, outf):
112 outf.write(get_pager_bin(elffile))
113
114
115def output_pageable_bin(elffile, outf):
116 outf.write(get_pageable_bin(elffile))
117
118
119def get_arch_id(elffile):
120 e_machine = elffile.header['e_machine']
121 if e_machine == 'EM_ARM':
122 return 0
123 if e_machine == 'EM_AARCH64':
124 return 1
125 eprint('Unknown e_machine "%s"' % e_machine)
126 sys.exit(1)
127
128
129def get_init_load_addr(elffile):
130 init_load_addr = get_symbol(elffile, '_start')['st_value']
131 init_load_addr_hi = init_load_addr >> 32
132 init_load_addr_lo = init_load_addr & 0xffffffff
133 return init_load_addr_hi, init_load_addr_lo
134
135
136def output_header_v1(elffile, outf):
137 arch_id = get_arch_id(elffile)
138 pager_bin = get_pager_bin(elffile)
139 pageable_bin = get_pageable_bin(elffile)
140 init_mem_usage = get_symbol(elffile, '__init_mem_usage')['st_value']
141 init_load_addr = get_init_load_addr(elffile)
142 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
143 pager_bin_size = len(pager_bin)
144 paged_area_size = len(pageable_bin)
145 hash_size = (paged_area_size // small_page_size *
146 hashlib.sha256().digest_size)
147
148 init_size = (pager_bin_size + min(init_bin_size, paged_area_size) +
149 hash_size)
150 paged_size = paged_area_size - min(init_bin_size, paged_area_size)
151
152 if paged_area_size % small_page_size != 0:
153 eprint("pageable size not a multiple of 4K: "
154 "{}".format(paged_area_size))
155 sys.exit(1)
156
157 magic = 0x4554504f # 'OPTE'
158 version = 1
159 flags = 0
160 outf.write(struct.pack('<IBBHIIIII', magic, version, arch_id, flags,
161 init_size, init_load_addr[0], init_load_addr[1],
162 init_mem_usage, paged_size))
163 outf.write(pager_bin)
164 outf.write(pageable_bin[:init_bin_size])
165 for n in range(0, len(pageable_bin), small_page_size):
166 page = pageable_bin[n:n + small_page_size]
167 outf.write(hashlib.sha256(page).digest())
168 outf.write(pageable_bin[init_bin_size:])
169
170
171def output_header_v2(elffile, outf):
172 arch_id = get_arch_id(elffile)
173 init_load_addr = get_init_load_addr(elffile)
174 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
175 pager_bin_size = len(get_pager_bin(elffile))
176 paged_area_size = len(get_pageable_bin(elffile))
177 hash_size = (paged_area_size // small_page_size *
178 hashlib.sha256().digest_size)
179
180 if paged_area_size % small_page_size != 0:
181 eprint("pageable size not a multiple of 4K: "
182 "{}".format(paged_area_size))
183 sys.exit(1)
184
185 init_size = (pager_bin_size + min(init_bin_size, paged_area_size) +
186 hash_size)
187 paged_size = paged_area_size - min(init_bin_size, paged_area_size)
188
189 magic = 0x4554504f # 'OPTE'
190 version = 2
191 flags = 0
192 nb_images = 1 if paged_size == 0 else 2
193 outf.write(struct.pack('<IBBHI', magic, version, arch_id, flags,
194 nb_images))
195 outf.write(struct.pack('<IIII', init_load_addr[0], init_load_addr[1],
196 0, init_size))
197 if nb_images == 2:
198 outf.write(struct.pack('<IIII', 0xffffffff, 0xffffffff, 1, paged_size))
199
200
201def output_pager_v2(elffile, outf):
202 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
203 pageable_bin = get_pageable_bin(elffile)
204
205 if len(pageable_bin) % small_page_size != 0:
206 eprint("pageable size not a multiple of 4K: "
207 "{}".format(paged_area_size))
208 sys.exit(1)
209
210 outf.write(get_pager_bin(elffile))
211 outf.write(pageable_bin[:init_bin_size])
212 for n in range(0, len(pageable_bin), small_page_size):
213 page = pageable_bin[n:n + small_page_size]
214 outf.write(hashlib.sha256(page).digest())
215
216
217def output_pageable_v2(elffile, outf):
218 init_bin_size = get_symbol(elffile, '__init_size')['st_value']
219 outf.write(get_pageable_bin(elffile)[init_bin_size:])
220
221
222def get_args():
223 parser = argparse.ArgumentParser()
224
225 parser.add_argument('--input',
226 required=True, type=argparse.FileType('rb'),
227 help='The input tee.elf')
228
229 parser.add_argument('--out_tee_bin',
230 required=False, type=argparse.FileType('wb'),
231 help='The output tee.bin')
232
233 parser.add_argument('--out_tee_pager_bin',
234 required=False, type=argparse.FileType('wb'),
235 help='The output tee_pager.bin')
236
237 parser.add_argument('--out_tee_pageable_bin',
238 required=False, type=argparse.FileType('wb'),
239 help='The output tee_pageable.bin')
240
241 parser.add_argument('--out_header_v2',
242 required=False, type=argparse.FileType('wb'),
243 help='The output tee_header_v2.bin')
244
245 parser.add_argument('--out_pager_v2',
246 required=False, type=argparse.FileType('wb'),
247 help='The output tee_pager_v2.bin')
248
249 parser.add_argument('--out_pageable_v2',
250 required=False, type=argparse.FileType('wb'),
251 help='The output tee_pageable_v2.bin')
252
253 return parser.parse_args()
254
255
256def main():
257 args = get_args()
258
259 elffile = ELFFile(args.input)
260
261 if args.out_tee_bin:
262 output_header_v1(elffile, args.out_tee_bin)
263
264 if args.out_tee_pager_bin:
265 output_pager_bin(elffile, args.out_tee_pager_bin)
266
267 if args.out_tee_pageable_bin:
268 output_pageable_bin(elffile, args.out_tee_pageable_bin)
269
270 if args.out_header_v2:
271 output_header_v2(elffile, args.out_header_v2)
272
273 if args.out_pager_v2:
274 output_pager_v2(elffile, args.out_pager_v2)
275
276 if args.out_pageable_v2:
277 output_pageable_v2(elffile, args.out_pageable_v2)
278
279
280if __name__ == "__main__":
281 main()