x86: convert gen_idt to Python

This is one less host tool we have to compile for every build,
and makes the build tools more portable across host OSes.
The code is also much simpler to maintain.

Issue: ZEP-2063
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-07-14 12:48:35 -07:00 committed by Anas Nashif
commit ddf9f4be31
7 changed files with 236 additions and 665 deletions

View file

@ -1276,10 +1276,8 @@ $(help-board-dirs): help-%:
host-tools:
$(Q)$(MAKE) $(build)=scripts/basic
$(Q)$(MAKE) $(build)=scripts/kconfig standalone
$(Q)$(MAKE) $(build)=scripts/gen_idt
@mkdir -p ${ZEPHYR_BASE}/bin
@cp scripts/basic/fixdep scripts/gen_idt/gen_idt scripts/kconfig/conf \
${ZEPHYR_BASE}/bin
@cp scripts/basic/fixdep scripts/kconfig/conf ${ZEPHYR_BASE}/bin
# Documentation targets

View file

@ -1,14 +1,10 @@
ifeq ($(KBUILD_VERBOSE),1)
GENIDT_EXTRA_ARGS := -d
GENIDT_EXTRA_ARGS := --verbose
else
GENIDT_EXTRA_ARGS :=
endif
ifeq ($(PREBUILT_HOST_TOOLS),)
GENIDT := scripts/gen_idt/gen_idt
else
GENIDT := $(PREBUILT_HOST_TOOLS)/gen_idt
endif
GENIDT := $(srctree)/scripts/gen_idt.py
OUTPUT_FORMAT ?= elf32-i386
OUTPUT_ARCH ?= i386
@ -16,21 +12,18 @@ OUTPUT_ARCH ?= i386
quiet_cmd_gen_idt = SIDT $@
cmd_gen_idt = \
( \
$(OBJCOPY) -I $(OUTPUT_FORMAT) -O binary -j intList $< isrList.bin && \
$(GENIDT) -i isrList.bin -n $(CONFIG_IDT_NUM_VECTORS) -o staticIdt.bin \
-m irq_int_vector_map.bin \
-l $(CONFIG_MAX_IRQ_LINES) $(GENIDT_EXTRA_ARGS) && \
$(GENIDT) --kernel $(PREBUILT_KERNEL) \
--output-idt staticIdt.bin \
--vector-map irq_int_vector_map.bin \
$(GENIDT_EXTRA_ARGS) && \
$(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) \
--rename-section .data=staticIdt staticIdt.bin staticIdt.o && \
$(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) \
--rename-section .data=irq_int_vector_map irq_int_vector_map.bin \
irq_int_vector_map.o && \
rm staticIdt.bin irq_int_vector_map.bin isrList.bin \
rm staticIdt.bin irq_int_vector_map.bin \
)
$(GENIDT):
$(Q)$(MAKE) $(build)=scripts/gen_idt
staticIdt.o: $(PREBUILT_KERNEL) $(GENIDT)
$(call cmd,gen_idt)

228
scripts/gen_idt.py Executable file
View file

