xref: /optee_os/scripts/ts_bin_to_c.py (revision e23cd783e85d3963fa184a3da973e95692ecf62c)
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*e23cd783SJelle Sels# Copyright (c) 2020-2022, Arm Limited.
6dea46be3SJelle Sels#
7dea46be3SJelle Sels
8dea46be3SJelle Selsimport argparse
9dea46be3SJelle Selsimport array
10dea46be3SJelle Selsfrom elftools.elf.elffile import ELFFile
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
46*e23cd783SJelle Sels    parser.add_argument(
47*e23cd783SJelle Sels        '--manifest',
48*e23cd783SJelle Sels        dest="manifest",
49*e23cd783SJelle Sels        required=False,
50*e23cd783SJelle Sels        help='path to the SP manifest file')
51*e23cd783SJelle 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:
77dea46be3SJelle Sels        elffile = ELFFile(f)
78dea46be3SJelle Sels
79dea46be3SJelle Sels        for s in elffile.iter_sections():
80dea46be3SJelle Sels            if get_name(s) == '.sp_head':
81dea46be3SJelle Sels                return struct.unpack('<16x4xI', s.data()[:24])[0]
82dea46be3SJelle Sels
83dea46be3SJelle Sels        raise Exception('.sp_head section not found')
84dea46be3SJelle Sels
85dea46be3SJelle Sels
86*e23cd783SJelle Selsdef dump_bin(f, ts, compress):
87*e23cd783SJelle Sels    with open(ts, 'rb') as _ts:
88*e23cd783SJelle Sels        bytes = _ts.read()
89*e23cd783SJelle Sels        uncompressed_size = len(bytes)
90*e23cd783SJelle Sels        if compress:
91*e23cd783SJelle Sels            bytes = zlib.compress(bytes)
92*e23cd783SJelle Sels        size = len(bytes)
93*e23cd783SJelle Sels
94*e23cd783SJelle Sels    i = 0
95*e23cd783SJelle Sels    while i < size:
96*e23cd783SJelle Sels        if i % 8 == 0:
97*e23cd783SJelle Sels            f.write('\t\t')
98*e23cd783SJelle Sels        f.write(hex(bytes[i]) + ',')
99*e23cd783SJelle Sels        i = i + 1
100*e23cd783SJelle Sels        if i % 8 == 0 or i == size:
101*e23cd783SJelle Sels            f.write('\n')
102*e23cd783SJelle Sels        else:
103*e23cd783SJelle Sels            f.write(' ')
104*e23cd783SJelle Sels    return (size, uncompressed_size)
105*e23cd783SJelle Sels
106*e23cd783SJelle Sels
107dea46be3SJelle Selsdef main():
108dea46be3SJelle Sels    args = get_args()
109dea46be3SJelle Sels    is_sp = False
110dea46be3SJelle Sels
111dea46be3SJelle Sels    if args.ta is None and args.sp is None:
112dea46be3SJelle Sels        raise Exception('The --ta or the --sp flag is required')
113dea46be3SJelle Sels
114dea46be3SJelle Sels    if args.ta is not None and args.sp is not None:
115dea46be3SJelle Sels        raise Exception('The --ta and the --sp can\'t be combined')
116dea46be3SJelle Sels
117dea46be3SJelle Sels    if args.ta is not None:
118dea46be3SJelle Sels        ts = args.ta
119dea46be3SJelle Sels        is_sp = False
120dea46be3SJelle Sels
121dea46be3SJelle Sels    if args.sp is not None:
122dea46be3SJelle Sels        ts = args.sp
123dea46be3SJelle Sels        is_sp = True
124dea46be3SJelle Sels
125dea46be3SJelle Sels    ts_uuid = uuid.UUID(re.sub(r'\..*', '', os.path.basename(ts)))
126dea46be3SJelle Sels
127dea46be3SJelle Sels    f = open(args.out, 'w')
128dea46be3SJelle Sels    f.write('/* Generated from ' + ts + ' by ' +
129dea46be3SJelle Sels            os.path.basename(__file__) + ' */\n\n')
130dea46be3SJelle Sels    f.write('#include <kernel/embedded_ts.h>\n\n')
131dea46be3SJelle Sels    f.write('#include <scattered_array.h>\n\n')
132dea46be3SJelle Sels    f.write('const uint8_t ts_bin_' + ts_uuid.hex + '[] = {\n')
133*e23cd783SJelle Sels    ts_size, ts_uncompressed_size = dump_bin(f, ts, args.compress)
134dea46be3SJelle Sels    f.write('};\n')
135dea46be3SJelle Sels
136dea46be3SJelle Sels    if is_sp:
137*e23cd783SJelle Sels
138*e23cd783SJelle Sels        f.write('#include <kernel/secure_partition.h>\n\n')
139*e23cd783SJelle Sels        f.write('const uint8_t fdt_bin_' + ts_uuid.hex + '[] = {\n')
140*e23cd783SJelle Sels        dump_bin(f, args.manifest, False)
141*e23cd783SJelle Sels        f.write('};\n')
142dea46be3SJelle Sels        f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(sp_images, struct \
143*e23cd783SJelle Sels                sp_image) = {\n')
144*e23cd783SJelle Sels        f.write('\t.fdt = fdt_bin_' + ts_uuid.hex + ',\n')
145*e23cd783SJelle Sels
146*e23cd783SJelle Sels        f.write('. image = {')
147dea46be3SJelle Sels        f.write('\t.flags = 0x{:04x},\n'.format(sp_get_flags(ts)))
148dea46be3SJelle Sels    else:
149dea46be3SJelle Sels        f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(early_tas, struct \
150dea46be3SJelle Sels                embedded_ts) = {\n')
151dea46be3SJelle Sels        f.write('\t.flags = 0x{:04x},\n'.format(ta_get_flags(ts)))
152dea46be3SJelle Sels    f.write('\t.uuid = {\n')
153dea46be3SJelle Sels    f.write('\t\t.timeLow = 0x{:08x},\n'.format(ts_uuid.time_low))
154dea46be3SJelle Sels    f.write('\t\t.timeMid = 0x{:04x},\n'.format(ts_uuid.time_mid))
155dea46be3SJelle Sels    f.write('\t\t.timeHiAndVersion = ' +
156dea46be3SJelle Sels            '0x{:04x},\n'.format(ts_uuid.time_hi_version))
157dea46be3SJelle Sels    f.write('\t\t.clockSeqAndNode = {\n')
158dea46be3SJelle Sels    csn = '{0:02x}{1:02x}{2:012x}'.format(ts_uuid.clock_seq_hi_variant,
159dea46be3SJelle Sels                                          ts_uuid.clock_seq_low, ts_uuid.node)
160dea46be3SJelle Sels    f.write('\t\t\t')
161dea46be3SJelle Sels    f.write(', '.join('0x' + csn[i:i + 2] for i in range(0, len(csn), 2)))
162dea46be3SJelle Sels    f.write('\n\t\t},\n\t},\n')
163dea46be3SJelle Sels    f.write('\t.size = sizeof(ts_bin_' + ts_uuid.hex +
164*e23cd783SJelle Sels            '), /* {:d} */\n'.format(ts_size))
165dea46be3SJelle Sels    f.write('\t.ts = ts_bin_' + ts_uuid.hex + ',\n')
166dea46be3SJelle Sels    if args.compress:
167dea46be3SJelle Sels        f.write('\t.uncompressed_size = '
168*e23cd783SJelle Sels                '{:d},\n'.format(ts_uncompressed_size))
169*e23cd783SJelle Sels    if is_sp:
170*e23cd783SJelle Sels        f.write('}\n')
171dea46be3SJelle Sels    f.write('};\n')
172dea46be3SJelle Sels    f.close()
173dea46be3SJelle Sels
174dea46be3SJelle Sels
175dea46be3SJelle Selsif __name__ == "__main__":
176dea46be3SJelle Sels    main()
177