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