@ -0,0 +1,228 @@
#!/usr/bin/env python3
#
# Copyright (c) 2017 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import argparse
import sys
import struct
import os
from elftools.elf.elffile import ELFFile
from elftools.elf.sections import SymbolTableSection
# 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
irq_gate_desc_format = "<HHBBH"
def create_irq_gate(handler, dpl):
present = 1
gate_type = 0xE # 32-bit interrupt gate
type_attr = gate_type | (dpl << 5) | (present << 7)
offset_hi = handler >> 16
offset_lo = handler & 0xFFFF
data = struct.pack(irq_gate_desc_format, offset_lo, KERNEL_CODE_SEG, 0,
type_attr, offset_hi)
return data
def create_idt_binary(idt_config, filename):
with open(filename, "wb") as fp:
for handler, dpl in idt_config:
data = create_irq_gate(handler, dpl)
fp.write(data)
map_fmt = "<B"
def create_irq_vec_map_binary(irq_vec_map, filename):
with open(filename, "wb") as fp:
for i in irq_vec_map:
fp.write(struct.pack(map_fmt, i))
def priority_range(prio):
# Priority levels are represented as groups of 16 vectors within the IDT
base = 32 + (prio * 16)
return range(base, base + 16)
def update_irq_vec_map(irq_vec_map, irq, vector, max_irq):
# No IRQ associated; exception or software interrupt
if irq == -1:
return
if irq >= 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 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] != None:
error("Multiple assignments for vector %d" % vec)
vectors[vec] = (handler, 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 in intlist:
if vec != -1:
continue
for vi in priority_range(prio):
if vi >= max_vec:
break
if vectors[vi] == None:
vec = vi
break
if vec == -1:
error("can't find a free vector in priority level %d" % prio)
vectors[vec] = (handler, 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] != None:
continue
if i in ERR_CODE_VECTORS:
handler = spur_code
else:
handler = spur_nocode
vectors[i] = (handler, 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 = "<IIi"
# struct genidt_entry_s {
# uint32_t isr;
# int32_t irq;
# int32_t priority;
# int32_t vector_id;
# int32_t dpl;
# };
intlist_entry_fmt = "<Iiiii"
def get_intlist(elf):
intdata = elf.get_section_by_name("intList").data()
header_sz = struct.calcsize(intlist_header_fmt)
header = struct.unpack_from(intlist_header_fmt, intdata, 0)
intdata = intdata[header_sz:]
spurious_code = header[0]
spurious_nocode = header[1]
debug("spurious handler (code) : %s" % hex(header[0]))
debug("spurious handler (no code) : %s" % hex(header[1]))
intlist = [i for i in
struct.iter_unpack(intlist_entry_fmt, intdata)]
debug("Configured interrupt routing")
debug("handler irq pri vec dpl")
debug("--------------------------")
for irq in intlist:
debug("{0:<10} {1:<3} {2:<3} {3:<3} {4:<2}".format(
hex(irq[0]),
"-" if irq[1] == -1 else irq[1],
"-" if irq[2] == -1 else irq[2],
"-" if irq[3] == -1 else irq[3],
irq[4]))
return (spurious_code, spurious_nocode, intlist)
def parse_args():
global args
parser = argparse.ArgumentParser(description = __doc__,
formatter_class = argparse.RawDescriptionHelpFormatter)
parser.add_argument("-m", "--vector-map", required=True,
help="Output file mapping IRQ lines to IDT vectors")
parser.add_argument("-o", "--output-idt", required=True,
help="Output file containing IDT binary")
parser.add_argument("-k", "--kernel", required=True,
help="Zephyr kernel image")
parser.add_argument("-v", "--verbose", action="store_true",
help="Print extra debugging information")
args = parser.parse_args()
def main():
parse_args()
with open(args.kernel, "rb") as fp:
kernel = ELFFile(fp)
syms = get_symbols(kernel)
spur_code, spur_nocode, intlist = get_intlist(kernel)
max_irq = syms["CONFIG_MAX_IRQ_LINES"]
max_vec = syms["CONFIG_IDT_NUM_VECTORS"]
vectors, irq_vec_map = setup_idt(spur_code, spur_nocode, intlist, max_vec,
max_irq)
create_idt_binary(vectors, args.output_idt)
create_irq_vec_map_binary(irq_vec_map, args.vector_map)
if __name__ == "__main__":
main()

View file

@ -1,8 +0,0 @@
HOSTCFLAGS_gen_idt.o += -I$(srctree)/include/arch/x86 -I$(srctree)/include
HOSTCFLAGS_gen_idt.o += -DKERNEL_VERSION=0 -Wall -Werror -g
HOSTCFLAGS_version.o += -DKERNEL_VERSION=0 -Wall -Werror -g
HOSTCFLAGS_gen_idt.o += -Wno-unused-result
hostprogs-y += gen_idt
gen_idt-objs := version.o gen_idt.o
always := $(hostprogs-y)

View file

@ -1,603 +0,0 @@
/*
* Copyright (c) 2012-2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Generate static IDT and a bitmap of allocated interrupt vectors.
* Creates a static IA-32 Interrupt Descriptor Table (IDT).
*
* This program expects to be invoked as follows:
* gen_idt -i <input file> -o <IDT output file> -n <# of interrupt vectors>
* -b <allocated vectors bitmap file>
* All parameters are required.
*
* The <input file> is assumed to be a binary file containing the intList
* section from the Zephyr Kernel ELF image.
*
* <number of interrupt vectors> is the same as CONFIG_IDT_NUM_VECTORS.
*
* It is expected that this program is invoked from within the build system
* during the link stage.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "version.h"
/* Define __packed for the idtEntry structure defined in idtEnt.h */
#define __packed __attribute__((__packed__))
/* This comes from the shared directory */
#include <segmentation.h>
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WIN32__)
#define O_BINARY 0
#endif
#define MAX_NUM_VECTORS 256
#define MAX_PRIORITIES 14
#define MAX_VECTORS_PER_PRIORITY 16
#define MAX_IRQS 256
#define UNSPECIFIED_INT_VECTOR ((unsigned int) -1)
#define UNSPECIFIED_PRIORITY ((unsigned int) -1)
#define UNSPECIFIED_IRQ ((unsigned int) -1)
#define KERNEL_CODE_SEG_SELECTOR 0x0008
static void get_exec_name(char *pathname);
static void usage(int len);
static void get_options(int argc, char *argv[]);
static void open_files(void);
static void read_input_file(void);
static void close_files(void);
static void validate_input_file(void);
static void generate_idt(void);
static void generate_interrupt_vector_bitmap(void);
static void clean_exit(int exit_code);
static void debug(const char *format, ...);
struct genidt_header_s {
uint32_t spurious_addr;
uint32_t spurious_no_error_addr;
unsigned int num_entries;
};
struct genidt_entry_s {
uint32_t isr;
unsigned int irq;
unsigned int priority;
unsigned int vector_id;
unsigned int dpl;
};
static struct genidt_header_s genidt_header;
static struct genidt_entry_s supplied_entry[MAX_NUM_VECTORS];
static struct genidt_entry_s generated_entry[MAX_NUM_VECTORS];
enum {
IFILE = 0, /* input file */
OFILE, /* output file */
MFILE, /* irq to interrupt vector mapping file */
NUSERFILES, /* number of user-provided file names */
EXECFILE = NUSERFILES, /* for name of executable */
NFILES /* total number of file names */
};
enum { SHORT_USAGE, LONG_USAGE };
static int fds[NUSERFILES] = {-1, -1};
static char *filenames[NFILES];
static unsigned int num_vectors = (unsigned int)-1;
static struct version version = {KERNEL_VERSION, 1, 1, 6};
static unsigned int num_irq_lines = -1;
static int verbose;
static void debug(const char *format, ...)
{
va_list vargs;
if (!verbose)
return;
va_start(vargs, format);
vfprintf(stderr, format, vargs);
va_end(vargs);
}
int main(int argc, char *argv[])
{
get_exec_name(argv[0]);
get_options(argc, argv); /* may exit */
open_files(); /* may exit */
read_input_file(); /* may exit */
validate_input_file(); /* may exit */
generate_interrupt_vector_bitmap(); /* may exit */
generate_idt(); /* may exit */
close_files();
return 0;
}
static void get_options(int argc, char *argv[])
{
char *endptr;
int ii, opt;
while ((opt = getopt(argc, argv, "hi:o:m:n:vl:d")) != -1) {
switch (opt) {
case 'i':
filenames[IFILE] = optarg;
break;
case 'o':
filenames[OFILE] = optarg;
break;
case 'm':
filenames[MFILE] = optarg;
break;
case 'h':
usage(LONG_USAGE);
exit(0);
case 'l':
num_irq_lines = (unsigned int) strtoul(optarg, &endptr, 10);
if ((*optarg == '\0') || (*endptr != '\0')) {
usage(SHORT_USAGE);
exit(-1);
}
break;
case 'n':
num_vectors = (unsigned int) strtoul(optarg, &endptr, 10);
if ((*optarg == '\0') || (*endptr != '\0')) {
usage(SHORT_USAGE);
exit(-1);
}
break;
case 'v':
show_version(filenames[EXECFILE], &version);
exit(0);
case 'd':
verbose = 1;
break;
default:
usage(SHORT_USAGE);
exit(-1);
}
}
if (num_vectors > MAX_NUM_VECTORS) {
usage(SHORT_USAGE);
exit(-1);
}
if (num_irq_lines > MAX_IRQS) {
usage(SHORT_USAGE);
exit(-1);
}
for (ii = IFILE; ii < NUSERFILES; ii++) {
if (!filenames[ii]) {
usage(SHORT_USAGE);
exit(-1);
}
}
}
static void get_exec_name(char *pathname)
{
int end = strlen(pathname) - 1;
while (end != -1) {
#if defined(WINDOWS) /* Might have both slashes in path */
if ((pathname[end] == '/') || (pathname[end] == '\\'))
#else
if (pathname[end] == '/')
#endif
{
if ((0 == end) || (pathname[end - 1] != '\\')) {
++end;
break;
}
}
--end;
}
filenames[EXECFILE] = &pathname[end];
}
static void open_files(void)
{
int ii;
fds[IFILE] = open(filenames[IFILE], O_RDONLY | O_BINARY);
fds[OFILE] = open(filenames[OFILE], O_WRONLY | O_BINARY |
O_TRUNC | O_CREAT,
S_IWUSR | S_IRUSR);
fds[MFILE] = open(filenames[MFILE], O_WRONLY | O_BINARY | O_CREAT |
O_TRUNC | O_BINARY,
S_IWUSR | S_IRUSR);
for (ii = 0; ii < NUSERFILES; ii++) {
int invalid = fds[ii] == -1;
if (invalid) {
char *invalid = filenames[ii];
fprintf(stderr, "invalid file %s\n", invalid);
for (--ii; ii >= 0; ii--) {
close(fds[ii]);
}
exit(-1);
}
}
}
static void show_entry(struct genidt_entry_s *entry)
{
debug("Vector %3d: ISR 0x%08x IRQ %3d PRI %2d DPL %2x\n",
entry->vector_id, entry->isr, entry->irq, entry->priority,
entry->dpl);
}
static void read_input_file(void)
{
ssize_t bytes_read;
size_t bytes_to_read;
/* Read the header information. */
bytes_read = read(fds[IFILE], &genidt_header, sizeof(genidt_header));
if (bytes_read != sizeof(genidt_header)) {
goto read_error;
}
debug("Spurious interrupt handlers found at 0x%x and 0x%x.\n",
genidt_header.spurious_addr, genidt_header.spurious_no_error_addr);
debug("There are %d ISR(s).\n", genidt_header.num_entries);
if (genidt_header.num_entries > num_vectors) {
fprintf(stderr,
"Too many ISRs found. Got %u. Expected no more than %u.\n"
"Malformed input file?\n",
genidt_header.num_entries, num_vectors);
clean_exit(-1);
}
bytes_to_read = sizeof(struct genidt_entry_s) * genidt_header.num_entries;
bytes_read = read(fds[IFILE], supplied_entry, bytes_to_read);
if (bytes_read != bytes_to_read) {
goto read_error;
}
int i;
for (i = 0; i < genidt_header.num_entries; i++) {
show_entry(&supplied_entry[i]);
}
return;
read_error:
fprintf(stderr, "Error occurred while reading input file. Aborting...\n");
clean_exit(-1);
}
static void validate_dpl(void)
{
int i;
for (i = 0; i < genidt_header.num_entries; i++) {
if (supplied_entry[i].dpl != 0) {
fprintf(stderr,
"Invalid DPL bits specified. Must be zero.\n");
show_entry(&supplied_entry[i]);
clean_exit(-1);
}
}
}
static void validate_vector_id(void)
{
int i;
int vectors[MAX_NUM_VECTORS] = {0};
for (i = 0; i < genidt_header.num_entries; i++) {
if (supplied_entry[i].vector_id == UNSPECIFIED_INT_VECTOR) {
/*
* Vector is to be allocated. No further validation to be
* done at the moment.
*/
continue;
}
if (supplied_entry[i].vector_id >= num_vectors) {
fprintf(stderr,
"Vector ID exceeds specified # of vectors (%d).\n",
num_vectors);
show_entry(&supplied_entry[i]);
clean_exit(-1);
}
if (vectors[supplied_entry[i].vector_id] != 0) {
fprintf(stderr, "Duplicate vector ID found.\n");
show_entry(&supplied_entry[i]);
clean_exit(-1);
}
vectors[supplied_entry[i].vector_id]++;
}
}
static void validate_priority(void)
{
int i;
/* Validate the priority. */
for (i = 0; i < genidt_header.num_entries; i++) {
if (supplied_entry[i].priority == UNSPECIFIED_PRIORITY) {
if (supplied_entry[i].vector_id == UNSPECIFIED_INT_VECTOR) {
fprintf(stderr,
"Either priority or vector ID must be specified.\n");
show_entry(&supplied_entry[i]);
clean_exit(-1);
}
} else if (supplied_entry[i].priority >= MAX_PRIORITIES) {
fprintf(stderr, "Priority must not exceed %d.\n",
MAX_PRIORITIES - 1);
show_entry(&supplied_entry[i]);
clean_exit(-1);
}
}
}
static void validate_irq(void)
{
int i;
int num_irqs[MAX_IRQS] = {0};
/* Validate the IRQ number */
for (i = 0; i < genidt_header.num_entries; i++) {
if (supplied_entry[i].irq == UNSPECIFIED_IRQ) {
if (supplied_entry[i].vector_id == UNSPECIFIED_INT_VECTOR) {
fprintf(stderr,
"Either IRQ or vector ID must be specified.\n");
show_entry(&supplied_entry[i]);
clean_exit(-1);
}
continue;
}
if (supplied_entry[i].irq >= num_irq_lines) {
/*
* If code to support the PIC is re-introduced, then this
* check will need to be updated.
*/
fprintf(stderr, "IRQ must be between 0 and %d inclusive.\n",
num_irq_lines - 1);
show_entry(&supplied_entry[i]);
clean_exit(-1);
}
num_irqs[supplied_entry[i].irq]++;
}
for (i = 0; i < num_irq_lines; i++) {
if (num_irqs[i] > 1) {
fprintf(stderr, "Multiple requests (%d) for IRQ %d detected.\n",
num_irqs[i], i);
clean_exit(-1);
}
}
}
static void validate_input_file(void)
{
validate_dpl(); /* exits on error */
validate_irq(); /* exits on error */
validate_vector_id(); /* exits on error */
validate_priority(); /* exits on error */
}
static void generate_idt(void)
{
unsigned int i;
unsigned int vector_id;
/*
* Initialize the generated entries with default
* spurious interrupt handlers.
*/
for (i = 0; i < num_vectors; i++) {
if ((((1 << i) & _EXC_ERROR_CODE_FAULTS)) && (i < 32)) {
generated_entry[i].isr = genidt_header.spurious_addr;
} else {
generated_entry[i].isr = genidt_header.spurious_no_error_addr;
}
/* Initialize the [irq] and [priority] fields to aid in debugging. */
generated_entry[i].irq = UNSPECIFIED_IRQ;
generated_entry[i].priority = UNSPECIFIED_PRIORITY;
generated_entry[i].vector_id = i;
generated_entry[i].dpl = 0;
}
/*
* Overwrite the generated entries as appropriate with the
* validated supplied entries.
*/
for (i = 0; i < genidt_header.num_entries; i++) {
vector_id = supplied_entry[i].vector_id;
generated_entry[vector_id] = supplied_entry[i];
}
/*
* We now have the address of all ISR stub/functions captured in
* generated_entry[]. Now construct the actual IDT.
*/
for (i = 0; i < num_vectors; i++) {
struct segment_descriptor idt_entry;
ssize_t bytes_written;
_init_irq_gate(&idt_entry, KERNEL_CODE_SEG_SELECTOR,
generated_entry[i].isr, generated_entry[i].dpl);
bytes_written = write(fds[OFILE], &idt_entry, sizeof(idt_entry));
if (bytes_written != sizeof(idt_entry)) {
fprintf(stderr, "Failed to write IDT entry %u.\n", num_vectors);
clean_exit(-1);
}
}
return;
}
static int find_first_set_lsb(unsigned int value)
{
int i;
for (i = 0; i < 32; i++) {
if ((value & (1 << i)) != 0) {
return i;
}
}
return -1;
}
static void generate_interrupt_vector_bitmap(void)
{
int i;
unsigned int num_elements = (num_vectors + 31) / 32;
unsigned int interrupt_vector_bitmap[num_elements];
uint8_t map_irq_to_vector_id[MAX_IRQS] = {0};
unsigned int value;
unsigned int index;
unsigned int mask_index;
int bit;
size_t bytes_to_write;
ssize_t bytes_written;
static unsigned int mask[2] = {0x0000ffff, 0xffff0000};
/* Initially mark each interrupt vector as available */
for (i = 0; i < num_elements; i++) {
interrupt_vector_bitmap[i] = 0xffffffff;
}
/* Ensure that any leftover entries are marked as allocated. */
for (i = num_vectors; i < num_elements * 32; i++) {
index = i / 32;
bit = i & 0x1f;
interrupt_vector_bitmap[index] &= ~(1 << bit);
}
/*
* Vector allocation is done in two steps.
* 1. Loop through each supplied entry and if an explicit vector was
* specified, mark it as allocated.
* 2. Loop through each supplied entry and allocate the vector if
* it is required.
* This approach guarantees that explicitly specified interrupt vectors
* will get their requested slots.
*/
for (i = 0; i < genidt_header.num_entries; i++) {
if (supplied_entry[i].vector_id == UNSPECIFIED_INT_VECTOR) {
/* This vector will be allocated in the next for-loop. */
continue;
}
index = supplied_entry[i].vector_id / 32;
bit = supplied_entry[i].vector_id & 31;
interrupt_vector_bitmap[index] &= ~(1 << bit);
}
for (i = 0; i < genidt_header.num_entries; i++) {
if (supplied_entry[i].vector_id != UNSPECIFIED_INT_VECTOR) {
/* This vector has already been processed. */
continue;
}
/* We can assume priority has been explicitly set as
* validate_priority() enforces that you can't use both
* UNSPECIFIED_INT_VECTOR and UNSPECIFIED_INT_PRIORITY
*/
index = (supplied_entry[i].priority + 2) / 2;
mask_index = (supplied_entry[i].priority + 2) & 1;
value = interrupt_vector_bitmap[index] & mask[mask_index];
bit = find_first_set_lsb(value);
if (bit < 0) {
fprintf(stderr,
"No remaining vectors for priority %d are available.\n",
supplied_entry[i].priority);
clean_exit(-1);
}
interrupt_vector_bitmap[index] &= ~(1 << bit);
map_irq_to_vector_id[supplied_entry[i].irq] = (index * 32) + bit;
supplied_entry[i].vector_id = (index * 32) + bit;
debug("Assigned IRQ %3d (priority %2d) vector %3d\n",
supplied_entry[i].irq, supplied_entry[i].priority,
supplied_entry[i].vector_id);
}
bytes_to_write = num_irq_lines;
bytes_written = write(fds[MFILE], map_irq_to_vector_id, bytes_to_write);
if (bytes_written != bytes_to_write) {
fprintf(stderr, "Failed to write all data to '%s'.\n",
filenames[MFILE]);
clean_exit(-1);
}
}
static void close_files(void)
{
int ii;
for (ii = 0; ii < NUSERFILES; ii++) {
close(fds[ii]);
}
}
static void clean_exit(int exit_code)
{
close_files();
exit(exit_code);
}
static void usage(int len)
{
fprintf(stderr, "\n%s -i <input file> -n <n>\n", filenames[EXECFILE]);
if (len == SHORT_USAGE) {
return;
}
fprintf(stderr,
"\n"
" options\n"
"\n"
" -b <allocated interrupt vector bitmap output file>\n\n"
" [Mandatory] The interrupt vector bitmap output file.\n\n"
" -i <binary file>\n\n"
" [Mandatory] The input file in binary format.\n\n"
" -o <IDT output file>\n\n"
" [Mandatory] The IDT output file.\n\n"
" -m <IRQ to interrupt vector map file>\n\n"
" [Mandatory] The IRQ to interrupt vector output file\n\n"
" -n <n>\n\n"
" [Mandatory] Number of vectors\n\n"
" -l <n>\n\n"
" [Mandatory] Number of IRQ lines\n\n"
" -v Display version.\n\n"
" -h Display this help.\n\n"
" -d Display extra debugging output.\n\n"
"\nReturns -1 on error, 0 on success\n\n");
}

View file

@ -1,21 +0,0 @@
/* version.c - version number library */
/*
* Copyright (c) 2013-2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "version.h"
void show_version(const char *name, const struct version *ver)
{
fprintf(stdout,
"\n%s"
" %4d.%d.%d.%3.3d, (c) Wind River Systems, Inc.\n"
" Built on %s at %s\n\n",
name,
ver->kernel, ver->major, ver->minor, ver->maintenance,
__DATE__, __TIME__);
}

View file

@ -1,16 +0,0 @@
/* version.h - version number library */
/*
* Copyright (c) 2013-2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
struct version {
int kernel;
int major;
int minor;
int maintenance;
};
extern void show_version(const char *name, const struct version *ver);