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