13c51966bSJens Wiklander#!/usr/bin/env python3 23c51966bSJens Wiklander# SPDX-License-Identifier: BSD-2-Clause 33c51966bSJens Wiklander# 43c51966bSJens Wiklander# Copyright (c) 2019, Linaro Limited 53c51966bSJens Wiklander# 63c51966bSJens Wiklander 73c51966bSJens Wiklanderfrom __future__ import print_function 83c51966bSJens Wiklanderfrom __future__ import division 93c51966bSJens Wiklander 103c51966bSJens Wiklanderimport argparse 113c51966bSJens Wiklanderimport sys 123c51966bSJens Wiklanderimport struct 133c51966bSJens Wiklanderimport re 143c51966bSJens Wiklanderimport hashlib 153c51966bSJens Wiklandertry: 163c51966bSJens Wiklander from elftools.elf.elffile import ELFFile 173c51966bSJens Wiklander from elftools.elf.constants import SH_FLAGS 18*5966660cSJens Wiklander from elftools.elf.enums import ENUM_RELOC_TYPE_ARM 19*5966660cSJens Wiklander from elftools.elf.enums import ENUM_RELOC_TYPE_AARCH64 203c51966bSJens Wiklander from elftools.elf.sections import SymbolTableSection 21*5966660cSJens Wiklander from elftools.elf.relocation import RelocationSection 223c51966bSJens Wiklander 233c51966bSJens Wiklanderexcept ImportError: 243c51966bSJens Wiklander print(""" 253c51966bSJens Wiklander*** 263c51966bSJens WiklanderCan't find elftools module. Probably it is not installed on your system. 273c51966bSJens WiklanderYou can install this module with 283c51966bSJens Wiklander 293c51966bSJens Wiklander$ apt install python3-pyelftools 303c51966bSJens Wiklander 313c51966bSJens Wiklanderif you are using Ubuntu. Or try to search for "pyelftools" or "elftools" in 323c51966bSJens Wiklanderyour package manager if you are using some other distribution. 333c51966bSJens Wiklander*** 343c51966bSJens Wiklander""") 353c51966bSJens Wiklander raise 363c51966bSJens Wiklander 373c51966bSJens Wiklandersmall_page_size = 4 * 1024 383c51966bSJens Wiklanderelffile_symbols = None 393c51966bSJens Wiklandertee_pageable_bin = None 403c51966bSJens Wiklandertee_pager_bin = None 415dd1570aSJens Wiklandertee_embdata_bin = None 423c51966bSJens Wiklander 433c51966bSJens Wiklander 443c51966bSJens Wiklanderdef eprint(*args, **kwargs): 453c51966bSJens Wiklander print(*args, file=sys.stderr, **kwargs) 463c51966bSJens Wiklander 473c51966bSJens Wiklander 485dd1570aSJens Wiklanderdef round_up(n, m): 495dd1570aSJens Wiklander if n == 0: 505dd1570aSJens Wiklander return 0 515dd1570aSJens Wiklander else: 525dd1570aSJens Wiklander return (((n - 1) // m) + 1) * m 535dd1570aSJens Wiklander 545dd1570aSJens Wiklander 555dd1570aSJens Wiklanderdef get_arch_id(elffile): 565dd1570aSJens Wiklander e_machine = elffile.header['e_machine'] 575dd1570aSJens Wiklander if e_machine == 'EM_ARM': 585dd1570aSJens Wiklander return 0 595dd1570aSJens Wiklander if e_machine == 'EM_AARCH64': 605dd1570aSJens Wiklander return 1 615dd1570aSJens Wiklander eprint('Unknown e_machine "%s"' % e_machine) 625dd1570aSJens Wiklander sys.exit(1) 635dd1570aSJens Wiklander 645dd1570aSJens Wiklander 653c51966bSJens Wiklanderdef get_symbol(elffile, name): 663c51966bSJens Wiklander global elffile_symbols 673c51966bSJens Wiklander if elffile_symbols is None: 683c51966bSJens Wiklander elffile_symbols = dict() 693c51966bSJens Wiklander symbol_tables = [s for s in elffile.iter_sections() 703c51966bSJens Wiklander if isinstance(s, SymbolTableSection)] 713c51966bSJens Wiklander for section in symbol_tables: 723c51966bSJens Wiklander for symbol in section.iter_symbols(): 733c51966bSJens Wiklander if symbol['st_info']['bind'] == 'STB_GLOBAL': 743c51966bSJens Wiklander elffile_symbols[symbol.name] = symbol 753c51966bSJens Wiklander 763c51966bSJens Wiklander try: 773c51966bSJens Wiklander return elffile_symbols[name] 783c51966bSJens Wiklander except (KeyError): 793c51966bSJens Wiklander eprint("Cannot find symbol %s" % name) 803c51966bSJens Wiklander sys.exit(1) 813c51966bSJens Wiklander 823c51966bSJens Wiklander 835dd1570aSJens Wiklanderdef get_sections(elffile, pad_to, dump_names): 843c51966bSJens Wiklander last_end = 0 853c51966bSJens Wiklander bin_data = bytearray() 863c51966bSJens Wiklander 873c51966bSJens Wiklander for section in elffile.iter_sections(): 883c51966bSJens Wiklander if (section['sh_type'] == 'SHT_NOBITS' or 893c51966bSJens Wiklander not (section['sh_flags'] & SH_FLAGS.SHF_ALLOC) or 903c51966bSJens Wiklander not dump_names.match(section.name)): 913c51966bSJens Wiklander continue 923c51966bSJens Wiklander 933c51966bSJens Wiklander if last_end == 0: 943c51966bSJens Wiklander bin_data = section.data() 953c51966bSJens Wiklander else: 963c51966bSJens Wiklander if section['sh_addr'] > last_end: 973c51966bSJens Wiklander bin_data += bytearray(section['sh_addr'] - last_end) 983c51966bSJens Wiklander bin_data += section.data() 993c51966bSJens Wiklander 1003c51966bSJens Wiklander last_end = section['sh_addr'] + section['sh_size'] 1013c51966bSJens Wiklander 1023c51966bSJens Wiklander if pad_to > last_end: 1033c51966bSJens Wiklander bin_data += bytearray(pad_to - last_end) 1043c51966bSJens Wiklander last_end = pad_to 1053c51966bSJens Wiklander 1063c51966bSJens Wiklander return bin_data 1073c51966bSJens Wiklander 1083c51966bSJens Wiklander 1093c51966bSJens Wiklanderdef get_pageable_bin(elffile): 1103c51966bSJens Wiklander global tee_pageable_bin 1113c51966bSJens Wiklander if tee_pageable_bin is None: 1123c51966bSJens Wiklander pad_to = 0 1133c51966bSJens Wiklander dump_names = re.compile(r'^\..*_(pageable|init)$') 1145dd1570aSJens Wiklander tee_pageable_bin = get_sections(elffile, pad_to, dump_names) 1153c51966bSJens Wiklander return tee_pageable_bin 1163c51966bSJens Wiklander 1173c51966bSJens Wiklander 1183c51966bSJens Wiklanderdef get_pager_bin(elffile): 1193c51966bSJens Wiklander global tee_pager_bin 1203c51966bSJens Wiklander if tee_pager_bin is None: 1213c51966bSJens Wiklander pad_to = get_symbol(elffile, '__data_end')['st_value'] 1225dd1570aSJens Wiklander dump_names = re.compile( 123*5966660cSJens Wiklander r'^\.(text|rodata|got|data|ARM\.exidx|ARM\.extab)$') 1245dd1570aSJens Wiklander tee_pager_bin = get_sections(elffile, pad_to, dump_names) 1253c51966bSJens Wiklander 1263c51966bSJens Wiklander return tee_pager_bin 1273c51966bSJens Wiklander 1283c51966bSJens Wiklander 129*5966660cSJens Wiklanderdef get_reloc_bin(elffile): 130*5966660cSJens Wiklander if get_arch_id(elffile) == 0: 131*5966660cSJens Wiklander exp_rel_type = ENUM_RELOC_TYPE_ARM['R_ARM_RELATIVE'] 132*5966660cSJens Wiklander else: 133*5966660cSJens Wiklander exp_rel_type = ENUM_RELOC_TYPE_AARCH64['R_AARCH64_RELATIVE'] 134*5966660cSJens Wiklander 135*5966660cSJens Wiklander link_address = get_symbol(elffile, '__text_start')['st_value'] 136*5966660cSJens Wiklander 137*5966660cSJens Wiklander addrs = [] 138*5966660cSJens Wiklander for section in elffile.iter_sections(): 139*5966660cSJens Wiklander if not isinstance(section, RelocationSection): 140*5966660cSJens Wiklander continue 141*5966660cSJens Wiklander for rel in section.iter_relocations(): 142*5966660cSJens Wiklander if rel['r_info_type'] == 0: 143*5966660cSJens Wiklander continue 144*5966660cSJens Wiklander if rel['r_info_type'] != exp_rel_type: 145*5966660cSJens Wiklander eprint("Unexpected relocation type 0x%x" % 146*5966660cSJens Wiklander rel['r_info_type']) 147*5966660cSJens Wiklander sys.exit(1) 148*5966660cSJens Wiklander addrs.append(rel['r_offset'] - link_address) 149*5966660cSJens Wiklander 150*5966660cSJens Wiklander addrs.sort() 151*5966660cSJens Wiklander data = bytearray() 152*5966660cSJens Wiklander for a in addrs: 153*5966660cSJens Wiklander data += struct.pack('<I', a) 154*5966660cSJens Wiklander 155*5966660cSJens Wiklander # Relocations has been reduced to only become the relative type with 156*5966660cSJens Wiklander # addend at the address (r_offset) of relocation, that is, increase by 157*5966660cSJens Wiklander # load_offset. The addresses (r_offset) are also sorted. The format is 158*5966660cSJens Wiklander # then: 159*5966660cSJens Wiklander # uint32_t: relocation #1 160*5966660cSJens Wiklander # uint32_t: relocation #2 161*5966660cSJens Wiklander # ... 162*5966660cSJens Wiklander # uint32_t: relocation #n 163*5966660cSJens Wiklander 164*5966660cSJens Wiklander return data 165*5966660cSJens Wiklander 166*5966660cSJens Wiklander 1675dd1570aSJens Wiklanderdef get_hashes_bin(elffile): 1685dd1570aSJens Wiklander pageable_bin = get_pageable_bin(elffile) 1695dd1570aSJens Wiklander if len(pageable_bin) % small_page_size != 0: 1705dd1570aSJens Wiklander eprint("pageable size not a multiple of 4K: " 1715dd1570aSJens Wiklander "{}".format(paged_area_size)) 1725dd1570aSJens Wiklander sys.exit(1) 1735dd1570aSJens Wiklander 1745dd1570aSJens Wiklander data = bytearray() 1755dd1570aSJens Wiklander for n in range(0, len(pageable_bin), small_page_size): 1765dd1570aSJens Wiklander page = pageable_bin[n:n + small_page_size] 1775dd1570aSJens Wiklander data += hashlib.sha256(page).digest() 1785dd1570aSJens Wiklander 1795dd1570aSJens Wiklander return data 1805dd1570aSJens Wiklander 1815dd1570aSJens Wiklander 1825dd1570aSJens Wiklanderdef get_embdata_bin(elffile): 1835dd1570aSJens Wiklander global tee_embdata_bin 1845dd1570aSJens Wiklander if tee_embdata_bin is None: 1855dd1570aSJens Wiklander hashes_bin = get_hashes_bin(elffile) 186*5966660cSJens Wiklander reloc_bin = get_reloc_bin(elffile) 1875dd1570aSJens Wiklander 188*5966660cSJens Wiklander num_entries = 2 1895dd1570aSJens Wiklander hash_offs = 2 * 4 + num_entries * (2 * 4) 1905dd1570aSJens Wiklander hash_pad = round_up(len(hashes_bin), 8) - len(hashes_bin) 191*5966660cSJens Wiklander reloc_offs = hash_offs + len(hashes_bin) + hash_pad 192*5966660cSJens Wiklander reloc_pad = round_up(len(reloc_bin), 8) - len(reloc_bin) 193*5966660cSJens Wiklander total_len = reloc_offs + len(reloc_bin) + reloc_pad 1945dd1570aSJens Wiklander 195*5966660cSJens Wiklander tee_embdata_bin = struct.pack('<IIIIII', total_len, num_entries, 196*5966660cSJens Wiklander hash_offs, len(hashes_bin), 197*5966660cSJens Wiklander reloc_offs, len(reloc_bin)) 1985dd1570aSJens Wiklander tee_embdata_bin += hashes_bin + bytearray(hash_pad) 199*5966660cSJens Wiklander tee_embdata_bin += reloc_bin + bytearray(reloc_pad) 2005dd1570aSJens Wiklander 2015dd1570aSJens Wiklander # The embedded data region is designed to be easy to extend when 2025dd1570aSJens Wiklander # needed, it's formatted as: 203*5966660cSJens Wiklander # +---------------------------------------------------------+ 2045dd1570aSJens Wiklander # | uint32_t: Length of entire area including this field | 205*5966660cSJens Wiklander # +---------------------------------------------------------+ 206*5966660cSJens Wiklander # | uint32_t: Number of entries "2" | 207*5966660cSJens Wiklander # +---------------------------------------------------------+ 2085dd1570aSJens Wiklander # | uint32_t: Offset of hashes from beginning of table | 209*5966660cSJens Wiklander # +---------------------------------------------------------+ 2105dd1570aSJens Wiklander # | uint32_t: Length of hashes | 211*5966660cSJens Wiklander # +---------------------------------------------------------+ 212*5966660cSJens Wiklander # | uint32_t: Offset of relocations from beginning of table | 213*5966660cSJens Wiklander # +---------------------------------------------------------+ 214*5966660cSJens Wiklander # | uint32_t: Length of relocations | 215*5966660cSJens Wiklander # +---------------------------------------------------------+ 2165dd1570aSJens Wiklander # | Data of hashes + eventual padding | 217*5966660cSJens Wiklander # +---------------------------------------------------------+ 218*5966660cSJens Wiklander # | Data of relocations + eventual padding | 219*5966660cSJens Wiklander # +---------------------------------------------------------+ 2205dd1570aSJens Wiklander 2215dd1570aSJens Wiklander return tee_embdata_bin 2225dd1570aSJens Wiklander 2235dd1570aSJens Wiklander 2243c51966bSJens Wiklanderdef output_pager_bin(elffile, outf): 2253c51966bSJens Wiklander outf.write(get_pager_bin(elffile)) 2263c51966bSJens Wiklander 2273c51966bSJens Wiklander 2283c51966bSJens Wiklanderdef output_pageable_bin(elffile, outf): 2293c51966bSJens Wiklander outf.write(get_pageable_bin(elffile)) 2303c51966bSJens Wiklander 2313c51966bSJens Wiklander 2323c51966bSJens Wiklanderdef get_init_load_addr(elffile): 2333c51966bSJens Wiklander init_load_addr = get_symbol(elffile, '_start')['st_value'] 2343c51966bSJens Wiklander init_load_addr_hi = init_load_addr >> 32 2353c51966bSJens Wiklander init_load_addr_lo = init_load_addr & 0xffffffff 2363c51966bSJens Wiklander return init_load_addr_hi, init_load_addr_lo 2373c51966bSJens Wiklander 2383c51966bSJens Wiklander 2393c51966bSJens Wiklanderdef output_header_v1(elffile, outf): 2403c51966bSJens Wiklander arch_id = get_arch_id(elffile) 2413c51966bSJens Wiklander pager_bin = get_pager_bin(elffile) 2423c51966bSJens Wiklander pageable_bin = get_pageable_bin(elffile) 2435dd1570aSJens Wiklander embdata_bin = get_embdata_bin(elffile) 2443c51966bSJens Wiklander init_load_addr = get_init_load_addr(elffile) 2453c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 2463c51966bSJens Wiklander pager_bin_size = len(pager_bin) 2473c51966bSJens Wiklander paged_area_size = len(pageable_bin) 2485dd1570aSJens Wiklander 2495dd1570aSJens Wiklander init_mem_usage = (get_symbol(elffile, '__init_end')['st_value'] - 2505dd1570aSJens Wiklander get_symbol(elffile, '__text_start')['st_value'] + 2515dd1570aSJens Wiklander len(embdata_bin)) 2523c51966bSJens Wiklander 2533c51966bSJens Wiklander init_size = (pager_bin_size + min(init_bin_size, paged_area_size) + 2545dd1570aSJens Wiklander len(embdata_bin)) 2553c51966bSJens Wiklander paged_size = paged_area_size - min(init_bin_size, paged_area_size) 2563c51966bSJens Wiklander 2573c51966bSJens Wiklander magic = 0x4554504f # 'OPTE' 2583c51966bSJens Wiklander version = 1 2593c51966bSJens Wiklander flags = 0 2603c51966bSJens Wiklander outf.write(struct.pack('<IBBHIIIII', magic, version, arch_id, flags, 2613c51966bSJens Wiklander init_size, init_load_addr[0], init_load_addr[1], 2623c51966bSJens Wiklander init_mem_usage, paged_size)) 2633c51966bSJens Wiklander outf.write(pager_bin) 2643c51966bSJens Wiklander outf.write(pageable_bin[:init_bin_size]) 2655dd1570aSJens Wiklander outf.write(embdata_bin) 2663c51966bSJens Wiklander outf.write(pageable_bin[init_bin_size:]) 2673c51966bSJens Wiklander 2683c51966bSJens Wiklander 2693c51966bSJens Wiklanderdef output_header_v2(elffile, outf): 2703c51966bSJens Wiklander arch_id = get_arch_id(elffile) 2713c51966bSJens Wiklander init_load_addr = get_init_load_addr(elffile) 2723c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 2733c51966bSJens Wiklander pager_bin_size = len(get_pager_bin(elffile)) 2743c51966bSJens Wiklander paged_area_size = len(get_pageable_bin(elffile)) 2755dd1570aSJens Wiklander embdata_bin_size = len(get_embdata_bin(elffile)) 2763c51966bSJens Wiklander 2773c51966bSJens Wiklander init_size = (pager_bin_size + min(init_bin_size, paged_area_size) + 2785dd1570aSJens Wiklander embdata_bin_size) 2793c51966bSJens Wiklander paged_size = paged_area_size - min(init_bin_size, paged_area_size) 2803c51966bSJens Wiklander 2813c51966bSJens Wiklander magic = 0x4554504f # 'OPTE' 2823c51966bSJens Wiklander version = 2 2833c51966bSJens Wiklander flags = 0 2843c51966bSJens Wiklander nb_images = 1 if paged_size == 0 else 2 2853c51966bSJens Wiklander outf.write(struct.pack('<IBBHI', magic, version, arch_id, flags, 2863c51966bSJens Wiklander nb_images)) 2873c51966bSJens Wiklander outf.write(struct.pack('<IIII', init_load_addr[0], init_load_addr[1], 2883c51966bSJens Wiklander 0, init_size)) 2893c51966bSJens Wiklander if nb_images == 2: 2903c51966bSJens Wiklander outf.write(struct.pack('<IIII', 0xffffffff, 0xffffffff, 1, paged_size)) 2913c51966bSJens Wiklander 2923c51966bSJens Wiklander 2933c51966bSJens Wiklanderdef output_pager_v2(elffile, outf): 2943c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 2955dd1570aSJens Wiklander pager_bin = get_pager_bin(elffile) 2963c51966bSJens Wiklander pageable_bin = get_pageable_bin(elffile) 2975dd1570aSJens Wiklander embdata_bin = get_embdata_bin(elffile) 2983c51966bSJens Wiklander 2995dd1570aSJens Wiklander outf.write(pager_bin) 3003c51966bSJens Wiklander outf.write(pageable_bin[:init_bin_size]) 3015dd1570aSJens Wiklander outf.write(embdata_bin) 3023c51966bSJens Wiklander 3033c51966bSJens Wiklander 3043c51966bSJens Wiklanderdef output_pageable_v2(elffile, outf): 3053c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 3063c51966bSJens Wiklander outf.write(get_pageable_bin(elffile)[init_bin_size:]) 3073c51966bSJens Wiklander 3083c51966bSJens Wiklander 3093c51966bSJens Wiklanderdef get_args(): 3103c51966bSJens Wiklander parser = argparse.ArgumentParser() 3113c51966bSJens Wiklander 3123c51966bSJens Wiklander parser.add_argument('--input', 3133c51966bSJens Wiklander required=True, type=argparse.FileType('rb'), 3143c51966bSJens Wiklander help='The input tee.elf') 3153c51966bSJens Wiklander 3163c51966bSJens Wiklander parser.add_argument('--out_tee_bin', 3173c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 3183c51966bSJens Wiklander help='The output tee.bin') 3193c51966bSJens Wiklander 3203c51966bSJens Wiklander parser.add_argument('--out_tee_pager_bin', 3213c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 3223c51966bSJens Wiklander help='The output tee_pager.bin') 3233c51966bSJens Wiklander 3243c51966bSJens Wiklander parser.add_argument('--out_tee_pageable_bin', 3253c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 3263c51966bSJens Wiklander help='The output tee_pageable.bin') 3273c51966bSJens Wiklander 3283c51966bSJens Wiklander parser.add_argument('--out_header_v2', 3293c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 3303c51966bSJens Wiklander help='The output tee_header_v2.bin') 3313c51966bSJens Wiklander 3323c51966bSJens Wiklander parser.add_argument('--out_pager_v2', 3333c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 3343c51966bSJens Wiklander help='The output tee_pager_v2.bin') 3353c51966bSJens Wiklander 3363c51966bSJens Wiklander parser.add_argument('--out_pageable_v2', 3373c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 3383c51966bSJens Wiklander help='The output tee_pageable_v2.bin') 3393c51966bSJens Wiklander 3403c51966bSJens Wiklander return parser.parse_args() 3413c51966bSJens Wiklander 3423c51966bSJens Wiklander 3433c51966bSJens Wiklanderdef main(): 3443c51966bSJens Wiklander args = get_args() 3453c51966bSJens Wiklander 3463c51966bSJens Wiklander elffile = ELFFile(args.input) 3473c51966bSJens Wiklander 3483c51966bSJens Wiklander if args.out_tee_bin: 3493c51966bSJens Wiklander output_header_v1(elffile, args.out_tee_bin) 3503c51966bSJens Wiklander 3513c51966bSJens Wiklander if args.out_tee_pager_bin: 3523c51966bSJens Wiklander output_pager_bin(elffile, args.out_tee_pager_bin) 3533c51966bSJens Wiklander 3543c51966bSJens Wiklander if args.out_tee_pageable_bin: 3553c51966bSJens Wiklander output_pageable_bin(elffile, args.out_tee_pageable_bin) 3563c51966bSJens Wiklander 3573c51966bSJens Wiklander if args.out_header_v2: 3583c51966bSJens Wiklander output_header_v2(elffile, args.out_header_v2) 3593c51966bSJens Wiklander 3603c51966bSJens Wiklander if args.out_pager_v2: 3613c51966bSJens Wiklander output_pager_v2(elffile, args.out_pager_v2) 3623c51966bSJens Wiklander 3633c51966bSJens Wiklander if args.out_pageable_v2: 3643c51966bSJens Wiklander output_pageable_v2(elffile, args.out_pageable_v2) 3653c51966bSJens Wiklander 3663c51966bSJens Wiklander 3673c51966bSJens Wiklanderif __name__ == "__main__": 3683c51966bSJens Wiklander main() 369