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