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 183c51966bSJens Wiklander from elftools.elf.sections import SymbolTableSection 193c51966bSJens Wiklander 203c51966bSJens Wiklanderexcept ImportError: 213c51966bSJens Wiklander print(""" 223c51966bSJens Wiklander*** 233c51966bSJens WiklanderCan't find elftools module. Probably it is not installed on your system. 243c51966bSJens WiklanderYou can install this module with 253c51966bSJens Wiklander 263c51966bSJens Wiklander$ apt install python3-pyelftools 273c51966bSJens Wiklander 283c51966bSJens Wiklanderif you are using Ubuntu. Or try to search for "pyelftools" or "elftools" in 293c51966bSJens Wiklanderyour package manager if you are using some other distribution. 303c51966bSJens Wiklander*** 313c51966bSJens Wiklander""") 323c51966bSJens Wiklander raise 333c51966bSJens Wiklander 343c51966bSJens Wiklandersmall_page_size = 4 * 1024 353c51966bSJens Wiklanderelffile_symbols = None 363c51966bSJens Wiklandertee_pageable_bin = None 373c51966bSJens Wiklandertee_pager_bin = None 38*5dd1570aSJens Wiklandertee_embdata_bin = None 393c51966bSJens Wiklander 403c51966bSJens Wiklander 413c51966bSJens Wiklanderdef eprint(*args, **kwargs): 423c51966bSJens Wiklander print(*args, file=sys.stderr, **kwargs) 433c51966bSJens Wiklander 443c51966bSJens Wiklander 45*5dd1570aSJens Wiklanderdef round_up(n, m): 46*5dd1570aSJens Wiklander if n == 0: 47*5dd1570aSJens Wiklander return 0 48*5dd1570aSJens Wiklander else: 49*5dd1570aSJens Wiklander return (((n - 1) // m) + 1) * m 50*5dd1570aSJens Wiklander 51*5dd1570aSJens Wiklander 52*5dd1570aSJens Wiklanderdef get_arch_id(elffile): 53*5dd1570aSJens Wiklander e_machine = elffile.header['e_machine'] 54*5dd1570aSJens Wiklander if e_machine == 'EM_ARM': 55*5dd1570aSJens Wiklander return 0 56*5dd1570aSJens Wiklander if e_machine == 'EM_AARCH64': 57*5dd1570aSJens Wiklander return 1 58*5dd1570aSJens Wiklander eprint('Unknown e_machine "%s"' % e_machine) 59*5dd1570aSJens Wiklander sys.exit(1) 60*5dd1570aSJens Wiklander 61*5dd1570aSJens Wiklander 623c51966bSJens Wiklanderdef get_symbol(elffile, name): 633c51966bSJens Wiklander global elffile_symbols 643c51966bSJens Wiklander if elffile_symbols is None: 653c51966bSJens Wiklander elffile_symbols = dict() 663c51966bSJens Wiklander symbol_tables = [s for s in elffile.iter_sections() 673c51966bSJens Wiklander if isinstance(s, SymbolTableSection)] 683c51966bSJens Wiklander for section in symbol_tables: 693c51966bSJens Wiklander for symbol in section.iter_symbols(): 703c51966bSJens Wiklander if symbol['st_info']['bind'] == 'STB_GLOBAL': 713c51966bSJens Wiklander elffile_symbols[symbol.name] = symbol 723c51966bSJens Wiklander 733c51966bSJens Wiklander try: 743c51966bSJens Wiklander return elffile_symbols[name] 753c51966bSJens Wiklander except (KeyError): 763c51966bSJens Wiklander eprint("Cannot find symbol %s" % name) 773c51966bSJens Wiklander sys.exit(1) 783c51966bSJens Wiklander 793c51966bSJens Wiklander 80*5dd1570aSJens Wiklanderdef get_sections(elffile, pad_to, dump_names): 813c51966bSJens Wiklander last_end = 0 823c51966bSJens Wiklander bin_data = bytearray() 833c51966bSJens Wiklander 843c51966bSJens Wiklander for section in elffile.iter_sections(): 853c51966bSJens Wiklander if (section['sh_type'] == 'SHT_NOBITS' or 863c51966bSJens Wiklander not (section['sh_flags'] & SH_FLAGS.SHF_ALLOC) or 873c51966bSJens Wiklander not dump_names.match(section.name)): 883c51966bSJens Wiklander continue 893c51966bSJens Wiklander 903c51966bSJens Wiklander if last_end == 0: 913c51966bSJens Wiklander bin_data = section.data() 923c51966bSJens Wiklander else: 933c51966bSJens Wiklander if section['sh_addr'] > last_end: 943c51966bSJens Wiklander bin_data += bytearray(section['sh_addr'] - last_end) 953c51966bSJens Wiklander bin_data += section.data() 963c51966bSJens Wiklander 973c51966bSJens Wiklander last_end = section['sh_addr'] + section['sh_size'] 983c51966bSJens Wiklander 993c51966bSJens Wiklander if pad_to > last_end: 1003c51966bSJens Wiklander bin_data += bytearray(pad_to - last_end) 1013c51966bSJens Wiklander last_end = pad_to 1023c51966bSJens Wiklander 1033c51966bSJens Wiklander return bin_data 1043c51966bSJens Wiklander 1053c51966bSJens Wiklander 1063c51966bSJens Wiklanderdef get_pageable_bin(elffile): 1073c51966bSJens Wiklander global tee_pageable_bin 1083c51966bSJens Wiklander if tee_pageable_bin is None: 1093c51966bSJens Wiklander pad_to = 0 1103c51966bSJens Wiklander dump_names = re.compile(r'^\..*_(pageable|init)$') 111*5dd1570aSJens Wiklander tee_pageable_bin = get_sections(elffile, pad_to, dump_names) 1123c51966bSJens Wiklander return tee_pageable_bin 1133c51966bSJens Wiklander 1143c51966bSJens Wiklander 1153c51966bSJens Wiklanderdef get_pager_bin(elffile): 1163c51966bSJens Wiklander global tee_pager_bin 1173c51966bSJens Wiklander if tee_pager_bin is None: 1183c51966bSJens Wiklander pad_to = get_symbol(elffile, '__data_end')['st_value'] 119*5dd1570aSJens Wiklander dump_names = re.compile( 120*5dd1570aSJens Wiklander r'^\.(text|rodata|got|data|ARM\.exidx|ARM\.extab|rel|rela)$') 121*5dd1570aSJens Wiklander tee_pager_bin = get_sections(elffile, pad_to, dump_names) 1223c51966bSJens Wiklander 1233c51966bSJens Wiklander return tee_pager_bin 1243c51966bSJens Wiklander 1253c51966bSJens Wiklander 126*5dd1570aSJens Wiklanderdef get_hashes_bin(elffile): 127*5dd1570aSJens Wiklander pageable_bin = get_pageable_bin(elffile) 128*5dd1570aSJens Wiklander if len(pageable_bin) % small_page_size != 0: 129*5dd1570aSJens Wiklander eprint("pageable size not a multiple of 4K: " 130*5dd1570aSJens Wiklander "{}".format(paged_area_size)) 131*5dd1570aSJens Wiklander sys.exit(1) 132*5dd1570aSJens Wiklander 133*5dd1570aSJens Wiklander data = bytearray() 134*5dd1570aSJens Wiklander for n in range(0, len(pageable_bin), small_page_size): 135*5dd1570aSJens Wiklander page = pageable_bin[n:n + small_page_size] 136*5dd1570aSJens Wiklander data += hashlib.sha256(page).digest() 137*5dd1570aSJens Wiklander 138*5dd1570aSJens Wiklander return data 139*5dd1570aSJens Wiklander 140*5dd1570aSJens Wiklander 141*5dd1570aSJens Wiklanderdef get_embdata_bin(elffile): 142*5dd1570aSJens Wiklander global tee_embdata_bin 143*5dd1570aSJens Wiklander if tee_embdata_bin is None: 144*5dd1570aSJens Wiklander hashes_bin = get_hashes_bin(elffile) 145*5dd1570aSJens Wiklander 146*5dd1570aSJens Wiklander num_entries = 1 147*5dd1570aSJens Wiklander hash_offs = 2 * 4 + num_entries * (2 * 4) 148*5dd1570aSJens Wiklander hash_pad = round_up(len(hashes_bin), 8) - len(hashes_bin) 149*5dd1570aSJens Wiklander total_len = hash_offs + len(hashes_bin) + hash_pad 150*5dd1570aSJens Wiklander 151*5dd1570aSJens Wiklander tee_embdata_bin = struct.pack('<IIII', total_len, num_entries, 152*5dd1570aSJens Wiklander hash_offs, len(hashes_bin)) 153*5dd1570aSJens Wiklander tee_embdata_bin += hashes_bin + bytearray(hash_pad) 154*5dd1570aSJens Wiklander 155*5dd1570aSJens Wiklander # The embedded data region is designed to be easy to extend when 156*5dd1570aSJens Wiklander # needed, it's formatted as: 157*5dd1570aSJens Wiklander # +--------------------------------------------------------+ 158*5dd1570aSJens Wiklander # | uint32_t: Length of entire area including this field | 159*5dd1570aSJens Wiklander # +--------------------------------------------------------+ 160*5dd1570aSJens Wiklander # | uint32_t: Number of entries "1" | 161*5dd1570aSJens Wiklander # +--------------------------------------------------------+ 162*5dd1570aSJens Wiklander # | uint32_t: Offset of hashes from beginning of table | 163*5dd1570aSJens Wiklander # +--------------------------------------------------------+ 164*5dd1570aSJens Wiklander # | uint32_t: Length of hashes | 165*5dd1570aSJens Wiklander # +--------------------------------------------------------+ 166*5dd1570aSJens Wiklander # | Data of hashes + eventual padding | 167*5dd1570aSJens Wiklander # +--------------------------------------------------------+ 168*5dd1570aSJens Wiklander 169*5dd1570aSJens Wiklander return tee_embdata_bin 170*5dd1570aSJens Wiklander 171*5dd1570aSJens Wiklander 1723c51966bSJens Wiklanderdef output_pager_bin(elffile, outf): 1733c51966bSJens Wiklander outf.write(get_pager_bin(elffile)) 1743c51966bSJens Wiklander 1753c51966bSJens Wiklander 1763c51966bSJens Wiklanderdef output_pageable_bin(elffile, outf): 1773c51966bSJens Wiklander outf.write(get_pageable_bin(elffile)) 1783c51966bSJens Wiklander 1793c51966bSJens Wiklander 1803c51966bSJens Wiklanderdef get_init_load_addr(elffile): 1813c51966bSJens Wiklander init_load_addr = get_symbol(elffile, '_start')['st_value'] 1823c51966bSJens Wiklander init_load_addr_hi = init_load_addr >> 32 1833c51966bSJens Wiklander init_load_addr_lo = init_load_addr & 0xffffffff 1843c51966bSJens Wiklander return init_load_addr_hi, init_load_addr_lo 1853c51966bSJens Wiklander 1863c51966bSJens Wiklander 1873c51966bSJens Wiklanderdef output_header_v1(elffile, outf): 1883c51966bSJens Wiklander arch_id = get_arch_id(elffile) 1893c51966bSJens Wiklander pager_bin = get_pager_bin(elffile) 1903c51966bSJens Wiklander pageable_bin = get_pageable_bin(elffile) 191*5dd1570aSJens Wiklander embdata_bin = get_embdata_bin(elffile) 1923c51966bSJens Wiklander init_load_addr = get_init_load_addr(elffile) 1933c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 1943c51966bSJens Wiklander pager_bin_size = len(pager_bin) 1953c51966bSJens Wiklander paged_area_size = len(pageable_bin) 196*5dd1570aSJens Wiklander 197*5dd1570aSJens Wiklander init_mem_usage = (get_symbol(elffile, '__init_end')['st_value'] - 198*5dd1570aSJens Wiklander get_symbol(elffile, '__text_start')['st_value'] + 199*5dd1570aSJens Wiklander len(embdata_bin)) 2003c51966bSJens Wiklander 2013c51966bSJens Wiklander init_size = (pager_bin_size + min(init_bin_size, paged_area_size) + 202*5dd1570aSJens Wiklander len(embdata_bin)) 2033c51966bSJens Wiklander paged_size = paged_area_size - min(init_bin_size, paged_area_size) 2043c51966bSJens Wiklander 2053c51966bSJens Wiklander magic = 0x4554504f # 'OPTE' 2063c51966bSJens Wiklander version = 1 2073c51966bSJens Wiklander flags = 0 2083c51966bSJens Wiklander outf.write(struct.pack('<IBBHIIIII', magic, version, arch_id, flags, 2093c51966bSJens Wiklander init_size, init_load_addr[0], init_load_addr[1], 2103c51966bSJens Wiklander init_mem_usage, paged_size)) 2113c51966bSJens Wiklander outf.write(pager_bin) 2123c51966bSJens Wiklander outf.write(pageable_bin[:init_bin_size]) 213*5dd1570aSJens Wiklander outf.write(embdata_bin) 2143c51966bSJens Wiklander outf.write(pageable_bin[init_bin_size:]) 2153c51966bSJens Wiklander 2163c51966bSJens Wiklander 2173c51966bSJens Wiklanderdef output_header_v2(elffile, outf): 2183c51966bSJens Wiklander arch_id = get_arch_id(elffile) 2193c51966bSJens Wiklander init_load_addr = get_init_load_addr(elffile) 2203c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 2213c51966bSJens Wiklander pager_bin_size = len(get_pager_bin(elffile)) 2223c51966bSJens Wiklander paged_area_size = len(get_pageable_bin(elffile)) 223*5dd1570aSJens Wiklander embdata_bin_size = len(get_embdata_bin(elffile)) 2243c51966bSJens Wiklander 2253c51966bSJens Wiklander init_size = (pager_bin_size + min(init_bin_size, paged_area_size) + 226*5dd1570aSJens Wiklander embdata_bin_size) 2273c51966bSJens Wiklander paged_size = paged_area_size - min(init_bin_size, paged_area_size) 2283c51966bSJens Wiklander 2293c51966bSJens Wiklander magic = 0x4554504f # 'OPTE' 2303c51966bSJens Wiklander version = 2 2313c51966bSJens Wiklander flags = 0 2323c51966bSJens Wiklander nb_images = 1 if paged_size == 0 else 2 2333c51966bSJens Wiklander outf.write(struct.pack('<IBBHI', magic, version, arch_id, flags, 2343c51966bSJens Wiklander nb_images)) 2353c51966bSJens Wiklander outf.write(struct.pack('<IIII', init_load_addr[0], init_load_addr[1], 2363c51966bSJens Wiklander 0, init_size)) 2373c51966bSJens Wiklander if nb_images == 2: 2383c51966bSJens Wiklander outf.write(struct.pack('<IIII', 0xffffffff, 0xffffffff, 1, paged_size)) 2393c51966bSJens Wiklander 2403c51966bSJens Wiklander 2413c51966bSJens Wiklanderdef output_pager_v2(elffile, outf): 2423c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 243*5dd1570aSJens Wiklander pager_bin = get_pager_bin(elffile) 2443c51966bSJens Wiklander pageable_bin = get_pageable_bin(elffile) 245*5dd1570aSJens Wiklander embdata_bin = get_embdata_bin(elffile) 2463c51966bSJens Wiklander 247*5dd1570aSJens Wiklander outf.write(pager_bin) 2483c51966bSJens Wiklander outf.write(pageable_bin[:init_bin_size]) 249*5dd1570aSJens Wiklander outf.write(embdata_bin) 2503c51966bSJens Wiklander 2513c51966bSJens Wiklander 2523c51966bSJens Wiklanderdef output_pageable_v2(elffile, outf): 2533c51966bSJens Wiklander init_bin_size = get_symbol(elffile, '__init_size')['st_value'] 2543c51966bSJens Wiklander outf.write(get_pageable_bin(elffile)[init_bin_size:]) 2553c51966bSJens Wiklander 2563c51966bSJens Wiklander 2573c51966bSJens Wiklanderdef get_args(): 2583c51966bSJens Wiklander parser = argparse.ArgumentParser() 2593c51966bSJens Wiklander 2603c51966bSJens Wiklander parser.add_argument('--input', 2613c51966bSJens Wiklander required=True, type=argparse.FileType('rb'), 2623c51966bSJens Wiklander help='The input tee.elf') 2633c51966bSJens Wiklander 2643c51966bSJens Wiklander parser.add_argument('--out_tee_bin', 2653c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 2663c51966bSJens Wiklander help='The output tee.bin') 2673c51966bSJens Wiklander 2683c51966bSJens Wiklander parser.add_argument('--out_tee_pager_bin', 2693c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 2703c51966bSJens Wiklander help='The output tee_pager.bin') 2713c51966bSJens Wiklander 2723c51966bSJens Wiklander parser.add_argument('--out_tee_pageable_bin', 2733c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 2743c51966bSJens Wiklander help='The output tee_pageable.bin') 2753c51966bSJens Wiklander 2763c51966bSJens Wiklander parser.add_argument('--out_header_v2', 2773c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 2783c51966bSJens Wiklander help='The output tee_header_v2.bin') 2793c51966bSJens Wiklander 2803c51966bSJens Wiklander parser.add_argument('--out_pager_v2', 2813c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 2823c51966bSJens Wiklander help='The output tee_pager_v2.bin') 2833c51966bSJens Wiklander 2843c51966bSJens Wiklander parser.add_argument('--out_pageable_v2', 2853c51966bSJens Wiklander required=False, type=argparse.FileType('wb'), 2863c51966bSJens Wiklander help='The output tee_pageable_v2.bin') 2873c51966bSJens Wiklander 2883c51966bSJens Wiklander return parser.parse_args() 2893c51966bSJens Wiklander 2903c51966bSJens Wiklander 2913c51966bSJens Wiklanderdef main(): 2923c51966bSJens Wiklander args = get_args() 2933c51966bSJens Wiklander 2943c51966bSJens Wiklander elffile = ELFFile(args.input) 2953c51966bSJens Wiklander 2963c51966bSJens Wiklander if args.out_tee_bin: 2973c51966bSJens Wiklander output_header_v1(elffile, args.out_tee_bin) 2983c51966bSJens Wiklander 2993c51966bSJens Wiklander if args.out_tee_pager_bin: 3003c51966bSJens Wiklander output_pager_bin(elffile, args.out_tee_pager_bin) 3013c51966bSJens Wiklander 3023c51966bSJens Wiklander if args.out_tee_pageable_bin: 3033c51966bSJens Wiklander output_pageable_bin(elffile, args.out_tee_pageable_bin) 3043c51966bSJens Wiklander 3053c51966bSJens Wiklander if args.out_header_v2: 3063c51966bSJens Wiklander output_header_v2(elffile, args.out_header_v2) 3073c51966bSJens Wiklander 3083c51966bSJens Wiklander if args.out_pager_v2: 3093c51966bSJens Wiklander output_pager_v2(elffile, args.out_pager_v2) 3103c51966bSJens Wiklander 3113c51966bSJens Wiklander if args.out_pageable_v2: 3123c51966bSJens Wiklander output_pageable_v2(elffile, args.out_pageable_v2) 3133c51966bSJens Wiklander 3143c51966bSJens Wiklander 3153c51966bSJens Wiklanderif __name__ == "__main__": 3163c51966bSJens Wiklander main() 317