1#!/usr/bin/env python3 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2017, 2020, Linaro Limited 5# Copyright (c) 2020-2022, 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 parser.add_argument( 47 '--manifest', 48 dest="manifest", 49 required=False, 50 help='path to the SP manifest file') 51 52 return parser.parse_args() 53 54 55def get_name(obj): 56 # Symbol or section .name can be a byte array or a string, we want a string 57 try: 58 name = obj.name.decode() 59 except (UnicodeDecodeError, AttributeError): 60 name = obj.name 61 return name 62 63 64def ta_get_flags(ta_f): 65 with open(ta_f, 'rb') as f: 66 elffile = ELFFile(f) 67 68 for s in elffile.iter_sections(): 69 if get_name(s) == '.ta_head': 70 return struct.unpack('<16x4xI', s.data()[:24])[0] 71 72 raise Exception('.ta_head section not found') 73 74 75def sp_get_flags(sp_f): 76 with open(sp_f, 'rb') as f: 77 elffile = ELFFile(f) 78 79 for s in elffile.iter_sections(): 80 if get_name(s) == '.sp_head': 81 return struct.unpack('<16x4xI', s.data()[:24])[0] 82 83 raise Exception('.sp_head section not found') 84 85 86def dump_bin(f, ts, compress): 87 with open(ts, 'rb') as _ts: 88 bytes = _ts.read() 89 uncompressed_size = len(bytes) 90 if compress: 91 bytes = zlib.compress(bytes) 92 size = len(bytes) 93 94 i = 0 95 while i < size: 96 if i % 8 == 0: 97 f.write('\t\t') 98 f.write(hex(bytes[i]) + ',') 99 i = i + 1 100 if i % 8 == 0 or i == size: 101 f.write('\n') 102 else: 103 f.write(' ') 104 return (size, uncompressed_size) 105 106 107def main(): 108 args = get_args() 109 is_sp = False 110 111 if args.ta is None and args.sp is None: 112 raise Exception('The --ta or the --sp flag is required') 113 114 if args.ta is not None and args.sp is not None: 115 raise Exception('The --ta and the --sp can\'t be combined') 116 117 if args.ta is not None: 118 ts = args.ta 119 is_sp = False 120 121 if args.sp is not None: 122 ts = args.sp 123 is_sp = True 124 125 ts_uuid = uuid.UUID(re.sub(r'\..*', '', os.path.basename(ts))) 126 127 f = open(args.out, 'w') 128 f.write('/* Generated from ' + ts + ' by ' + 129 os.path.basename(__file__) + ' */\n\n') 130 f.write('#include <kernel/embedded_ts.h>\n\n') 131 f.write('#include <scattered_array.h>\n\n') 132 f.write('const uint8_t ts_bin_' + ts_uuid.hex + '[] = {\n') 133 ts_size, ts_uncompressed_size = dump_bin(f, ts, args.compress) 134 f.write('};\n') 135 136 if is_sp: 137 138 f.write('#include <kernel/secure_partition.h>\n\n') 139 f.write('const uint8_t fdt_bin_' + ts_uuid.hex + '[] = {\n') 140 dump_bin(f, args.manifest, False) 141 f.write('};\n') 142 f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(sp_images, struct \ 143 sp_image) = {\n') 144 f.write('\t.fdt = fdt_bin_' + ts_uuid.hex + ',\n') 145 146 f.write('. image = {') 147 f.write('\t.flags = 0x{:04x},\n'.format(sp_get_flags(ts))) 148 else: 149 f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(early_tas, struct \ 150 embedded_ts) = {\n') 151 f.write('\t.flags = 0x{:04x},\n'.format(ta_get_flags(ts))) 152 f.write('\t.uuid = {\n') 153 f.write('\t\t.timeLow = 0x{:08x},\n'.format(ts_uuid.time_low)) 154 f.write('\t\t.timeMid = 0x{:04x},\n'.format(ts_uuid.time_mid)) 155 f.write('\t\t.timeHiAndVersion = ' + 156 '0x{:04x},\n'.format(ts_uuid.time_hi_version)) 157 f.write('\t\t.clockSeqAndNode = {\n') 158 csn = '{0:02x}{1:02x}{2:012x}'.format(ts_uuid.clock_seq_hi_variant, 159 ts_uuid.clock_seq_low, ts_uuid.node) 160 f.write('\t\t\t') 161 f.write(', '.join('0x' + csn[i:i + 2] for i in range(0, len(csn), 2))) 162 f.write('\n\t\t},\n\t},\n') 163 f.write('\t.size = sizeof(ts_bin_' + ts_uuid.hex + 164 '), /* {:d} */\n'.format(ts_size)) 165 f.write('\t.ts = ts_bin_' + ts_uuid.hex + ',\n') 166 if args.compress: 167 f.write('\t.uncompressed_size = ' 168 '{:d},\n'.format(ts_uncompressed_size)) 169 if is_sp: 170 f.write('}\n') 171 f.write('};\n') 172 f.close() 173 174 175if __name__ == "__main__": 176 main() 177