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