Mike Banon would like build bot (Jenkins), Patrick Georgi, Paul Menzel and Alexandru Gagniuc to review this change.

View Change

Revert "util: Remove 'getpir' and 'mptable' tools"

This reverts commit 6c90f3334e65ff4b0ff4900df77bc33d53beb677.

Reason for revert: Although the output of these tools is indeed far from being perfect, still it could be used as a nice starting point.

Change-Id: Ieff7673387ae9275b8271f4a483926b774697a8d
---
A util/getpir/Makefile
A util/getpir/README
A util/getpir/checkpir.c
A util/getpir/checksum.c
A util/getpir/checksum.h
A util/getpir/code_gen.c
A util/getpir/code_gen.h
A util/getpir/getpir.c
A util/getpir/pirq_routing.h
A util/mptable/Makefile
A util/mptable/mptable.c
11 files changed, 1,708 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/22/48322/1
diff --git a/util/getpir/Makefile b/util/getpir/Makefile
new file mode 100644
index 0000000..94270f5
--- /dev/null
+++ b/util/getpir/Makefile
@@ -0,0 +1,24 @@
+#
+#
+#
+
+CC=gcc
+CFLAGS=-O2 -D_GNU_SOURCE -DGETPIR -Wall
+
+all: getpir
+
+getpir: getpir.o checksum.o code_gen.o
+ $(CC) $(CFLAGS) -o getpir $^
+
+checkpir: checkpir.c checksum.o irq_tables.o
+ $(CC) $(CFLAGS) -o checkpir $^
+
+irq_tables.c: getpir
+ ./getpir
+
+clean:
+ rm -f getpir checkpir *.o *~
+
+distclean: clean
+ rm -f irq_tables.o irq_tables.c
+
diff --git a/util/getpir/README b/util/getpir/README
new file mode 100644
index 0000000..6514585
--- /dev/null
+++ b/util/getpir/README
@@ -0,0 +1,30 @@
+ABOUT:
+
+This utility will help to create irq_table.c file, that is very hard to create
+manually, specialy when you are testing new motherboards, changing your
+hardware often, placing new cards, etc..
+
+USAGE:
+
+Steps
+1. make distclean;
+2. make getpir
+3. ./getpir
+
+ Will dump irq table to the file called irq_tables.c, ready to use with
+ coreboot. Just move the file to corresponding place in the coreboot tree.
+
+
+4. CHECKING CUSTOM irq_tables.c:
+
+ make checkpir
+ ./checkpir
+
+ checkpir.c Will verify the irq_tables.c, currently it only checks the
+ checksum. In case of wrong checksum, a good value is proposed, so you can
+ edit irq_tables.c manualy and replace checksum.
+
+
+Do not run make checkpir and ./checkpir directly because it needs to be linked
+to irq_table.o first.
+
diff --git a/util/getpir/checkpir.c b/util/getpir/checkpir.c
new file mode 100644
index 0000000..c9703c6
--- /dev/null
+++ b/util/getpir/checkpir.c
@@ -0,0 +1,31 @@
+/* checkpir.c : This software is released under GPL
+ * For coreboot use only
+ * Aug 26 2001 , Nikolai Vladychevski, <niko@isl.net.mx>
+ */
+
+#include <stdio.h>
+#include "pirq_routing.h"
+#include "checksum.h"
+
+struct irq_routing_table *rt;
+
+int main(void)
+{
+ uint8_t sum, newsum;
+
+ rt = (struct irq_routing_table *) &intel_irq_routing_table;
+ sum = calc_checksum(rt);
+
+ printf("Validating checksum, file: irq_tables.c that was in ./ at compile time...\n");
+ printf("(no other tests are done)\n");
+
+ if (!sum) {
+ printf("Checksum for IRQ Routing table is ok. You can use irq_tables.c in coreboot now.\n");
+ } else {
+ newsum = rt->checksum - sum;
+ printf("BAD CHECKSUM for IRQ Routing table !!!!\n");
+ printf("If you want to make it valid, change the checksum to: %#x\n",
+ newsum);
+ }
+ return 0;
+}
diff --git a/util/getpir/checksum.c b/util/getpir/checksum.c
new file mode 100644
index 0000000..bcf3425
--- /dev/null
+++ b/util/getpir/checksum.c
@@ -0,0 +1,13 @@
+#include "pirq_routing.h"
+#include "checksum.h"
+
+int calc_checksum(struct irq_routing_table *rt)
+{
+ long i;
+ uint8_t *addr, sum = 0;
+
+ addr = (uint8_t *) rt;
+ for (i = 0; i < rt->size; i++)
+ sum += addr[i];
+ return (sum);
+}
diff --git a/util/getpir/checksum.h b/util/getpir/checksum.h
new file mode 100644
index 0000000..2acc433
--- /dev/null
+++ b/util/getpir/checksum.h
@@ -0,0 +1,6 @@
+#ifndef __CHECKSUM_H__
+#define __CHECKSUM_H__
+
+int calc_checksum(struct irq_routing_table *rt);
+
+#endif /* __CHECKSUM_H__ */
diff --git a/util/getpir/code_gen.c b/util/getpir/code_gen.c
new file mode 100644
index 0000000..d15715c
--- /dev/null
+++ b/util/getpir/code_gen.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "pirq_routing.h"
+
+static char *preamble[] = {
+
+ "/*\n",
+ " * This file is part of the coreboot project.\n",
+ " *\n",
+ " * Copyright (C) 200x TODO <TODO@TODO>\n",
+ " *\n",
+ " * This program is free software; you can redistribute it and/or modify\n",
+ " * it under the terms of the GNU General Public License as published by\n",
+ " * the Free Software Foundation; either version 2 of the License, or\n",
+ " * (at your option) any later version.\n",
+ " *\n",
+ " * This program is distributed in the hope that it will be useful,\n",
+ " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n",
+ " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n",
+ " * GNU General Public License for more details.\n",
+ " *\n",
+ " * You should have received a copy of the GNU General Public License\n",
+ " * along with this program; if not, write to the Free Software\n",
+ " * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
+ " */\n\n",
+ "#ifdef GETPIR /* TODO: Drop this when copying to coreboot. */\n",
+ "#include \"pirq_routing.h\" /* TODO: Drop this when copying to coreboot. */\n",
+ "#else /* TODO: Drop this when copying to coreboot. */\n"
+ "#include <arch/pirq_routing.h>\n",
+ "#endif /* TODO: Drop this when copying to coreboot. */\n\n"
+ "const struct irq_routing_table intel_irq_routing_table = {\n",
+ "\tPIRQ_SIGNATURE, /* u32 signature */\n",
+ "\tPIRQ_VERSION, /* u16 version */\n",
+ 0
+};
+
+void code_gen(char *filename, struct irq_routing_table *rt)
+{
+ char **code = preamble;
+ struct irq_info *se_arr = (struct irq_info *) ((char *) rt + 32);
+ int i, ts = (rt->size - 32) / 16;
+ FILE *fpir;
+
+ if ((fpir = fopen(filename, "w")) == NULL) {
+ printf("Failed creating file!\n");
+ exit(2);
+ }
+
+ while (*code)
+ fprintf(fpir, "%s", *code++);
+
+ fprintf(fpir, "\t32 + 16 * %d, /* Max. number of devices on the bus */\n",
+ ts);
+ fprintf(fpir, "\t0x%02x, /* Interrupt router bus */\n",
+ rt->rtr_bus);
+ fprintf(fpir, "\t(0x%02x << 3) | 0x%01x, /* Interrupt router dev */\n",
+ rt->rtr_devfn >> 3, rt->rtr_devfn & 7);
+ fprintf(fpir, "\t%#x, /* IRQs devoted exclusively to PCI usage */\n",
+ rt->exclusive_irqs);
+ fprintf(fpir, "\t%#x, /* Vendor */\n", rt->rtr_vendor);
+ fprintf(fpir, "\t%#x, /* Device */\n", rt->rtr_device);
+ fprintf(fpir, "\t%#x, /* Miniport */\n",
+ rt->miniport_data);
+ fprintf(fpir, "\t{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */\n");
+ fprintf(fpir, "\t%#x, /* Checksum (has to be set to some value that\n * would give 0 after the sum of all bytes\n * for this structure (including checksum).\n */\n",
+ rt->checksum);
+ fprintf(fpir, "\t{\n");
+ fprintf(fpir, "\t\t/* bus, dev | fn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */\n");
+ for (i = 0; i < ts; i++) {
+ fprintf(fpir, "\t\t{0x%02x, (0x%02x << 3) | 0x%01x, {{0x%02x, 0x%04x}, {0x%02x, 0x%04x}, {0x%02x, 0x%04x}, {0x%02x, 0x%04x}}, 0x%x, 0x%x},\n",
+ (se_arr+i)->bus, (se_arr+i)->devfn >> 3,
+ (se_arr+i)->devfn & 7, (se_arr+i)->irq[0].link,
+ (se_arr+i)->irq[0].bitmap, (se_arr+i)->irq[1].link,
+ (se_arr+i)->irq[1].bitmap, (se_arr+i)->irq[2].link,
+ (se_arr+i)->irq[2].bitmap, (se_arr+i)->irq[3].link,
+ (se_arr+i)->irq[3].bitmap, (se_arr+i)->slot,
+ (se_arr+i)->rfu);
+ }
+ fprintf(fpir, "\t}\n");
+ fprintf(fpir, "};\n");
+
+ fprintf(fpir, "\nunsigned long write_pirq_routing_table(unsigned long addr)\n");
+ fprintf(fpir, "{\n");
+ fprintf(fpir, "\treturn copy_pirq_routing_table(addr);\n");
+ fprintf(fpir, "}\n");
+
+ fclose(fpir);
+}
diff --git a/util/getpir/code_gen.h b/util/getpir/code_gen.h
new file mode 100644
index 0000000..93bdaec
--- /dev/null
+++ b/util/getpir/code_gen.h
@@ -0,0 +1,6 @@
+#ifndef __CODE_GEN_H__
+#define __CODE_GEN_H__
+
+void code_gen(char *filename, struct irq_routing_table *rt);
+
+#endif /* __CODE_GEN_H__ */
diff --git a/util/getpir/getpir.c b/util/getpir/getpir.c
new file mode 100644
index 0000000..9853d7c
--- /dev/null
+++ b/util/getpir/getpir.c
@@ -0,0 +1,189 @@
+/* getpir.c : This software is released under GPL
+ * For coreboot use only
+ * Aug 26 2001 , Nikolai Vladychevski, <niko@isl.net.mx>
+ * 2007.04.09 Jeremy Jackson <jerj@coplanar.net>
+ * updated for amd64 and general 64 bit portability
+ * 2010.04.24 Marc Bertens <mbertens@xs4all.nl>
+ * Added functionality to read a image file for checking the checksum of the PIR
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "pirq_routing.h"
+#include "checksum.h"
+#include "code_gen.h"
+
+#if defined (__sun) && (defined(__i386) || defined(__amd64))
+# define MEM_DEV "/dev/xsvc"
+#else
+# define MEM_DEV "/dev/mem"
+#endif
+
+/**
+ * The probe_table() is now called with the pointer to the memory,
+ * this is to handle both the assessing memory and a file.
+ *
+ * This function now dumps the table found to the stdout, with
+ * descriptions, it is special handy when building a PIRQ table
+ * for a board to check the checksum.
+ */
+static struct irq_routing_table *probe_table(char* ptr)
+{
+ /**
+ * Signature to search for $PIR<2-byte-version>
+ *
+ * this is to be sure that we find the correct table.
+ */
+ char signature[] = "$PIR\x00\x01";
+ /** cast the pointer */
+ struct irq_routing_table *rt = (struct irq_routing_table *)ptr;
+ int size = 16;
+ int checksum_result;
+ do {
+ /** find the PIRQ table */
+ rt = (struct irq_routing_table *) memmem(ptr + size, 16, signature, 6);
+ if (rt != NULL) {
+ /** found the table */
+ int i, ts = (rt->size - 32) / 16;
+ struct irq_info *se_arr;
+ se_arr = (struct irq_info *) ((char *) rt + 32);
+ /** Dump the table information to the stdout */
+ printf("Found PCI IRQ routing table signature at %p.\n", (void *) ((char *) rt - ptr + 0xf0000));
+ printf("SIGNATURE = %s\n", (char*)&rt->signature);
+ printf("VERSION = %04x\n", rt->version);
+ printf("SIZE = %i\n", rt->size);
+ printf("MAX_DEVICES_ON_BUS = 32 + 16 * %d\n", ts);
+ printf("INT_ROUTER_BUS = 0x%02x\n", rt->rtr_bus);
+ printf("INT_ROUTER DEVICE = (0x%02x << 3) | 0x%01x\n", rt->rtr_devfn >> 3, rt->rtr_devfn & 7);
+ printf("IRQ_DEVOTED_TO_PCI = %#x\n", rt->exclusive_irqs);
+ printf("VENDOR = %#x\n", rt->rtr_vendor);
+ printf("DEVICE = %#x\n", rt->rtr_device);
+ printf("MINIPORT = %#x\n", rt->miniport_data);
+ printf("CHECKSUM = %#x\n", rt->checksum);
+ printf("\tbus , dev | fn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu\n");
+ for (i = 0; i < ts; i++) {
+ printf("\t0x%02x, (0x%02x << 3) | 0x%01x, {{0x%02x, 0x%04x}, {0x%02x, 0x%04x}, {0x%02x, 0x%04x}, {0x%02x, 0x%04x}}, 0x%x, 0x%x},\n",
+ (se_arr+i)->bus, (se_arr+i)->devfn >> 3,
+ (se_arr+i)->devfn & 7, (se_arr+i)->irq[0].link,
+ (se_arr+i)->irq[0].bitmap, (se_arr+i)->irq[1].link,
+ (se_arr+i)->irq[1].bitmap, (se_arr+i)->irq[2].link,
+ (se_arr+i)->irq[2].bitmap, (se_arr+i)->irq[3].link,
+ (se_arr+i)->irq[3].bitmap, (se_arr+i)->slot,
+ (se_arr+i)->rfu);
+ }
+ /** A table should not be over 0x400 bytes */
+ if (rt->size > 0x400) {
+ return NULL;
+ }
+ printf("Validating...\n");
+ /** Calculate the checksum value */
+ checksum_result = calc_checksum(rt);
+ /** Show the calculatedchecksum value */
+ printf("CHECKSUM = %#x\n", 0x100-((checksum_result - rt->checksum) & 0xFF));
+ /** and the result of the calculation */
+ if (!checksum_result) {
+ printf("checksum is ok.\n");
+ break;
+ } else {
+ printf("checksum is wrong.\n");
+ }
+ }
+ size += 16;
+ } while (size < 0xFFFF);
+ if (size >= 0xFFFF) {
+ /** When the functions comes here there is no PIRQ table found. */
+ printf("No PCI IRQ routing table signature found.\n");
+ return NULL;
+ }
+
+ return rt;
+}
+
+int main(int argc, char* argv[])
+{
+ char* ptr;
+ int fd_mem = -1;
+ struct irq_routing_table* rt = NULL;
+ void* bios_image = NULL;
+ if ( argc > 1 )
+ {
+ /** there a paramater passed to the program, assume that it is a menory file */
+ printf("Opening memory image file '%s'\n", argv[1]);
+ /** Open the file */
+ fd_mem = open(argv[1], O_RDONLY);
+ if (fd_mem > 0) {
+ /** get tyhe size of the file */
+ int file_size = lseek(fd_mem, 0, SEEK_END);
+ printf("Memory image '%i'\n", file_size);
+ /** get a memory block for it. */
+ bios_image = malloc(file_size);
+ if (bios_image) {
+ /** Fill the created buffer */
+ lseek(fd_mem, 0, SEEK_SET);
+ read(fd_mem, bios_image, file_size);
+ /** set the pointer for the probe function */
+ ptr = (char*)bios_image;
+ } else {
+ /* no memory available ? */
+ perror("Failed to open imagefile\n");
+ return (-3);
+ }
+ } else {
+ /** An error occourd, just exit with a message */
+ perror("Failed to open imagefile");
+ return (-2);
+ }
+ } else {
+ /** No paramaters means that the program will access the system memory */
+ printf("Accessing memory\n");
+ if (getuid()) {
+ /** i'm not root message !!!! */
+ fprintf(stderr, "Run me as root, I need access to " MEM_DEV ".\n");
+ }
+ /** open the system memory */
+ fd_mem = open(MEM_DEV, O_RDONLY);
+ if (fd_mem < 0) {
+ /** could not open the system memory, exit with a message */
+ perror("Could not open " MEM_DEV ":");
+ exit(1);
+ }
+ printf("Probing PIRQ table in memory.\n");
+ ptr = mmap(0, 0x10000, PROT_READ, MAP_SHARED, fd_mem, (off_t)0xf0000);
+ if (ptr == MAP_FAILED) {
+ /** could not map the system memory, exit with a message */
+ perror("Mapping system memory failed: ");
+ close(fd_mem);
+ return (1);
+ }
+ }
+ if (ptr) {
+ /** now do the actual probe function */
+ rt = probe_table(ptr);
+ if (rt != NULL && bios_image == NULL) {
+ /** when probing system memory we write the 'irq_tables.c' code file */
+ printf("Creating irq_tables.c ...\n");
+ code_gen("irq_tables.c", rt);
+ printf("Done, you can move the file to the coreboot tree now.\n");
+ }
+ } else {
+ printf("invalid memory pointer\n");
+ }
+ if (bios_image) {
+ /** when we are reading from a file the memory must be released */
+ free(bios_image);
+ } else {
+ /** when reading from the system memory, it must be unmapped */
+ munmap(ptr, 0x10000);
+ }
+ /** Close the file handle */
+ close(fd_mem);
+ /** return 0 as OK ) */
+ return 0;
+}
diff --git a/util/getpir/pirq_routing.h b/util/getpir/pirq_routing.h
new file mode 100644
index 0000000..88adc21
--- /dev/null
+++ b/util/getpir/pirq_routing.h
@@ -0,0 +1,55 @@
+#ifndef ARCH_PIRQ_ROUTING_H
+#define ARCH_PIRQ_ROUTING_H
+
+#include <stdint.h>
+
+#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
+#define PIRQ_VERSION 0x0100
+
+struct irq_info {
+ uint8_t bus, devfn; /* Bus, device and function */
+ struct {
+ uint8_t link; /* IRQ line ID, chipset dependent, 0=not routed */
+ uint16_t bitmap; /* Available IRQs */
+ } __attribute__((packed)) irq[4];
+ uint8_t slot; /* Slot number, 0=onboard */
+ uint8_t rfu;
+} __attribute__((packed));
+
+#if defined(CONFIG_IRQ_SLOT_COUNT)
+#define IRQ_SLOTS_COUNT CONFIG_IRQ_SLOT_COUNT
+#elif (__GNUC__ < 3)
+#define IRQ_SLOTS_COUNT 1
+#else
+#define IRQ_SLOTS_COUNT
+#endif
+
+struct irq_routing_table {
+ uint32_t signature; /* PIRQ_SIGNATURE should be here */
+ uint16_t version; /* PIRQ_VERSION */
+ uint16_t size; /* Table size in bytes */
+ uint8_t rtr_bus, rtr_devfn; /* Where the interrupt router lies */
+ uint16_t exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
+ uint16_t rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
+ uint32_t miniport_data; /* Miniport data */
+ uint8_t rfu[11];
+ uint8_t checksum; /* Modulo 256 checksum must give zero */
+ struct irq_info slots[IRQ_SLOTS_COUNT];
+} __attribute__((packed));
+
+extern const struct irq_routing_table intel_irq_routing_table;
+
+#ifdef GETPIR
+#define copy_pirq_routing_table(start) (start)
+unsigned long write_pirq_routing_table(unsigned long start);
+#else
+#if CONFIG_HAVE_PIRQ_TABLE==1
+unsigned long copy_pirq_routing_table(unsigned long start);
+unsigned long write_pirq_routing_table(unsigned long start);
+#else
+#define copy_pirq_routing_table(start) (start)
+#define write_pirq_routing_table(start) (start)
+#endif
+#endif
+
+#endif /* ARCH_PIRQ_ROUTING_H */
diff --git a/util/mptable/Makefile b/util/mptable/Makefile
new file mode 100644
index 0000000..f88367e
--- /dev/null
+++ b/util/mptable/Makefile
@@ -0,0 +1,8 @@
+CC=gcc
+CFLAGS=-O2 -Wall -Wextra -Wshadow -Wno-sign-compare
+
+mptable: mptable.c
+ $(CC) $(CFLAGS) -o $@ $<
+
+clean:
+ rm -f mptable
diff --git a/util/mptable/mptable.c b/util/mptable/mptable.c
new file mode 100644
index 0000000..5b8a59d
--- /dev/null
+++ b/util/mptable/mptable.c
@@ -0,0 +1,1258 @@
+/*
+ * Copyright (c) 1996, by Steve Passe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * mptable.c
+ */
+
+#define VMAJOR 2
+#define VMINOR 0
+#define VDELTA 15
+
+/*
+ * this will cause the raw mp table to be dumped to /tmp/mpdump
+ *
+#define RAW_DUMP
+ */
+
+#define MP_SIG 0x5f504d5f /* _MP_ */
+#define EXTENDED_PROCESSING_READY
+#define OEM_PROCESSING_READY_NOT
+
+#include <sys/types.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#define ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0]))
+#define SEP_LINE \
+"\n-------------------------------------------------------------------------------\n"
+
+#define SEP_LINE2 \
+"\n===============================================================================\n"
+
+/* EBDA is @ 40:0e in real-mode terms */
+#define EBDA_POINTER 0x040e /* location of EBDA pointer */
+
+/* CMOS 'top of mem' is @ 40:13 in real-mode terms */
+#define TOPOFMEM_POINTER 0x0413 /* BIOS: base memory size */
+
+#define DEFAULT_TOPOFMEM 0xa0000
+
+#define BIOS_BASE 0xf0000
+#define BIOS_BASE2 0xe0000
+#define BIOS_SIZE 0x10000
+#define ONE_KBYTE 1024
+
+#define GROPE_AREA1 0x80000
+#define GROPE_AREA2 0x90000
+#define GROPE_SIZE 0x10000
+
+#define PROCENTRY_FLAG_EN 0x01
+#define PROCENTRY_FLAG_BP 0x02
+#define IOAPICENTRY_FLAG_EN 0x01
+
+#define MAXPNSTR 132
+
+#define COREBOOT_MP_TABLE 0
+
+enum busTypes {
+ CBUS = 1,
+ CBUSII = 2,
+ EISA = 3,
+ ISA = 6,
+ PCI = 13,
+ XPRESS = 18,
+ MAX_BUSTYPE = 18,
+ UNKNOWN_BUSTYPE = 0xff
+};
+
+typedef struct BUSTYPENAME {
+ uint8_t type;
+ char name[7];
+} busTypeName;
+
+static busTypeName busTypeTable[] = {
+ {CBUS, "CBUS"},
+ {CBUSII, "CBUSII"},
+ {EISA, "EISA"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {ISA, "ISA"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {PCI, "PCI"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {UNKNOWN_BUSTYPE, "---"},
+ {UNKNOWN_BUSTYPE, "---"}
+};
+
+char *whereStrings[] = {
+ "Extended BIOS Data Area",
+ "BIOS top of memory",
+ "Default top of memory",
+ "BIOS",
+ "Extended BIOS",
+ "GROPE AREA #1",
+ "GROPE AREA #2"
+};
+
+typedef struct TABLE_ENTRY {
+ uint8_t type;
+ uint8_t length;
+ char name[32];
+} tableEntry;
+
+tableEntry basetableEntryTypes[] = {
+ {0, 20, "Processor"},
+ {1, 8, "Bus"},
+ {2, 8, "I/O APIC"},
+ {3, 8, "I/O INT"},
+ {4, 8, "Local INT"}
+};
+
+tableEntry extendedtableEntryTypes[] = {
+ {128, 20, "System Address Space"},
+ {129, 8, "Bus Heirarchy"},
+ {130, 8, "Compatibility Bus Address"}
+};
+
+/* MP Floating Pointer Structure */
+typedef struct MPFPS {
+ uint8_t signature[4];
+ uint32_t pap;
+ uint8_t length;
+ uint8_t spec_rev;
+ uint8_t checksum;
+ uint8_t mpfb1;
+ uint8_t mpfb2;
+ uint8_t mpfb3;
+ uint8_t mpfb4;
+ uint8_t mpfb5;
+} mpfps_t;
+
+/* MP Configuration Table Header */
+typedef struct MPCTH {
+ uint8_t signature[4];
+ uint16_t base_table_length;
+ uint8_t spec_rev;
+ uint8_t checksum;
+ uint8_t oem_id[8];
+ uint8_t product_id[12];
+ uint32_t oem_table_pointer;
+ uint16_t oem_table_size;
+ uint16_t entry_count;
+ uint32_t apic_address;
+ uint16_t extended_table_length;
+ uint8_t extended_table_checksum;
+ uint8_t reserved;
+} mpcth_t;
+
+typedef struct PROCENTRY {
+ uint8_t type;
+ uint8_t apicID;
+ uint8_t apicVersion;
+ uint8_t cpuFlags;
+ uint32_t cpuSignature;
+ uint32_t featureFlags;
+ uint32_t reserved1;
+ uint32_t reserved2;
+} ProcEntry;
+
+typedef struct BUSENTRY {
+ uint8_t type;
+ uint8_t busID;
+ uint8_t busType[6];
+} BusEntry;
+
+typedef struct IOAPICENTRY {
+ uint8_t type;
+ uint8_t apicID;
+ uint8_t apicVersion;
+ uint8_t apicFlags;
+ uint32_t apicAddress;
+} IOApicEntry;
+
+typedef struct INTENTRY {
+ uint8_t type;
+ uint8_t intType;
+ uint16_t intFlags;
+ uint8_t srcBusID;
+ uint8_t srcBusIRQ;
+ uint8_t dstApicID;
+ uint8_t dstApicINT;
+} IntEntry;
+
+/*
+ * extended entry type structures
+ */
+
+typedef struct SASENTRY {
+ uint8_t type;
+ uint8_t length;
+ uint8_t busID;
+ uint8_t addressType;
+ uint64_t addressBase;
+ uint64_t addressLength;
+} SasEntry;
+
+typedef struct BHDENTRY {
+ uint8_t type;
+ uint8_t length;
+ uint8_t busID;
+ uint8_t busInfo;
+ uint8_t busParent;
+ uint8_t reserved[3];
+} BhdEntry;
+
+typedef struct CBASMENTRY {
+ uint8_t type;
+ uint8_t length;
+ uint8_t busID;
+ uint8_t addressMod;
+ uint32_t predefinedRange;
+} CbasmEntry;
+
+typedef uint32_t vm_offset_t;
+
+static void apic_probe(vm_offset_t * paddr, int *where);
+
+static void MPConfigDefault(int featureByte);
+
+static void MPFloatingPointer(vm_offset_t paddr, int where, mpfps_t * mpfps);
+static void MPConfigTableHeader(uint32_t pap);
+
+static int readType(void);
+static void seekEntry(vm_offset_t addr);
+static void readEntry(void *entry, int size);
+
+static void processorEntry(void);
+static void busEntry(void);
+static void ioApicEntry(void);
+static void intEntry(void);
+static void lintEntry(void);
+
+static void sasEntry(void);
+static void bhdEntry(void);
+static void cbasmEntry(void);
+
+static void doOptionList(void);
+static void doDmesg(void);
+static void pnstr(uint8_t * s, int c);
+
+/* global data */
+int pfd; /* physical /dev/mem fd */
+
+int busses[32];
+int apics[16];
+
+int ncpu;
+int nbus;
+int napic;
+int nintr;
+
+int dmesg = 0;
+int grope = 0;
+int verbose = 0;
+int noisy = 0;
+/* preamble to the mptable. This is fixed for all coreboots */
+
+char *preamble[] = {
+ "#include <console/console.h>",
+ "#include <arch/smp/mpspec.h>",
+ "#include <arch/ioapic.h>",
+ "#include <device/pci.h>",
+ "#include <string.h>",
+ "#include <stdint.h>",
+ "",
+ "#define INTA 0x00",
+ "#define INTB 0x01",
+ "#define INTC 0x02",
+ "#define INTD 0x03",
+ "",
+ "static void *smp_write_config_table(void *v)",
+ "{",
+ " struct mp_config_table *mc;",
+ "",
+ " mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);",
+ "",
+ " mptable_init(mc, \"TODO \", LOCAL_APIC_ADDR);",
+ "",
+ " smp_write_processors(mc);",
+ "",
+ 0
+};
+
+char *postamble[] = {
+ " /* Compute the checksums. */",
+ " mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);",
+ " mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);",
+ " printk(BIOS_DEBUG, \"Wrote the mp table end at: %p - %p\\n\",",
+ " mc, smp_next_mpe_entry(mc));",
+ " return smp_next_mpe_entry(mc);",
+ "}",
+ "",
+ "unsigned long write_smp_table(unsigned long addr)",
+ "{",
+ " void *v;",
+ " v = smp_write_floating_table(addr);",
+ " return (unsigned long)smp_write_config_table(v);",
+ "}",
+ 0
+};
+
+static void usage(void)
+{
+ fprintf(stderr,
+ "usage: mptable [-dmesg] [-verbose] [-grope] [-help]\n");
+ exit(0);
+}
+
+void write_code(char **code)
+{
+ while (*code)
+ printf("%s\n", *code++);
+}
+
+/*
+ *
+ */
+int main(int argc, char *argv[])
+{
+ vm_offset_t paddr;
+ int where;
+ mpfps_t mpfps;
+ int defaultConfig;
+
+ /* announce ourselves */
+
+ if (verbose)
+ puts(SEP_LINE2);
+
+ printf("/* generated by MPTable, version %d.%d.%d*/\n", VMAJOR, VMINOR,
+ VDELTA);
+ printf("/* as modified by RGM for coreboot */\n");
+ write_code(preamble);
+
+ /* Ron hates getopt() */
+
+ for (argc--, argv++; argc; argc--, argv++) {
+ if (strcmp(argv[0], "-dmesg") == 0) {
+ dmesg = 1;
+ } else if (strcmp(argv[0], "-help") == 0) {
+ usage();
+ } else if (strcmp(argv[0], "-grope") == 0) {
+ grope = 1;
+ } else if (strcmp(argv[0], "-verbose") == 0)
+ verbose = 1;
+ else if (strcmp(argv[0], "-noisy") == 0)
+ noisy = 1;
+ else
+ usage();
+ }
+
+ /* open physical memory for access to MP structures */
+ if ((pfd = open("/dev/mem", O_RDONLY)) < 0)
+ err(1, "mem open");
+
+ /* probe for MP structures */
+ apic_probe(&paddr, &where);
+ if (where <= 0) {
+ fprintf(stderr, "\n MP FPS NOT found,\n");
+ fprintf(stderr, " suggest trying -grope option!!!\n\n");
+ return 1;
+ }
+
+ if (verbose)
+ printf("\n MP FPS found in %s @ physical addr: 0x%08x\n",
+ whereStrings[where - 1], paddr);
+
+ if (verbose)
+ puts(SEP_LINE);
+
+ /* analyze the MP Floating Pointer Structure */
+ MPFloatingPointer(paddr, where, &mpfps);
+
+ if (verbose)
+ puts(SEP_LINE);
+
+ /* check whether an MP config table exists */
+ if ((defaultConfig = mpfps.mpfb1))
+ MPConfigDefault(defaultConfig);
+ else
+ MPConfigTableHeader(mpfps.pap);
+
+ /* build "options" entries for the kernel config file */
+ if (noisy)
+ doOptionList();
+
+ write_code(postamble);
+ /* do a dmesg output */
+ if (dmesg)
+ doDmesg();
+
+ if (verbose)
+ puts(SEP_LINE2);
+
+ return 0;
+}
+
+/*
+ * set PHYSICAL address of MP floating pointer structure
+ */
+#define NEXT(X) ((X) += 4)
+static void apic_probe(vm_offset_t * paddr, int *where)
+{
+ /*
+ * c rewrite of apic_probe() by Jack F. Vogel
+ */
+
+ int x;
+ u_short segment;
+ vm_offset_t target;
+ u_int buffer[BIOS_SIZE / sizeof(int)];
+
+ if (verbose)
+ printf("\n");
+
+ /* search Extended Bios Data Area, if present */
+ if (verbose)
+ printf(" looking for EBDA pointer @ 0x%04x, ", EBDA_POINTER);
+ seekEntry((vm_offset_t) EBDA_POINTER);
+ readEntry(&segment, 2);
+ if (segment) { /* search EBDA */
+ target = (vm_offset_t) segment << 4;
+ if (verbose)
+ printf("found, searching EBDA @ 0x%08x\n", target);
+ seekEntry(target);
+ readEntry(buffer, ONE_KBYTE);
+
+ for (x = 0; x < ONE_KBYTE / sizeof(unsigned int); NEXT(x)) {
+ if (buffer[x] == MP_SIG) {
+ *where = 1;
+ *paddr = (x * sizeof(unsigned int)) + target;
+ return;
+ }
+ }
+ } else {
+ if (verbose)
+ printf("NOT found\n");
+ }
+
+ target = 0;
+ segment = 0;
+ if (verbose)
+ printf(" searching for coreboot MP table @ 0x%08x (%dK)\n",
+ target, segment);
+ seekEntry(target);
+ readEntry(buffer, ONE_KBYTE);
+
+ for (x = 0; x < ONE_KBYTE / sizeof(unsigned int); NEXT(x)) {
+ if (buffer[x] == MP_SIG) {
+ *where = 2;
+ *paddr = (x * sizeof(unsigned int)) + target;
+ return;
+ }
+ }
+
+ /* read CMOS for real top of mem */
+ seekEntry((vm_offset_t) TOPOFMEM_POINTER);
+ readEntry(&segment, 2);
+ --segment; /* less ONE_KBYTE */
+ target = segment * 1024;
+ if (verbose)
+ printf(" searching CMOS 'top of mem' @ 0x%08x (%dK)\n",
+ target, segment);
+ seekEntry(target);
+ readEntry(buffer, ONE_KBYTE);
+
+ for (x = 0; x < ONE_KBYTE / sizeof(unsigned int); NEXT(x)) {
+ if (buffer[x] == MP_SIG) {
+ *where = 2;
+ *paddr = (x * sizeof(unsigned int)) + target;
+ return;
+ }
+ }
+
+ /* we don't necessarily believe CMOS, check base of the last 1K of 640K */
+ if (target != (DEFAULT_TOPOFMEM - 1024)) {
+ target = (DEFAULT_TOPOFMEM - 1024);
+ if (verbose)
+ printf
+ (" searching default 'top of mem' @ 0x%08x (%dK)\n",
+ target, (target / 1024));
+ seekEntry(target);
+ readEntry(buffer, ONE_KBYTE);
+
+ for (x = 0; x < ONE_KBYTE / sizeof(unsigned int); NEXT(x)) {
+ if (buffer[x] == MP_SIG) {
+ *where = 3;
+ *paddr = (x * sizeof(unsigned int)) + target;
+ return;
+ }
+ }
+ }
+
+ /* search the BIOS */
+ if (verbose)
+ printf(" searching BIOS @ 0x%08x\n", BIOS_BASE);
+ seekEntry(BIOS_BASE);
+ readEntry(buffer, BIOS_SIZE);
+
+ for (x = 0; x < BIOS_SIZE / sizeof(unsigned int); NEXT(x)) {
+ if (buffer[x] == MP_SIG) {
+ *where = 4;
+ *paddr = (x * sizeof(unsigned int)) + BIOS_BASE;
+ return;
+ }
+ }
+
+ /* search the extended BIOS */
+ if (verbose)
+ printf(" searching extended BIOS @ 0x%08x\n", BIOS_BASE2);
+ seekEntry(BIOS_BASE2);
+ readEntry(buffer, BIOS_SIZE);
+
+ for (x = 0; x < BIOS_SIZE / sizeof(unsigned int); NEXT(x)) {
+ if (buffer[x] == MP_SIG) {
+ *where = 5;
+ *paddr = (x * sizeof(unsigned int)) + BIOS_BASE2;
+ return;
+ }
+ }
+
+ if (grope) {
+ /* search additional memory */
+ target = GROPE_AREA1;
+ if (verbose)
+ printf(" groping memory @ 0x%08x\n", target);
+ seekEntry(target);
+ readEntry(buffer, GROPE_SIZE);
+
+ for (x = 0; x < GROPE_SIZE / sizeof(unsigned int); NEXT(x)) {
+ if (buffer[x] == MP_SIG) {
+ *where = 6;
+ *paddr =
+ (x * sizeof(unsigned int)) + GROPE_AREA1;
+ return;
+ }
+ }
+
+ target = GROPE_AREA2;
+ if (verbose)
+ printf(" groping memory @ 0x%08x\n", target);
+ seekEntry(target);
+ readEntry(buffer, GROPE_SIZE);
+
+ for (x = 0; x < GROPE_SIZE / sizeof(unsigned int); NEXT(x)) {
+ if (buffer[x] == MP_SIG) {
+ *where = 7;
+ *paddr =
+ (x * sizeof(unsigned int)) + GROPE_AREA2;
+ return;
+ }
+ }
+ }
+
+ *where = 0;
+ *paddr = (vm_offset_t) 0;
+}
+
+/*
+ *
+ */
+static void MPFloatingPointer(vm_offset_t paddr, int where, mpfps_t * mpfps)
+{
+
+ /* read in mpfps structure */
+ seekEntry(paddr);
+ readEntry(mpfps, sizeof(mpfps_t));
+
+ /* show its contents */
+ if (verbose) {
+ printf("MP Floating Pointer Structure:\n\n");
+
+ printf(" location:\t\t\t");
+ switch (where) {
+ case 1:
+ printf("EBDA\n");
+ break;
+ case 2:
+ printf("BIOS base memory\n");
+ break;
+ case 3:
+ printf("DEFAULT base memory (639K)\n");
+ break;
+ case 4:
+ printf("BIOS\n");
+ break;
+ case 5:
+ printf("Extended BIOS\n");
+ break;
+
+ case 0:
+ printf("NOT found!\n");
+ exit(1);
+ default:
+ printf("BOGUS!\n");
+ exit(1);
+ }
+ printf(" physical address:\t\t0x%08x\n", paddr);
+
+ printf(" signature:\t\t\t'");
+ pnstr(mpfps->signature, 4);
+ printf("'\n");
+
+ printf(" length:\t\t\t%d bytes\n", mpfps->length * 16);
+ printf(" version:\t\t\t1.%1d\n", mpfps->spec_rev);
+ printf(" checksum:\t\t\t0x%02x\n", mpfps->checksum);
+
+ /* bits 0:6 are RESERVED */
+ if (mpfps->mpfb2 & 0x7f) {
+ printf(" warning, MP feature byte 2: 0x%02x\n",
+ mpfps->mpfb2);
+ }
+
+ /* bit 7 is IMCRP */
+ printf(" mode:\t\t\t\t%s\n", (mpfps->mpfb2 & 0x80) ?
+ "PIC" : "Virtual Wire");
+
+ /* MP feature bytes 3-5 are expected to be ZERO */
+ if (mpfps->mpfb3)
+ printf(" warning, MP feature byte 3 NONZERO!\n");
+ if (mpfps->mpfb4)
+ printf(" warning, MP feature byte 4 NONZERO!\n");
+ if (mpfps->mpfb5)
+ printf(" warning, MP feature byte 5 NONZERO!\n");
+ }
+}
+
+/*
+ *
+ */
+static void MPConfigDefault(int featureByte)
+{
+ printf(" MP default config type: %d\n\n", featureByte);
+ switch (featureByte) {
+ case 1:
+ printf(" bus: ISA, APIC: 82489DX\n");
+ break;
+ case 2:
+ printf(" bus: EISA, APIC: 82489DX\n");
+ break;
+ case 3:
+ printf(" bus: EISA, APIC: 82489DX\n");
+ break;
+ case 4:
+ printf(" bus: MCA, APIC: 82489DX\n");
+ break;
+ case 5:
+ printf(" bus: ISA+PCI, APIC: Integrated\n");
+ break;
+ case 6:
+ printf(" bus: EISA+PCI, APIC: Integrated\n");
+ break;
+ case 7:
+ printf(" bus: MCA+PCI, APIC: Integrated\n");
+ break;
+ default:
+ printf(" future type\n");
+ break;
+ }
+
+ switch (featureByte) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ nbus = 1;
+ break;
+ case 5:
+ case 6:
+ case 7:
+ nbus = 2;
+ break;
+ default:
+ printf(" future type\n");
+ break;
+ }
+
+ ncpu = 2;
+ napic = 1;
+ nintr = 16;
+}
+
+/*
+ *
+ */
+static void MPConfigTableHeader(uint32_t pap)
+{
+ vm_offset_t paddr;
+ mpcth_t cth;
+ int x;
+ int totalSize;
+ int count, c;
+ int type;
+
+ if (pap == 0) {
+ printf("MP Configuration Table Header MISSING!\n");
+ exit(1);
+ }
+
+ /* convert physical address to virtual address */
+ paddr = (vm_offset_t) pap;
+
+ /* read in cth structure */
+ seekEntry(paddr);
+ readEntry(&cth, sizeof(cth));
+
+ if (verbose) {
+ printf("MP Config Table Header:\n\n");
+
+ printf(" physical address:\t\t0x%08x\n", pap);
+
+ printf(" signature:\t\t\t'");
+ pnstr(cth.signature, 4);
+ printf("'\n");
+
+ printf(" base table length:\t\t%d\n", cth.base_table_length);
+
+ printf(" version:\t\t\t1.%1d\n", cth.spec_rev);
+ printf(" checksum:\t\t\t0x%02x\n", cth.checksum);
+
+ printf(" OEM ID:\t\t\t'");
+ pnstr(cth.oem_id, 8);
+ printf("'\n");
+
+ printf(" Product ID:\t\t\t'");
+ pnstr(cth.product_id, 12);
+ printf("'\n");
+
+ printf(" OEM table pointer:\t\t0x%08x\n",
+ cth.oem_table_pointer);
+ printf(" OEM table size:\t\t%d\n", cth.oem_table_size);
+
+ printf(" entry count:\t\t\t%d\n", cth.entry_count);
+
+ printf(" local APIC address:\t\t0x%08x\n", cth.apic_address);
+
+ printf(" extended table length:\t%d\n",
+ cth.extended_table_length);
+ printf(" extended table checksum:\t%d\n",
+ cth.extended_table_checksum);
+ }
+
+ totalSize = cth.base_table_length - sizeof(struct MPCTH);
+ count = cth.entry_count;
+
+ if (verbose) {
+ if (verbose)
+ puts(SEP_LINE);
+
+ printf("MP Config Base Table Entries:\n\n");
+ }
+
+ /* initialze tables */
+ for(x = 0; x < ARRAY_SIZE(busses); x++)
+ busses[x] = UNKNOWN_BUSTYPE;
+ for(x = 0; x < ARRAY_SIZE(apics); x++)
+ apics[x] = 0xff;
+
+ ncpu = 0;
+ nbus = 0;
+ napic = 0;
+ nintr = 0;
+
+ /* process all the CPUs */
+ if (verbose) {
+ printf("--\nProcessors:\tAPIC ID\tVersion\tState"
+ "\t\tFamily\tModel\tStep\tFlags\n");
+ }
+ for (c = count; c; c--) {
+ if (readType() == 0)
+ processorEntry();
+ totalSize -= basetableEntryTypes[0].length;
+ }
+
+ /* process all the busses */
+ printf("\t/* Bus: Bus ID Type */\n");
+ for (c = count; c; c--) {
+ if (readType() == 1)
+ busEntry();
+ totalSize -= basetableEntryTypes[1].length;
+ }
+
+ /* process all the apics */
+ printf("\t/* I/O APICs: APIC ID Version State Address */\n");
+ for (c = count; c; c--) {
+ if (readType() == 2)
+ ioApicEntry();
+ totalSize -= basetableEntryTypes[2].length;
+ }
+
+ /* process all the I/O Ints */
+ printf("\t/* I/O Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN#*/ \n");
+ for (c = count; c; c--) {
+ if (readType() == 3)
+ intEntry();
+ totalSize -= basetableEntryTypes[3].length;
+ }
+
+ /* process all the Local Ints */
+ printf
+ ("\t/* Local Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */\n");
+ for (c = count; c; c--) {
+ if (readType() == 4)
+ lintEntry();
+ totalSize -= basetableEntryTypes[4].length;
+ }
+
+#if defined( EXTENDED_PROCESSING_READY )
+ /* process any extended data */
+ if ((totalSize = cth.extended_table_length)) {
+ if (verbose)
+ puts(SEP_LINE);
+
+ printf("MP Config Extended Table Entries:\n\n");
+
+ while (totalSize > 0) {
+ switch (type = readType()) {
+ case 128:
+ sasEntry();
+ break;
+ case 129:
+ bhdEntry();
+ break;
+ case 130:
+ cbasmEntry();
+ break;
+ default:
+ printf("Extended Table HOSED!\n");
+ exit(1);
+ }
+
+ totalSize -= extendedtableEntryTypes[type - 128].length;
+ }
+ }
+#endif /* EXTENDED_PROCESSING_READY */
+
+ /* process any OEM data */
+ if (cth.oem_table_pointer && (cth.oem_table_size > 0)) {
+#if defined( OEM_PROCESSING_READY )
+#error your on your own here!
+ /* convert OEM table pointer to virtual address */
+ poemtp = (vm_offset_t) cth.oem_table_pointer;
+
+ /* read in oem table structure */
+ if ((oemdata = (void *)malloc(cth.oem_table_size)) == NULL)
+ err(1, "oem malloc");
+
+ seekEntry(poemtp);
+ readEntry(oemdata, cth.oem_table_size);
+
+ /** process it */
+
+ free(oemdata);
+#else
+ printf
+ ("\nyou need to modify the source to handle OEM data!\n\n");
+#endif /* OEM_PROCESSING_READY */
+ }
+
+ fflush(stdout);
+
+#if defined( RAW_DUMP )
+ {
+ int ofd;
+ u_char dumpbuf[4096];
+
+ ofd = open("/tmp/mpdump", O_CREAT | O_RDWR);
+ seekEntry(paddr);
+ readEntry(dumpbuf, 1024);
+ write(ofd, dumpbuf, 1024);
+ close(ofd);
+ }
+#endif /* RAW_DUMP */
+}
+
+/*
+ *
+ */
+static int readType(void)
+{
+ u_char type;
+
+ if (read(pfd, &type, sizeof(u_char)) != sizeof(u_char))
+ err(1, "type read; pfd: %d", pfd);
+
+ if (lseek(pfd, -1, SEEK_CUR) < 0)
+ err(1, "type seek");
+
+ return (int)type;
+}
+
+/*
+ *
+ */
+static void seekEntry(vm_offset_t addr)
+{
+ if (lseek(pfd, (off_t) addr, SEEK_SET) < 0)
+ err(1, "/dev/mem seek");
+}
+
+/*
+ *
+ */
+static void readEntry(void *entry, int size)
+{
+ if (read(pfd, entry, size) != size)
+ err(1, "readEntry");
+}
+
+static void processorEntry(void)
+{
+ ProcEntry entry;
+
+ /* read it into local memory */
+ readEntry(&entry, sizeof(entry));
+
+ /* count it */
+ ++ncpu;
+ if (noisy) {
+ printf("\t\t%2d", entry.apicID);
+ printf("\t 0x%2x", entry.apicVersion);
+
+ printf("\t %s, %s",
+ (entry.cpuFlags & PROCENTRY_FLAG_BP) ? "BSP" : "AP",
+ (entry.
+ cpuFlags & PROCENTRY_FLAG_EN) ? "usable" : "unusable");
+
+ printf("\t %d\t %d\t %d",
+ (entry.cpuSignature >> 8) & 0x0f,
+ (entry.cpuSignature >> 4) & 0x0f,
+ entry.cpuSignature & 0x0f);
+
+ printf("\t 0x%04x\n", entry.featureFlags);
+ }
+}
+
+/*
+ *
+ */
+static int lookupBusType(char *name)
+{
+ int x;
+
+ for (x = 0; x < MAX_BUSTYPE; ++x)
+ if (strcmp(busTypeTable[x].name, name) == 0)
+ return busTypeTable[x].type;
+
+ return UNKNOWN_BUSTYPE;
+}
+
+static void busEntry(void)
+{
+ char name[8];
+ BusEntry entry;
+ int i;
+ /* read it into local memory */
+ readEntry(&entry, sizeof(entry));
+
+ /* count it */
+ ++nbus;
+
+ if (verbose) {
+ printf("\t\t%2d", entry.busID);
+ printf("\t ");
+ pnstr(entry.busType, 6);
+ printf("\n");
+ }
+
+ memset(name, '\0', sizeof(name));
+ for(i = 0; i < 6; i++) {
+ switch(entry.busType[i]) {
+ case ' ':
+ case '\0':
+ break;
+ default:
+ name[i] = entry.busType[i];
+ break;
+ }
+ }
+
+ if (entry.busID > ARRAY_SIZE(busses)) {
+ fprintf(stderr, "busses array to small!\n");
+ exit(1);
+ }
+
+ busses[entry.busID] = lookupBusType(name);
+ printf("\tsmp_write_bus(mc, %d, \"", entry.busID);
+ pnstr(entry.busType, 6);
+ printf("\");\n");
+}
+
+static void ioApicEntry(void)
+{
+ IOApicEntry entry;
+
+ /* read it into local memory */
+ readEntry(&entry, sizeof(entry));
+
+ /* count it */
+ ++napic;
+
+ if (noisy) {
+ printf("\t\t%2d", entry.apicID);
+ printf("\t 0x%02x", entry.apicVersion);
+ printf("\t %s",
+ (entry.
+ apicFlags & IOAPICENTRY_FLAG_EN) ? "usable" :
+ "unusable");
+ printf("\t\t 0x%x\n", entry.apicAddress);
+ }
+
+ apics[entry.apicID] = entry.apicID;
+
+ if (entry.apicFlags & IOAPICENTRY_FLAG_EN)
+ printf("\tsmp_write_ioapic(mc, 0x%x, 0x%x, 0x%x);\n",
+ entry.apicID, entry.apicVersion, entry.apicAddress);
+}
+
+char *intTypes[] = {
+ "mp_INT", "mp_NMI", "mp_SMI", "mp_ExtINT"
+};
+
+char *polarityMode[] = {
+ "MP_IRQ_POLARITY_DEFAULT", "MP_IRQ_POLARITY_HIGH", "reserved",
+ "MP_IRQ_POLARITY_LOW"
+};
+
+char *triggerMode[] = {
+ "MP_IRQ_TRIGGER_DEFAULT", "MP_IRQ_TRIGGER_EDGE", "reserved",
+ "MP_IRQ_TRIGGER_LEVEL"
+};
+
+static void intEntry(void)
+{
+ IntEntry entry;
+
+ /* read it into local memory */
+ readEntry(&entry, sizeof(entry));
+
+ /* count it */
+ if ((int)entry.type == 3)
+ ++nintr;
+
+ if (noisy) {
+ printf("\n\t\t%s", intTypes[(int)entry.intType]);
+
+ printf("\t%9s", polarityMode[(int)entry.intFlags & 0x03]);
+ printf("%12s", triggerMode[((int)entry.intFlags >> 2) & 0x03]);
+
+ printf("\t %5d", (int)entry.srcBusID);
+ if (busses[(int)entry.srcBusID] == PCI)
+ printf("\t%2d:%c",
+ ((int)entry.srcBusIRQ >> 2) & 0x1f,
+ ((int)entry.srcBusIRQ & 0x03) + 'A');
+ else
+ printf("\t 0x%x:0x%x(0x%x)",
+ (int)entry.srcBusIRQ >> 2,
+ (int)entry.srcBusIRQ & 3, (int)entry.srcBusIRQ);
+ printf("\t %6d", (int)entry.dstApicID);
+ printf("\t %3d\n", (int)entry.dstApicINT);
+ }
+
+ if (busses[(int)entry.srcBusID] == PCI) {
+ printf("\tsmp_write_intsrc(mc, %s, %s|%s, 0x%x, (0x%02x << 2) | INT%c, 0x%x, 0x%x);\n",
+ intTypes[(int)entry.intType],
+ triggerMode[((int)entry.intFlags >> 2) & 0x03],
+ polarityMode[(int)entry.intFlags & 0x03],
+ (int)entry.srcBusID,
+ (int)entry.srcBusIRQ >> 2,
+ ((int)entry.srcBusIRQ & 3) + 'A',
+ (int)entry.dstApicID, (int)entry.dstApicINT);
+ } else {
+ printf("\tsmp_write_intsrc(mc, %s, %s|%s, 0x%x, 0x%x, 0x%x, 0x%x);\n",
+ intTypes[(int)entry.intType],
+ triggerMode[((int)entry.intFlags >> 2) & 0x03],
+ polarityMode[(int)entry.intFlags & 0x03],
+ (int)entry.srcBusID,
+ (int)entry.srcBusIRQ,
+ (int)entry.dstApicID, (int)entry.dstApicINT);
+ }
+}
+
+static void lintEntry(void)
+{
+ IntEntry entry;
+
+ /* read it into local memory */
+ readEntry(&entry, sizeof(entry));
+
+ /* count it */
+ if ((int)entry.type == 3)
+ ++nintr;
+
+ if (noisy) {
+ printf("\t\t%s", intTypes[(int)entry.intType]);
+
+ printf("\t%9s", polarityMode[(int)entry.intFlags & 0x03]);
+ printf("%12s", triggerMode[((int)entry.intFlags >> 2) & 0x03]);
+
+ printf("\t %5d", (int)entry.srcBusID);
+ if (busses[(int)entry.srcBusID] == PCI)
+ printf("\t%2d:%c",
+ ((int)entry.srcBusIRQ >> 2) & 0x1f,
+ ((int)entry.srcBusIRQ & 0x03) + 'A');
+ else
+ printf("\t %3d", (int)entry.srcBusIRQ);
+ printf("\t %6d", (int)entry.dstApicID);
+ printf("\t %3d\n", (int)entry.dstApicINT);
+ }
+ printf
+ ("\tsmp_write_lintsrc(mc, %s, %s|%s, 0x%x, 0x%x, MP_APIC_ALL, 0x%x);\n",
+ intTypes[(int)entry.intType],
+ triggerMode[((int)entry.intFlags >> 2) & 0x03],
+ polarityMode[(int)entry.intFlags & 0x03], (int)entry.srcBusID,
+ (int)entry.srcBusIRQ, (int)entry.dstApicINT);
+
+}
+
+static void sasEntry(void)
+{
+ SasEntry entry;
+
+ /* read it into local memory */
+ readEntry(&entry, sizeof(entry));
+
+ printf("--\n%s\n", extendedtableEntryTypes[entry.type - 128].name);
+ printf(" bus ID: %d", entry.busID);
+ printf(" address type: ");
+ switch (entry.addressType) {
+ case 0:
+ printf("I/O address\n");
+ break;
+ case 1:
+ printf("memory address\n");
+ break;
+ case 2:
+ printf("prefetch address\n");
+ break;
+ default:
+ printf("UNKNOWN type\n");
+ break;
+ }
+
+ printf(" address base: 0x%lx\n", entry.addressBase);
+ printf(" address range: 0x%lx\n", entry.addressLength);
+}
+
+static void bhdEntry(void)
+{
+ BhdEntry entry;
+
+ /* read it into local memory */
+ readEntry(&entry, sizeof(entry));
+
+ printf("--\n%s\n", extendedtableEntryTypes[entry.type - 128].name);
+ printf(" bus ID: %d", entry.busID);
+ printf(" bus info: 0x%02x", entry.busInfo);
+ printf(" parent bus ID: %d", entry.busParent);
+}
+
+static void cbasmEntry(void)
+{
+ CbasmEntry entry;
+
+ /* read it into local memory */
+ readEntry(&entry, sizeof(entry));
+
+ printf("--\n%s\n", extendedtableEntryTypes[entry.type - 128].name);
+ printf(" bus ID: %d", entry.busID);
+ printf(" address modifier: %s\n", (entry.addressMod & 0x01) ?
+ "subtract" : "add");
+ printf(" predefined range: 0x%08x", entry.predefinedRange);
+}
+
+/*
+ * do a dmesg output
+ */
+static void doDmesg(void)
+{
+ if (verbose)
+ puts(SEP_LINE);
+
+ printf("dmesg output:\n\n");
+ fflush(stdout);
+ system("dmesg");
+}
+
+/*
+ * build "options" entries for the kernel config file
+ */
+static void doOptionList(void)
+{
+ if (verbose)
+ puts(SEP_LINE);
+
+ printf("# SMP kernel config file options:\n\n");
+ printf("\n# Required:\n");
+ printf("options SMP\t\t\t# Symmetric MultiProcessor Kernel\n");
+ printf("options APIC_IO\t\t\t# Symmetric (APIC) I/O\n");
+
+ printf("\n# Optional (built-in defaults will work in most cases):\n");
+ printf("#options NCPU=%d\t\t\t# number of CPUs\n", ncpu);
+ printf("#options NBUS=%d\t\t\t# number of busses\n",
+ nbus);
+ printf("#options NAPIC=%d\t\t\t# number of IO APICs\n",
+ napic);
+ printf("#options NINTR=%d\t\t# number of INTs\n",
+ (nintr < 24) ? 24 : nintr);
+}
+
+/*
+ *
+ */
+static void pnstr(uint8_t * s, int c)
+{
+ uint8_t string[MAXPNSTR + 1];
+
+ if (c > MAXPNSTR)
+ c = MAXPNSTR;
+ strncpy((char *)string, (char *)s, c);
+ string[c] = '\0';
+ printf("%s", string);
+}

To view, visit change 48322. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Ieff7673387ae9275b8271f4a483926b774697a8d
Gerrit-Change-Number: 48322
Gerrit-PatchSet: 1
Gerrit-Owner: Mike Banon <mikebdp2@gmail.com>
Gerrit-Reviewer: Alexandru Gagniuc <alexandrux.gagniuc@intel.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-Reviewer: Paul Menzel <paulepanter@users.sourceforge.net>
Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org>
Gerrit-MessageType: newchange