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