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