1*3c51966bSJens Wiklander#!/usr/bin/env python3 2*3c51966bSJens Wiklander# SPDX-License-Identifier: BSD-2-Clause 3*3c51966bSJens Wiklander# 4*3c51966bSJens Wiklander# Copyright (c) 2019, Linaro Limited 5*3c51966bSJens Wiklander# 6*3c51966bSJens Wiklander 7*3c51966bSJens Wiklanderfrom __future__ import print_function 8*3c51966bSJens Wiklanderfrom __future__ import division 9*3c51966bSJens Wiklander 10*3c51966bSJens Wiklanderimport argparse 11*3c51966bSJens Wiklanderimport sys 12*3c51966bSJens Wiklanderimport struct 13*3c51966bSJens Wiklanderimport re 14*3c51966bSJens Wiklanderimport hashlib 15*3c51966bSJens Wiklandertry: 16*3c51966bSJens Wiklander from elftools.elf.elffile import ELFFile 17*3c51966bSJens Wiklander from elftools.elf.constants import SH_FLAGS 18*3c51966bSJens Wiklander from elftools.elf.sections import SymbolTableSection 19*3c51966bSJens Wiklander 20*3c51966bSJens Wiklanderexcept ImportError: 21*3c51966bSJens Wiklander print(""" 22*3c51966bSJens Wiklander*** 23*3c51966bSJens WiklanderCan't find elftools module. Probably it is not installed on your system. 24*3c51966bSJens WiklanderYou can install this module with 25*3c51966bSJens Wiklander 26*3c51966bSJens Wiklander$ apt install python3-pyelftools 27*3c51966bSJens Wiklander 28*3c51966bSJens Wiklanderif you are using Ubuntu. Or try to search for "pyelftools" or "elftools" in 29*3c51966bSJens Wiklanderyour package manager if you are using some other distribution. 30*3c51966bSJens Wiklander*** 31*3c51966bSJens Wiklander""") 32*3c51966bSJens Wiklander raise 33*3c51966bSJens Wiklander 34*3c51966bSJens Wiklandersmall_page_size = 4 * 1024 35*3c51966bSJens Wiklanderelffile_symbols = None 36*3c51966bSJens Wiklandertee_pageable_bin = None 37*3c51966bSJens Wiklandertee_pager_bin = None 38*3c51966bSJens Wiklander 39*3c51966bSJens Wiklander 40*3c51966bSJens Wiklanderdef eprint(*args, **kwargs): 41*3c51966bSJens Wiklander print(*args, file=sys.stderr, **kwargs) 42*3c51966bSJens Wiklander 43*3c51966bSJens Wiklander 44*3c51966bSJens Wiklanderdef get_symbol(elffile, name): 45*3c51966bSJens Wiklander global elffile_symbols 46*3c51966bSJens Wiklander if elffile_symbols is None: 47*3c51966bSJens Wiklander elffile_symbols = dict() 48*3c51966bSJens Wiklander symbol_tables = [s for s in elffile.iter_sections() 49*3c51966bSJens Wiklander if isinstance(s, SymbolTableSection)] 50*3c51966bSJens Wiklander for section in symbol_tables: 51*3c51966bSJens Wiklander for symbol in section.iter_symbols(): 52*3c51966bSJens Wiklander if symbol['st_info']['bind'] == 'STB_GLOBAL': 53*3c51966bSJens Wiklander elffile_symbols[symbol.name] = symbol 54*3c51966bSJens Wiklander 55*3c51966bSJens Wiklander try: 56*3c51966bSJens Wiklander return elffile_symbols[name] 57*3c51966bSJens Wiklander except (KeyError): 58*3c51966bSJens Wiklander eprint("Cannot find symbol %s" % name) 59*3c51966bSJens Wiklander sys.exit(1) 60*3c51966bSJens Wiklander 61*3c51966bSJens Wiklander 62*3c51966bSJens Wiklanderdef get_sections(elffile, pad_to, skip_names, dump_names): 63*3c51966bSJens Wiklander last_end = 0 64*3c51966bSJens Wiklander bin_data = bytearray() 65*3c51966bSJens Wiklander 66*3c51966bSJens Wiklander for section in elffile.iter_sections(): 67*3c51966bSJens Wiklander if (section['sh_type'] == 'SHT_NOBITS' or 68*3c51966bSJens Wiklander not (section['sh_flags'] & SH_FLAGS.SHF_ALLOC) or 69*3c51966bSJens Wiklander skip_names.match(section.name) or 70*3c51966bSJens Wiklander not dump_names.match(section.name)): 71*3c51966bSJens Wiklander continue 72*3c51966bSJens Wiklander 73*3c51966bSJens Wiklander if last_end == 0: 74*3c51966bSJens Wiklander bin_data = section.data() 75*3c51966bSJens Wiklander else: 76*3c51966bSJens Wiklander if section['sh_addr'] > last_end: 77*3c51966bSJens Wiklander bin_data += bytearray(section['sh_addr'] - last_end) 78*3c51966bSJens Wiklander bin_data += section.data() 79*3c51966bSJens Wiklander 80*3c51966bSJens Wiklander last_end = section['sh_addr'] + section['sh_size'] 81*3c51966bSJens Wiklander 82*3c51966bSJens Wiklander if pad_to > last_end: 83*3c51966bSJens Wiklander bin_data += bytearray(pad_to - last_end) 84*3c51966bSJens Wiklander last_end = pad_to 85*3c51966bSJens Wiklander 86*3c51966bSJens Wiklander return bin_data 87*3c51966bSJens Wiklander 88*3c51966bSJens Wiklander 89*3c51966bSJens Wiklanderdef get_pageable_bin(elffile): 90*3c51966bSJens Wiklander global tee_pageable_bin 91*3c51966bSJens Wiklander if tee_pageable_bin is None: 92*3c51966bSJens Wiklander pad_to = 0 93*3c51966bSJens Wiklander skip_names = re.compile(r'^$') 94*3c51966bSJens Wiklander dump_names = re.compile(r'^\..*_(pageable|init)$') 95*3c51966bSJens Wiklander tee_pageable_bin = get_sections(elffile, pad_to, skip_names, 96*3c51966bSJens Wiklander dump_names) 97*3c51966bSJens Wiklander return tee_pageable_bin 98*3c51966bSJens Wiklander 99*3c51966bSJens Wiklander 100*3c51966bSJens Wiklanderdef get_pager_bin(elffile): 101*3c51966bSJens Wiklander global tee_pager_bin 102*3c51966bSJens Wiklander if tee_pager_bin is None: 103*3c51966bSJens Wiklander pad_to = get_symbol(elffile, '__data_end')['st_value'] 104*3c51966bSJens Wiklander skip_names = re.compile(r'^\..*_(pageable|init)$') 105*3c51966bSJens Wiklander dump_names = re.compile(r'') 106*3c51966bSJens Wiklander tee_pager_bin = get_sections(elffile, pad_to, skip_names, dump_names) 107*3c51966bSJens Wiklander 108*3c51966bSJens Wiklander return tee_pager_bin 109*3c51966bSJens Wiklander 110*3c51966bSJens Wiklander 111*3c51966bSJens Wiklanderdef output_pager_bin(elffile, outf): 112*3c51966bSJens Wiklander outf.write(get_pager_bin(elffile)) 113*3c51966bSJens Wiklander 114*3c51966bSJens Wiklander 115*3c51966bSJens Wiklanderdef output_pageable_bin(elffile, outf): 116*3c51966bSJens Wiklander outf.write(get_pageable_bin(elffile)) 117*3c51966bSJens Wiklander 118*3c51966bSJens Wiklander 119*3c51966bSJens Wiklanderdef get_arch_id(elffile): 120*3c51966bSJens Wiklander e_machine = elffile.header['e_machine'] 121*3c51966bSJens Wiklander if e_machine == 'EM_ARM': 122*3c51966bSJens Wiklander return 0 123*3c51966bSJens Wiklander if e_machine == 'EM_AARCH64': 124*3c51966bSJens Wiklander return 1 125*3c51966bSJens Wiklander eprint('Unknown e_machine "%s"' % e_machine) 126*3c51966bSJens Wiklander sys.exit(1) 127*3c51966bSJens Wiklander 128*3c51966bSJens Wiklander 129*3c51966bSJens Wiklanderdef get_init_load_addr(elffile): 130*3c51966bSJens Wiklander init_load_addr = get_symbol(elffile, '_start')['st_value'] 131*3c51966bSJens Wiklander init_load_addr_hi = init_load_addr >> 32 132*3c51966bSJens Wiklander init_load_addr_lo = init_load_addr & 0xffffffff 133*3c51966bSJens Wiklander return init_load_addr_hi, init_load_addr_lo 134*3c51966bSJens Wiklander 135*3c51966bSJens Wiklander 136*3c51966bSJens Wiklanderdef output_header_v1(elffile, outf): 137*3c51966bSJens Wiklander arch_id = get_arch_id(elffile) 138*3c51966bSJens Wiklander pager_bin = get_pager_bin(elffile) 139*3c51966bSJens Wiklander pageable_bin = get_pageable_bin(elffile) 140*3c51966bSJens Wiklander init_mem_usage = get_symbol(elffile, '__init_mem_usage')['st_value'] 141*3c51966bSJens Wiklander init_load_addr = get_init_load_addr(elffile) 142*3c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 143*3c51966bSJens Wiklander pager_bin_size = len(pager_bin) 144*3c51966bSJens Wiklander paged_area_size = len(pageable_bin) 145*3c51966bSJens Wiklander hash_size = (paged_area_size // small_page_size * 146*3c51966bSJens Wiklander hashlib.sha256().digest_size) 147*3c51966bSJens Wiklander 148*3c51966bSJens Wiklander init_size = (pager_bin_size + min(init_bin_size, paged_area_size) + 149*3c51966bSJens Wiklander hash_size) 150*3c51966bSJens Wiklander paged_size = paged_area_size - min(init_bin_size, paged_area_size) 151*3c51966bSJens Wiklander 152*3c51966bSJens Wiklander if paged_area_size % small_page_size != 0: 153*3c51966bSJens Wiklander eprint("pageable size not a multiple of 4K: " 154*3c51966bSJens Wiklander "{}".format(paged_area_size)) 155*3c51966bSJens Wiklander sys.exit(1) 156*3c51966bSJens Wiklander 157*3c51966bSJens Wiklander magic = 0x4554504f # 'OPTE' 158*3c51966bSJens Wiklander version = 1 159*3c51966bSJens Wiklander flags = 0 160*3c51966bSJens Wiklander outf.write(struct.pack('<IBBHIIIII', magic, version, arch_id, flags, 161*3c51966bSJens Wiklander init_size, init_load_addr[0], init_load_addr[1], 162*3c51966bSJens Wiklander init_mem_usage, paged_size)) 163*3c51966bSJens Wiklander outf.write(pager_bin) 164*3c51966bSJens Wiklander outf.write(pageable_bin[:init_bin_size]) 165*3c51966bSJens Wiklander for n in range(0, len(pageable_bin), small_page_size): 166*3c51966bSJens Wiklander page = pageable_bin[n:n + small_page_size] 167*3c51966bSJens Wiklander outf.write(hashlib.sha256(page).digest()) 168*3c51966bSJens Wiklander outf.write(pageable_bin[init_bin_size:]) 169*3c51966bSJens Wiklander 170*3c51966bSJens Wiklander 171*3c51966bSJens Wiklanderdef output_header_v2(elffile, outf): 172*3c51966bSJens Wiklander arch_id = get_arch_id(elffile) 173*3c51966bSJens Wiklander init_load_addr = get_init_load_addr(elffile) 174*3c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 175*3c51966bSJens Wiklander pager_bin_size = len(get_pager_bin(elffile)) 176*3c51966bSJens Wiklander paged_area_size = len(get_pageable_bin(elffile)) 177*3c51966bSJens Wiklander hash_size = (paged_area_size // small_page_size * 178*3c51966bSJens Wiklander hashlib.sha256().digest_size) 179*3c51966bSJens Wiklander 180*3c51966bSJens Wiklander if paged_area_size % small_page_size != 0: 181*3c51966bSJens Wiklander eprint("pageable size not a multiple of 4K: " 182*3c51966bSJens Wiklander "{}".format(paged_area_size)) 183*3c51966bSJens Wiklander sys.exit(1) 184*3c51966bSJens Wiklander 185*3c51966bSJens Wiklander init_size = (pager_bin_size + min(init_bin_size, paged_area_size) + 186*3c51966bSJens Wiklander hash_size) 187*3c51966bSJens Wiklander paged_size = paged_area_size - min(init_bin_size, paged_area_size) 188*3c51966bSJens Wiklander 189*3c51966bSJens Wiklander magic = 0x4554504f # 'OPTE' 190*3c51966bSJens Wiklander version = 2 191*3c51966bSJens Wiklander flags = 0 192*3c51966bSJens Wiklander nb_images = 1 if paged_size == 0 else 2 193*3c51966bSJens Wiklander outf.write(struct.pack('<IBBHI', magic, version, arch_id, flags, 194*3c51966bSJens Wiklander nb_images)) 195*3c51966bSJens Wiklander outf.write(struct.pack('<IIII', init_load_addr[0], init_load_addr[1], 196*3c51966bSJens Wiklander 0, init_size)) 197*3c51966bSJens Wiklander if nb_images == 2: 198*3c51966bSJens Wiklander outf.write(struct.pack('<IIII', 0xffffffff, 0xffffffff, 1, paged_size)) 199*3c51966bSJens Wiklander 200*3c51966bSJens Wiklander 201*3c51966bSJens Wiklanderdef output_pager_v2(elffile, outf): 202*3c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 203*3c51966bSJens Wiklander pageable_bin = get_pageable_bin(elffile) 204*3c51966bSJens Wiklander 205*3c51966bSJens Wiklander if len(pageable_bin) % small_page_size != 0: 206*3c51966bSJens Wiklander eprint("pageable size not a multiple of 4K: " 207*3c51966bSJens Wiklander "{}".format(paged_area_size)) 208*3c51966bSJens Wiklander sys.exit(1) 209*3c51966bSJens Wiklander 210*3c51966bSJens Wiklander outf.write(get_pager_bin(elffile)) 211*3c51966bSJens Wiklander outf.write(pageable_bin[:init_bin_size]) 212*3c51966bSJens Wiklander for n in range(0, len(pageable_bin), small_page_size): 213*3c51966bSJens Wiklander page = pageable_bin[n:n + small_page_size] 214*3c51966bSJens Wiklander outf.write(hashlib.sha256(page).digest()) 215*3c51966bSJens Wiklander 216*3c51966bSJens Wiklander 217*3c51966bSJens Wiklanderdef output_pageable_v2(elffile, outf): 218*3c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 219*3c51966bSJens Wiklander outf.write(get_pageable_bin(elffile)[init_bin_size:]) 220*3c51966bSJens Wiklander 221*3c51966bSJens Wiklander 222*3c51966bSJens Wiklanderdef get_args(): 223*3c51966bSJens Wiklander parser = argparse.ArgumentParser() 224*3c51966bSJens Wiklander 225*3c51966bSJens Wiklander parser.add_argument('--input', 226*3c51966bSJens Wiklander required=True, type=argparse.FileType('rb'), 227*3c51966bSJens Wiklander help='The input tee.elf') 228*3c51966bSJens Wiklander 229*3c51966bSJens Wiklander parser.add_argument('--out_tee_bin', 230*3c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 231*3c51966bSJens Wiklander help='The output tee.bin') 232*3c51966bSJens Wiklander 233*3c51966bSJens Wiklander parser.add_argument('--out_tee_pager_bin', 234*3c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 235*3c51966bSJens Wiklander help='The output tee_pager.bin') 236*3c51966bSJens Wiklander 237*3c51966bSJens Wiklander parser.add_argument('--out_tee_pageable_bin', 238*3c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 239*3c51966bSJens Wiklander help='The output tee_pageable.bin') 240*3c51966bSJens Wiklander 241*3c51966bSJens Wiklander parser.add_argument('--out_header_v2', 242*3c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 243*3c51966bSJens Wiklander help='The output tee_header_v2.bin') 244*3c51966bSJens Wiklander 245*3c51966bSJens Wiklander parser.add_argument('--out_pager_v2', 246*3c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 247*3c51966bSJens Wiklander help='The output tee_pager_v2.bin') 248*3c51966bSJens Wiklander 249*3c51966bSJens Wiklander parser.add_argument('--out_pageable_v2', 250*3c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 251*3c51966bSJens Wiklander help='The output tee_pageable_v2.bin') 252*3c51966bSJens Wiklander 253*3c51966bSJens Wiklander return parser.parse_args() 254*3c51966bSJens Wiklander 255*3c51966bSJens Wiklander 256*3c51966bSJens Wiklanderdef main(): 257*3c51966bSJens Wiklander args = get_args() 258*3c51966bSJens Wiklander 259*3c51966bSJens Wiklander elffile = ELFFile(args.input) 260*3c51966bSJens Wiklander 261*3c51966bSJens Wiklander if args.out_tee_bin: 262*3c51966bSJens Wiklander output_header_v1(elffile, args.out_tee_bin) 263*3c51966bSJens Wiklander 264*3c51966bSJens Wiklander if args.out_tee_pager_bin: 265*3c51966bSJens Wiklander output_pager_bin(elffile, args.out_tee_pager_bin) 266*3c51966bSJens Wiklander 267*3c51966bSJens Wiklander if args.out_tee_pageable_bin: 268*3c51966bSJens Wiklander output_pageable_bin(elffile, args.out_tee_pageable_bin) 269*3c51966bSJens Wiklander 270*3c51966bSJens Wiklander if args.out_header_v2: 271*3c51966bSJens Wiklander output_header_v2(elffile, args.out_header_v2) 272*3c51966bSJens Wiklander 273*3c51966bSJens Wiklander if args.out_pager_v2: 274*3c51966bSJens Wiklander output_pager_v2(elffile, args.out_pager_v2) 275*3c51966bSJens Wiklander 276*3c51966bSJens Wiklander if args.out_pageable_v2: 277*3c51966bSJens Wiklander output_pageable_v2(elffile, args.out_pageable_v2) 278*3c51966bSJens Wiklander 279*3c51966bSJens Wiklander 280*3c51966bSJens Wiklanderif __name__ == "__main__": 281*3c51966bSJens Wiklander main() 282