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 11from elftools.elf.sections import SymbolTableSection 12import os 13import re 14import struct 15import uuid 16import zlib 17 18 19def get_args(): 20 parser = argparse.ArgumentParser( 21 description='Converts a Trusted ' 22 'Application ELF file into a C source file, ready for ' 23 'inclusion in the TEE binary as an "early TA".') 24 25 parser.add_argument('--out', required=True, 26 help='Name of the output C file') 27 28 parser.add_argument( 29 '--ta', 30 required=False, 31 help='Path to the TA binary. File name has to be: <uuid>.* ' 32 'such as: 8aaaf200-2450-11e4-abe2-0002a5d5c51b.stripped.elf') 33 34 parser.add_argument( 35 '--sp', 36 required=False, 37 help='Path to the SP binary. File name has to be: <uuid>.* ' 38 'such as: 8aaaf200-2450-11e4-abe2-0002a5d5c51b.stripped.elf') 39 40 parser.add_argument( 41 '--compress', 42 dest="compress", 43 action="store_true", 44 help='Compress the image using the DEFLATE ' 45 'algorithm') 46 47 parser.add_argument( 48 '--manifest', 49 dest="manifest", 50 required=False, 51 help='path to the SP manifest file') 52 53 return parser.parse_args() 54 55 56def get_name(obj): 57 # Symbol or section .name can be a byte array or a string, we want a string 58 try: 59 name = obj.name.decode() 60 except (UnicodeDecodeError, AttributeError): 61 name = obj.name 62 return name 63 64 65def ta_get_flags(ta_f): 66 with open(ta_f, 'rb') as f: 67 elffile = ELFFile(f) 68 69 for s in elffile.iter_sections(): 70 if isinstance(s, SymbolTableSection): 71 for symbol in s.iter_symbols(): 72 if symbol.name == 'ta_head': 73 # Get the section containing the symbol 74 s2 = elffile.get_section(symbol.entry['st_shndx']) 75 offs = s2.header['sh_offset'] - s2.header['sh_addr'] 76 # ta_head offset into ELF binary 77 offs = offs + symbol.entry['st_value'] 78 offs = offs + 20 # Flags offset in ta_head 79 f.seek(offs) 80 flags = struct.unpack('<I', f.read(4))[0] 81 return flags 82 83 # For compatibility with older TAs 84 for s in elffile.iter_sections(): 85 if get_name(s) == '.ta_head': 86 return struct.unpack('<16x4xI', s.data()[:24])[0] 87 88 raise Exception('.ta_head section not found') 89 90 91def sp_get_flags(sp_f): 92 with open(sp_f, 'rb') as f: 93 try: 94 elffile = ELFFile(f) 95 except ELFError: 96 # Binary format SP, return zero flags 97 return 0 98 99 for s in elffile.iter_sections(): 100 if get_name(s) == '.sp_head': 101 return struct.unpack('<16x4xI', s.data()[:24])[0] 102 103 raise Exception('.sp_head section not found') 104 105 106def dump_bin(f, ts, compress): 107 with open(ts, 'rb') as _ts: 108 bytes = _ts.read() 109 uncompressed_size = len(bytes) 110 if compress: 111 bytes = zlib.compress(bytes) 112 size = len(bytes) 113 114 i = 0 115 while i < size: 116 if i % 8 == 0: 117 f.write('\t\t') 118 f.write(hex(bytes[i]) + ',') 119 i = i + 1 120 if i % 8 == 0 or i == size: 121 f.write('\n') 122 else: 123 f.write(' ') 124 return (size, uncompressed_size) 125 126 127def main(): 128 args = get_args() 129 is_sp = False 130 131 if args.ta is None and args.sp is None: 132 raise Exception('The --ta or the --sp flag is required') 133 134 if args.ta is not None and args.sp is not None: 135 raise Exception('The --ta and the --sp can\'t be combined') 136 137 if args.ta is not None: 138 ts = args.ta 139 is_sp = False 140 141 if args.sp is not None: 142 ts = args.sp 143 is_sp = True 144 145 ts_uuid = uuid.UUID(re.sub(r'\..*', '', os.path.basename(ts))) 146 147 f = open(args.out, 'w') 148 f.write('/* Generated from ' + ts + ' by ' + 149 os.path.basename(__file__) + ' */\n\n') 150 f.write('#include <kernel/embedded_ts.h>\n\n') 151 f.write('#include <scattered_array.h>\n\n') 152 f.write('const uint8_t ts_bin_' + ts_uuid.hex + '[] = {\n') 153 ts_size, ts_uncompressed_size = dump_bin(f, ts, args.compress) 154 f.write('};\n') 155 156 if is_sp: 157 158 f.write('#include <kernel/secure_partition.h>\n\n') 159 f.write('const uint8_t fdt_bin_' + ts_uuid.hex + '[] = {\n') 160 dump_bin(f, args.manifest, False) 161 f.write('};\n') 162 f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(sp_images, struct \ 163 sp_image) = {\n') 164 f.write('\t.fdt = fdt_bin_' + ts_uuid.hex + ',\n') 165 166 f.write('. image = {') 167 f.write('\t.flags = 0x{:04x},\n'.format(sp_get_flags(ts))) 168 else: 169 f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(early_tas, struct \ 170 embedded_ts) = {\n') 171 f.write('\t.flags = 0x{:04x},\n'.format(ta_get_flags(ts))) 172 f.write('\t.uuid = {\n') 173 f.write('\t\t.timeLow = 0x{:08x},\n'.format(ts_uuid.time_low)) 174 f.write('\t\t.timeMid = 0x{:04x},\n'.format(ts_uuid.time_mid)) 175 f.write('\t\t.timeHiAndVersion = ' + 176 '0x{:04x},\n'.format(ts_uuid.time_hi_version)) 177 f.write('\t\t.clockSeqAndNode = {\n') 178 csn = '{0:02x}{1:02x}{2:012x}'.format(ts_uuid.clock_seq_hi_variant, 179 ts_uuid.clock_seq_low, ts_uuid.node) 180 f.write('\t\t\t') 181 f.write(', '.join('0x' + csn[i:i + 2] for i in range(0, len(csn), 2))) 182 f.write('\n\t\t},\n\t},\n') 183 f.write('\t.size = sizeof(ts_bin_' + ts_uuid.hex + 184 '), /* {:d} */\n'.format(ts_size)) 185 f.write('\t.ts = ts_bin_' + ts_uuid.hex + ',\n') 186 if args.compress: 187 f.write('\t.uncompressed_size = ' 188 '{:d},\n'.format(ts_uncompressed_size)) 189 if is_sp: 190 f.write('}\n') 191 f.write('};\n') 192 f.close() 193 194 195if __name__ == "__main__": 196 main() 197