xref: /optee_os/scripts/ts_bin_to_c.py (revision 731185b11620a6de1f824278ab3c166c7853ef66)
1dea46be3SJelle Sels#!/usr/bin/env python3
2dea46be3SJelle Sels# SPDX-License-Identifier: BSD-2-Clause
3dea46be3SJelle Sels#
4dea46be3SJelle Sels# Copyright (c) 2017, 2020, Linaro Limited
5d0747e2eSImre Kis# Copyright (c) 2020-2023, Arm Limited.
6dea46be3SJelle Sels#
7dea46be3SJelle Sels
8dea46be3SJelle Selsimport argparse
9dea46be3SJelle Selsimport array
10d0747e2eSImre Kisfrom elftools.elf.elffile import ELFFile, ELFError
11*731185b1SJens Wiklanderfrom elftools.elf.sections import SymbolTableSection
12dea46be3SJelle Selsimport os
13dea46be3SJelle Selsimport re
14dea46be3SJelle Selsimport struct
15dea46be3SJelle Selsimport uuid
16dea46be3SJelle Selsimport zlib
17dea46be3SJelle Sels
18dea46be3SJelle Sels
19dea46be3SJelle Selsdef get_args():
20dea46be3SJelle Sels    parser = argparse.ArgumentParser(
21dea46be3SJelle Sels        description='Converts a Trusted '
22dea46be3SJelle Sels        'Application ELF file into a C source file, ready for '
23dea46be3SJelle Sels        'inclusion in the TEE binary as an "early TA".')
24dea46be3SJelle Sels
25dea46be3SJelle Sels    parser.add_argument('--out', required=True,
26dea46be3SJelle Sels                        help='Name of the output C file')
27dea46be3SJelle Sels
28dea46be3SJelle Sels    parser.add_argument(
29dea46be3SJelle Sels        '--ta',
30dea46be3SJelle Sels        required=False,
31dea46be3SJelle Sels        help='Path to the TA binary. File name has to be: <uuid>.* '
32dea46be3SJelle Sels        'such as: 8aaaf200-2450-11e4-abe2-0002a5d5c51b.stripped.elf')
33dea46be3SJelle Sels
34dea46be3SJelle Sels    parser.add_argument(
35dea46be3SJelle Sels        '--sp',
36dea46be3SJelle Sels        required=False,
37dea46be3SJelle Sels        help='Path to the SP binary. File name has to be: <uuid>.* '
38dea46be3SJelle Sels        'such as: 8aaaf200-2450-11e4-abe2-0002a5d5c51b.stripped.elf')
39dea46be3SJelle Sels
40dea46be3SJelle Sels    parser.add_argument(
41dea46be3SJelle Sels        '--compress',
42dea46be3SJelle Sels        dest="compress",
43dea46be3SJelle Sels        action="store_true",
44dea46be3SJelle Sels        help='Compress the image using the DEFLATE '
45dea46be3SJelle Sels        'algorithm')
46dea46be3SJelle Sels
47e23cd783SJelle Sels    parser.add_argument(
48e23cd783SJelle Sels        '--manifest',
49e23cd783SJelle Sels        dest="manifest",
50e23cd783SJelle Sels        required=False,
51e23cd783SJelle Sels        help='path to the SP manifest file')
52e23cd783SJelle Sels
53dea46be3SJelle Sels    return parser.parse_args()
54dea46be3SJelle Sels
55dea46be3SJelle Sels
56dea46be3SJelle Selsdef get_name(obj):
57dea46be3SJelle Sels    # Symbol or section .name can be a byte array or a string, we want a string
58dea46be3SJelle Sels    try:
59dea46be3SJelle Sels        name = obj.name.decode()
60dea46be3SJelle Sels    except (UnicodeDecodeError, AttributeError):
61dea46be3SJelle Sels        name = obj.name
62dea46be3SJelle Sels    return name
63dea46be3SJelle Sels
64dea46be3SJelle Sels
65dea46be3SJelle Selsdef ta_get_flags(ta_f):
66dea46be3SJelle Sels    with open(ta_f, 'rb') as f:
67dea46be3SJelle Sels        elffile = ELFFile(f)
68dea46be3SJelle Sels
69dea46be3SJelle Sels        for s in elffile.iter_sections():
70*731185b1SJens Wiklander            if isinstance(s, SymbolTableSection):
71*731185b1SJens Wiklander                for symbol in s.iter_symbols():
72*731185b1SJens Wiklander                    if symbol.name == 'ta_head':
73*731185b1SJens Wiklander                        # Get the section containing the symbol
74*731185b1SJens Wiklander                        s2 = elffile.get_section(symbol.entry['st_shndx'])
75*731185b1SJens Wiklander                        offs = s2.header['sh_offset'] - s2.header['sh_addr']
76*731185b1SJens Wiklander                        # ta_head offset into ELF binary
77*731185b1SJens Wiklander                        offs = offs + symbol.entry['st_value']
78*731185b1SJens Wiklander                        offs = offs + 20    # Flags offset in ta_head
79*731185b1SJens Wiklander                        f.seek(offs)
80*731185b1SJens Wiklander                        flags = struct.unpack('<I', f.read(4))[0]
81*731185b1SJens Wiklander                        return flags
82*731185b1SJens Wiklander
83*731185b1SJens Wiklander        # For compatibility with older TAs
84*731185b1SJens Wiklander        for s in elffile.iter_sections():
85dea46be3SJelle Sels            if get_name(s) == '.ta_head':
86dea46be3SJelle Sels                return struct.unpack('<16x4xI', s.data()[:24])[0]
87dea46be3SJelle Sels
88dea46be3SJelle Sels        raise Exception('.ta_head section not found')
89dea46be3SJelle Sels
90dea46be3SJelle Sels
91dea46be3SJelle Selsdef sp_get_flags(sp_f):
92dea46be3SJelle Sels    with open(sp_f, 'rb') as f:
93d0747e2eSImre Kis        try:
94dea46be3SJelle Sels            elffile = ELFFile(f)
95d0747e2eSImre Kis        except ELFError:
96d0747e2eSImre Kis            # Binary format SP, return zero flags
97d0747e2eSImre Kis            return 0
98dea46be3SJelle Sels
99dea46be3SJelle Sels        for s in elffile.iter_sections():
100dea46be3SJelle Sels            if get_name(s) == '.sp_head':
101dea46be3SJelle Sels                return struct.unpack('<16x4xI', s.data()[:24])[0]
102dea46be3SJelle Sels
103dea46be3SJelle Sels        raise Exception('.sp_head section not found')
104dea46be3SJelle Sels
105dea46be3SJelle Sels
106e23cd783SJelle Selsdef dump_bin(f, ts, compress):
107e23cd783SJelle Sels    with open(ts, 'rb') as _ts:
108e23cd783SJelle Sels        bytes = _ts.read()
109e23cd783SJelle Sels        uncompressed_size = len(bytes)
110e23cd783SJelle Sels        if compress:
111e23cd783SJelle Sels            bytes = zlib.compress(bytes)
112e23cd783SJelle Sels        size = len(bytes)
113e23cd783SJelle Sels
114e23cd783SJelle Sels    i = 0
115e23cd783SJelle Sels    while i < size:
116e23cd783SJelle Sels        if i % 8 == 0:
117e23cd783SJelle Sels            f.write('\t\t')
118e23cd783SJelle Sels        f.write(hex(bytes[i]) + ',')
119e23cd783SJelle Sels        i = i + 1
120e23cd783SJelle Sels        if i % 8 == 0 or i == size:
121e23cd783SJelle Sels            f.write('\n')
122e23cd783SJelle Sels        else:
123e23cd783SJelle Sels            f.write(' ')
124e23cd783SJelle Sels    return (size, uncompressed_size)
125e23cd783SJelle Sels
126e23cd783SJelle Sels
127dea46be3SJelle Selsdef main():
128dea46be3SJelle Sels    args = get_args()
129dea46be3SJelle Sels    is_sp = False
130dea46be3SJelle Sels
131dea46be3SJelle Sels    if args.ta is None and args.sp is None:
132dea46be3SJelle Sels        raise Exception('The --ta or the --sp flag is required')
133dea46be3SJelle Sels
134dea46be3SJelle Sels    if args.ta is not None and args.sp is not None:
135dea46be3SJelle Sels        raise Exception('The --ta and the --sp can\'t be combined')
136dea46be3SJelle Sels
137dea46be3SJelle Sels    if args.ta is not None:
138dea46be3SJelle Sels        ts = args.ta
139dea46be3SJelle Sels        is_sp = False
140dea46be3SJelle Sels
141dea46be3SJelle Sels    if args.sp is not None:
142dea46be3SJelle Sels        ts = args.sp
143dea46be3SJelle Sels        is_sp = True
144dea46be3SJelle Sels
145dea46be3SJelle Sels    ts_uuid = uuid.UUID(re.sub(r'\..*', '', os.path.basename(ts)))
146dea46be3SJelle Sels
147dea46be3SJelle Sels    f = open(args.out, 'w')
148dea46be3SJelle Sels    f.write('/* Generated from ' + ts + ' by ' +
149dea46be3SJelle Sels            os.path.basename(__file__) + ' */\n\n')
150dea46be3SJelle Sels    f.write('#include <kernel/embedded_ts.h>\n\n')
151dea46be3SJelle Sels    f.write('#include <scattered_array.h>\n\n')
152dea46be3SJelle Sels    f.write('const uint8_t ts_bin_' + ts_uuid.hex + '[] = {\n')
153e23cd783SJelle Sels    ts_size, ts_uncompressed_size = dump_bin(f, ts, args.compress)
154dea46be3SJelle Sels    f.write('};\n')
155dea46be3SJelle Sels
156dea46be3SJelle Sels    if is_sp:
157e23cd783SJelle Sels
158e23cd783SJelle Sels        f.write('#include <kernel/secure_partition.h>\n\n')
159e23cd783SJelle Sels        f.write('const uint8_t fdt_bin_' + ts_uuid.hex + '[] = {\n')
160e23cd783SJelle Sels        dump_bin(f, args.manifest, False)
161e23cd783SJelle Sels        f.write('};\n')
162dea46be3SJelle Sels        f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(sp_images, struct \
163e23cd783SJelle Sels                sp_image) = {\n')
164e23cd783SJelle Sels        f.write('\t.fdt = fdt_bin_' + ts_uuid.hex + ',\n')
165e23cd783SJelle Sels
166e23cd783SJelle Sels        f.write('. image = {')
167dea46be3SJelle Sels        f.write('\t.flags = 0x{:04x},\n'.format(sp_get_flags(ts)))
168dea46be3SJelle Sels    else:
169dea46be3SJelle Sels        f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(early_tas, struct \
170dea46be3SJelle Sels                embedded_ts) = {\n')
171dea46be3SJelle Sels        f.write('\t.flags = 0x{:04x},\n'.format(ta_get_flags(ts)))
172dea46be3SJelle Sels    f.write('\t.uuid = {\n')
173dea46be3SJelle Sels    f.write('\t\t.timeLow = 0x{:08x},\n'.format(ts_uuid.time_low))
174dea46be3SJelle Sels    f.write('\t\t.timeMid = 0x{:04x},\n'.format(ts_uuid.time_mid))
175dea46be3SJelle Sels    f.write('\t\t.timeHiAndVersion = ' +
176dea46be3SJelle Sels            '0x{:04x},\n'.format(ts_uuid.time_hi_version))
177dea46be3SJelle Sels    f.write('\t\t.clockSeqAndNode = {\n')
178dea46be3SJelle Sels    csn = '{0:02x}{1:02x}{2:012x}'.format(ts_uuid.clock_seq_hi_variant,
179dea46be3SJelle Sels                                          ts_uuid.clock_seq_low, ts_uuid.node)
180dea46be3SJelle Sels    f.write('\t\t\t')
181dea46be3SJelle Sels    f.write(', '.join('0x' + csn[i:i + 2] for i in range(0, len(csn), 2)))
182dea46be3SJelle Sels    f.write('\n\t\t},\n\t},\n')
183dea46be3SJelle Sels    f.write('\t.size = sizeof(ts_bin_' + ts_uuid.hex +
184e23cd783SJelle Sels            '), /* {:d} */\n'.format(ts_size))
185dea46be3SJelle Sels    f.write('\t.ts = ts_bin_' + ts_uuid.hex + ',\n')
186dea46be3SJelle Sels    if args.compress:
187dea46be3SJelle Sels        f.write('\t.uncompressed_size = '
188e23cd783SJelle Sels                '{:d},\n'.format(ts_uncompressed_size))
189e23cd783SJelle Sels    if is_sp:
190e23cd783SJelle Sels        f.write('}\n')
191dea46be3SJelle Sels    f.write('};\n')
192dea46be3SJelle Sels    f.close()
193dea46be3SJelle Sels
194dea46be3SJelle Sels
195dea46be3SJelle Selsif __name__ == "__main__":
196dea46be3SJelle Sels    main()
197