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