xref: /optee_os/scripts/gen_ldelf_hex.py (revision 7ba36df95867d688e01fd9f65c791ecc8b00c46a)
184c0da04SRouven Czerwinski#!/usr/bin/env python3
2b8c97753SJens Wiklander# SPDX-License-Identifier: BSD-2-Clause
3b8c97753SJens Wiklander#
4b8c97753SJens Wiklander# Copyright (c) 2019, Linaro Limited
5b8c97753SJens Wiklander#
6b8c97753SJens Wiklander
7b8c97753SJens Wiklanderfrom __future__ import print_function
8b8c97753SJens Wiklanderfrom __future__ import division
9b8c97753SJens Wiklander
10b8c97753SJens Wiklanderimport argparse
11b8c97753SJens Wiklanderimport sys
12*7ba36df9SVolodymyr Babchuktry:
13b8c97753SJens Wiklander    from elftools.elf.elffile import ELFFile
14b8c97753SJens Wiklander    from elftools.elf.sections import SymbolTableSection
15b8c97753SJens Wiklander    from elftools.elf.constants import P_FLAGS
16*7ba36df9SVolodymyr Babchukexcept ImportError:
17*7ba36df9SVolodymyr Babchuk    print("""
18*7ba36df9SVolodymyr Babchuk***
19*7ba36df9SVolodymyr BabchukCan't find elftools module. Probably it is not installed on your system.
20*7ba36df9SVolodymyr BabchukYou can install this module with
21*7ba36df9SVolodymyr Babchuk
22*7ba36df9SVolodymyr Babchuk$ apt install python3-pyelftools
23*7ba36df9SVolodymyr Babchuk
24*7ba36df9SVolodymyr Babchukif you are using Ubuntu. Or try to search for "pyelftools" or "elftools" in
25*7ba36df9SVolodymyr Babchukyour package manager if you are using some other distribution.
26*7ba36df9SVolodymyr Babchuk***
27*7ba36df9SVolodymyr Babchuk""")
28*7ba36df9SVolodymyr Babchuk    raise
29*7ba36df9SVolodymyr Babchuk
30b8c97753SJens Wiklanderimport struct
31b8c97753SJens Wiklanderimport re
32b8c97753SJens Wiklanderfrom collections import deque
33b8c97753SJens Wiklander
34b8c97753SJens Wiklander
35b8c97753SJens Wiklanderdef round_up(n, m):
36b8c97753SJens Wiklander    if n == 0:
37b8c97753SJens Wiklander        return 0
38b8c97753SJens Wiklander    else:
39b8c97753SJens Wiklander        return (((n - 1) // m) + 1) * m
40b8c97753SJens Wiklander
41b8c97753SJens Wiklander
42b8c97753SJens Wiklanderdef emit_load_segments(elffile, outf):
43b8c97753SJens Wiklander    load_size = 0
44d2fb6900SJerome Forissier    data_size = 0
45d2fb6900SJerome Forissier    next_rwseg_va = 0
46b8c97753SJens Wiklander    n = 0
47b8c97753SJens Wiklander    for segment in elffile.iter_segments():
48b8c97753SJens Wiklander        if segment['p_type'] == 'PT_LOAD':
49b8c97753SJens Wiklander            if n == 0:
50b8c97753SJens Wiklander                if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_X):
51b8c97753SJens Wiklander                    print('Expected first load segment to be read/execute')
52b8c97753SJens Wiklander                    sys.exit(1)
53b8c97753SJens Wiklander                code_size = segment['p_filesz']
54d2fb6900SJerome Forissier            else:
55b8c97753SJens Wiklander                if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_W):
56d2fb6900SJerome Forissier                    print('Expected load segment to be read/write')
57b8c97753SJens Wiklander                    sys.exit(1)
58d2fb6900SJerome Forissier                if next_rwseg_va and segment['p_vaddr'] != next_rwseg_va:
59d2fb6900SJerome Forissier                    print('Expected contiguous read/write segments')
60d2fb6900SJerome Forissier                    print(segment['p_vaddr'])
61d2fb6900SJerome Forissier                    print(next_rwseg_va)
62b8c97753SJens Wiklander                    sys.exit(1)
63d2fb6900SJerome Forissier                data_size += segment['p_filesz']
64d2fb6900SJerome Forissier                next_rwseg_va = segment['p_vaddr'] + segment['p_filesz']
65b8c97753SJens Wiklander            load_size += segment['p_filesz']
66b8c97753SJens Wiklander            n = n + 1
67b8c97753SJens Wiklander
6884c0da04SRouven Czerwinski    outf.write(b'const uint8_t ldelf_data[%d]' % round_up(load_size, 4096))
6984c0da04SRouven Czerwinski    outf.write(b' __aligned(4096) = {\n')
70b8c97753SJens Wiklander    i = 0
71b8c97753SJens Wiklander    for segment in elffile.iter_segments():
72b8c97753SJens Wiklander        if segment['p_type'] == 'PT_LOAD':
73b8c97753SJens Wiklander            data = segment.data()
74b8c97753SJens Wiklander            for n in range(segment['p_filesz']):
75b8c97753SJens Wiklander                if i % 8 == 0:
7684c0da04SRouven Czerwinski                    outf.write(b'\t')
7784c0da04SRouven Czerwinski                outf.write(b'0x' + '{:02x}'.format(data[n]).encode('utf-8')
7884c0da04SRouven Czerwinski                           + b',')
79b8c97753SJens Wiklander                i = i + 1
80b8c97753SJens Wiklander                if i % 8 == 0 or i == load_size:
8184c0da04SRouven Czerwinski                    outf.write(b'\n')
82b8c97753SJens Wiklander                else:
8384c0da04SRouven Czerwinski                    outf.write(b' ')
8484c0da04SRouven Czerwinski    outf.write(b'};\n')
85b8c97753SJens Wiklander
8684c0da04SRouven Czerwinski    outf.write(b'const unsigned int ldelf_code_size = %d;\n' % code_size)
8784c0da04SRouven Czerwinski    outf.write(b'const unsigned int ldelf_data_size = %d;\n' % data_size)
88b8c97753SJens Wiklander
89b8c97753SJens Wiklander
90b8c97753SJens Wiklanderdef get_args():
91b8c97753SJens Wiklander    parser = argparse.ArgumentParser()
92b8c97753SJens Wiklander
93b8c97753SJens Wiklander    parser.add_argument('--input',
94b8c97753SJens Wiklander                        required=True, type=argparse.FileType('rb'),
95b8c97753SJens Wiklander                        help='The input ldelf.elf')
96b8c97753SJens Wiklander
97b8c97753SJens Wiklander    parser.add_argument('--output',
98b8c97753SJens Wiklander                        required=True, type=argparse.FileType('wb'),
99b8c97753SJens Wiklander                        help='The output ldelf_hex.c')
100b8c97753SJens Wiklander
101b8c97753SJens Wiklander    return parser.parse_args()
102b8c97753SJens Wiklander
103b8c97753SJens Wiklander
104b8c97753SJens Wiklanderdef main():
105b8c97753SJens Wiklander    args = get_args()
106b8c97753SJens Wiklander    inf = args.input
107b8c97753SJens Wiklander    outf = args.output
108b8c97753SJens Wiklander
109b8c97753SJens Wiklander    elffile = ELFFile(inf)
110b8c97753SJens Wiklander
11184c0da04SRouven Czerwinski    outf.write(b'/* Automatically generated, do no edit */\n')
11284c0da04SRouven Czerwinski    outf.write(b'#include <compiler.h>\n')
11384c0da04SRouven Czerwinski    outf.write(b'#include <stdint.h>\n')
114b8c97753SJens Wiklander    emit_load_segments(elffile, outf)
11584c0da04SRouven Czerwinski    outf.write(b'const unsigned long ldelf_entry = %lu;\n' %
116b8c97753SJens Wiklander               elffile.header['e_entry'])
117b8c97753SJens Wiklander
118b8c97753SJens Wiklander    inf.close()
119b8c97753SJens Wiklander    outf.close()
120b8c97753SJens Wiklander
121b8c97753SJens Wiklander
122b8c97753SJens Wiklanderif __name__ == "__main__":
123b8c97753SJens Wiklander    main()
124