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