xref: /optee_os/scripts/gen_ldelf_hex.py (revision d3642135ed1e64903056e17facf2aa018495d40a)
1#!/usr/bin/env python3
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(b'const uint8_t ldelf_data[%d]' % round_up(load_size, 4096))
49    outf.write(b' __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(b'\t')
57                outf.write(b'0x' + '{:02x}'.format(data[n]).encode('utf-8')
58                           + b',')
59                i = i + 1
60                if i % 8 == 0 or i == load_size:
61                    outf.write(b'\n')
62                else:
63                    outf.write(b' ')
64    outf.write(b'};\n')
65
66    outf.write(b'const unsigned int ldelf_code_size = %d;\n' % code_size)
67    outf.write(b'const unsigned int ldelf_data_size = %d;\n' % data_size)
68
69
70def get_args():
71    parser = argparse.ArgumentParser()
72
73    parser.add_argument('--input',
74                        required=True, type=argparse.FileType('rb'),
75                        help='The input ldelf.elf')
76
77    parser.add_argument('--output',
78                        required=True, type=argparse.FileType('wb'),
79                        help='The output ldelf_hex.c')
80
81    return parser.parse_args()
82
83
84def main():
85    args = get_args()
86    inf = args.input
87    outf = args.output
88
89    elffile = ELFFile(inf)
90
91    outf.write(b'/* Automatically generated, do no edit */\n')
92    outf.write(b'#include <compiler.h>\n')
93    outf.write(b'#include <stdint.h>\n')
94    emit_load_segments(elffile, outf)
95    outf.write(b'const unsigned long ldelf_entry = %lu;\n' %
96               elffile.header['e_entry'])
97
98    inf.close()
99    outf.close()
100
101
102if __name__ == "__main__":
103    main()
104