#!/usr/bin/env python3 # # Copyright (c) 2017 Intel Corporation # # SPDX-License-Identifier: Apache-2.0 import argparse import sys import struct import os import elftools from distutils.version import LooseVersion from elftools.elf.elffile import ELFFile from elftools.elf.sections import SymbolTableSection if LooseVersion(elftools.__version__) < LooseVersion('0.24'): sys.stderr.write("pyelftools is out of date, need version 0.24 or later\n") sys.exit(1) # This will never change, first selector in the GDT after the null selector KERNEL_CODE_SEG = 0x08 # These exception vectors push an error code onto the stack. ERR_CODE_VECTORS = [8, 10, 11, 12, 13, 14, 17] def debug(text): if not args.verbose: return sys.stdout.write(os.path.basename(sys.argv[0]) + ": " + text + "\n") def error(text): sys.stderr.write(os.path.basename(sys.argv[0]) + ": " + text + "\n") sys.exit(1) # See Section 6.11 of the Intel Architecture Software Developer's Manual gate_desc_format = "> 16 offset_lo = handler & 0xFFFF data = struct.pack(gate_desc_format, offset_lo, KERNEL_CODE_SEG, 0, type_attr, offset_hi) return data def create_task_gate(tss, dpl): present = 1 gate_type = 0x5 # 32-bit task gate type_attr = gate_type | (dpl << 5) | (present << 7) data = struct.pack(gate_desc_format, 0, tss, 0, type_attr, 0) return data def create_idt_binary(idt_config, filename): with open(filename, "wb") as fp: for handler, tss, dpl in idt_config: if handler and tss: error("entry specifies both handler function and tss") if not handler and not tss: error("entry does not specify either handler or tss") if handler: data = create_irq_gate(handler, dpl) else: data = create_task_gate(tss, dpl) fp.write(data) map_fmt = "= max_irq: error("irq %d specified, but CONFIG_MAX_IRQ_LINES is %d" % (irq, max_irq)) # This table will never have values less than 32 since those are for # exceptions; 0 means unconfigured if irq_vec_map[irq] != 0: error("multiple vector assignments for interrupt line %d", irq) debug("assign IRQ %d to vector %d" % (irq, vector)) irq_vec_map[irq] = vector def setup_idt(spur_code, spur_nocode, intlist, max_vec, max_irq): irq_vec_map = [0 for i in range(max_irq)] vectors = [None for i in range(max_vec)] # Pass 1: sanity check and set up hard-coded interrupt vectors for handler, irq, prio, vec, dpl, tss in intlist: if vec == -1: if prio == -1: error("entry does not specify vector or priority level") continue if vec >= max_vec: error("Vector %d specified, but size of IDT is only %d vectors" % (vec, max_vec)) if vectors[vec] is not None: error("Multiple assignments for vector %d" % vec) vectors[vec] = (handler, tss, dpl) update_irq_vec_map(irq_vec_map, irq, vec, max_irq) # Pass 2: set up priority-based interrupt vectors for handler, irq, prio, vec, dpl, tss in intlist: if vec != -1: continue for vi in priority_range(prio): if vi >= max_vec: break if vectors[vi] is None: vec = vi break if vec == -1: error("can't find a free vector in priority level %d" % prio) vectors[vec] = (handler, tss, dpl) update_irq_vec_map(irq_vec_map, irq, vec, max_irq) # Pass 3: fill in unused vectors with spurious handler at dpl=0 for i in range(max_vec): if vectors[i] is not None: continue if i in ERR_CODE_VECTORS: handler = spur_code else: handler = spur_nocode vectors[i] = (handler, 0, 0) return vectors, irq_vec_map def get_symbols(obj): for section in obj.iter_sections(): if isinstance(section, SymbolTableSection): return {sym.name: sym.entry.st_value for sym in section.iter_symbols()} raise LookupError("Could not find symbol table") # struct genidt_header_s { # uint32_t spurious_addr; # uint32_t spurious_no_error_addr; # int32_t num_entries; # }; intlist_header_fmt = "