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