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