xref: /optee_os/scripts/gen_ldelf_hex.py (revision 84c0da042fd5da583a2b95d045e22878d921b78f)
1*84c0da04SRouven 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
12b8c97753SJens Wiklanderfrom elftools.elf.elffile import ELFFile
13b8c97753SJens Wiklanderfrom elftools.elf.sections import SymbolTableSection
14b8c97753SJens Wiklanderfrom elftools.elf.constants import P_FLAGS
15b8c97753SJens Wiklanderimport struct
16b8c97753SJens Wiklanderimport re
17b8c97753SJens Wiklanderfrom collections import deque
18b8c97753SJens Wiklander
19b8c97753SJens Wiklander
20b8c97753SJens Wiklanderdef round_up(n, m):
21b8c97753SJens Wiklander    if n == 0:
22b8c97753SJens Wiklander        return 0
23b8c97753SJens Wiklander    else:
24b8c97753SJens Wiklander        return (((n - 1) // m) + 1) * m
25b8c97753SJens Wiklander
26b8c97753SJens Wiklander
27b8c97753SJens Wiklanderdef emit_load_segments(elffile, outf):
28b8c97753SJens Wiklander    load_size = 0
29b8c97753SJens Wiklander    n = 0
30b8c97753SJens Wiklander    for segment in elffile.iter_segments():
31b8c97753SJens Wiklander        if segment['p_type'] == 'PT_LOAD':
32b8c97753SJens Wiklander            if n == 0:
33b8c97753SJens Wiklander                if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_X):
34b8c97753SJens Wiklander                    print('Expected first load segment to be read/execute')
35b8c97753SJens Wiklander                    sys.exit(1)
36b8c97753SJens Wiklander                code_size = segment['p_filesz']
37b8c97753SJens Wiklander            if n == 1:
38b8c97753SJens Wiklander                if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_W):
39b8c97753SJens Wiklander                    print('Expected second load segment to be read/write')
40b8c97753SJens Wiklander                    sys.exit(1)
41b8c97753SJens Wiklander                data_size = segment['p_filesz']
42b8c97753SJens Wiklander            if n > 1:
43b8c97753SJens Wiklander                print('Only expected two load segments')
44b8c97753SJens Wiklander                sys.exit(1)
45b8c97753SJens Wiklander            load_size += segment['p_filesz']
46b8c97753SJens Wiklander            n = n + 1
47b8c97753SJens Wiklander
48*84c0da04SRouven Czerwinski    outf.write(b'const uint8_t ldelf_data[%d]' % round_up(load_size, 4096))
49*84c0da04SRouven Czerwinski    outf.write(b' __aligned(4096) = {\n')
50b8c97753SJens Wiklander    i = 0
51b8c97753SJens Wiklander    for segment in elffile.iter_segments():
52b8c97753SJens Wiklander        if segment['p_type'] == 'PT_LOAD':
53b8c97753SJens Wiklander            data = segment.data()
54b8c97753SJens Wiklander            for n in range(segment['p_filesz']):
55b8c97753SJens Wiklander                if i % 8 == 0:
56*84c0da04SRouven Czerwinski                    outf.write(b'\t')
57*84c0da04SRouven Czerwinski                outf.write(b'0x' + '{:02x}'.format(data[n]).encode('utf-8')
58*84c0da04SRouven Czerwinski                           + b',')
59b8c97753SJens Wiklander                i = i + 1
60b8c97753SJens Wiklander                if i % 8 == 0 or i == load_size:
61*84c0da04SRouven Czerwinski                    outf.write(b'\n')
62b8c97753SJens Wiklander                else:
63*84c0da04SRouven Czerwinski                    outf.write(b' ')
64*84c0da04SRouven Czerwinski    outf.write(b'};\n')
65b8c97753SJens Wiklander
66*84c0da04SRouven Czerwinski    outf.write(b'const unsigned int ldelf_code_size = %d;\n' % code_size)
67*84c0da04SRouven Czerwinski    outf.write(b'const unsigned int ldelf_data_size = %d;\n' % data_size)
68b8c97753SJens Wiklander
69b8c97753SJens Wiklander
70b8c97753SJens Wiklanderdef get_args():
71b8c97753SJens Wiklander    parser = argparse.ArgumentParser()
72b8c97753SJens Wiklander
73b8c97753SJens Wiklander    parser.add_argument('--input',
74b8c97753SJens Wiklander                        required=True, type=argparse.FileType('rb'),
75b8c97753SJens Wiklander                        help='The input ldelf.elf')
76b8c97753SJens Wiklander
77b8c97753SJens Wiklander    parser.add_argument('--output',
78b8c97753SJens Wiklander                        required=True, type=argparse.FileType('wb'),
79b8c97753SJens Wiklander                        help='The output ldelf_hex.c')
80b8c97753SJens Wiklander
81b8c97753SJens Wiklander    return parser.parse_args()
82b8c97753SJens Wiklander
83b8c97753SJens Wiklander
84b8c97753SJens Wiklanderdef main():
85b8c97753SJens Wiklander    args = get_args()
86b8c97753SJens Wiklander    inf = args.input
87b8c97753SJens Wiklander    outf = args.output
88b8c97753SJens Wiklander
89b8c97753SJens Wiklander    elffile = ELFFile(inf)
90b8c97753SJens Wiklander
91*84c0da04SRouven Czerwinski    outf.write(b'/* Automatically generated, do no edit */\n')
92*84c0da04SRouven Czerwinski    outf.write(b'#include <compiler.h>\n')
93*84c0da04SRouven Czerwinski    outf.write(b'#include <stdint.h>\n')
94b8c97753SJens Wiklander    emit_load_segments(elffile, outf)
95*84c0da04SRouven Czerwinski    outf.write(b'const unsigned long ldelf_entry = %lu;\n' %
96b8c97753SJens Wiklander               elffile.header['e_entry'])
97b8c97753SJens Wiklander
98b8c97753SJens Wiklander    inf.close()
99b8c97753SJens Wiklander    outf.close()
100b8c97753SJens Wiklander
101b8c97753SJens Wiklander
102b8c97753SJens Wiklanderif __name__ == "__main__":
103b8c97753SJens Wiklander    main()
104