[coreboot-gerrit] New patch to review for coreboot: x86: flatten hierarchy
Stefan Reinauer (stefan.reinauer@coreboot.org)
gerrit at coreboot.org
Mon Jul 13 09:42:09 CEST 2015
Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10901
-gerrit
commit 27eba53ef8354510415ef46864833a2938eccf16
Author: Stefan Reinauer <stefan.reinauer at coreboot.org>
Date: Mon Jul 13 09:39:15 2015 +0200
x86: flatten hierarchy
It never made sense to have bootblock_* in init, but
pirq_routing.c in boot, and some ld scripts on the main
level while others live in subdirectories.
This patch flattens the directory hierarchy and makes
x86 more similar to the other architectures.
Change-Id: I4056038fe7813e4d3d3042c441e7ab6076a36384
Signed-off-by: Stefan Reinauer <stefan.reinauer at coreboot.org>
---
src/arch/x86/Makefile.inc | 61 ++
src/arch/x86/acpi.c | 1137 +++++++++++++++++++++++++++++
src/arch/x86/acpigen.c | 728 ++++++++++++++++++
src/arch/x86/boot.c | 210 ++++++
src/arch/x86/boot/Makefile.inc | 22 -
src/arch/x86/boot/acpi.c | 1137 -----------------------------
src/arch/x86/boot/acpigen.c | 728 ------------------
src/arch/x86/boot/boot.c | 210 ------
src/arch/x86/boot/cbmem.c | 76 --
src/arch/x86/boot/gdt.c | 62 --
src/arch/x86/boot/mpspec.c | 597 ---------------
src/arch/x86/boot/pirq_routing.c | 208 ------
src/arch/x86/boot/smbios.c | 581 ---------------
src/arch/x86/boot/tables.c | 221 ------
src/arch/x86/boot/wakeup.S | 99 ---
src/arch/x86/bootblock_normal.c | 52 ++
src/arch/x86/bootblock_simple.c | 23 +
src/arch/x86/c_start.S | 421 +++++++++++
src/arch/x86/cbfs_and_run.c | 26 +
src/arch/x86/cbmem.c | 76 ++
src/arch/x86/cpu.c | 273 +++++++
src/arch/x86/cpu_common.c | 65 ++
src/arch/x86/crt0_romcc_epilogue.inc | 21 +
src/arch/x86/ebda.c | 52 ++
src/arch/x86/exception.c | 511 +++++++++++++
src/arch/x86/failover.ld | 70 ++
src/arch/x86/gdt.c | 62 ++
src/arch/x86/id.inc | 18 +
src/arch/x86/id.ld | 6 +
src/arch/x86/init/Makefile.inc | 1 -
src/arch/x86/init/bootblock_normal.c | 52 --
src/arch/x86/init/bootblock_simple.c | 23 -
src/arch/x86/init/crt0_romcc_epilogue.inc | 21 -
src/arch/x86/init/failover.ld | 70 --
src/arch/x86/init/prologue.inc | 23 -
src/arch/x86/init/romstage.ld | 87 ---
src/arch/x86/ioapic.c | 153 ++++
src/arch/x86/lib/Makefile.inc | 48 --
src/arch/x86/lib/c_start.S | 421 -----------
src/arch/x86/lib/cbfs_and_run.c | 26 -
src/arch/x86/lib/cpu.c | 273 -------
src/arch/x86/lib/cpu_common.c | 65 --
src/arch/x86/lib/ebda.c | 52 --
src/arch/x86/lib/exception.c | 511 -------------
src/arch/x86/lib/id.inc | 18 -
src/arch/x86/lib/id.ld | 6 -
src/arch/x86/lib/ioapic.c | 153 ----
src/arch/x86/lib/memcpy.c | 22 -
src/arch/x86/lib/memmove.c | 187 -----
src/arch/x86/lib/memset.c | 84 ---
src/arch/x86/lib/mmap_boot.c | 75 --
src/arch/x86/lib/pci_ops_conf1.c | 71 --
src/arch/x86/lib/pci_ops_mmconf.c | 61 --
src/arch/x86/lib/romcc_console.c | 87 ---
src/arch/x86/lib/stages.c | 25 -
src/arch/x86/lib/thread.c | 65 --
src/arch/x86/lib/thread_switch.S | 58 --
src/arch/x86/lib/timestamp.c | 26 -
src/arch/x86/lib/walkcbfs.S | 117 ---
src/arch/x86/memcpy.c | 22 +
src/arch/x86/memmove.c | 187 +++++
src/arch/x86/memset.c | 84 +++
src/arch/x86/mmap_boot.c | 75 ++
src/arch/x86/mpspec.c | 597 +++++++++++++++
src/arch/x86/pci_ops_conf1.c | 71 ++
src/arch/x86/pci_ops_mmconf.c | 61 ++
src/arch/x86/pirq_routing.c | 208 ++++++
src/arch/x86/prologue.inc | 23 +
src/arch/x86/romcc_console.c | 87 +++
src/arch/x86/romstage.ld | 87 +++
src/arch/x86/smbios.c | 581 +++++++++++++++
src/arch/x86/stages.c | 25 +
src/arch/x86/tables.c | 221 ++++++
src/arch/x86/thread.c | 65 ++
src/arch/x86/thread_switch.S | 58 ++
src/arch/x86/timestamp.c | 26 +
src/arch/x86/wakeup.S | 99 +++
src/arch/x86/walkcbfs.S | 117 +++
78 files changed, 6659 insertions(+), 6669 deletions(-)
diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc
index 2448590..472cd00 100644
--- a/src/arch/x86/Makefile.inc
+++ b/src/arch/x86/Makefile.inc
@@ -339,3 +339,64 @@ endif
endif # CONFIG_ARCH_RAMSTAGE_X86_32 / CONFIG_ARCH_RAMSTAGE_X86_64
+ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32)$(CONFIG_ARCH_ROMSTAGE_X86_64),y)
+
+romstage-y += cbmem.c
+romstage-y += boot.c
+
+romstage-y += cbfs_and_run.c
+romstage-$(CONFIG_ARCH_RAMSTAGE_X86_32) += cpu_common.c
+romstage-y += memset.c
+romstage-y += memcpy.c
+romstage-y += memmove.c
+romstage-y += mmap_boot.c
+
+romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
+
+endif # CONFIG_ARCH_ROMSTAGE_X86_32 / CONFIG_ARCH_ROMSTAGE_X86_64
+
+ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32)$(CONFIG_ARCH_RAMSTAGE_X86_64),y)
+
+ramstage-y += boot.c
+ramstage-y += gdt.c
+ramstage-y += tables.c
+ramstage-y += cbmem.c
+ramstage-$(CONFIG_GENERATE_MP_TABLE) += mpspec.c
+ramstage-$(CONFIG_GENERATE_PIRQ_TABLE) += pirq_routing.c
+ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
+ramstage-$(CONFIG_GENERATE_SMBIOS_TABLES) += smbios.c
+ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpigen.c
+ramstage-$(CONFIG_HAVE_ACPI_RESUME) += wakeup.S
+
+ramstage-y += c_start.S
+ramstage-y += cpu.c
+ramstage-y += cpu_common.c
+ramstage-y += pci_ops_conf1.c
+ramstage-$(CONFIG_MMCONF_SUPPORT) += pci_ops_mmconf.c
+ramstage-y += exception.c
+ramstage-$(CONFIG_IOAPIC) += ioapic.c
+ramstage-y += memset.c
+ramstage-y += memcpy.c
+ramstage-y += memmove.c
+ramstage-y += ebda.c
+ramstage-y += mmap_boot.c
+ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c
+ramstage-$(CONFIG_COOP_MULTITASKING) += thread_switch.S
+ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
+
+smm-y += memset.c
+smm-y += memcpy.c
+smm-y += memmove.c
+smm-y += mmap_boot.c
+
+ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y)
+rmodules_x86_32-y += memset.c
+rmodules_x86_32-y += memcpy.c
+rmodules_x86_32-y += memmove.c
+else
+rmodules_x86_64-y += memset.c
+rmodules_x86_64-y += memcpy.c
+rmodules_x86_64-y += memmove.c
+endif
+
+endif # CONFIG_ARCH_RAMSTAGE_X86_32 / CONFIG_ARCH_RAMSTAGE_X86_64
diff --git a/src/arch/x86/acpi.c b/src/arch/x86/acpi.c
new file mode 100644
index 0000000..134e437
--- /dev/null
+++ b/src/arch/x86/acpi.c
@@ -0,0 +1,1137 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * coreboot ACPI Table support
+ * written by Stefan Reinauer <stepan at openbios.org>
+ *
+ * Copyright (C) 2004 SUSE LINUX AG
+ * Copyright (C) 2005-2009 coresystems GmbH
+ *
+ * ACPI FADT, FACS, and DSDT table support added by
+ * Nick Barker <nick.barker9 at btinternet.com>, and those portions
+ * Copyright (C) 2004 Nick Barker
+ *
+ * Copyright (C) 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+ * 2005.9 yhlu add SRAT table generation
+ */
+
+/*
+ * Each system port implementing ACPI has to provide two functions:
+ *
+ * write_acpi_tables()
+ * acpi_dump_apics()
+ *
+ * See Kontron 986LCD-M port for a good example of an ACPI implementation
+ * in coreboot.
+ */
+
+#include <console/console.h>
+#include <string.h>
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <device/pci.h>
+#include <cbmem.h>
+#include <cpu/x86/lapic_def.h>
+#include <cpu/cpu.h>
+#include <cbfs.h>
+#include <timestamp.h>
+#include <romstage_handoff.h>
+
+/* FIXME: Kconfig doesn't support overridable defaults :-( */
+#ifndef CONFIG_HPET_MIN_TICKS
+#define CONFIG_HPET_MIN_TICKS 0x1000
+#endif
+
+u8 acpi_checksum(u8 *table, u32 length)
+{
+ u8 ret = 0;
+ while (length--) {
+ ret += *table;
+ table++;
+ }
+ return -ret;
+}
+
+/**
+ * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length
+ * and checksum.
+ */
+void acpi_add_table(acpi_rsdp_t *rsdp, void *table)
+{
+ int i, entries_num;
+ acpi_rsdt_t *rsdt;
+ acpi_xsdt_t *xsdt = NULL;
+
+ /* The RSDT is mandatory... */
+ rsdt = (acpi_rsdt_t *)(uintptr_t)rsdp->rsdt_address;
+
+ /* ...while the XSDT is not. */
+ if (rsdp->xsdt_address)
+ xsdt = (acpi_xsdt_t *)((uintptr_t)rsdp->xsdt_address);
+
+ /* This should always be MAX_ACPI_TABLES. */
+ entries_num = ARRAY_SIZE(rsdt->entry);
+
+ for (i = 0; i < entries_num; i++) {
+ if (rsdt->entry[i] == 0)
+ break;
+ }
+
+ if (i >= entries_num) {
+ printk(BIOS_ERR, "ACPI: Error: Could not add ACPI table, "
+ "too many tables.\n");
+ return;
+ }
+
+ /* Add table to the RSDT. */
+ rsdt->entry[i] = (uintptr_t)table;
+
+ /* Fix RSDT length or the kernel will assume invalid entries. */
+ rsdt->header.length = sizeof(acpi_header_t) + (sizeof(u32) * (i + 1));
+
+ /* Re-calculate checksum. */
+ rsdt->header.checksum = 0; /* Hope this won't get optimized away */
+ rsdt->header.checksum = acpi_checksum((u8 *)rsdt, rsdt->header.length);
+
+ /*
+ * And now the same thing for the XSDT. We use the same index as for
+ * now we want the XSDT and RSDT to always be in sync in coreboot.
+ */
+ if (xsdt) {
+ /* Add table to the XSDT. */
+ xsdt->entry[i] = (u64)(uintptr_t)table;
+
+ /* Fix XSDT length. */
+ xsdt->header.length = sizeof(acpi_header_t) +
+ (sizeof(u64) * (i + 1));
+
+ /* Re-calculate checksum. */
+ xsdt->header.checksum = 0;
+ xsdt->header.checksum = acpi_checksum((u8 *)xsdt,
+ xsdt->header.length);
+ }
+
+ printk(BIOS_DEBUG, "ACPI: added table %d/%d, length now %d\n",
+ i + 1, entries_num, rsdt->header.length);
+}
+
+int acpi_create_mcfg_mmconfig(acpi_mcfg_mmconfig_t *mmconfig, u32 base,
+ u16 seg_nr, u8 start, u8 end)
+{
+ memset(mmconfig, 0, sizeof(*mmconfig));
+ mmconfig->base_address = base;
+ mmconfig->base_reserved = 0;
+ mmconfig->pci_segment_group_number = seg_nr;
+ mmconfig->start_bus_number = start;
+ mmconfig->end_bus_number = end;
+
+ return sizeof(acpi_mcfg_mmconfig_t);
+}
+
+int acpi_create_madt_lapic(acpi_madt_lapic_t *lapic, u8 cpu, u8 apic)
+{
+ lapic->type = 0; /* Local APIC structure */
+ lapic->length = sizeof(acpi_madt_lapic_t);
+ lapic->flags = (1 << 0); /* Processor/LAPIC enabled */
+ lapic->processor_id = cpu;
+ lapic->apic_id = apic;
+
+ return lapic->length;
+}
+
+unsigned long acpi_create_madt_lapics(unsigned long current)
+{
+ struct device *cpu;
+ int index = 0;
+
+ for (cpu = all_devices; cpu; cpu = cpu->next) {
+ if ((cpu->path.type != DEVICE_PATH_APIC) ||
+ (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
+ continue;
+ }
+ if (!cpu->enabled)
+ continue;
+ current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current,
+ index, cpu->path.apic.apic_id);
+ index++;
+ }
+
+ return current;
+}
+
+int acpi_create_madt_ioapic(acpi_madt_ioapic_t *ioapic, u8 id, u32 addr,
+ u32 gsi_base)
+{
+ ioapic->type = 1; /* I/O APIC structure */
+ ioapic->length = sizeof(acpi_madt_ioapic_t);
+ ioapic->reserved = 0x00;
+ ioapic->gsi_base = gsi_base;
+ ioapic->ioapic_id = id;
+ ioapic->ioapic_addr = addr;
+
+ return ioapic->length;
+}
+
+int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t *irqoverride,
+ u8 bus, u8 source, u32 gsirq, u16 flags)
+{
+ irqoverride->type = 2; /* Interrupt source override */
+ irqoverride->length = sizeof(acpi_madt_irqoverride_t);
+ irqoverride->bus = bus;
+ irqoverride->source = source;
+ irqoverride->gsirq = gsirq;
+ irqoverride->flags = flags;
+
+ return irqoverride->length;
+}
+
+int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t *lapic_nmi, u8 cpu,
+ u16 flags, u8 lint)
+{
+ lapic_nmi->type = 4; /* Local APIC NMI structure */
+ lapic_nmi->length = sizeof(acpi_madt_lapic_nmi_t);
+ lapic_nmi->flags = flags;
+ lapic_nmi->processor_id = cpu;
+ lapic_nmi->lint = lint;
+
+ return lapic_nmi->length;
+}
+
+void acpi_create_madt(acpi_madt_t *madt)
+{
+ acpi_header_t *header = &(madt->header);
+ unsigned long current = (unsigned long)madt + sizeof(acpi_madt_t);
+
+ memset((void *)madt, 0, sizeof(acpi_madt_t));
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "APIC", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->length = sizeof(acpi_madt_t);
+ header->revision = 1; /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
+
+ madt->lapic_addr = LOCAL_APIC_ADDR;
+ madt->flags = 0x1; /* PCAT_COMPAT */
+
+ current = acpi_fill_madt(current);
+
+ /* (Re)calculate length and checksum. */
+ header->length = current - (unsigned long)madt;
+
+ header->checksum = acpi_checksum((void *)madt, header->length);
+}
+
+/* MCFG is defined in the PCI Firmware Specification 3.0. */
+void acpi_create_mcfg(acpi_mcfg_t *mcfg)
+{
+ acpi_header_t *header = &(mcfg->header);
+ unsigned long current = (unsigned long)mcfg + sizeof(acpi_mcfg_t);
+
+ memset((void *)mcfg, 0, sizeof(acpi_mcfg_t));
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "MCFG", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->length = sizeof(acpi_mcfg_t);
+ header->revision = 1;
+
+ current = acpi_fill_mcfg(current);
+
+ /* (Re)calculate length and checksum. */
+ header->length = current - (unsigned long)mcfg;
+ header->checksum = acpi_checksum((void *)mcfg, header->length);
+}
+
+static void *get_tcpa_log(u32 *size)
+{
+ const struct cbmem_entry *ce;
+ const u32 tcpa_default_log_len = 0x10000;
+ void *lasa;
+ ce = cbmem_entry_find(CBMEM_ID_TCPA_LOG);
+ if (ce) {
+ lasa = cbmem_entry_start(ce);
+ *size = cbmem_entry_size(ce);
+ printk(BIOS_DEBUG, "TCPA log found at %p\n", lasa);
+ return lasa;
+ }
+ lasa = cbmem_add(CBMEM_ID_TCPA_LOG, tcpa_default_log_len);
+ if (!lasa) {
+ printk(BIOS_ERR, "TCPA log creation failed\n");
+ return NULL;
+ }
+
+ printk(BIOS_DEBUG, "TCPA log created at %p\n", lasa);
+ memset (lasa, 0, tcpa_default_log_len);
+
+ *size = tcpa_default_log_len;
+ return lasa;
+}
+
+static void acpi_create_tcpa(acpi_tcpa_t *tcpa)
+{
+ acpi_header_t *header = &(tcpa->header);
+ u32 tcpa_log_len;
+ void *lasa;
+
+ memset((void *)tcpa, 0, sizeof(acpi_tcpa_t));
+
+ lasa = get_tcpa_log(&tcpa_log_len);
+ if (!lasa) {
+ return;
+ }
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "TCPA", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->length = sizeof(acpi_tcpa_t);
+ header->revision = 2;
+
+ tcpa->platform_class = 0;
+ tcpa->laml = tcpa_log_len;
+ tcpa->lasa = (uintptr_t) lasa;
+
+ /* Calculate checksum. */
+ header->checksum = acpi_checksum((void *)tcpa, header->length);
+}
+
+void acpi_create_ssdt_generator(acpi_header_t *ssdt, const char *oem_table_id)
+{
+ unsigned long current = (unsigned long)ssdt + sizeof(acpi_header_t);
+
+ memset((void *)ssdt, 0, sizeof(acpi_header_t));
+
+ memcpy(&ssdt->signature, "SSDT", 4);
+ ssdt->revision = 2; /* ACPI 1.0/2.0: ?, ACPI 3.0/4.0: 2 */
+ memcpy(&ssdt->oem_id, OEM_ID, 6);
+ memcpy(&ssdt->oem_table_id, oem_table_id, 8);
+ ssdt->oem_revision = 42;
+ memcpy(&ssdt->asl_compiler_id, ASLC, 4);
+ ssdt->asl_compiler_revision = 42;
+ ssdt->length = sizeof(acpi_header_t);
+
+ acpigen_set_current((char *) current);
+ {
+ struct device *dev;
+ for (dev = all_devices; dev; dev = dev->next)
+ if (dev->ops && dev->ops->acpi_fill_ssdt_generator) {
+ dev->ops->acpi_fill_ssdt_generator(dev);
+ }
+ current = (unsigned long) acpigen_get_current();
+ }
+
+ /* (Re)calculate length and checksum. */
+ ssdt->length = current - (unsigned long)ssdt;
+ ssdt->checksum = acpi_checksum((void *)ssdt, ssdt->length);
+}
+
+int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic)
+{
+ memset((void *)lapic, 0, sizeof(acpi_srat_lapic_t));
+
+ lapic->type = 0; /* Processor local APIC/SAPIC affinity structure */
+ lapic->length = sizeof(acpi_srat_lapic_t);
+ lapic->flags = (1 << 0); /* Enabled (the use of this structure). */
+ lapic->proximity_domain_7_0 = node;
+ /* TODO: proximity_domain_31_8, local SAPIC EID, clock domain. */
+ lapic->apic_id = apic;
+
+ return lapic->length;
+}
+
+int acpi_create_srat_mem(acpi_srat_mem_t *mem, u8 node, u32 basek, u32 sizek,
+ u32 flags)
+{
+ mem->type = 1; /* Memory affinity structure */
+ mem->length = sizeof(acpi_srat_mem_t);
+ mem->base_address_low = (basek << 10);
+ mem->base_address_high = (basek >> (32 - 10));
+ mem->length_low = (sizek << 10);
+ mem->length_high = (sizek >> (32 - 10));
+ mem->proximity_domain = node;
+ mem->flags = flags;
+
+ return mem->length;
+}
+
+/* http://www.microsoft.com/whdc/system/sysinternals/sratdwn.mspx */
+void acpi_create_srat(acpi_srat_t *srat,
+ unsigned long (*acpi_fill_srat)(unsigned long current))
+{
+ acpi_header_t *header = &(srat->header);
+ unsigned long current = (unsigned long)srat + sizeof(acpi_srat_t);
+
+ memset((void *)srat, 0, sizeof(acpi_srat_t));
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "SRAT", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->length = sizeof(acpi_srat_t);
+ header->revision = 1; /* ACPI 1.0: N/A, 2.0: 1, 3.0: 2, 4.0: 3 */
+
+ srat->resv = 1; /* Spec: Reserved to 1 for backwards compatibility. */
+
+ current = acpi_fill_srat(current);
+
+ /* (Re)calculate length and checksum. */
+ header->length = current - (unsigned long)srat;
+ header->checksum = acpi_checksum((void *)srat, header->length);
+}
+
+void acpi_create_dmar(acpi_dmar_t *dmar,
+ unsigned long (*acpi_fill_dmar) (unsigned long))
+{
+ acpi_header_t *header = &(dmar->header);
+ unsigned long current = (unsigned long)dmar + sizeof(acpi_dmar_t);
+
+ memset((void *)dmar, 0, sizeof(acpi_dmar_t));
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "DMAR", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->length = sizeof(acpi_dmar_t);
+ header->revision = 1;
+
+ dmar->host_address_width = 40 - 1; /* FIXME: == MTRR size? */
+ dmar->flags = 0;
+
+ current = acpi_fill_dmar(current);
+
+ /* (Re)calculate length and checksum. */
+ header->length = current - (unsigned long)dmar;
+ header->checksum = acpi_checksum((void *)dmar, header->length);
+}
+
+unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
+ u16 segment, u32 bar)
+{
+ dmar_entry_t *drhd = (dmar_entry_t *)current;
+ memset(drhd, 0, sizeof(*drhd));
+ drhd->type = DMAR_DRHD;
+ drhd->length = sizeof(*drhd); /* will be fixed up later */
+ drhd->flags = flags;
+ drhd->segment = segment;
+ drhd->bar = bar;
+
+ return drhd->length;
+}
+
+void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current)
+{
+ dmar_entry_t *drhd = (dmar_entry_t *)base;
+ drhd->length = current - base;
+}
+
+unsigned long acpi_create_dmar_drhd_ds_pci(unsigned long current, u8 segment,
+ u8 dev, u8 fn)
+{
+ dev_scope_t *ds = (dev_scope_t *)current;
+ memset(ds, 0, sizeof(*ds));
+ ds->type = SCOPE_PCI_ENDPOINT;
+ ds->length = sizeof(*ds) + 2; /* we don't support longer paths yet */
+ ds->start_bus = segment;
+ ds->path[0].dev = dev;
+ ds->path[0].fn = fn;
+
+ return ds->length;
+}
+
+/* http://h21007.www2.hp.com/portal/download/files/unprot/Itanium/slit.pdf */
+void acpi_create_slit(acpi_slit_t *slit,
+ unsigned long (*acpi_fill_slit)(unsigned long current))
+{
+ acpi_header_t *header = &(slit->header);
+ unsigned long current = (unsigned long)slit + sizeof(acpi_slit_t);
+
+ memset((void *)slit, 0, sizeof(acpi_slit_t));
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "SLIT", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->length = sizeof(acpi_slit_t);
+ header->revision = 1; /* ACPI 1.0: N/A, ACPI 2.0/3.0/4.0: 1 */
+
+ current = acpi_fill_slit(current);
+
+ /* (Re)calculate length and checksum. */
+ header->length = current - (unsigned long)slit;
+ header->checksum = acpi_checksum((void *)slit, header->length);
+}
+
+/* http://www.intel.com/hardwaredesign/hpetspec_1.pdf */
+void acpi_create_hpet(acpi_hpet_t *hpet)
+{
+ acpi_header_t *header = &(hpet->header);
+ acpi_addr_t *addr = &(hpet->addr);
+
+ memset((void *)hpet, 0, sizeof(acpi_hpet_t));
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "HPET", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->length = sizeof(acpi_hpet_t);
+ header->revision = 1; /* Currently 1. Table added in ACPI 2.0. */
+
+ /* Fill out HPET address. */
+ addr->space_id = 0; /* Memory */
+ addr->bit_width = 64;
+ addr->bit_offset = 0;
+ addr->addrl = CONFIG_HPET_ADDRESS & 0xffffffff;
+ addr->addrh = ((unsigned long long)CONFIG_HPET_ADDRESS) >> 32;
+
+ hpet->id = *(unsigned int*)CONFIG_HPET_ADDRESS;
+ hpet->number = 0;
+ hpet->min_tick = CONFIG_HPET_MIN_TICKS;
+
+ header->checksum = acpi_checksum((void *)hpet, sizeof(acpi_hpet_t));
+}
+
+unsigned long acpi_write_hpet(device_t device, unsigned long current, acpi_rsdp_t *rsdp)
+{
+ acpi_hpet_t *hpet;
+
+ /*
+ * We explicitly add these tables later on:
+ */
+ printk(BIOS_DEBUG, "ACPI: * HPET\n");
+
+ hpet = (acpi_hpet_t *) current;
+ current += sizeof(acpi_hpet_t);
+ current = ALIGN(current, 16);
+ acpi_create_hpet(hpet);
+ acpi_add_table(rsdp, hpet);
+
+ return current;
+}
+
+void acpi_create_facs(acpi_facs_t *facs)
+{
+ memset((void *)facs, 0, sizeof(acpi_facs_t));
+
+ memcpy(facs->signature, "FACS", 4);
+ facs->length = sizeof(acpi_facs_t);
+ facs->hardware_signature = 0;
+ facs->firmware_waking_vector = 0;
+ facs->global_lock = 0;
+ facs->flags = 0;
+ facs->x_firmware_waking_vector_l = 0;
+ facs->x_firmware_waking_vector_h = 0;
+ facs->version = 1; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */
+}
+
+static void acpi_write_rsdt(acpi_rsdt_t *rsdt, char *oem_id, char *oem_table_id)
+{
+ acpi_header_t *header = &(rsdt->header);
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "RSDT", 4);
+ memcpy(header->oem_id, oem_id, 6);
+ memcpy(header->oem_table_id, oem_table_id, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->length = sizeof(acpi_rsdt_t);
+ header->revision = 1; /* ACPI 1.0/2.0/3.0/4.0: 1 */
+
+ /* Entries are filled in later, we come with an empty set. */
+
+ /* Fix checksum. */
+ header->checksum = acpi_checksum((void *)rsdt, sizeof(acpi_rsdt_t));
+}
+
+static void acpi_write_xsdt(acpi_xsdt_t *xsdt, char *oem_id, char *oem_table_id)
+{
+ acpi_header_t *header = &(xsdt->header);
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "XSDT", 4);
+ memcpy(header->oem_id, oem_id, 6);
+ memcpy(header->oem_table_id, oem_table_id, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->length = sizeof(acpi_xsdt_t);
+ header->revision = 1; /* ACPI 1.0: N/A, 2.0/3.0/4.0: 1 */
+
+ /* Entries are filled in later, we come with an empty set. */
+
+ /* Fix checksum. */
+ header->checksum = acpi_checksum((void *)xsdt, sizeof(acpi_xsdt_t));
+}
+
+static void acpi_write_rsdp(acpi_rsdp_t *rsdp, acpi_rsdt_t *rsdt,
+ acpi_xsdt_t *xsdt, char *oem_id)
+{
+ memset(rsdp, 0, sizeof(acpi_rsdp_t));
+
+ memcpy(rsdp->signature, RSDP_SIG, 8);
+ memcpy(rsdp->oem_id, oem_id, 6);
+
+ rsdp->length = sizeof(acpi_rsdp_t);
+ rsdp->rsdt_address = (uintptr_t)rsdt;
+
+ /*
+ * Revision: ACPI 1.0: 0, ACPI 2.0/3.0/4.0: 2.
+ *
+ * Some OSes expect an XSDT to be present for RSD PTR revisions >= 2.
+ * If we don't have an ACPI XSDT, force ACPI 1.0 (and thus RSD PTR
+ * revision 0).
+ */
+ if (xsdt == NULL) {
+ rsdp->revision = 0;
+ } else {
+ rsdp->xsdt_address = (u64)(uintptr_t)xsdt;
+ rsdp->revision = 2;
+ }
+
+ /* Calculate checksums. */
+ rsdp->checksum = acpi_checksum((void *)rsdp, 20);
+ rsdp->ext_checksum = acpi_checksum((void *)rsdp, sizeof(acpi_rsdp_t));
+}
+
+unsigned long acpi_create_hest_error_source(acpi_hest_t *hest, acpi_hest_esd_t *esd, u16 type, void *data, u16 data_len)
+{
+ acpi_header_t *header = &(hest->header);
+ acpi_hest_hen_t *hen;
+ void *pos;
+ u16 len;
+
+ pos = esd;
+ memset(pos, 0, sizeof(acpi_hest_esd_t));
+ len = 0;
+ esd->type = type; /* MCE */
+ esd->source_id = hest->error_source_count;
+ esd->flags = 0; /* FIRMWARE_FIRST */
+ esd->enabled = 1;
+ esd->prealloc_erecords = 1;
+ esd->max_section_per_record = 0x1;
+
+ len += sizeof(acpi_hest_esd_t);
+ pos = esd + 1;
+
+ switch (type) {
+ case 0: /* MCE */
+ break;
+ case 1: /* CMC */
+ hen = (acpi_hest_hen_t *) (pos);
+ memset(pos, 0, sizeof(acpi_hest_hen_t));
+ hen->type = 3; /* SCI? */
+ hen->length = sizeof(acpi_hest_hen_t);
+ hen->conf_we = 0; /* Configuration Write Enable. */
+ hen->poll_interval = 0;
+ hen->vector = 0;
+ hen->sw2poll_threshold_val = 0;
+ hen->sw2poll_threshold_win = 0;
+ hen->error_threshold_val = 0;
+ hen->error_threshold_win = 0;
+ len += sizeof(acpi_hest_hen_t);
+ pos = hen + 1;
+ break;
+ case 2: /* NMI */
+ case 6: /* AER Root Port */
+ case 7: /* AER Endpoint */
+ case 8: /* AER Bridge */
+ case 9: /* Generic Hardware Error Source. */
+ /* TODO: */
+ break;
+ default:
+ printk(BIOS_DEBUG, "Invalid type of Error Source.");
+ break;
+ }
+ hest->error_source_count ++;
+
+ memcpy(pos, data, data_len);
+ len += data_len;
+ header->length += len;
+
+ return len;
+}
+
+/* ACPI 4.0 */
+void acpi_write_hest(acpi_hest_t *hest,
+ unsigned long (*acpi_fill_hest)(acpi_hest_t *hest))
+{
+ acpi_header_t *header = &(hest->header);
+
+ memset(hest, 0, sizeof(acpi_hest_t));
+
+ memcpy(header->signature, "HEST", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+ header->length += sizeof(acpi_hest_t);
+ header->revision = 1;
+
+ acpi_fill_hest(hest);
+
+ /* Calculate checksums. */
+ header->checksum = acpi_checksum((void *)hest, header->length);
+}
+
+#if IS_ENABLED(CONFIG_COMMON_FADT)
+void acpi_create_fadt(acpi_fadt_t *fadt,acpi_facs_t *facs, void *dsdt)
+{
+ acpi_header_t *header = &(fadt->header);
+
+ memset((void *) fadt, 0, sizeof(acpi_fadt_t));
+ memcpy(header->signature, "FACP", 4);
+ header->length = sizeof(acpi_fadt_t);
+ header->revision = 4;
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+ header->asl_compiler_revision = 0;
+
+ fadt->firmware_ctrl = (unsigned long) facs;
+ fadt->dsdt = (unsigned long) dsdt;
+
+ fadt->x_firmware_ctl_l = (unsigned long)facs;
+ fadt->x_firmware_ctl_h = 0;
+ fadt->x_dsdt_l = (unsigned long)dsdt;
+ fadt->x_dsdt_h = 0;
+
+ if(IS_ENABLED(CONFIG_SYSTEM_TYPE_LAPTOP)) {
+ fadt->preferred_pm_profile = PM_MOBILE;
+ } else {
+ fadt->preferred_pm_profile = PM_DESKTOP;
+ }
+
+ acpi_fill_fadt(fadt);
+
+ header->checksum =
+ acpi_checksum((void *) fadt, header->length);
+}
+#endif
+
+unsigned long __attribute__ ((weak)) fw_cfg_acpi_tables(unsigned long start)
+{
+ return 0;
+}
+
+#define ALIGN_CURRENT current = (ALIGN(current, 16))
+unsigned long write_acpi_tables(unsigned long start)
+{
+ unsigned long current;
+ acpi_rsdp_t *rsdp;
+ acpi_rsdt_t *rsdt;
+ acpi_xsdt_t *xsdt;
+ acpi_fadt_t *fadt;
+ acpi_facs_t *facs;
+ acpi_header_t *slic_file, *slic;
+ acpi_header_t *ssdt;
+ acpi_header_t *dsdt_file, *dsdt;
+ acpi_mcfg_t *mcfg;
+ acpi_tcpa_t *tcpa;
+ acpi_madt_t *madt;
+ struct device *dev;
+ unsigned long fw;
+ size_t slic_size, dsdt_size;
+ char oem_id[6], oem_table_id[8];
+
+ current = start;
+
+ /* Align ACPI tables to 16byte */
+ ALIGN_CURRENT;
+
+ fw = fw_cfg_acpi_tables(current);
+ if (fw)
+ return fw;
+
+#if CONFIG_COMPILE_IN_DSDT
+ extern char _binary_dsdt_aml_start;
+ extern char _binary_dsdt_aml_end;
+ dsdt_file = (acpi_header_t *)&_binary_dsdt_aml_start;
+ dsdt_size = (size_t)(&_binary_dsdt_aml_end - &_binary_dsdt_aml_start);
+#else
+ dsdt_file = cbfs_boot_map_with_leak(
+ CONFIG_CBFS_PREFIX "/dsdt.aml",
+ CBFS_TYPE_RAW, &dsdt_size);
+#endif
+ if (!dsdt_file) {
+ printk(BIOS_ERR, "No DSDT file, skipping ACPI tables\n");
+ return current;
+ }
+
+ if (dsdt_file->length > dsdt_size
+ || dsdt_file->length < sizeof (acpi_header_t)
+ || memcmp(dsdt_file->signature, "DSDT", 4) != 0) {
+ printk(BIOS_ERR, "Invalid DSDT file, skipping ACPI tables\n");
+ return current;
+ }
+
+ slic_file = cbfs_boot_map_with_leak(CONFIG_CBFS_PREFIX "/slic",
+ CBFS_TYPE_RAW, &slic_size);
+ if (slic_file
+ && (slic_file->length > slic_size
+ || slic_file->length < sizeof (acpi_header_t)
+ || memcmp(slic_file->signature, "SLIC", 4) != 0)) {
+ slic_file = 0;
+ }
+
+ if (slic_file) {
+ memcpy(oem_id, slic_file->oem_id, 6);
+ memcpy(oem_table_id, slic_file->oem_table_id, 8);
+ } else {
+ memcpy(oem_id, OEM_ID, 6);
+ memcpy(oem_table_id, ACPI_TABLE_CREATOR, 8);
+ }
+
+ printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start);
+
+ /* We need at least an RSDP and an RSDT Table */
+ rsdp = (acpi_rsdp_t *) current;
+ current += sizeof(acpi_rsdp_t);
+ ALIGN_CURRENT;
+ rsdt = (acpi_rsdt_t *) current;
+ current += sizeof(acpi_rsdt_t);
+ ALIGN_CURRENT;
+ xsdt = (acpi_xsdt_t *) current;
+ current += sizeof(acpi_xsdt_t);
+ ALIGN_CURRENT;
+
+ /* clear all table memory */
+ memset((void *) start, 0, current - start);
+
+ acpi_write_rsdp(rsdp, rsdt, xsdt, oem_id);
+ acpi_write_rsdt(rsdt, oem_id, oem_table_id);
+ acpi_write_xsdt(xsdt, oem_id, oem_table_id);
+
+ printk(BIOS_DEBUG, "ACPI: * FACS\n");
+ facs = (acpi_facs_t *) current;
+ current += sizeof(acpi_facs_t);
+ ALIGN_CURRENT;
+ acpi_create_facs(facs);
+
+ printk(BIOS_DEBUG, "ACPI: * DSDT\n");
+ dsdt = (acpi_header_t *) current;
+ memcpy(dsdt, dsdt_file, sizeof(acpi_header_t));
+ if (dsdt->length >= sizeof(acpi_header_t)) {
+ current += sizeof(acpi_header_t);
+
+ acpigen_set_current((char *) current);
+ for (dev = all_devices; dev; dev = dev->next)
+ if (dev->ops && dev->ops->acpi_inject_dsdt_generator) {
+ dev->ops->acpi_inject_dsdt_generator(dev);
+ }
+ current = (unsigned long) acpigen_get_current();
+ memcpy((char *)current,
+ (char *)dsdt_file + sizeof(acpi_header_t),
+ dsdt->length - sizeof(acpi_header_t));
+ current += dsdt->length - sizeof(acpi_header_t);
+
+ /* (Re)calculate length and checksum. */
+ dsdt->length = current - (unsigned long)dsdt;
+ dsdt->checksum = 0;
+ dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length);
+ }
+
+ ALIGN_CURRENT;
+
+ printk(BIOS_DEBUG, "ACPI: * FADT\n");
+ fadt = (acpi_fadt_t *) current;
+ current += sizeof(acpi_fadt_t);
+ ALIGN_CURRENT;
+
+ acpi_create_fadt(fadt, facs, dsdt);
+ acpi_add_table(rsdp, fadt);
+
+ if (slic_file) {
+ printk(BIOS_DEBUG, "ACPI: * SLIC\n");
+ slic = (acpi_header_t *)current;
+ memcpy(slic, slic_file, slic_file->length);
+ current += slic_file->length;
+ ALIGN_CURRENT;
+ acpi_add_table(rsdp, slic);
+ }
+
+ printk(BIOS_DEBUG, "ACPI: * SSDT\n");
+ ssdt = (acpi_header_t *)current;
+ acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR);
+ if (ssdt->length > sizeof(acpi_header_t)) {
+ current += ssdt->length;
+ acpi_add_table(rsdp, ssdt);
+ ALIGN_CURRENT;
+ }
+
+ printk(BIOS_DEBUG, "ACPI: * MCFG\n");
+ mcfg = (acpi_mcfg_t *) current;
+ acpi_create_mcfg(mcfg);
+ if (mcfg->header.length > sizeof(acpi_mcfg_t)) {
+ current += mcfg->header.length;
+ ALIGN_CURRENT;
+ acpi_add_table(rsdp, mcfg);
+ }
+
+ printk(BIOS_DEBUG, "ACPI: * TCPA\n");
+ tcpa = (acpi_tcpa_t *) current;
+ acpi_create_tcpa(tcpa);
+ if (tcpa->header.length >= sizeof(acpi_tcpa_t)) {
+ current += tcpa->header.length;
+ ALIGN_CURRENT;
+ acpi_add_table(rsdp, tcpa);
+ }
+
+ printk(BIOS_DEBUG, "ACPI: * MADT\n");
+
+ madt = (acpi_madt_t *) current;
+ acpi_create_madt(madt);
+ if (madt->header.length > sizeof(acpi_madt_t)) {
+ current+=madt->header.length;
+ acpi_add_table(rsdp,madt);
+ }
+ ALIGN_CURRENT;
+
+ printk(BIOS_DEBUG, "current = %lx\n", current);
+
+ for (dev = all_devices; dev; dev = dev->next) {
+ if (dev->ops && dev->ops->write_acpi_tables) {
+ current = dev->ops->write_acpi_tables(dev, current, rsdp);
+ ALIGN_CURRENT;
+ }
+ }
+
+ printk(BIOS_INFO, "ACPI: done.\n");
+ return current;
+}
+
+#if CONFIG_HAVE_ACPI_RESUME
+void __attribute__((weak)) mainboard_suspend_resume(void)
+{
+}
+
+void acpi_resume(void *wake_vec)
+{
+#if CONFIG_HAVE_SMI_HANDLER
+ u32 *gnvs_address = cbmem_find(CBMEM_ID_ACPI_GNVS_PTR);
+
+ /* Restore GNVS pointer in SMM if found */
+ if (gnvs_address && *gnvs_address) {
+ printk(BIOS_DEBUG, "Restore GNVS pointer to 0x%08x\n",
+ *gnvs_address);
+ smm_setup_structures((void *)*gnvs_address, NULL, NULL);
+ }
+#endif
+
+ /* Call mainboard resume handler first, if defined. */
+ mainboard_suspend_resume();
+
+ post_code(POST_OS_RESUME);
+ acpi_jump_to_wakeup(wake_vec);
+}
+
+/* This is filled with acpi_is_wakeup() call early in ramstage. */
+int acpi_slp_type = -1;
+
+#if IS_ENABLED(CONFIG_EARLY_CBMEM_INIT)
+int acpi_get_sleep_type(void)
+{
+ struct romstage_handoff *handoff;
+
+ handoff = cbmem_find(CBMEM_ID_ROMSTAGE_INFO);
+
+ if (handoff == NULL) {
+ printk(BIOS_DEBUG, "Unknown boot method, assuming normal.\n");
+ return 0;
+ } else if (handoff->s3_resume) {
+ printk(BIOS_DEBUG, "S3 Resume.\n");
+ return 3;
+ } else {
+ printk(BIOS_DEBUG, "Normal boot.\n");
+ return 0;
+ }
+}
+#endif
+
+static void acpi_handoff_wakeup(void)
+{
+ if (acpi_slp_type < 0)
+ acpi_slp_type = acpi_get_sleep_type();
+}
+
+int acpi_is_wakeup(void)
+{
+ acpi_handoff_wakeup();
+ /* Both resume from S2 and resume from S3 restart at CPU reset */
+ return (acpi_slp_type == 3 || acpi_slp_type == 2);
+}
+
+int acpi_is_wakeup_s3(void)
+{
+ acpi_handoff_wakeup();
+ return (acpi_slp_type == 3);
+}
+
+void acpi_fail_wakeup(void)
+{
+ if (acpi_slp_type == 3 || acpi_slp_type == 2)
+ acpi_slp_type = 0;
+}
+
+void acpi_prepare_resume_backup(void)
+{
+ if (!acpi_s3_resume_allowed())
+ return;
+
+ /* Let's prepare the ACPI S3 Resume area now already, so we can rely on
+ * it being there during reboot time. We don't need the pointer, nor
+ * the result right now. If it fails, ACPI resume will be disabled.
+ */
+
+ if (HIGH_MEMORY_SAVE)
+ cbmem_add(CBMEM_ID_RESUME, HIGH_MEMORY_SAVE);
+}
+
+static acpi_rsdp_t *valid_rsdp(acpi_rsdp_t *rsdp)
+{
+ if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0)
+ return NULL;
+
+ printk(BIOS_DEBUG, "Looking on %p for valid checksum\n", rsdp);
+
+ if (acpi_checksum((void *)rsdp, 20) != 0)
+ return NULL;
+ printk(BIOS_DEBUG, "Checksum 1 passed\n");
+
+ if ((rsdp->revision > 1) && (acpi_checksum((void *)rsdp,
+ rsdp->length) != 0))
+ return NULL;
+ printk(BIOS_DEBUG, "Checksum 2 passed all OK\n");
+
+ return rsdp;
+}
+
+static acpi_rsdp_t *rsdp;
+
+void *acpi_get_wakeup_rsdp(void)
+{
+ return rsdp;
+}
+
+void *acpi_find_wakeup_vector(void)
+{
+ char *p, *end;
+ acpi_rsdt_t *rsdt;
+ acpi_facs_t *facs;
+ acpi_fadt_t *fadt = NULL;
+ void *wake_vec;
+ int i;
+
+ rsdp = NULL;
+
+ if (!acpi_is_wakeup())
+ return NULL;
+
+ printk(BIOS_DEBUG, "Trying to find the wakeup vector...\n");
+
+ /* Find RSDP. */
+ for (p = (char *)0xe0000; p < (char *)0xfffff; p += 16) {
+ if ((rsdp = valid_rsdp((acpi_rsdp_t *)p)))
+ break;
+ }
+
+ if (rsdp == NULL)
+ return NULL;
+
+ printk(BIOS_DEBUG, "RSDP found at %p\n", rsdp);
+ rsdt = (acpi_rsdt_t *) rsdp->rsdt_address;
+
+ end = (char *)rsdt + rsdt->header.length;
+ printk(BIOS_DEBUG, "RSDT found at %p ends at %p\n", rsdt, end);
+
+ for (i = 0; ((char *)&rsdt->entry[i]) < end; i++) {
+ fadt = (acpi_fadt_t *)rsdt->entry[i];
+ if (strncmp((char *)fadt, "FACP", 4) == 0)
+ break;
+ fadt = NULL;
+ }
+
+ if (fadt == NULL)
+ return NULL;
+
+ printk(BIOS_DEBUG, "FADT found at %p\n", fadt);
+ facs = (acpi_facs_t *)fadt->firmware_ctrl;
+
+ if (facs == NULL) {
+ printk(BIOS_DEBUG, "No FACS found, wake up from S3 not "
+ "possible.\n");
+ return NULL;
+ }
+
+ printk(BIOS_DEBUG, "FACS found at %p\n", facs);
+ wake_vec = (void *)facs->firmware_waking_vector;
+ printk(BIOS_DEBUG, "OS waking vector is %p\n", wake_vec);
+
+ return wake_vec;
+}
+
+#if CONFIG_SMP
+extern char *lowmem_backup;
+extern char *lowmem_backup_ptr;
+extern int lowmem_backup_size;
+#endif
+
+#define WAKEUP_BASE 0x600
+
+void (*acpi_do_wakeup)(u32 vector, u32 backup_source, u32 backup_target,
+ u32 backup_size) asmlinkage = (void *)WAKEUP_BASE;
+
+extern unsigned char __wakeup;
+extern unsigned int __wakeup_size;
+
+void acpi_jump_to_wakeup(void *vector)
+{
+ u32 acpi_backup_memory = 0;
+
+ if (HIGH_MEMORY_SAVE && acpi_s3_resume_allowed()) {
+ acpi_backup_memory = (u32)cbmem_find(CBMEM_ID_RESUME);
+
+ if (!acpi_backup_memory) {
+ printk(BIOS_WARNING, "ACPI: Backup memory missing. "
+ "No S3 resume.\n");
+ return;
+ }
+ }
+
+#if CONFIG_SMP
+ // FIXME: This should go into the ACPI backup memory, too. No pork sausages.
+ /*
+ * Just restore the SMP trampoline and continue with wakeup on
+ * assembly level.
+ */
+ memcpy(lowmem_backup_ptr, lowmem_backup, lowmem_backup_size);
+#endif
+
+ /* Copy wakeup trampoline in place. */
+ memcpy((void *)WAKEUP_BASE, &__wakeup, __wakeup_size);
+
+ timestamp_add_now(TS_ACPI_WAKE_JUMP);
+
+ acpi_do_wakeup((u32)vector, acpi_backup_memory, CONFIG_RAMBASE,
+ HIGH_MEMORY_SAVE);
+}
+#endif
+
+void acpi_save_gnvs(u32 gnvs_address)
+{
+ u32 *gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS_PTR, sizeof(*gnvs));
+ if (gnvs)
+ *gnvs = gnvs_address;
+}
diff --git a/src/arch/x86/acpigen.c b/src/arch/x86/acpigen.c
new file mode 100644
index 0000000..3aa823c
--- /dev/null
+++ b/src/arch/x86/acpigen.c
@@ -0,0 +1,728 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 Rudolf Marek <r.marek at assembler.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+/* How much nesting do we support? */
+#define ACPIGEN_LENSTACK_SIZE 10
+
+/*
+ * If you need to change this, change acpigen_write_f and
+ * acpigen_pop_len
+ */
+
+#define ACPIGEN_MAXLEN 0xfff
+
+#include <string.h>
+#include <arch/acpigen.h>
+#include <console/console.h>
+#include <device/device.h>
+
+static char *gencurrent;
+
+char *len_stack[ACPIGEN_LENSTACK_SIZE];
+int ltop = 0;
+
+void acpigen_write_len_f(void)
+{
+ ASSERT(ltop < (ACPIGEN_LENSTACK_SIZE - 1))
+ len_stack[ltop++] = gencurrent;
+ acpigen_emit_byte(0);
+ acpigen_emit_byte(0);
+}
+
+void acpigen_pop_len(void)
+{
+ int len;
+ ASSERT(ltop > 0)
+ char *p = len_stack[--ltop];
+ len = gencurrent - p;
+ ASSERT(len <= ACPIGEN_MAXLEN)
+ /* generate store length for 0xfff max */
+ p[0] = (0x40 | (len & 0xf));
+ p[1] = (len >> 4 & 0xff);
+
+}
+
+void acpigen_set_current(char *curr)
+{
+ gencurrent = curr;
+}
+
+char *acpigen_get_current(void)
+{
+ return gencurrent;
+}
+
+void acpigen_emit_byte(unsigned char b)
+{
+ (*gencurrent++) = b;
+}
+
+void acpigen_write_package(int nr_el)
+{
+ /* package op */
+ acpigen_emit_byte(0x12);
+ acpigen_write_len_f();
+ acpigen_emit_byte(nr_el);
+}
+
+void acpigen_write_byte(unsigned int data)
+{
+ /* byte op */
+ acpigen_emit_byte(0xa);
+ acpigen_emit_byte(data & 0xff);
+}
+
+void acpigen_write_dword(unsigned int data)
+{
+ /* dword op */
+ acpigen_emit_byte(0xc);
+ acpigen_emit_byte(data & 0xff);
+ acpigen_emit_byte((data >> 8) & 0xff);
+ acpigen_emit_byte((data >> 16) & 0xff);
+ acpigen_emit_byte((data >> 24) & 0xff);
+}
+
+void acpigen_write_qword(uint64_t data)
+{
+ /* qword op */
+ acpigen_emit_byte(0xe);
+ acpigen_emit_byte(data & 0xff);
+ acpigen_emit_byte((data >> 8) & 0xff);
+ acpigen_emit_byte((data >> 16) & 0xff);
+ acpigen_emit_byte((data >> 24) & 0xff);
+ acpigen_emit_byte((data >> 32) & 0xff);
+ acpigen_emit_byte((data >> 40) & 0xff);
+ acpigen_emit_byte((data >> 48) & 0xff);
+ acpigen_emit_byte((data >> 56) & 0xff);
+}
+
+void acpigen_write_name_byte(const char *name, uint8_t val)
+{
+ acpigen_write_name(name);
+ acpigen_write_byte(val);
+}
+
+void acpigen_write_name_dword(const char *name, uint32_t val)
+{
+ acpigen_write_name(name);
+ acpigen_write_dword(val);
+}
+
+void acpigen_write_name_qword(const char *name, uint64_t val)
+{
+ acpigen_write_name(name);
+ acpigen_write_qword(val);
+}
+
+void acpigen_emit_stream(const char *data, int size)
+{
+ int i;
+ for (i = 0; i < size; i++) {
+ acpigen_emit_byte(data[i]);
+ }
+}
+
+/*
+ * The naming conventions for ACPI namespace names are a bit tricky as
+ * each element has to be 4 chars wide (»All names are a fixed 32 bits.«)
+ * and »By convention, when an ASL compiler pads a name shorter than 4
+ * characters, it is done so with trailing underscores (‘_’).«.
+ *
+ * Check sections 5.3, 18.2.2 and 18.4 of ACPI spec 3.0 for details.
+ */
+
+static void acpigen_emit_simple_namestring(const char *name) {
+ int i;
+ char ud[] = "____";
+ for (i = 0; i < 4; i++) {
+ if ((name[i] == '\0') || (name[i] == '.')) {
+ acpigen_emit_stream(ud, 4 - i);
+ break;
+ } else {
+ acpigen_emit_byte(name[i]);
+ }
+ }
+}
+
+static void acpigen_emit_double_namestring(const char *name, int dotpos) {
+ /* mark dual name prefix */
+ acpigen_emit_byte(0x2e);
+ acpigen_emit_simple_namestring(name);
+ acpigen_emit_simple_namestring(&name[dotpos + 1]);
+}
+
+static void acpigen_emit_multi_namestring(const char *name) {
+ int count = 0;
+ unsigned char *pathlen;
+ /* mark multi name prefix */
+ acpigen_emit_byte(0x2f);
+ acpigen_emit_byte(0x0);
+ pathlen = ((unsigned char *) acpigen_get_current()) - 1;
+
+ while (name[0] != '\0') {
+ acpigen_emit_simple_namestring(name);
+ /* find end or next entity */
+ while ((name[0] != '.') && (name[0] != '\0'))
+ name++;
+ /* forward to next */
+ if (name[0] == '.')
+ name++;
+ count++;
+ }
+
+ pathlen[0] = count;
+}
+
+
+void acpigen_emit_namestring(const char *namepath) {
+ int dotcount = 0, i;
+ int dotpos = 0;
+
+ /* We can start with a '\'. */
+ if (namepath[0] == '\\') {
+ acpigen_emit_byte('\\');
+ namepath++;
+ }
+
+ /* And there can be any number of '^' */
+ while (namepath[0] == '^') {
+ acpigen_emit_byte('^');
+ namepath++;
+ }
+
+ /* If we have only \\ or only ^...^. Then we need to put a null
+ name (0x00). */
+ if(namepath[0] == '\0') {
+ acpigen_emit_byte(0x00);
+ return;
+ }
+
+ i = 0;
+ while (namepath[i] != '\0') {
+ if (namepath[i] == '.') {
+ dotcount++;
+ dotpos = i;
+ }
+ i++;
+ }
+
+ if (dotcount == 0) {
+ acpigen_emit_simple_namestring(namepath);
+ } else if (dotcount == 1) {
+ acpigen_emit_double_namestring(namepath, dotpos);
+ } else {
+ acpigen_emit_multi_namestring(namepath);
+ }
+}
+
+void acpigen_write_name(const char *name)
+{
+ /* name op */
+ acpigen_emit_byte(0x8);
+ acpigen_emit_namestring(name);
+}
+
+void acpigen_write_scope(const char *name)
+{
+ /* scope op */
+ acpigen_emit_byte(0x10);
+ acpigen_write_len_f();
+ acpigen_emit_namestring(name);
+}
+
+void acpigen_write_processor(u8 cpuindex, u32 pblock_addr, u8 pblock_len)
+{
+/*
+ Processor (\_PR.CPUcpuindex, cpuindex, pblock_addr, pblock_len)
+ {
+*/
+ char pscope[16];
+ /* processor op */
+ acpigen_emit_byte(0x5b);
+ acpigen_emit_byte(0x83);
+ acpigen_write_len_f();
+
+ snprintf(pscope, sizeof (pscope),
+ "\\_PR.CP%02d", (unsigned int) cpuindex);
+ acpigen_emit_namestring(pscope);
+ acpigen_emit_byte(cpuindex);
+ acpigen_emit_byte(pblock_addr & 0xff);
+ acpigen_emit_byte((pblock_addr >> 8) & 0xff);
+ acpigen_emit_byte((pblock_addr >> 16) & 0xff);
+ acpigen_emit_byte((pblock_addr >> 24) & 0xff);
+ acpigen_emit_byte(pblock_len);
+}
+
+void acpigen_write_empty_PCT(void)
+{
+/*
+ Name (_PCT, Package (0x02)
+ {
+ ResourceTemplate ()
+ {
+ Register (FFixedHW,
+ 0x00, // Bit Width
+ 0x00, // Bit Offset
+ 0x0000000000000000, // Address
+ ,)
+ },
+
+ ResourceTemplate ()
+ {
+ Register (FFixedHW,
+ 0x00, // Bit Width
+ 0x00, // Bit Offset
+ 0x0000000000000000, // Address
+ ,)
+ }
+ })
+*/
+ static char stream[] = {
+ 0x08, 0x5F, 0x50, 0x43, 0x54, 0x12, 0x2C, /* 00000030 "0._PCT.," */
+ 0x02, 0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, /* 00000038 "........" */
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00000040 "........" */
+ 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14, /* 00000048 "....y..." */
+ 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F, 0x00, 0x00, /* 00000050 "........" */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00000058 "........" */
+ 0x00, 0x79, 0x00
+ };
+ acpigen_emit_stream(stream, ARRAY_SIZE(stream));
+}
+
+void acpigen_write_empty_PTC(void)
+{
+/*
+ Name (_PTC, Package (0x02)
+ {
+ ResourceTemplate ()
+ {
+ Register (FFixedHW,
+ 0x00, // Bit Width
+ 0x00, // Bit Offset
+ 0x0000000000000000, // Address
+ ,)
+ },
+
+ ResourceTemplate ()
+ {
+ Register (FFixedHW,
+ 0x00, // Bit Width
+ 0x00, // Bit Offset
+ 0x0000000000000000, // Address
+ ,)
+ }
+ })
+*/
+ acpi_addr_t addr = {
+ .space_id = ACPI_ADDRESS_SPACE_FIXED,
+ .bit_width = 0,
+ .bit_offset = 0,
+ {
+ .resv = 0
+ },
+ .addrl = 0,
+ .addrh = 0,
+ };
+
+ acpigen_write_name("_PTC");
+ acpigen_write_package(2);
+
+ /* ControlRegister */
+ acpigen_write_resourcetemplate_header();
+ acpigen_write_register(&addr);
+ acpigen_write_resourcetemplate_footer();
+
+ /* StatusRegister */
+ acpigen_write_resourcetemplate_header();
+ acpigen_write_register(&addr);
+ acpigen_write_resourcetemplate_footer();
+
+ acpigen_pop_len();
+}
+
+void acpigen_write_method(const char *name, int nargs)
+{
+ /* method op */
+ acpigen_emit_byte(0x14);
+ acpigen_write_len_f();
+ acpigen_emit_namestring(name);
+ acpigen_emit_byte(nargs & 7);
+}
+
+void acpigen_write_device(const char *name)
+{
+ /* method op */
+ acpigen_emit_byte(0x5b);
+ acpigen_emit_byte(0x82);
+ acpigen_write_len_f();
+ acpigen_emit_namestring(name);
+}
+
+/*
+ * Generates a func with max supported P-states.
+ */
+void acpigen_write_PPC(u8 nr)
+{
+/*
+ Method (_PPC, 0, NotSerialized)
+ {
+ Return (nr)
+ }
+*/
+ acpigen_write_method("_PPC", 0);
+ /* return */
+ acpigen_emit_byte(0xa4);
+ /* arg */
+ acpigen_write_byte(nr);
+ acpigen_pop_len();
+}
+
+/*
+ * Generates a func with max supported P-states saved
+ * in the variable PPCM.
+ */
+void acpigen_write_PPC_NVS(void)
+{
+/*
+ Method (_PPC, 0, NotSerialized)
+ {
+ Return (PPCM)
+ }
+*/
+ acpigen_write_method("_PPC", 0);
+ /* return */
+ acpigen_emit_byte(0xa4);
+ /* arg */
+ acpigen_emit_namestring("PPCM");
+ acpigen_pop_len();
+}
+
+void acpigen_write_TPC(const char *gnvs_tpc_limit)
+{
+/*
+ // Sample _TPC method
+ Method (_TPC, 0, NotSerialized)
+ {
+ Return (\TLVL)
+ }
+ */
+ acpigen_write_method("_TPC", 0);
+ acpigen_emit_byte(0xa4); /* ReturnOp */
+ acpigen_emit_namestring(gnvs_tpc_limit);
+ acpigen_pop_len();
+}
+
+void acpigen_write_PSS_package(u32 coreFreq, u32 power, u32 transLat,
+ u32 busmLat, u32 control, u32 status)
+{
+ acpigen_write_package(6);
+ acpigen_write_dword(coreFreq);
+ acpigen_write_dword(power);
+ acpigen_write_dword(transLat);
+ acpigen_write_dword(busmLat);
+ acpigen_write_dword(control);
+ acpigen_write_dword(status);
+ acpigen_pop_len();
+
+ printk(BIOS_DEBUG, "PSS: %uMHz power %u control 0x%x status 0x%x\n",
+ coreFreq, power, control, status);
+}
+
+void acpigen_write_PSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
+{
+ acpigen_write_name("_PSD");
+ acpigen_write_package(1);
+ acpigen_write_package(5);
+ acpigen_write_byte(5); // 5 values
+ acpigen_write_byte(0); // revision 0
+ acpigen_write_dword(domain);
+ acpigen_write_dword(coordtype);
+ acpigen_write_dword(numprocs);
+ acpigen_pop_len();
+ acpigen_pop_len();
+}
+
+void acpigen_write_CST_package_entry(acpi_cstate_t *cstate)
+{
+ acpigen_write_package(4);
+ acpigen_write_resourcetemplate_header();
+ acpigen_write_register(&cstate->resource);
+ acpigen_write_resourcetemplate_footer();
+ acpigen_write_dword(cstate->ctype);
+ acpigen_write_dword(cstate->latency);
+ acpigen_write_dword(cstate->power);
+ acpigen_pop_len();
+}
+
+void acpigen_write_CST_package(acpi_cstate_t *cstate, int nentries)
+{
+ int i;
+ acpigen_write_name("_CST");
+ acpigen_write_package(nentries+1);
+ acpigen_write_dword(nentries);
+
+ for (i = 0; i < nentries; i++)
+ acpigen_write_CST_package_entry(cstate + i);
+
+ acpigen_pop_len();
+}
+
+void acpigen_write_TSS_package(int entries, acpi_tstate_t *tstate_list)
+{
+/*
+ Sample _TSS package with 100% and 50% duty cycles
+ Name (_TSS, Package (0x02)
+ {
+ Package(){100, 1000, 0, 0x00, 0)
+ Package(){50, 520, 0, 0x18, 0)
+ })
+ */
+ int i;
+ acpi_tstate_t *tstate = tstate_list;
+
+ acpigen_write_name("_TSS");
+ acpigen_write_package(entries);
+
+ for (i = 0; i < entries; i++) {
+ acpigen_write_package(5);
+ acpigen_write_dword(tstate->percent);
+ acpigen_write_dword(tstate->power);
+ acpigen_write_dword(tstate->latency);
+ acpigen_write_dword(tstate->control);
+ acpigen_write_dword(tstate->status);
+ acpigen_pop_len();
+ tstate++;
+ }
+
+ acpigen_pop_len();
+}
+
+void acpigen_write_TSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
+{
+ acpigen_write_name("_TSD");
+ acpigen_write_package(1);
+ acpigen_write_package(5);
+ acpigen_write_byte(5); // 5 values
+ acpigen_write_byte(0); // revision 0
+ acpigen_write_dword(domain);
+ acpigen_write_dword(coordtype);
+ acpigen_write_dword(numprocs);
+ acpigen_pop_len();
+ acpigen_pop_len();
+}
+
+
+
+void acpigen_write_mem32fixed(int readwrite, u32 base, u32 size)
+{
+ /*
+ * acpi 4.0 section 6.4.3.4: 32-Bit Fixed Memory Range Descriptor
+ * Byte 0:
+ * Bit7 : 1 => big item
+ * Bit6-0: 0000110 (0x6) => 32-bit fixed memory
+ */
+ acpigen_emit_byte(0x86);
+ /* Byte 1+2: length (0x0009) */
+ acpigen_emit_byte(0x09);
+ acpigen_emit_byte(0x00);
+ /* bit1-7 are ignored */
+ acpigen_emit_byte(readwrite ? 0x01 : 0x00);
+ acpigen_emit_byte(base & 0xff);
+ acpigen_emit_byte((base >> 8) & 0xff);
+ acpigen_emit_byte((base >> 16) & 0xff);
+ acpigen_emit_byte((base >> 24) & 0xff);
+ acpigen_emit_byte(size & 0xff);
+ acpigen_emit_byte((size >> 8) & 0xff);
+ acpigen_emit_byte((size >> 16) & 0xff);
+ acpigen_emit_byte((size >> 24) & 0xff);
+}
+
+void acpigen_write_register(acpi_addr_t *addr)
+{
+ acpigen_emit_byte(0x82); /* Register Descriptor */
+ acpigen_emit_byte(0x0c); /* Register Length 7:0 */
+ acpigen_emit_byte(0x00); /* Register Length 15:8 */
+ acpigen_emit_byte(addr->space_id); /* Address Space ID */
+ acpigen_emit_byte(addr->bit_width); /* Register Bit Width */
+ acpigen_emit_byte(addr->bit_offset); /* Register Bit Offset */
+ acpigen_emit_byte(addr->resv); /* Register Access Size */
+ acpigen_emit_byte(addr->addrl & 0xff); /* Register Address Low */
+ acpigen_emit_byte((addr->addrl >> 8) & 0xff);
+ acpigen_emit_byte((addr->addrl >> 16) & 0xff);
+ acpigen_emit_byte((addr->addrl >> 24) & 0xff);
+ acpigen_emit_byte(addr->addrh & 0xff); /* Register Address High */
+ acpigen_emit_byte((addr->addrh >> 8) & 0xff);
+ acpigen_emit_byte((addr->addrh >> 16) & 0xff);
+ acpigen_emit_byte((addr->addrh >> 24) & 0xff);
+}
+
+void acpigen_write_irq(u16 mask)
+{
+ /*
+ * acpi 3.0b section 6.4.2.1: IRQ Descriptor
+ * Byte 0:
+ * Bit7 : 0 => small item
+ * Bit6-3: 0100 (0x4) => IRQ port descriptor
+ * Bit2-0: 010 (0x2) => 2 Bytes long
+ */
+ acpigen_emit_byte(0x22);
+ acpigen_emit_byte(mask & 0xff);
+ acpigen_emit_byte((mask >> 8) & 0xff);
+}
+
+void acpigen_write_io16(u16 min, u16 max, u8 align, u8 len, u8 decode16)
+{
+ /*
+ * acpi 4.0 section 6.4.2.6: I/O Port Descriptor
+ * Byte 0:
+ * Bit7 : 0 => small item
+ * Bit6-3: 1000 (0x8) => I/O port descriptor
+ * Bit2-0: 111 (0x7) => 7 Bytes long
+ */
+ acpigen_emit_byte(0x47);
+ /* Does the device decode all 16 or just 10 bits? */
+ /* bit1-7 are ignored */
+ acpigen_emit_byte(decode16 ? 0x01 : 0x00);
+ /* minimum base address the device may be configured for */
+ acpigen_emit_byte(min & 0xff);
+ acpigen_emit_byte((min >> 8) & 0xff);
+ /* maximum base address the device may be configured for */
+ acpigen_emit_byte(max & 0xff);
+ acpigen_emit_byte((max >> 8) & 0xff);
+ /* alignment for min base */
+ acpigen_emit_byte(align & 0xff);
+ acpigen_emit_byte(len & 0xff);
+}
+
+void acpigen_write_resourcetemplate_header(void)
+{
+ /*
+ * A ResourceTemplate() is a Buffer() with a
+ * (Byte|Word|DWord) containing the length, followed by one or more
+ * resource items, terminated by the end tag.
+ * (small item 0xf, len 1)
+ */
+ acpigen_emit_byte(0x11); /* Buffer opcode */
+ acpigen_write_len_f();
+ acpigen_emit_byte(0x0b); /* Word opcode */
+ len_stack[ltop++] = acpigen_get_current();
+ acpigen_emit_byte(0x00);
+ acpigen_emit_byte(0x00);
+}
+
+void acpigen_write_resourcetemplate_footer(void)
+{
+ char *p = len_stack[--ltop];
+ int len;
+ /*
+ * end tag (acpi 4.0 Section 6.4.2.8)
+ * 0x79 <checksum>
+ * 0x00 is treated as a good checksum according to the spec
+ * and is what iasl generates.
+ */
+ acpigen_emit_byte(0x79);
+ acpigen_emit_byte(0x00);
+
+ len = gencurrent - p;
+
+ /* patch len word */
+ p[0] = len & 0xff;
+ p[1] = (len >> 8) & 0xff;
+ /* patch len field */
+ acpigen_pop_len();
+}
+
+static void acpigen_add_mainboard_rsvd_mem32(void *gp, struct device *dev,
+ struct resource *res)
+{
+ acpigen_write_mem32fixed(0, res->base, res->size);
+}
+
+static void acpigen_add_mainboard_rsvd_io(void *gp, struct device *dev,
+ struct resource *res)
+{
+ resource_t base = res->base;
+ resource_t size = res->size;
+ while (size > 0) {
+ resource_t sz = size > 255 ? 255 : size;
+ acpigen_write_io16(base, base, 0, sz, 1);
+ size -= sz;
+ base += sz;
+ }
+}
+
+void acpigen_write_mainboard_resource_template(void)
+{
+ acpigen_write_resourcetemplate_header();
+
+ /* Add reserved memory ranges. */
+ search_global_resources(
+ IORESOURCE_MEM | IORESOURCE_RESERVE,
+ IORESOURCE_MEM | IORESOURCE_RESERVE,
+ acpigen_add_mainboard_rsvd_mem32, 0);
+
+ /* Add reserved io ranges. */
+ search_global_resources(
+ IORESOURCE_IO | IORESOURCE_RESERVE,
+ IORESOURCE_IO | IORESOURCE_RESERVE,
+ acpigen_add_mainboard_rsvd_io, 0);
+
+ acpigen_write_resourcetemplate_footer();
+}
+
+void acpigen_write_mainboard_resources(const char *scope, const char *name)
+{
+ acpigen_write_scope(scope);
+ acpigen_write_name(name);
+ acpigen_write_mainboard_resource_template();
+ acpigen_pop_len();
+}
+
+static int hex2bin(const char c)
+{
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return c - '0';
+}
+
+void acpigen_emit_eisaid(const char *eisaid)
+{
+ u32 compact = 0;
+
+ /* Clamping individual values would be better but
+ there is a disagreement over what is a valid
+ EISA id, so accept anything and don't clamp,
+ parent code should create a valid EISAid.
+ */
+ compact |= (eisaid[0] - 'A' + 1) << 26;
+ compact |= (eisaid[1] - 'A' + 1) << 21;
+ compact |= (eisaid[2] - 'A' + 1) << 16;
+ compact |= hex2bin(eisaid[3]) << 12;
+ compact |= hex2bin(eisaid[4]) << 8;
+ compact |= hex2bin(eisaid[5]) << 4;
+ compact |= hex2bin(eisaid[6]);
+
+ acpigen_emit_byte(0xc);
+ acpigen_emit_byte((compact >> 24) & 0xff);
+ acpigen_emit_byte((compact >> 16) & 0xff);
+ acpigen_emit_byte((compact >> 8) & 0xff);
+ acpigen_emit_byte(compact & 0xff);
+}
diff --git a/src/arch/x86/boot.c b/src/arch/x86/boot.c
new file mode 100644
index 0000000..7eb87fb
--- /dev/null
+++ b/src/arch/x86/boot.c
@@ -0,0 +1,210 @@
+#include <console/console.h>
+#include <arch/stages.h>
+#include <program_loading.h>
+#include <ip_checksum.h>
+#include <string.h>
+#include <symbols.h>
+
+/* When the ramstage is relocatable the elf loading ensures an elf image cannot
+ * be loaded over the ramstage code. */
+static void jmp_payload_no_bounce_buffer(void *entry)
+{
+ /* Jump to kernel */
+ __asm__ __volatile__(
+ " cld \n\t"
+ /* Now jump to the loaded image */
+ " call *%0\n\t"
+
+ /* The loaded image returned? */
+ " cli \n\t"
+ " cld \n\t"
+
+ ::
+ "r" (entry)
+ );
+}
+
+static void jmp_payload(void *entry, unsigned long buffer, unsigned long size)
+{
+ unsigned long lb_start, lb_size;
+
+ lb_start = (unsigned long)&_program;
+ lb_size = _program_size;
+
+ printk(BIOS_SPEW, "entry = 0x%08lx\n", (unsigned long)entry);
+ printk(BIOS_SPEW, "lb_start = 0x%08lx\n", lb_start);
+ printk(BIOS_SPEW, "lb_size = 0x%08lx\n", lb_size);
+ printk(BIOS_SPEW, "buffer = 0x%08lx\n", buffer);
+
+ /* Jump to kernel */
+ __asm__ __volatile__(
+ " cld \n\t"
+#ifdef __x86_64__
+ /* switch back to 32-bit mode */
+ " push %4\n\t"
+ " push %3\n\t"
+ " push %2\n\t"
+ " push %1\n\t"
+ " push %0\n\t"
+
+ ".intel_syntax noprefix\n\t"
+ /* use iret to switch to 32-bit code segment */
+ " xor rax,rax\n\t"
+ " mov ax, ss\n\t"
+ " push rax\n\t"
+ " mov rax, rsp\n\t"
+ " add rax, 8\n\t"
+ " push rax\n\t"
+ " pushfq\n\t"
+ " push 0x10\n\t"
+ " lea rax,[rip+3]\n\t"
+ " push rax\n\t"
+ " iretq\n\t"
+ ".code32\n\t"
+ /* disable paging */
+ " mov eax, cr0\n\t"
+ " btc eax, 31\n\t"
+ " mov cr0, eax\n\t"
+ /* disable long mode */
+ " mov ecx, 0xC0000080\n\t"
+ " rdmsr\n\t"
+ " btc eax, 8\n\t"
+ " wrmsr\n\t"
+
+ " pop eax\n\t"
+ " add esp, 4\n\t"
+ " pop ebx\n\t"
+ " add esp, 4\n\t"
+ " pop ecx\n\t"
+
+ " add esp, 4\n\t"
+ " pop edx\n\t"
+ " add esp, 4\n\t"
+ " pop esi\n\t"
+ " add esp, 4\n\t"
+
+ ".att_syntax prefix\n\t"
+#endif
+
+ /* Save the callee save registers... */
+ " pushl %%esi\n\t"
+ " pushl %%edi\n\t"
+ " pushl %%ebx\n\t"
+ /* Save the parameters I was passed */
+#ifdef __x86_64__
+ " pushl $0\n\t" /* 20 adjust */
+ " pushl %%eax\n\t" /* 16 lb_start */
+ " pushl %%ebx\n\t" /* 12 buffer */
+ " pushl %%ecx\n\t" /* 8 lb_size */
+ " pushl %%edx\n\t" /* 4 entry */
+ " pushl %%esi\n\t" /* 0 elf_boot_notes */
+#else
+ " pushl $0\n\t" /* 20 adjust */
+ " pushl %0\n\t" /* 16 lb_start */
+ " pushl %1\n\t" /* 12 buffer */
+ " pushl %2\n\t" /* 8 lb_size */
+ " pushl %3\n\t" /* 4 entry */
+ " pushl %4\n\t" /* 0 elf_boot_notes */
+
+#endif
+ /* Compute the adjustment */
+ " xorl %%eax, %%eax\n\t"
+ " subl 16(%%esp), %%eax\n\t"
+ " addl 12(%%esp), %%eax\n\t"
+ " addl 8(%%esp), %%eax\n\t"
+ " movl %%eax, 20(%%esp)\n\t"
+ /* Place a copy of coreboot in its new location */
+ /* Move ``longs'' the coreboot size is 4 byte aligned */
+ " movl 12(%%esp), %%edi\n\t"
+ " addl 8(%%esp), %%edi\n\t"
+ " movl 16(%%esp), %%esi\n\t"
+ " movl 8(%%esp), %%ecx\n\n"
+ " shrl $2, %%ecx\n\t"
+ " rep movsl\n\t"
+
+ /* Adjust the stack pointer to point into the new coreboot image */
+ " addl 20(%%esp), %%esp\n\t"
+ /* Adjust the instruction pointer to point into the new coreboot image */
+ " movl $1f, %%eax\n\t"
+ " addl 20(%%esp), %%eax\n\t"
+ " jmp *%%eax\n\t"
+ "1: \n\t"
+
+ /* Copy the coreboot bounce buffer over coreboot */
+ /* Move ``longs'' the coreboot size is 4 byte aligned */
+ " movl 16(%%esp), %%edi\n\t"
+ " movl 12(%%esp), %%esi\n\t"
+ " movl 8(%%esp), %%ecx\n\t"
+ " shrl $2, %%ecx\n\t"
+ " rep movsl\n\t"
+
+ /* Now jump to the loaded image */
+ " movl %5, %%eax\n\t"
+ " movl 0(%%esp), %%ebx\n\t"
+ " call *4(%%esp)\n\t"
+
+ /* The loaded image returned? */
+ " cli \n\t"
+ " cld \n\t"
+
+ /* Copy the saved copy of coreboot where coreboot runs */
+ /* Move ``longs'' the coreboot size is 4 byte aligned */
+ " movl 16(%%esp), %%edi\n\t"
+ " movl 12(%%esp), %%esi\n\t"
+ " addl 8(%%esp), %%esi\n\t"
+ " movl 8(%%esp), %%ecx\n\t"
+ " shrl $2, %%ecx\n\t"
+ " rep movsl\n\t"
+
+ /* Adjust the stack pointer to point into the old coreboot image */
+ " subl 20(%%esp), %%esp\n\t"
+
+ /* Adjust the instruction pointer to point into the old coreboot image */
+ " movl $1f, %%eax\n\t"
+ " subl 20(%%esp), %%eax\n\t"
+ " jmp *%%eax\n\t"
+ "1: \n\t"
+
+ /* Drop the parameters I was passed */
+ " addl $24, %%esp\n\t"
+
+ /* Restore the callee save registers */
+ " popl %%ebx\n\t"
+ " popl %%edi\n\t"
+ " popl %%esi\n\t"
+#ifdef __x86_64__
+ ".code64\n\t"
+#endif
+ ::
+ "ri" (lb_start), "ri" (buffer), "ri" (lb_size),
+ "ri" (entry),
+ "ri"(0), "ri" (0)
+ );
+}
+
+static void try_payload(struct prog *prog)
+{
+ if (prog_type(prog) == ASSET_PAYLOAD) {
+ if (IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE))
+ jmp_payload_no_bounce_buffer(prog_entry(prog));
+ else
+ jmp_payload(prog_entry(prog),
+ (uintptr_t)prog_start(prog),
+ prog_size(prog));
+ }
+}
+
+void arch_prog_run(struct prog *prog)
+{
+ if (ENV_RAMSTAGE)
+ try_payload(prog);
+ __asm__ volatile (
+#ifdef __x86_64__
+ "jmp *%%rdi\n"
+#else
+ "jmp *%%edi\n"
+#endif
+
+ :: "D"(prog_entry(prog))
+ );
+}
diff --git a/src/arch/x86/boot/Makefile.inc b/src/arch/x86/boot/Makefile.inc
deleted file mode 100644
index 10a1efd..0000000
--- a/src/arch/x86/boot/Makefile.inc
+++ /dev/null
@@ -1,22 +0,0 @@
-
-ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32)$(CONFIG_ARCH_ROMSTAGE_X86_64),y)
-
-romstage-y += cbmem.c
-romstage-y += boot.c
-
-endif # CONFIG_ARCH_ROMSTAGE_X86_32 / CONFIG_ARCH_ROMSTAGE_X86_64
-
-ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32)$(CONFIG_ARCH_RAMSTAGE_X86_64),y)
-
-ramstage-y += boot.c
-ramstage-y += gdt.c
-ramstage-y += tables.c
-ramstage-y += cbmem.c
-ramstage-$(CONFIG_GENERATE_MP_TABLE) += mpspec.c
-ramstage-$(CONFIG_GENERATE_PIRQ_TABLE) += pirq_routing.c
-ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
-ramstage-$(CONFIG_GENERATE_SMBIOS_TABLES) += smbios.c
-ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpigen.c
-ramstage-$(CONFIG_HAVE_ACPI_RESUME) += wakeup.S
-
-endif # CONFIG_ARCH_RAMSTAGE_X86_32 / CONFIG_ARCH_RAMSTAGE_X86_64
diff --git a/src/arch/x86/boot/acpi.c b/src/arch/x86/boot/acpi.c
deleted file mode 100644
index 134e437..0000000
--- a/src/arch/x86/boot/acpi.c
+++ /dev/null
@@ -1,1137 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * coreboot ACPI Table support
- * written by Stefan Reinauer <stepan at openbios.org>
- *
- * Copyright (C) 2004 SUSE LINUX AG
- * Copyright (C) 2005-2009 coresystems GmbH
- *
- * ACPI FADT, FACS, and DSDT table support added by
- * Nick Barker <nick.barker9 at btinternet.com>, and those portions
- * Copyright (C) 2004 Nick Barker
- *
- * Copyright (C) 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
- * 2005.9 yhlu add SRAT table generation
- */
-
-/*
- * Each system port implementing ACPI has to provide two functions:
- *
- * write_acpi_tables()
- * acpi_dump_apics()
- *
- * See Kontron 986LCD-M port for a good example of an ACPI implementation
- * in coreboot.
- */
-
-#include <console/console.h>
-#include <string.h>
-#include <arch/acpi.h>
-#include <arch/acpigen.h>
-#include <device/pci.h>
-#include <cbmem.h>
-#include <cpu/x86/lapic_def.h>
-#include <cpu/cpu.h>
-#include <cbfs.h>
-#include <timestamp.h>
-#include <romstage_handoff.h>
-
-/* FIXME: Kconfig doesn't support overridable defaults :-( */
-#ifndef CONFIG_HPET_MIN_TICKS
-#define CONFIG_HPET_MIN_TICKS 0x1000
-#endif
-
-u8 acpi_checksum(u8 *table, u32 length)
-{
- u8 ret = 0;
- while (length--) {
- ret += *table;
- table++;
- }
- return -ret;
-}
-
-/**
- * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length
- * and checksum.
- */
-void acpi_add_table(acpi_rsdp_t *rsdp, void *table)
-{
- int i, entries_num;
- acpi_rsdt_t *rsdt;
- acpi_xsdt_t *xsdt = NULL;
-
- /* The RSDT is mandatory... */
- rsdt = (acpi_rsdt_t *)(uintptr_t)rsdp->rsdt_address;
-
- /* ...while the XSDT is not. */
- if (rsdp->xsdt_address)
- xsdt = (acpi_xsdt_t *)((uintptr_t)rsdp->xsdt_address);
-
- /* This should always be MAX_ACPI_TABLES. */
- entries_num = ARRAY_SIZE(rsdt->entry);
-
- for (i = 0; i < entries_num; i++) {
- if (rsdt->entry[i] == 0)
- break;
- }
-
- if (i >= entries_num) {
- printk(BIOS_ERR, "ACPI: Error: Could not add ACPI table, "
- "too many tables.\n");
- return;
- }
-
- /* Add table to the RSDT. */
- rsdt->entry[i] = (uintptr_t)table;
-
- /* Fix RSDT length or the kernel will assume invalid entries. */
- rsdt->header.length = sizeof(acpi_header_t) + (sizeof(u32) * (i + 1));
-
- /* Re-calculate checksum. */
- rsdt->header.checksum = 0; /* Hope this won't get optimized away */
- rsdt->header.checksum = acpi_checksum((u8 *)rsdt, rsdt->header.length);
-
- /*
- * And now the same thing for the XSDT. We use the same index as for
- * now we want the XSDT and RSDT to always be in sync in coreboot.
- */
- if (xsdt) {
- /* Add table to the XSDT. */
- xsdt->entry[i] = (u64)(uintptr_t)table;
-
- /* Fix XSDT length. */
- xsdt->header.length = sizeof(acpi_header_t) +
- (sizeof(u64) * (i + 1));
-
- /* Re-calculate checksum. */
- xsdt->header.checksum = 0;
- xsdt->header.checksum = acpi_checksum((u8 *)xsdt,
- xsdt->header.length);
- }
-
- printk(BIOS_DEBUG, "ACPI: added table %d/%d, length now %d\n",
- i + 1, entries_num, rsdt->header.length);
-}
-
-int acpi_create_mcfg_mmconfig(acpi_mcfg_mmconfig_t *mmconfig, u32 base,
- u16 seg_nr, u8 start, u8 end)
-{
- memset(mmconfig, 0, sizeof(*mmconfig));
- mmconfig->base_address = base;
- mmconfig->base_reserved = 0;
- mmconfig->pci_segment_group_number = seg_nr;
- mmconfig->start_bus_number = start;
- mmconfig->end_bus_number = end;
-
- return sizeof(acpi_mcfg_mmconfig_t);
-}
-
-int acpi_create_madt_lapic(acpi_madt_lapic_t *lapic, u8 cpu, u8 apic)
-{
- lapic->type = 0; /* Local APIC structure */
- lapic->length = sizeof(acpi_madt_lapic_t);
- lapic->flags = (1 << 0); /* Processor/LAPIC enabled */
- lapic->processor_id = cpu;
- lapic->apic_id = apic;
-
- return lapic->length;
-}
-
-unsigned long acpi_create_madt_lapics(unsigned long current)
-{
- struct device *cpu;
- int index = 0;
-
- for (cpu = all_devices; cpu; cpu = cpu->next) {
- if ((cpu->path.type != DEVICE_PATH_APIC) ||
- (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
- continue;
- }
- if (!cpu->enabled)
- continue;
- current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current,
- index, cpu->path.apic.apic_id);
- index++;
- }
-
- return current;
-}
-
-int acpi_create_madt_ioapic(acpi_madt_ioapic_t *ioapic, u8 id, u32 addr,
- u32 gsi_base)
-{
- ioapic->type = 1; /* I/O APIC structure */
- ioapic->length = sizeof(acpi_madt_ioapic_t);
- ioapic->reserved = 0x00;
- ioapic->gsi_base = gsi_base;
- ioapic->ioapic_id = id;
- ioapic->ioapic_addr = addr;
-
- return ioapic->length;
-}
-
-int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t *irqoverride,
- u8 bus, u8 source, u32 gsirq, u16 flags)
-{
- irqoverride->type = 2; /* Interrupt source override */
- irqoverride->length = sizeof(acpi_madt_irqoverride_t);
- irqoverride->bus = bus;
- irqoverride->source = source;
- irqoverride->gsirq = gsirq;
- irqoverride->flags = flags;
-
- return irqoverride->length;
-}
-
-int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t *lapic_nmi, u8 cpu,
- u16 flags, u8 lint)
-{
- lapic_nmi->type = 4; /* Local APIC NMI structure */
- lapic_nmi->length = sizeof(acpi_madt_lapic_nmi_t);
- lapic_nmi->flags = flags;
- lapic_nmi->processor_id = cpu;
- lapic_nmi->lint = lint;
-
- return lapic_nmi->length;
-}
-
-void acpi_create_madt(acpi_madt_t *madt)
-{
- acpi_header_t *header = &(madt->header);
- unsigned long current = (unsigned long)madt + sizeof(acpi_madt_t);
-
- memset((void *)madt, 0, sizeof(acpi_madt_t));
-
- /* Fill out header fields. */
- memcpy(header->signature, "APIC", 4);
- memcpy(header->oem_id, OEM_ID, 6);
- memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
- memcpy(header->asl_compiler_id, ASLC, 4);
-
- header->length = sizeof(acpi_madt_t);
- header->revision = 1; /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
-
- madt->lapic_addr = LOCAL_APIC_ADDR;
- madt->flags = 0x1; /* PCAT_COMPAT */
-
- current = acpi_fill_madt(current);
-
- /* (Re)calculate length and checksum. */
- header->length = current - (unsigned long)madt;
-
- header->checksum = acpi_checksum((void *)madt, header->length);
-}
-
-/* MCFG is defined in the PCI Firmware Specification 3.0. */
-void acpi_create_mcfg(acpi_mcfg_t *mcfg)
-{
- acpi_header_t *header = &(mcfg->header);
- unsigned long current = (unsigned long)mcfg + sizeof(acpi_mcfg_t);
-
- memset((void *)mcfg, 0, sizeof(acpi_mcfg_t));
-
- /* Fill out header fields. */
- memcpy(header->signature, "MCFG", 4);
- memcpy(header->oem_id, OEM_ID, 6);
- memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
- memcpy(header->asl_compiler_id, ASLC, 4);
-
- header->length = sizeof(acpi_mcfg_t);
- header->revision = 1;
-
- current = acpi_fill_mcfg(current);
-
- /* (Re)calculate length and checksum. */
- header->length = current - (unsigned long)mcfg;
- header->checksum = acpi_checksum((void *)mcfg, header->length);
-}
-
-static void *get_tcpa_log(u32 *size)
-{
- const struct cbmem_entry *ce;
- const u32 tcpa_default_log_len = 0x10000;
- void *lasa;
- ce = cbmem_entry_find(CBMEM_ID_TCPA_LOG);
- if (ce) {
- lasa = cbmem_entry_start(ce);
- *size = cbmem_entry_size(ce);
- printk(BIOS_DEBUG, "TCPA log found at %p\n", lasa);
- return lasa;
- }
- lasa = cbmem_add(CBMEM_ID_TCPA_LOG, tcpa_default_log_len);
- if (!lasa) {
- printk(BIOS_ERR, "TCPA log creation failed\n");
- return NULL;
- }
-
- printk(BIOS_DEBUG, "TCPA log created at %p\n", lasa);
- memset (lasa, 0, tcpa_default_log_len);
-
- *size = tcpa_default_log_len;
- return lasa;
-}
-
-static void acpi_create_tcpa(acpi_tcpa_t *tcpa)
-{
- acpi_header_t *header = &(tcpa->header);
- u32 tcpa_log_len;
- void *lasa;
-
- memset((void *)tcpa, 0, sizeof(acpi_tcpa_t));
-
- lasa = get_tcpa_log(&tcpa_log_len);
- if (!lasa) {
- return;
- }
-
- /* Fill out header fields. */
- memcpy(header->signature, "TCPA", 4);
- memcpy(header->oem_id, OEM_ID, 6);
- memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
- memcpy(header->asl_compiler_id, ASLC, 4);
-
- header->length = sizeof(acpi_tcpa_t);
- header->revision = 2;
-
- tcpa->platform_class = 0;
- tcpa->laml = tcpa_log_len;
- tcpa->lasa = (uintptr_t) lasa;
-
- /* Calculate checksum. */
- header->checksum = acpi_checksum((void *)tcpa, header->length);
-}
-
-void acpi_create_ssdt_generator(acpi_header_t *ssdt, const char *oem_table_id)
-{
- unsigned long current = (unsigned long)ssdt + sizeof(acpi_header_t);
-
- memset((void *)ssdt, 0, sizeof(acpi_header_t));
-
- memcpy(&ssdt->signature, "SSDT", 4);
- ssdt->revision = 2; /* ACPI 1.0/2.0: ?, ACPI 3.0/4.0: 2 */
- memcpy(&ssdt->oem_id, OEM_ID, 6);
- memcpy(&ssdt->oem_table_id, oem_table_id, 8);
- ssdt->oem_revision = 42;
- memcpy(&ssdt->asl_compiler_id, ASLC, 4);
- ssdt->asl_compiler_revision = 42;
- ssdt->length = sizeof(acpi_header_t);
-
- acpigen_set_current((char *) current);
- {
- struct device *dev;
- for (dev = all_devices; dev; dev = dev->next)
- if (dev->ops && dev->ops->acpi_fill_ssdt_generator) {
- dev->ops->acpi_fill_ssdt_generator(dev);
- }
- current = (unsigned long) acpigen_get_current();
- }
-
- /* (Re)calculate length and checksum. */
- ssdt->length = current - (unsigned long)ssdt;
- ssdt->checksum = acpi_checksum((void *)ssdt, ssdt->length);
-}
-
-int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic)
-{
- memset((void *)lapic, 0, sizeof(acpi_srat_lapic_t));
-
- lapic->type = 0; /* Processor local APIC/SAPIC affinity structure */
- lapic->length = sizeof(acpi_srat_lapic_t);
- lapic->flags = (1 << 0); /* Enabled (the use of this structure). */
- lapic->proximity_domain_7_0 = node;
- /* TODO: proximity_domain_31_8, local SAPIC EID, clock domain. */
- lapic->apic_id = apic;
-
- return lapic->length;
-}
-
-int acpi_create_srat_mem(acpi_srat_mem_t *mem, u8 node, u32 basek, u32 sizek,
- u32 flags)
-{
- mem->type = 1; /* Memory affinity structure */
- mem->length = sizeof(acpi_srat_mem_t);
- mem->base_address_low = (basek << 10);
- mem->base_address_high = (basek >> (32 - 10));
- mem->length_low = (sizek << 10);
- mem->length_high = (sizek >> (32 - 10));
- mem->proximity_domain = node;
- mem->flags = flags;
-
- return mem->length;
-}
-
-/* http://www.microsoft.com/whdc/system/sysinternals/sratdwn.mspx */
-void acpi_create_srat(acpi_srat_t *srat,
- unsigned long (*acpi_fill_srat)(unsigned long current))
-{
- acpi_header_t *header = &(srat->header);
- unsigned long current = (unsigned long)srat + sizeof(acpi_srat_t);
-
- memset((void *)srat, 0, sizeof(acpi_srat_t));
-
- /* Fill out header fields. */
- memcpy(header->signature, "SRAT", 4);
- memcpy(header->oem_id, OEM_ID, 6);
- memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
- memcpy(header->asl_compiler_id, ASLC, 4);
-
- header->length = sizeof(acpi_srat_t);
- header->revision = 1; /* ACPI 1.0: N/A, 2.0: 1, 3.0: 2, 4.0: 3 */
-
- srat->resv = 1; /* Spec: Reserved to 1 for backwards compatibility. */
-
- current = acpi_fill_srat(current);
-
- /* (Re)calculate length and checksum. */
- header->length = current - (unsigned long)srat;
- header->checksum = acpi_checksum((void *)srat, header->length);
-}
-
-void acpi_create_dmar(acpi_dmar_t *dmar,
- unsigned long (*acpi_fill_dmar) (unsigned long))
-{
- acpi_header_t *header = &(dmar->header);
- unsigned long current = (unsigned long)dmar + sizeof(acpi_dmar_t);
-
- memset((void *)dmar, 0, sizeof(acpi_dmar_t));
-
- /* Fill out header fields. */
- memcpy(header->signature, "DMAR", 4);
- memcpy(header->oem_id, OEM_ID, 6);
- memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
- memcpy(header->asl_compiler_id, ASLC, 4);
-
- header->length = sizeof(acpi_dmar_t);
- header->revision = 1;
-
- dmar->host_address_width = 40 - 1; /* FIXME: == MTRR size? */
- dmar->flags = 0;
-
- current = acpi_fill_dmar(current);
-
- /* (Re)calculate length and checksum. */
- header->length = current - (unsigned long)dmar;
- header->checksum = acpi_checksum((void *)dmar, header->length);
-}
-
-unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
- u16 segment, u32 bar)
-{
- dmar_entry_t *drhd = (dmar_entry_t *)current;
- memset(drhd, 0, sizeof(*drhd));
- drhd->type = DMAR_DRHD;
- drhd->length = sizeof(*drhd); /* will be fixed up later */
- drhd->flags = flags;
- drhd->segment = segment;
- drhd->bar = bar;
-
- return drhd->length;
-}
-
-void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current)
-{
- dmar_entry_t *drhd = (dmar_entry_t *)base;
- drhd->length = current - base;
-}
-
-unsigned long acpi_create_dmar_drhd_ds_pci(unsigned long current, u8 segment,
- u8 dev, u8 fn)
-{
- dev_scope_t *ds = (dev_scope_t *)current;
- memset(ds, 0, sizeof(*ds));
- ds->type = SCOPE_PCI_ENDPOINT;
- ds->length = sizeof(*ds) + 2; /* we don't support longer paths yet */
- ds->start_bus = segment;
- ds->path[0].dev = dev;
- ds->path[0].fn = fn;
-
- return ds->length;
-}
-
-/* http://h21007.www2.hp.com/portal/download/files/unprot/Itanium/slit.pdf */
-void acpi_create_slit(acpi_slit_t *slit,
- unsigned long (*acpi_fill_slit)(unsigned long current))
-{
- acpi_header_t *header = &(slit->header);
- unsigned long current = (unsigned long)slit + sizeof(acpi_slit_t);
-
- memset((void *)slit, 0, sizeof(acpi_slit_t));
-
- /* Fill out header fields. */
- memcpy(header->signature, "SLIT", 4);
- memcpy(header->oem_id, OEM_ID, 6);
- memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
- memcpy(header->asl_compiler_id, ASLC, 4);
-
- header->length = sizeof(acpi_slit_t);
- header->revision = 1; /* ACPI 1.0: N/A, ACPI 2.0/3.0/4.0: 1 */
-
- current = acpi_fill_slit(current);
-
- /* (Re)calculate length and checksum. */
- header->length = current - (unsigned long)slit;
- header->checksum = acpi_checksum((void *)slit, header->length);
-}
-
-/* http://www.intel.com/hardwaredesign/hpetspec_1.pdf */
-void acpi_create_hpet(acpi_hpet_t *hpet)
-{
- acpi_header_t *header = &(hpet->header);
- acpi_addr_t *addr = &(hpet->addr);
-
- memset((void *)hpet, 0, sizeof(acpi_hpet_t));
-
- /* Fill out header fields. */
- memcpy(header->signature, "HPET", 4);
- memcpy(header->oem_id, OEM_ID, 6);
- memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
- memcpy(header->asl_compiler_id, ASLC, 4);
-
- header->length = sizeof(acpi_hpet_t);
- header->revision = 1; /* Currently 1. Table added in ACPI 2.0. */
-
- /* Fill out HPET address. */
- addr->space_id = 0; /* Memory */
- addr->bit_width = 64;
- addr->bit_offset = 0;
- addr->addrl = CONFIG_HPET_ADDRESS & 0xffffffff;
- addr->addrh = ((unsigned long long)CONFIG_HPET_ADDRESS) >> 32;
-
- hpet->id = *(unsigned int*)CONFIG_HPET_ADDRESS;
- hpet->number = 0;
- hpet->min_tick = CONFIG_HPET_MIN_TICKS;
-
- header->checksum = acpi_checksum((void *)hpet, sizeof(acpi_hpet_t));
-}
-
-unsigned long acpi_write_hpet(device_t device, unsigned long current, acpi_rsdp_t *rsdp)
-{
- acpi_hpet_t *hpet;
-
- /*
- * We explicitly add these tables later on:
- */
- printk(BIOS_DEBUG, "ACPI: * HPET\n");
-
- hpet = (acpi_hpet_t *) current;
- current += sizeof(acpi_hpet_t);
- current = ALIGN(current, 16);
- acpi_create_hpet(hpet);
- acpi_add_table(rsdp, hpet);
-
- return current;
-}
-
-void acpi_create_facs(acpi_facs_t *facs)
-{
- memset((void *)facs, 0, sizeof(acpi_facs_t));
-
- memcpy(facs->signature, "FACS", 4);
- facs->length = sizeof(acpi_facs_t);
- facs->hardware_signature = 0;
- facs->firmware_waking_vector = 0;
- facs->global_lock = 0;
- facs->flags = 0;
- facs->x_firmware_waking_vector_l = 0;
- facs->x_firmware_waking_vector_h = 0;
- facs->version = 1; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */
-}
-
-static void acpi_write_rsdt(acpi_rsdt_t *rsdt, char *oem_id, char *oem_table_id)
-{
- acpi_header_t *header = &(rsdt->header);
-
- /* Fill out header fields. */
- memcpy(header->signature, "RSDT", 4);
- memcpy(header->oem_id, oem_id, 6);
- memcpy(header->oem_table_id, oem_table_id, 8);
- memcpy(header->asl_compiler_id, ASLC, 4);
-
- header->length = sizeof(acpi_rsdt_t);
- header->revision = 1; /* ACPI 1.0/2.0/3.0/4.0: 1 */
-
- /* Entries are filled in later, we come with an empty set. */
-
- /* Fix checksum. */
- header->checksum = acpi_checksum((void *)rsdt, sizeof(acpi_rsdt_t));
-}
-
-static void acpi_write_xsdt(acpi_xsdt_t *xsdt, char *oem_id, char *oem_table_id)
-{
- acpi_header_t *header = &(xsdt->header);
-
- /* Fill out header fields. */
- memcpy(header->signature, "XSDT", 4);
- memcpy(header->oem_id, oem_id, 6);
- memcpy(header->oem_table_id, oem_table_id, 8);
- memcpy(header->asl_compiler_id, ASLC, 4);
-
- header->length = sizeof(acpi_xsdt_t);
- header->revision = 1; /* ACPI 1.0: N/A, 2.0/3.0/4.0: 1 */
-
- /* Entries are filled in later, we come with an empty set. */
-
- /* Fix checksum. */
- header->checksum = acpi_checksum((void *)xsdt, sizeof(acpi_xsdt_t));
-}
-
-static void acpi_write_rsdp(acpi_rsdp_t *rsdp, acpi_rsdt_t *rsdt,
- acpi_xsdt_t *xsdt, char *oem_id)
-{
- memset(rsdp, 0, sizeof(acpi_rsdp_t));
-
- memcpy(rsdp->signature, RSDP_SIG, 8);
- memcpy(rsdp->oem_id, oem_id, 6);
-
- rsdp->length = sizeof(acpi_rsdp_t);
- rsdp->rsdt_address = (uintptr_t)rsdt;
-
- /*
- * Revision: ACPI 1.0: 0, ACPI 2.0/3.0/4.0: 2.
- *
- * Some OSes expect an XSDT to be present for RSD PTR revisions >= 2.
- * If we don't have an ACPI XSDT, force ACPI 1.0 (and thus RSD PTR
- * revision 0).
- */
- if (xsdt == NULL) {
- rsdp->revision = 0;
- } else {
- rsdp->xsdt_address = (u64)(uintptr_t)xsdt;
- rsdp->revision = 2;
- }
-
- /* Calculate checksums. */
- rsdp->checksum = acpi_checksum((void *)rsdp, 20);
- rsdp->ext_checksum = acpi_checksum((void *)rsdp, sizeof(acpi_rsdp_t));
-}
-
-unsigned long acpi_create_hest_error_source(acpi_hest_t *hest, acpi_hest_esd_t *esd, u16 type, void *data, u16 data_len)
-{
- acpi_header_t *header = &(hest->header);
- acpi_hest_hen_t *hen;
- void *pos;
- u16 len;
-
- pos = esd;
- memset(pos, 0, sizeof(acpi_hest_esd_t));
- len = 0;
- esd->type = type; /* MCE */
- esd->source_id = hest->error_source_count;
- esd->flags = 0; /* FIRMWARE_FIRST */
- esd->enabled = 1;
- esd->prealloc_erecords = 1;
- esd->max_section_per_record = 0x1;
-
- len += sizeof(acpi_hest_esd_t);
- pos = esd + 1;
-
- switch (type) {
- case 0: /* MCE */
- break;
- case 1: /* CMC */
- hen = (acpi_hest_hen_t *) (pos);
- memset(pos, 0, sizeof(acpi_hest_hen_t));
- hen->type = 3; /* SCI? */
- hen->length = sizeof(acpi_hest_hen_t);
- hen->conf_we = 0; /* Configuration Write Enable. */
- hen->poll_interval = 0;
- hen->vector = 0;
- hen->sw2poll_threshold_val = 0;
- hen->sw2poll_threshold_win = 0;
- hen->error_threshold_val = 0;
- hen->error_threshold_win = 0;
- len += sizeof(acpi_hest_hen_t);
- pos = hen + 1;
- break;
- case 2: /* NMI */
- case 6: /* AER Root Port */
- case 7: /* AER Endpoint */
- case 8: /* AER Bridge */
- case 9: /* Generic Hardware Error Source. */
- /* TODO: */
- break;
- default:
- printk(BIOS_DEBUG, "Invalid type of Error Source.");
- break;
- }
- hest->error_source_count ++;
-
- memcpy(pos, data, data_len);
- len += data_len;
- header->length += len;
-
- return len;
-}
-
-/* ACPI 4.0 */
-void acpi_write_hest(acpi_hest_t *hest,
- unsigned long (*acpi_fill_hest)(acpi_hest_t *hest))
-{
- acpi_header_t *header = &(hest->header);
-
- memset(hest, 0, sizeof(acpi_hest_t));
-
- memcpy(header->signature, "HEST", 4);
- memcpy(header->oem_id, OEM_ID, 6);
- memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
- memcpy(header->asl_compiler_id, ASLC, 4);
- header->length += sizeof(acpi_hest_t);
- header->revision = 1;
-
- acpi_fill_hest(hest);
-
- /* Calculate checksums. */
- header->checksum = acpi_checksum((void *)hest, header->length);
-}
-
-#if IS_ENABLED(CONFIG_COMMON_FADT)
-void acpi_create_fadt(acpi_fadt_t *fadt,acpi_facs_t *facs, void *dsdt)
-{
- acpi_header_t *header = &(fadt->header);
-
- memset((void *) fadt, 0, sizeof(acpi_fadt_t));
- memcpy(header->signature, "FACP", 4);
- header->length = sizeof(acpi_fadt_t);
- header->revision = 4;
- memcpy(header->oem_id, OEM_ID, 6);
- memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
- memcpy(header->asl_compiler_id, ASLC, 4);
- header->asl_compiler_revision = 0;
-
- fadt->firmware_ctrl = (unsigned long) facs;
- fadt->dsdt = (unsigned long) dsdt;
-
- fadt->x_firmware_ctl_l = (unsigned long)facs;
- fadt->x_firmware_ctl_h = 0;
- fadt->x_dsdt_l = (unsigned long)dsdt;
- fadt->x_dsdt_h = 0;
-
- if(IS_ENABLED(CONFIG_SYSTEM_TYPE_LAPTOP)) {
- fadt->preferred_pm_profile = PM_MOBILE;
- } else {
- fadt->preferred_pm_profile = PM_DESKTOP;
- }
-
- acpi_fill_fadt(fadt);
-
- header->checksum =
- acpi_checksum((void *) fadt, header->length);
-}
-#endif
-
-unsigned long __attribute__ ((weak)) fw_cfg_acpi_tables(unsigned long start)
-{
- return 0;
-}
-
-#define ALIGN_CURRENT current = (ALIGN(current, 16))
-unsigned long write_acpi_tables(unsigned long start)
-{
- unsigned long current;
- acpi_rsdp_t *rsdp;
- acpi_rsdt_t *rsdt;
- acpi_xsdt_t *xsdt;
- acpi_fadt_t *fadt;
- acpi_facs_t *facs;
- acpi_header_t *slic_file, *slic;
- acpi_header_t *ssdt;
- acpi_header_t *dsdt_file, *dsdt;
- acpi_mcfg_t *mcfg;
- acpi_tcpa_t *tcpa;
- acpi_madt_t *madt;
- struct device *dev;
- unsigned long fw;
- size_t slic_size, dsdt_size;
- char oem_id[6], oem_table_id[8];
-
- current = start;
-
- /* Align ACPI tables to 16byte */
- ALIGN_CURRENT;
-
- fw = fw_cfg_acpi_tables(current);
- if (fw)
- return fw;
-
-#if CONFIG_COMPILE_IN_DSDT
- extern char _binary_dsdt_aml_start;
- extern char _binary_dsdt_aml_end;
- dsdt_file = (acpi_header_t *)&_binary_dsdt_aml_start;
- dsdt_size = (size_t)(&_binary_dsdt_aml_end - &_binary_dsdt_aml_start);
-#else
- dsdt_file = cbfs_boot_map_with_leak(
- CONFIG_CBFS_PREFIX "/dsdt.aml",
- CBFS_TYPE_RAW, &dsdt_size);
-#endif
- if (!dsdt_file) {
- printk(BIOS_ERR, "No DSDT file, skipping ACPI tables\n");
- return current;
- }
-
- if (dsdt_file->length > dsdt_size
- || dsdt_file->length < sizeof (acpi_header_t)
- || memcmp(dsdt_file->signature, "DSDT", 4) != 0) {
- printk(BIOS_ERR, "Invalid DSDT file, skipping ACPI tables\n");
- return current;
- }
-
- slic_file = cbfs_boot_map_with_leak(CONFIG_CBFS_PREFIX "/slic",
- CBFS_TYPE_RAW, &slic_size);
- if (slic_file
- && (slic_file->length > slic_size
- || slic_file->length < sizeof (acpi_header_t)
- || memcmp(slic_file->signature, "SLIC", 4) != 0)) {
- slic_file = 0;
- }
-
- if (slic_file) {
- memcpy(oem_id, slic_file->oem_id, 6);
- memcpy(oem_table_id, slic_file->oem_table_id, 8);
- } else {
- memcpy(oem_id, OEM_ID, 6);
- memcpy(oem_table_id, ACPI_TABLE_CREATOR, 8);
- }
-
- printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start);
-
- /* We need at least an RSDP and an RSDT Table */
- rsdp = (acpi_rsdp_t *) current;
- current += sizeof(acpi_rsdp_t);
- ALIGN_CURRENT;
- rsdt = (acpi_rsdt_t *) current;
- current += sizeof(acpi_rsdt_t);
- ALIGN_CURRENT;
- xsdt = (acpi_xsdt_t *) current;
- current += sizeof(acpi_xsdt_t);
- ALIGN_CURRENT;
-
- /* clear all table memory */
- memset((void *) start, 0, current - start);
-
- acpi_write_rsdp(rsdp, rsdt, xsdt, oem_id);
- acpi_write_rsdt(rsdt, oem_id, oem_table_id);
- acpi_write_xsdt(xsdt, oem_id, oem_table_id);
-
- printk(BIOS_DEBUG, "ACPI: * FACS\n");
- facs = (acpi_facs_t *) current;
- current += sizeof(acpi_facs_t);
- ALIGN_CURRENT;
- acpi_create_facs(facs);
-
- printk(BIOS_DEBUG, "ACPI: * DSDT\n");
- dsdt = (acpi_header_t *) current;
- memcpy(dsdt, dsdt_file, sizeof(acpi_header_t));
- if (dsdt->length >= sizeof(acpi_header_t)) {
- current += sizeof(acpi_header_t);
-
- acpigen_set_current((char *) current);
- for (dev = all_devices; dev; dev = dev->next)
- if (dev->ops && dev->ops->acpi_inject_dsdt_generator) {
- dev->ops->acpi_inject_dsdt_generator(dev);
- }
- current = (unsigned long) acpigen_get_current();
- memcpy((char *)current,
- (char *)dsdt_file + sizeof(acpi_header_t),
- dsdt->length - sizeof(acpi_header_t));
- current += dsdt->length - sizeof(acpi_header_t);
-
- /* (Re)calculate length and checksum. */
- dsdt->length = current - (unsigned long)dsdt;
- dsdt->checksum = 0;
- dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length);
- }
-
- ALIGN_CURRENT;
-
- printk(BIOS_DEBUG, "ACPI: * FADT\n");
- fadt = (acpi_fadt_t *) current;
- current += sizeof(acpi_fadt_t);
- ALIGN_CURRENT;
-
- acpi_create_fadt(fadt, facs, dsdt);
- acpi_add_table(rsdp, fadt);
-
- if (slic_file) {
- printk(BIOS_DEBUG, "ACPI: * SLIC\n");
- slic = (acpi_header_t *)current;
- memcpy(slic, slic_file, slic_file->length);
- current += slic_file->length;
- ALIGN_CURRENT;
- acpi_add_table(rsdp, slic);
- }
-
- printk(BIOS_DEBUG, "ACPI: * SSDT\n");
- ssdt = (acpi_header_t *)current;
- acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR);
- if (ssdt->length > sizeof(acpi_header_t)) {
- current += ssdt->length;
- acpi_add_table(rsdp, ssdt);
- ALIGN_CURRENT;
- }
-
- printk(BIOS_DEBUG, "ACPI: * MCFG\n");
- mcfg = (acpi_mcfg_t *) current;
- acpi_create_mcfg(mcfg);
- if (mcfg->header.length > sizeof(acpi_mcfg_t)) {
- current += mcfg->header.length;
- ALIGN_CURRENT;
- acpi_add_table(rsdp, mcfg);
- }
-
- printk(BIOS_DEBUG, "ACPI: * TCPA\n");
- tcpa = (acpi_tcpa_t *) current;
- acpi_create_tcpa(tcpa);
- if (tcpa->header.length >= sizeof(acpi_tcpa_t)) {
- current += tcpa->header.length;
- ALIGN_CURRENT;
- acpi_add_table(rsdp, tcpa);
- }
-
- printk(BIOS_DEBUG, "ACPI: * MADT\n");
-
- madt = (acpi_madt_t *) current;
- acpi_create_madt(madt);
- if (madt->header.length > sizeof(acpi_madt_t)) {
- current+=madt->header.length;
- acpi_add_table(rsdp,madt);
- }
- ALIGN_CURRENT;
-
- printk(BIOS_DEBUG, "current = %lx\n", current);
-
- for (dev = all_devices; dev; dev = dev->next) {
- if (dev->ops && dev->ops->write_acpi_tables) {
- current = dev->ops->write_acpi_tables(dev, current, rsdp);
- ALIGN_CURRENT;
- }
- }
-
- printk(BIOS_INFO, "ACPI: done.\n");
- return current;
-}
-
-#if CONFIG_HAVE_ACPI_RESUME
-void __attribute__((weak)) mainboard_suspend_resume(void)
-{
-}
-
-void acpi_resume(void *wake_vec)
-{
-#if CONFIG_HAVE_SMI_HANDLER
- u32 *gnvs_address = cbmem_find(CBMEM_ID_ACPI_GNVS_PTR);
-
- /* Restore GNVS pointer in SMM if found */
- if (gnvs_address && *gnvs_address) {
- printk(BIOS_DEBUG, "Restore GNVS pointer to 0x%08x\n",
- *gnvs_address);
- smm_setup_structures((void *)*gnvs_address, NULL, NULL);
- }
-#endif
-
- /* Call mainboard resume handler first, if defined. */
- mainboard_suspend_resume();
-
- post_code(POST_OS_RESUME);
- acpi_jump_to_wakeup(wake_vec);
-}
-
-/* This is filled with acpi_is_wakeup() call early in ramstage. */
-int acpi_slp_type = -1;
-
-#if IS_ENABLED(CONFIG_EARLY_CBMEM_INIT)
-int acpi_get_sleep_type(void)
-{
- struct romstage_handoff *handoff;
-
- handoff = cbmem_find(CBMEM_ID_ROMSTAGE_INFO);
-
- if (handoff == NULL) {
- printk(BIOS_DEBUG, "Unknown boot method, assuming normal.\n");
- return 0;
- } else if (handoff->s3_resume) {
- printk(BIOS_DEBUG, "S3 Resume.\n");
- return 3;
- } else {
- printk(BIOS_DEBUG, "Normal boot.\n");
- return 0;
- }
-}
-#endif
-
-static void acpi_handoff_wakeup(void)
-{
- if (acpi_slp_type < 0)
- acpi_slp_type = acpi_get_sleep_type();
-}
-
-int acpi_is_wakeup(void)
-{
- acpi_handoff_wakeup();
- /* Both resume from S2 and resume from S3 restart at CPU reset */
- return (acpi_slp_type == 3 || acpi_slp_type == 2);
-}
-
-int acpi_is_wakeup_s3(void)
-{
- acpi_handoff_wakeup();
- return (acpi_slp_type == 3);
-}
-
-void acpi_fail_wakeup(void)
-{
- if (acpi_slp_type == 3 || acpi_slp_type == 2)
- acpi_slp_type = 0;
-}
-
-void acpi_prepare_resume_backup(void)
-{
- if (!acpi_s3_resume_allowed())
- return;
-
- /* Let's prepare the ACPI S3 Resume area now already, so we can rely on
- * it being there during reboot time. We don't need the pointer, nor
- * the result right now. If it fails, ACPI resume will be disabled.
- */
-
- if (HIGH_MEMORY_SAVE)
- cbmem_add(CBMEM_ID_RESUME, HIGH_MEMORY_SAVE);
-}
-
-static acpi_rsdp_t *valid_rsdp(acpi_rsdp_t *rsdp)
-{
- if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0)
- return NULL;
-
- printk(BIOS_DEBUG, "Looking on %p for valid checksum\n", rsdp);
-
- if (acpi_checksum((void *)rsdp, 20) != 0)
- return NULL;
- printk(BIOS_DEBUG, "Checksum 1 passed\n");
-
- if ((rsdp->revision > 1) && (acpi_checksum((void *)rsdp,
- rsdp->length) != 0))
- return NULL;
- printk(BIOS_DEBUG, "Checksum 2 passed all OK\n");
-
- return rsdp;
-}
-
-static acpi_rsdp_t *rsdp;
-
-void *acpi_get_wakeup_rsdp(void)
-{
- return rsdp;
-}
-
-void *acpi_find_wakeup_vector(void)
-{
- char *p, *end;
- acpi_rsdt_t *rsdt;
- acpi_facs_t *facs;
- acpi_fadt_t *fadt = NULL;
- void *wake_vec;
- int i;
-
- rsdp = NULL;
-
- if (!acpi_is_wakeup())
- return NULL;
-
- printk(BIOS_DEBUG, "Trying to find the wakeup vector...\n");
-
- /* Find RSDP. */
- for (p = (char *)0xe0000; p < (char *)0xfffff; p += 16) {
- if ((rsdp = valid_rsdp((acpi_rsdp_t *)p)))
- break;
- }
-
- if (rsdp == NULL)
- return NULL;
-
- printk(BIOS_DEBUG, "RSDP found at %p\n", rsdp);
- rsdt = (acpi_rsdt_t *) rsdp->rsdt_address;
-
- end = (char *)rsdt + rsdt->header.length;
- printk(BIOS_DEBUG, "RSDT found at %p ends at %p\n", rsdt, end);
-
- for (i = 0; ((char *)&rsdt->entry[i]) < end; i++) {
- fadt = (acpi_fadt_t *)rsdt->entry[i];
- if (strncmp((char *)fadt, "FACP", 4) == 0)
- break;
- fadt = NULL;
- }
-
- if (fadt == NULL)
- return NULL;
-
- printk(BIOS_DEBUG, "FADT found at %p\n", fadt);
- facs = (acpi_facs_t *)fadt->firmware_ctrl;
-
- if (facs == NULL) {
- printk(BIOS_DEBUG, "No FACS found, wake up from S3 not "
- "possible.\n");
- return NULL;
- }
-
- printk(BIOS_DEBUG, "FACS found at %p\n", facs);
- wake_vec = (void *)facs->firmware_waking_vector;
- printk(BIOS_DEBUG, "OS waking vector is %p\n", wake_vec);
-
- return wake_vec;
-}
-
-#if CONFIG_SMP
-extern char *lowmem_backup;
-extern char *lowmem_backup_ptr;
-extern int lowmem_backup_size;
-#endif
-
-#define WAKEUP_BASE 0x600
-
-void (*acpi_do_wakeup)(u32 vector, u32 backup_source, u32 backup_target,
- u32 backup_size) asmlinkage = (void *)WAKEUP_BASE;
-
-extern unsigned char __wakeup;
-extern unsigned int __wakeup_size;
-
-void acpi_jump_to_wakeup(void *vector)
-{
- u32 acpi_backup_memory = 0;
-
- if (HIGH_MEMORY_SAVE && acpi_s3_resume_allowed()) {
- acpi_backup_memory = (u32)cbmem_find(CBMEM_ID_RESUME);
-
- if (!acpi_backup_memory) {
- printk(BIOS_WARNING, "ACPI: Backup memory missing. "
- "No S3 resume.\n");
- return;
- }
- }
-
-#if CONFIG_SMP
- // FIXME: This should go into the ACPI backup memory, too. No pork sausages.
- /*
- * Just restore the SMP trampoline and continue with wakeup on
- * assembly level.
- */
- memcpy(lowmem_backup_ptr, lowmem_backup, lowmem_backup_size);
-#endif
-
- /* Copy wakeup trampoline in place. */
- memcpy((void *)WAKEUP_BASE, &__wakeup, __wakeup_size);
-
- timestamp_add_now(TS_ACPI_WAKE_JUMP);
-
- acpi_do_wakeup((u32)vector, acpi_backup_memory, CONFIG_RAMBASE,
- HIGH_MEMORY_SAVE);
-}
-#endif
-
-void acpi_save_gnvs(u32 gnvs_address)
-{
- u32 *gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS_PTR, sizeof(*gnvs));
- if (gnvs)
- *gnvs = gnvs_address;
-}
diff --git a/src/arch/x86/boot/acpigen.c b/src/arch/x86/boot/acpigen.c
deleted file mode 100644
index 3aa823c..0000000
--- a/src/arch/x86/boot/acpigen.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2009 Rudolf Marek <r.marek at assembler.cz>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-/* How much nesting do we support? */
-#define ACPIGEN_LENSTACK_SIZE 10
-
-/*
- * If you need to change this, change acpigen_write_f and
- * acpigen_pop_len
- */
-
-#define ACPIGEN_MAXLEN 0xfff
-
-#include <string.h>
-#include <arch/acpigen.h>
-#include <console/console.h>
-#include <device/device.h>
-
-static char *gencurrent;
-
-char *len_stack[ACPIGEN_LENSTACK_SIZE];
-int ltop = 0;
-
-void acpigen_write_len_f(void)
-{
- ASSERT(ltop < (ACPIGEN_LENSTACK_SIZE - 1))
- len_stack[ltop++] = gencurrent;
- acpigen_emit_byte(0);
- acpigen_emit_byte(0);
-}
-
-void acpigen_pop_len(void)
-{
- int len;
- ASSERT(ltop > 0)
- char *p = len_stack[--ltop];
- len = gencurrent - p;
- ASSERT(len <= ACPIGEN_MAXLEN)
- /* generate store length for 0xfff max */
- p[0] = (0x40 | (len & 0xf));
- p[1] = (len >> 4 & 0xff);
-
-}
-
-void acpigen_set_current(char *curr)
-{
- gencurrent = curr;
-}
-
-char *acpigen_get_current(void)
-{
- return gencurrent;
-}
-
-void acpigen_emit_byte(unsigned char b)
-{
- (*gencurrent++) = b;
-}
-
-void acpigen_write_package(int nr_el)
-{
- /* package op */
- acpigen_emit_byte(0x12);
- acpigen_write_len_f();
- acpigen_emit_byte(nr_el);
-}
-
-void acpigen_write_byte(unsigned int data)
-{
- /* byte op */
- acpigen_emit_byte(0xa);
- acpigen_emit_byte(data & 0xff);
-}
-
-void acpigen_write_dword(unsigned int data)
-{
- /* dword op */
- acpigen_emit_byte(0xc);
- acpigen_emit_byte(data & 0xff);
- acpigen_emit_byte((data >> 8) & 0xff);
- acpigen_emit_byte((data >> 16) & 0xff);
- acpigen_emit_byte((data >> 24) & 0xff);
-}
-
-void acpigen_write_qword(uint64_t data)
-{
- /* qword op */
- acpigen_emit_byte(0xe);
- acpigen_emit_byte(data & 0xff);
- acpigen_emit_byte((data >> 8) & 0xff);
- acpigen_emit_byte((data >> 16) & 0xff);
- acpigen_emit_byte((data >> 24) & 0xff);
- acpigen_emit_byte((data >> 32) & 0xff);
- acpigen_emit_byte((data >> 40) & 0xff);
- acpigen_emit_byte((data >> 48) & 0xff);
- acpigen_emit_byte((data >> 56) & 0xff);
-}
-
-void acpigen_write_name_byte(const char *name, uint8_t val)
-{
- acpigen_write_name(name);
- acpigen_write_byte(val);
-}
-
-void acpigen_write_name_dword(const char *name, uint32_t val)
-{
- acpigen_write_name(name);
- acpigen_write_dword(val);
-}
-
-void acpigen_write_name_qword(const char *name, uint64_t val)
-{
- acpigen_write_name(name);
- acpigen_write_qword(val);
-}
-
-void acpigen_emit_stream(const char *data, int size)
-{
- int i;
- for (i = 0; i < size; i++) {
- acpigen_emit_byte(data[i]);
- }
-}
-
-/*
- * The naming conventions for ACPI namespace names are a bit tricky as
- * each element has to be 4 chars wide (»All names are a fixed 32 bits.«)
- * and »By convention, when an ASL compiler pads a name shorter than 4
- * characters, it is done so with trailing underscores (‘_’).«.
- *
- * Check sections 5.3, 18.2.2 and 18.4 of ACPI spec 3.0 for details.
- */
-
-static void acpigen_emit_simple_namestring(const char *name) {
- int i;
- char ud[] = "____";
- for (i = 0; i < 4; i++) {
- if ((name[i] == '\0') || (name[i] == '.')) {
- acpigen_emit_stream(ud, 4 - i);
- break;
- } else {
- acpigen_emit_byte(name[i]);
- }
- }
-}
-
-static void acpigen_emit_double_namestring(const char *name, int dotpos) {
- /* mark dual name prefix */
- acpigen_emit_byte(0x2e);
- acpigen_emit_simple_namestring(name);
- acpigen_emit_simple_namestring(&name[dotpos + 1]);
-}
-
-static void acpigen_emit_multi_namestring(const char *name) {
- int count = 0;
- unsigned char *pathlen;
- /* mark multi name prefix */
- acpigen_emit_byte(0x2f);
- acpigen_emit_byte(0x0);
- pathlen = ((unsigned char *) acpigen_get_current()) - 1;
-
- while (name[0] != '\0') {
- acpigen_emit_simple_namestring(name);
- /* find end or next entity */
- while ((name[0] != '.') && (name[0] != '\0'))
- name++;
- /* forward to next */
- if (name[0] == '.')
- name++;
- count++;
- }
-
- pathlen[0] = count;
-}
-
-
-void acpigen_emit_namestring(const char *namepath) {
- int dotcount = 0, i;
- int dotpos = 0;
-
- /* We can start with a '\'. */
- if (namepath[0] == '\\') {
- acpigen_emit_byte('\\');
- namepath++;
- }
-
- /* And there can be any number of '^' */
- while (namepath[0] == '^') {
- acpigen_emit_byte('^');
- namepath++;
- }
-
- /* If we have only \\ or only ^...^. Then we need to put a null
- name (0x00). */
- if(namepath[0] == '\0') {
- acpigen_emit_byte(0x00);
- return;
- }
-
- i = 0;
- while (namepath[i] != '\0') {
- if (namepath[i] == '.') {
- dotcount++;
- dotpos = i;
- }
- i++;
- }
-
- if (dotcount == 0) {
- acpigen_emit_simple_namestring(namepath);
- } else if (dotcount == 1) {
- acpigen_emit_double_namestring(namepath, dotpos);
- } else {
- acpigen_emit_multi_namestring(namepath);
- }
-}
-
-void acpigen_write_name(const char *name)
-{
- /* name op */
- acpigen_emit_byte(0x8);
- acpigen_emit_namestring(name);
-}
-
-void acpigen_write_scope(const char *name)
-{
- /* scope op */
- acpigen_emit_byte(0x10);
- acpigen_write_len_f();
- acpigen_emit_namestring(name);
-}
-
-void acpigen_write_processor(u8 cpuindex, u32 pblock_addr, u8 pblock_len)
-{
-/*
- Processor (\_PR.CPUcpuindex, cpuindex, pblock_addr, pblock_len)
- {
-*/
- char pscope[16];
- /* processor op */
- acpigen_emit_byte(0x5b);
- acpigen_emit_byte(0x83);
- acpigen_write_len_f();
-
- snprintf(pscope, sizeof (pscope),
- "\\_PR.CP%02d", (unsigned int) cpuindex);
- acpigen_emit_namestring(pscope);
- acpigen_emit_byte(cpuindex);
- acpigen_emit_byte(pblock_addr & 0xff);
- acpigen_emit_byte((pblock_addr >> 8) & 0xff);
- acpigen_emit_byte((pblock_addr >> 16) & 0xff);
- acpigen_emit_byte((pblock_addr >> 24) & 0xff);
- acpigen_emit_byte(pblock_len);
-}
-
-void acpigen_write_empty_PCT(void)
-{
-/*
- Name (_PCT, Package (0x02)
- {
- ResourceTemplate ()
- {
- Register (FFixedHW,
- 0x00, // Bit Width
- 0x00, // Bit Offset
- 0x0000000000000000, // Address
- ,)
- },
-
- ResourceTemplate ()
- {
- Register (FFixedHW,
- 0x00, // Bit Width
- 0x00, // Bit Offset
- 0x0000000000000000, // Address
- ,)
- }
- })
-*/
- static char stream[] = {
- 0x08, 0x5F, 0x50, 0x43, 0x54, 0x12, 0x2C, /* 00000030 "0._PCT.," */
- 0x02, 0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, /* 00000038 "........" */
- 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00000040 "........" */
- 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14, /* 00000048 "....y..." */
- 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F, 0x00, 0x00, /* 00000050 "........" */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00000058 "........" */
- 0x00, 0x79, 0x00
- };
- acpigen_emit_stream(stream, ARRAY_SIZE(stream));
-}
-
-void acpigen_write_empty_PTC(void)
-{
-/*
- Name (_PTC, Package (0x02)
- {
- ResourceTemplate ()
- {
- Register (FFixedHW,
- 0x00, // Bit Width
- 0x00, // Bit Offset
- 0x0000000000000000, // Address
- ,)
- },
-
- ResourceTemplate ()
- {
- Register (FFixedHW,
- 0x00, // Bit Width
- 0x00, // Bit Offset
- 0x0000000000000000, // Address
- ,)
- }
- })
-*/
- acpi_addr_t addr = {
- .space_id = ACPI_ADDRESS_SPACE_FIXED,
- .bit_width = 0,
- .bit_offset = 0,
- {
- .resv = 0
- },
- .addrl = 0,
- .addrh = 0,
- };
-
- acpigen_write_name("_PTC");
- acpigen_write_package(2);
-
- /* ControlRegister */
- acpigen_write_resourcetemplate_header();
- acpigen_write_register(&addr);
- acpigen_write_resourcetemplate_footer();
-
- /* StatusRegister */
- acpigen_write_resourcetemplate_header();
- acpigen_write_register(&addr);
- acpigen_write_resourcetemplate_footer();
-
- acpigen_pop_len();
-}
-
-void acpigen_write_method(const char *name, int nargs)
-{
- /* method op */
- acpigen_emit_byte(0x14);
- acpigen_write_len_f();
- acpigen_emit_namestring(name);
- acpigen_emit_byte(nargs & 7);
-}
-
-void acpigen_write_device(const char *name)
-{
- /* method op */
- acpigen_emit_byte(0x5b);
- acpigen_emit_byte(0x82);
- acpigen_write_len_f();
- acpigen_emit_namestring(name);
-}
-
-/*
- * Generates a func with max supported P-states.
- */
-void acpigen_write_PPC(u8 nr)
-{
-/*
- Method (_PPC, 0, NotSerialized)
- {
- Return (nr)
- }
-*/
- acpigen_write_method("_PPC", 0);
- /* return */
- acpigen_emit_byte(0xa4);
- /* arg */
- acpigen_write_byte(nr);
- acpigen_pop_len();
-}
-
-/*
- * Generates a func with max supported P-states saved
- * in the variable PPCM.
- */
-void acpigen_write_PPC_NVS(void)
-{
-/*
- Method (_PPC, 0, NotSerialized)
- {
- Return (PPCM)
- }
-*/
- acpigen_write_method("_PPC", 0);
- /* return */
- acpigen_emit_byte(0xa4);
- /* arg */
- acpigen_emit_namestring("PPCM");
- acpigen_pop_len();
-}
-
-void acpigen_write_TPC(const char *gnvs_tpc_limit)
-{
-/*
- // Sample _TPC method
- Method (_TPC, 0, NotSerialized)
- {
- Return (\TLVL)
- }
- */
- acpigen_write_method("_TPC", 0);
- acpigen_emit_byte(0xa4); /* ReturnOp */
- acpigen_emit_namestring(gnvs_tpc_limit);
- acpigen_pop_len();
-}
-
-void acpigen_write_PSS_package(u32 coreFreq, u32 power, u32 transLat,
- u32 busmLat, u32 control, u32 status)
-{
- acpigen_write_package(6);
- acpigen_write_dword(coreFreq);
- acpigen_write_dword(power);
- acpigen_write_dword(transLat);
- acpigen_write_dword(busmLat);
- acpigen_write_dword(control);
- acpigen_write_dword(status);
- acpigen_pop_len();
-
- printk(BIOS_DEBUG, "PSS: %uMHz power %u control 0x%x status 0x%x\n",
- coreFreq, power, control, status);
-}
-
-void acpigen_write_PSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
-{
- acpigen_write_name("_PSD");
- acpigen_write_package(1);
- acpigen_write_package(5);
- acpigen_write_byte(5); // 5 values
- acpigen_write_byte(0); // revision 0
- acpigen_write_dword(domain);
- acpigen_write_dword(coordtype);
- acpigen_write_dword(numprocs);
- acpigen_pop_len();
- acpigen_pop_len();
-}
-
-void acpigen_write_CST_package_entry(acpi_cstate_t *cstate)
-{
- acpigen_write_package(4);
- acpigen_write_resourcetemplate_header();
- acpigen_write_register(&cstate->resource);
- acpigen_write_resourcetemplate_footer();
- acpigen_write_dword(cstate->ctype);
- acpigen_write_dword(cstate->latency);
- acpigen_write_dword(cstate->power);
- acpigen_pop_len();
-}
-
-void acpigen_write_CST_package(acpi_cstate_t *cstate, int nentries)
-{
- int i;
- acpigen_write_name("_CST");
- acpigen_write_package(nentries+1);
- acpigen_write_dword(nentries);
-
- for (i = 0; i < nentries; i++)
- acpigen_write_CST_package_entry(cstate + i);
-
- acpigen_pop_len();
-}
-
-void acpigen_write_TSS_package(int entries, acpi_tstate_t *tstate_list)
-{
-/*
- Sample _TSS package with 100% and 50% duty cycles
- Name (_TSS, Package (0x02)
- {
- Package(){100, 1000, 0, 0x00, 0)
- Package(){50, 520, 0, 0x18, 0)
- })
- */
- int i;
- acpi_tstate_t *tstate = tstate_list;
-
- acpigen_write_name("_TSS");
- acpigen_write_package(entries);
-
- for (i = 0; i < entries; i++) {
- acpigen_write_package(5);
- acpigen_write_dword(tstate->percent);
- acpigen_write_dword(tstate->power);
- acpigen_write_dword(tstate->latency);
- acpigen_write_dword(tstate->control);
- acpigen_write_dword(tstate->status);
- acpigen_pop_len();
- tstate++;
- }
-
- acpigen_pop_len();
-}
-
-void acpigen_write_TSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
-{
- acpigen_write_name("_TSD");
- acpigen_write_package(1);
- acpigen_write_package(5);
- acpigen_write_byte(5); // 5 values
- acpigen_write_byte(0); // revision 0
- acpigen_write_dword(domain);
- acpigen_write_dword(coordtype);
- acpigen_write_dword(numprocs);
- acpigen_pop_len();
- acpigen_pop_len();
-}
-
-
-
-void acpigen_write_mem32fixed(int readwrite, u32 base, u32 size)
-{
- /*
- * acpi 4.0 section 6.4.3.4: 32-Bit Fixed Memory Range Descriptor
- * Byte 0:
- * Bit7 : 1 => big item
- * Bit6-0: 0000110 (0x6) => 32-bit fixed memory
- */
- acpigen_emit_byte(0x86);
- /* Byte 1+2: length (0x0009) */
- acpigen_emit_byte(0x09);
- acpigen_emit_byte(0x00);
- /* bit1-7 are ignored */
- acpigen_emit_byte(readwrite ? 0x01 : 0x00);
- acpigen_emit_byte(base & 0xff);
- acpigen_emit_byte((base >> 8) & 0xff);
- acpigen_emit_byte((base >> 16) & 0xff);
- acpigen_emit_byte((base >> 24) & 0xff);
- acpigen_emit_byte(size & 0xff);
- acpigen_emit_byte((size >> 8) & 0xff);
- acpigen_emit_byte((size >> 16) & 0xff);
- acpigen_emit_byte((size >> 24) & 0xff);
-}
-
-void acpigen_write_register(acpi_addr_t *addr)
-{
- acpigen_emit_byte(0x82); /* Register Descriptor */
- acpigen_emit_byte(0x0c); /* Register Length 7:0 */
- acpigen_emit_byte(0x00); /* Register Length 15:8 */
- acpigen_emit_byte(addr->space_id); /* Address Space ID */
- acpigen_emit_byte(addr->bit_width); /* Register Bit Width */
- acpigen_emit_byte(addr->bit_offset); /* Register Bit Offset */
- acpigen_emit_byte(addr->resv); /* Register Access Size */
- acpigen_emit_byte(addr->addrl & 0xff); /* Register Address Low */
- acpigen_emit_byte((addr->addrl >> 8) & 0xff);
- acpigen_emit_byte((addr->addrl >> 16) & 0xff);
- acpigen_emit_byte((addr->addrl >> 24) & 0xff);
- acpigen_emit_byte(addr->addrh & 0xff); /* Register Address High */
- acpigen_emit_byte((addr->addrh >> 8) & 0xff);
- acpigen_emit_byte((addr->addrh >> 16) & 0xff);
- acpigen_emit_byte((addr->addrh >> 24) & 0xff);
-}
-
-void acpigen_write_irq(u16 mask)
-{
- /*
- * acpi 3.0b section 6.4.2.1: IRQ Descriptor
- * Byte 0:
- * Bit7 : 0 => small item
- * Bit6-3: 0100 (0x4) => IRQ port descriptor
- * Bit2-0: 010 (0x2) => 2 Bytes long
- */
- acpigen_emit_byte(0x22);
- acpigen_emit_byte(mask & 0xff);
- acpigen_emit_byte((mask >> 8) & 0xff);
-}
-
-void acpigen_write_io16(u16 min, u16 max, u8 align, u8 len, u8 decode16)
-{
- /*
- * acpi 4.0 section 6.4.2.6: I/O Port Descriptor
- * Byte 0:
- * Bit7 : 0 => small item
- * Bit6-3: 1000 (0x8) => I/O port descriptor
- * Bit2-0: 111 (0x7) => 7 Bytes long
- */
- acpigen_emit_byte(0x47);
- /* Does the device decode all 16 or just 10 bits? */
- /* bit1-7 are ignored */
- acpigen_emit_byte(decode16 ? 0x01 : 0x00);
- /* minimum base address the device may be configured for */
- acpigen_emit_byte(min & 0xff);
- acpigen_emit_byte((min >> 8) & 0xff);
- /* maximum base address the device may be configured for */
- acpigen_emit_byte(max & 0xff);
- acpigen_emit_byte((max >> 8) & 0xff);
- /* alignment for min base */
- acpigen_emit_byte(align & 0xff);
- acpigen_emit_byte(len & 0xff);
-}
-
-void acpigen_write_resourcetemplate_header(void)
-{
- /*
- * A ResourceTemplate() is a Buffer() with a
- * (Byte|Word|DWord) containing the length, followed by one or more
- * resource items, terminated by the end tag.
- * (small item 0xf, len 1)
- */
- acpigen_emit_byte(0x11); /* Buffer opcode */
- acpigen_write_len_f();
- acpigen_emit_byte(0x0b); /* Word opcode */
- len_stack[ltop++] = acpigen_get_current();
- acpigen_emit_byte(0x00);
- acpigen_emit_byte(0x00);
-}
-
-void acpigen_write_resourcetemplate_footer(void)
-{
- char *p = len_stack[--ltop];
- int len;
- /*
- * end tag (acpi 4.0 Section 6.4.2.8)
- * 0x79 <checksum>
- * 0x00 is treated as a good checksum according to the spec
- * and is what iasl generates.
- */
- acpigen_emit_byte(0x79);
- acpigen_emit_byte(0x00);
-
- len = gencurrent - p;
-
- /* patch len word */
- p[0] = len & 0xff;
- p[1] = (len >> 8) & 0xff;
- /* patch len field */
- acpigen_pop_len();
-}
-
-static void acpigen_add_mainboard_rsvd_mem32(void *gp, struct device *dev,
- struct resource *res)
-{
- acpigen_write_mem32fixed(0, res->base, res->size);
-}
-
-static void acpigen_add_mainboard_rsvd_io(void *gp, struct device *dev,
- struct resource *res)
-{
- resource_t base = res->base;
- resource_t size = res->size;
- while (size > 0) {
- resource_t sz = size > 255 ? 255 : size;
- acpigen_write_io16(base, base, 0, sz, 1);
- size -= sz;
- base += sz;
- }
-}
-
-void acpigen_write_mainboard_resource_template(void)
-{
- acpigen_write_resourcetemplate_header();
-
- /* Add reserved memory ranges. */
- search_global_resources(
- IORESOURCE_MEM | IORESOURCE_RESERVE,
- IORESOURCE_MEM | IORESOURCE_RESERVE,
- acpigen_add_mainboard_rsvd_mem32, 0);
-
- /* Add reserved io ranges. */
- search_global_resources(
- IORESOURCE_IO | IORESOURCE_RESERVE,
- IORESOURCE_IO | IORESOURCE_RESERVE,
- acpigen_add_mainboard_rsvd_io, 0);
-
- acpigen_write_resourcetemplate_footer();
-}
-
-void acpigen_write_mainboard_resources(const char *scope, const char *name)
-{
- acpigen_write_scope(scope);
- acpigen_write_name(name);
- acpigen_write_mainboard_resource_template();
- acpigen_pop_len();
-}
-
-static int hex2bin(const char c)
-{
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- return c - '0';
-}
-
-void acpigen_emit_eisaid(const char *eisaid)
-{
- u32 compact = 0;
-
- /* Clamping individual values would be better but
- there is a disagreement over what is a valid
- EISA id, so accept anything and don't clamp,
- parent code should create a valid EISAid.
- */
- compact |= (eisaid[0] - 'A' + 1) << 26;
- compact |= (eisaid[1] - 'A' + 1) << 21;
- compact |= (eisaid[2] - 'A' + 1) << 16;
- compact |= hex2bin(eisaid[3]) << 12;
- compact |= hex2bin(eisaid[4]) << 8;
- compact |= hex2bin(eisaid[5]) << 4;
- compact |= hex2bin(eisaid[6]);
-
- acpigen_emit_byte(0xc);
- acpigen_emit_byte((compact >> 24) & 0xff);
- acpigen_emit_byte((compact >> 16) & 0xff);
- acpigen_emit_byte((compact >> 8) & 0xff);
- acpigen_emit_byte(compact & 0xff);
-}
diff --git a/src/arch/x86/boot/boot.c b/src/arch/x86/boot/boot.c
deleted file mode 100644
index 7eb87fb..0000000
--- a/src/arch/x86/boot/boot.c
+++ /dev/null
@@ -1,210 +0,0 @@
-#include <console/console.h>
-#include <arch/stages.h>
-#include <program_loading.h>
-#include <ip_checksum.h>
-#include <string.h>
-#include <symbols.h>
-
-/* When the ramstage is relocatable the elf loading ensures an elf image cannot
- * be loaded over the ramstage code. */
-static void jmp_payload_no_bounce_buffer(void *entry)
-{
- /* Jump to kernel */
- __asm__ __volatile__(
- " cld \n\t"
- /* Now jump to the loaded image */
- " call *%0\n\t"
-
- /* The loaded image returned? */
- " cli \n\t"
- " cld \n\t"
-
- ::
- "r" (entry)
- );
-}
-
-static void jmp_payload(void *entry, unsigned long buffer, unsigned long size)
-{
- unsigned long lb_start, lb_size;
-
- lb_start = (unsigned long)&_program;
- lb_size = _program_size;
-
- printk(BIOS_SPEW, "entry = 0x%08lx\n", (unsigned long)entry);
- printk(BIOS_SPEW, "lb_start = 0x%08lx\n", lb_start);
- printk(BIOS_SPEW, "lb_size = 0x%08lx\n", lb_size);
- printk(BIOS_SPEW, "buffer = 0x%08lx\n", buffer);
-
- /* Jump to kernel */
- __asm__ __volatile__(
- " cld \n\t"
-#ifdef __x86_64__
- /* switch back to 32-bit mode */
- " push %4\n\t"
- " push %3\n\t"
- " push %2\n\t"
- " push %1\n\t"
- " push %0\n\t"
-
- ".intel_syntax noprefix\n\t"
- /* use iret to switch to 32-bit code segment */
- " xor rax,rax\n\t"
- " mov ax, ss\n\t"
- " push rax\n\t"
- " mov rax, rsp\n\t"
- " add rax, 8\n\t"
- " push rax\n\t"
- " pushfq\n\t"
- " push 0x10\n\t"
- " lea rax,[rip+3]\n\t"
- " push rax\n\t"
- " iretq\n\t"
- ".code32\n\t"
- /* disable paging */
- " mov eax, cr0\n\t"
- " btc eax, 31\n\t"
- " mov cr0, eax\n\t"
- /* disable long mode */
- " mov ecx, 0xC0000080\n\t"
- " rdmsr\n\t"
- " btc eax, 8\n\t"
- " wrmsr\n\t"
-
- " pop eax\n\t"
- " add esp, 4\n\t"
- " pop ebx\n\t"
- " add esp, 4\n\t"
- " pop ecx\n\t"
-
- " add esp, 4\n\t"
- " pop edx\n\t"
- " add esp, 4\n\t"
- " pop esi\n\t"
- " add esp, 4\n\t"
-
- ".att_syntax prefix\n\t"
-#endif
-
- /* Save the callee save registers... */
- " pushl %%esi\n\t"
- " pushl %%edi\n\t"
- " pushl %%ebx\n\t"
- /* Save the parameters I was passed */
-#ifdef __x86_64__
- " pushl $0\n\t" /* 20 adjust */
- " pushl %%eax\n\t" /* 16 lb_start */
- " pushl %%ebx\n\t" /* 12 buffer */
- " pushl %%ecx\n\t" /* 8 lb_size */
- " pushl %%edx\n\t" /* 4 entry */
- " pushl %%esi\n\t" /* 0 elf_boot_notes */
-#else
- " pushl $0\n\t" /* 20 adjust */
- " pushl %0\n\t" /* 16 lb_start */
- " pushl %1\n\t" /* 12 buffer */
- " pushl %2\n\t" /* 8 lb_size */
- " pushl %3\n\t" /* 4 entry */
- " pushl %4\n\t" /* 0 elf_boot_notes */
-
-#endif
- /* Compute the adjustment */
- " xorl %%eax, %%eax\n\t"
- " subl 16(%%esp), %%eax\n\t"
- " addl 12(%%esp), %%eax\n\t"
- " addl 8(%%esp), %%eax\n\t"
- " movl %%eax, 20(%%esp)\n\t"
- /* Place a copy of coreboot in its new location */
- /* Move ``longs'' the coreboot size is 4 byte aligned */
- " movl 12(%%esp), %%edi\n\t"
- " addl 8(%%esp), %%edi\n\t"
- " movl 16(%%esp), %%esi\n\t"
- " movl 8(%%esp), %%ecx\n\n"
- " shrl $2, %%ecx\n\t"
- " rep movsl\n\t"
-
- /* Adjust the stack pointer to point into the new coreboot image */
- " addl 20(%%esp), %%esp\n\t"
- /* Adjust the instruction pointer to point into the new coreboot image */
- " movl $1f, %%eax\n\t"
- " addl 20(%%esp), %%eax\n\t"
- " jmp *%%eax\n\t"
- "1: \n\t"
-
- /* Copy the coreboot bounce buffer over coreboot */
- /* Move ``longs'' the coreboot size is 4 byte aligned */
- " movl 16(%%esp), %%edi\n\t"
- " movl 12(%%esp), %%esi\n\t"
- " movl 8(%%esp), %%ecx\n\t"
- " shrl $2, %%ecx\n\t"
- " rep movsl\n\t"
-
- /* Now jump to the loaded image */
- " movl %5, %%eax\n\t"
- " movl 0(%%esp), %%ebx\n\t"
- " call *4(%%esp)\n\t"
-
- /* The loaded image returned? */
- " cli \n\t"
- " cld \n\t"
-
- /* Copy the saved copy of coreboot where coreboot runs */
- /* Move ``longs'' the coreboot size is 4 byte aligned */
- " movl 16(%%esp), %%edi\n\t"
- " movl 12(%%esp), %%esi\n\t"
- " addl 8(%%esp), %%esi\n\t"
- " movl 8(%%esp), %%ecx\n\t"
- " shrl $2, %%ecx\n\t"
- " rep movsl\n\t"
-
- /* Adjust the stack pointer to point into the old coreboot image */
- " subl 20(%%esp), %%esp\n\t"
-
- /* Adjust the instruction pointer to point into the old coreboot image */
- " movl $1f, %%eax\n\t"
- " subl 20(%%esp), %%eax\n\t"
- " jmp *%%eax\n\t"
- "1: \n\t"
-
- /* Drop the parameters I was passed */
- " addl $24, %%esp\n\t"
-
- /* Restore the callee save registers */
- " popl %%ebx\n\t"
- " popl %%edi\n\t"
- " popl %%esi\n\t"
-#ifdef __x86_64__
- ".code64\n\t"
-#endif
- ::
- "ri" (lb_start), "ri" (buffer), "ri" (lb_size),
- "ri" (entry),
- "ri"(0), "ri" (0)
- );
-}
-
-static void try_payload(struct prog *prog)
-{
- if (prog_type(prog) == ASSET_PAYLOAD) {
- if (IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE))
- jmp_payload_no_bounce_buffer(prog_entry(prog));
- else
- jmp_payload(prog_entry(prog),
- (uintptr_t)prog_start(prog),
- prog_size(prog));
- }
-}
-
-void arch_prog_run(struct prog *prog)
-{
- if (ENV_RAMSTAGE)
- try_payload(prog);
- __asm__ volatile (
-#ifdef __x86_64__
- "jmp *%%rdi\n"
-#else
- "jmp *%%edi\n"
-#endif
-
- :: "D"(prog_entry(prog))
- );
-}
diff --git a/src/arch/x86/boot/cbmem.c b/src/arch/x86/boot/cbmem.c
deleted file mode 100644
index e279db9..0000000
--- a/src/arch/x86/boot/cbmem.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <stdlib.h>
-#include <console/console.h>
-#include <cbmem.h>
-#include <arch/acpi.h>
-
-#if IS_ENABLED(CONFIG_LATE_CBMEM_INIT)
-
-#if !defined(__PRE_RAM__)
-void __attribute__((weak)) backup_top_of_ram(uint64_t ramtop)
-{
- /* Do nothing. Chipset may have implementation to save ramtop in NVRAM. */
-}
-
-static void *ramtop_pointer;
-
-void set_top_of_ram(uint64_t ramtop)
-{
- backup_top_of_ram(ramtop);
- ramtop_pointer = (void *)(uintptr_t)ramtop;
-}
-
-static inline void *saved_ramtop(void)
-{
- return ramtop_pointer;
-}
-#else
-static inline void *saved_ramtop(void)
-{
- return NULL;
-}
-#endif /* !__PRE_RAM__ */
-
-unsigned long __attribute__((weak)) get_top_of_ram(void)
-{
- return 0;
-}
-
-void *cbmem_top(void)
-{
- /* Top of cbmem is at lowest usable DRAM address below 4GiB. */
- void *ptr = saved_ramtop();
-
- if (ptr != NULL)
- return ptr;
-
- return (void *)get_top_of_ram();
-}
-
-#endif /* LATE_CBMEM_INIT */
-
-/* Something went wrong, our high memory area got wiped */
-void cbmem_fail_resume(void)
-{
-#if !defined(__PRE_RAM__) && IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
- /* ACPI resume needs to be cleared in the fail-to-recover case, but that
- * condition is only handled during ramstage. */
- acpi_fail_wakeup();
-#endif
-}
diff --git a/src/arch/x86/boot/gdt.c b/src/arch/x86/boot/gdt.c
deleted file mode 100644
index a21fab2..0000000
--- a/src/arch/x86/boot/gdt.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2008-2009 coresystems GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <types.h>
-#include <string.h>
-#include <cbmem.h>
-#include <console/console.h>
-#include <cpu/x86/gdt.h>
-
-/* i386 lgdt argument */
-struct gdtarg {
- u16 limit;
-#ifdef __x86_64__
- u64 base;
-#else
- u32 base;
-#endif
-} __attribute__((packed));
-
-/* Copy GDT to new location and reload it.
- * FIXME: We only do this for BSP CPU.
- */
-static void move_gdt(int is_recovery)
-{
- void *newgdt;
- u16 num_gdt_bytes = (uintptr_t)&gdt_end - (uintptr_t)&gdt;
- struct gdtarg gdtarg;
-
- newgdt = cbmem_find(CBMEM_ID_GDT);
- if (!newgdt) {
- newgdt = cbmem_add(CBMEM_ID_GDT, ALIGN(num_gdt_bytes, 512));
- if (!newgdt) {
- printk(BIOS_ERR, "Error: Could not relocate GDT.\n");
- return;
- }
- printk(BIOS_DEBUG, "Moving GDT to %p...", newgdt);
- memcpy((void*)newgdt, &gdt, num_gdt_bytes);
- }
-
- gdtarg.base = (uintptr_t)newgdt;
- gdtarg.limit = num_gdt_bytes - 1;
-
- __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg));
- printk(BIOS_DEBUG, "ok\n");
-}
-RAMSTAGE_CBMEM_INIT_HOOK(move_gdt)
diff --git a/src/arch/x86/boot/mpspec.c b/src/arch/x86/boot/mpspec.c
deleted file mode 100644
index 1a0ac31..0000000
--- a/src/arch/x86/boot/mpspec.c
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2014 Sage Electronic Engineering, LLC.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <console/console.h>
-#include <device/path.h>
-#include <device/pci_ids.h>
-#include <cpu/cpu.h>
-#include <arch/smp/mpspec.h>
-#include <string.h>
-#include <arch/cpu.h>
-#include <cpu/x86/lapic.h>
-#include <drivers/generic/ioapic/chip.h>
-
-/* Initialize the specified "mc" struct with initial values. */
-void mptable_init(struct mp_config_table *mc, u32 lapic_addr)
-{
- int i;
-
- memset(mc, 0, sizeof(*mc));
-
- memcpy(mc->mpc_signature, MPC_SIGNATURE, 4);
-
- mc->mpc_length = sizeof(*mc); /* Initially just the header size. */
- mc->mpc_spec = 0x04; /* MultiProcessor specification 1.4 */
- mc->mpc_checksum = 0; /* Not yet computed. */
- mc->mpc_oemptr = 0;
- mc->mpc_oemsize = 0;
- mc->mpc_entry_count = 0; /* No entries yet... */
- mc->mpc_lapic = lapic_addr;
- mc->mpe_length = 0;
- mc->mpe_checksum = 0;
- mc->reserved = 0;
-
- strncpy(mc->mpc_oem, CONFIG_MAINBOARD_VENDOR, 8);
- strncpy(mc->mpc_productid, CONFIG_MAINBOARD_PART_NUMBER, 12);
-
- /*
- * The oem/productid fields are exactly 8/12 bytes long. If the resp.
- * entry is shorter, the remaining bytes are filled with spaces.
- */
- for (i = MIN(strlen(CONFIG_MAINBOARD_VENDOR), 8); i < 8; i++)
- mc->mpc_oem[i] = ' ';
- for (i = MIN(strlen(CONFIG_MAINBOARD_PART_NUMBER), 12); i < 12; i++)
- mc->mpc_productid[i] = ' ';
-}
-
-static unsigned char smp_compute_checksum(void *v, int len)
-{
- unsigned char *bytes;
- unsigned char checksum;
- int i;
- bytes = v;
- checksum = 0;
- for(i = 0; i < len; i++) {
- checksum -= bytes[i];
- }
- return checksum;
-}
-
-static void *smp_write_floating_table_physaddr(uintptr_t addr, uintptr_t mpf_physptr, unsigned int virtualwire)
-{
- struct intel_mp_floating *mf;
- void *v;
-
- v = (void *)addr;
- mf = v;
- mf->mpf_signature[0] = '_';
- mf->mpf_signature[1] = 'M';
- mf->mpf_signature[2] = 'P';
- mf->mpf_signature[3] = '_';
- mf->mpf_physptr = mpf_physptr;
- mf->mpf_length = 1;
- mf->mpf_specification = 4;
- mf->mpf_checksum = 0;
- mf->mpf_feature1 = 0;
- mf->mpf_feature2 = virtualwire?MP_FEATURE_PIC:MP_FEATURE_VIRTUALWIRE;
- mf->mpf_feature3 = 0;
- mf->mpf_feature4 = 0;
- mf->mpf_feature5 = 0;
- mf->mpf_checksum = smp_compute_checksum(mf, mf->mpf_length*16);
- return v;
-}
-
-void *smp_write_floating_table(unsigned long addr, unsigned int virtualwire)
-{
- /* 16 byte align the table address */
- addr = (addr + 0xf) & (~0xf);
- return smp_write_floating_table_physaddr(addr, addr + SMP_FLOATING_TABLE_LEN, virtualwire);
-}
-
-void *smp_next_mpc_entry(struct mp_config_table *mc)
-{
- void *v;
- v = (void *)(((char *)mc) + mc->mpc_length);
-
- return v;
-}
-static void smp_add_mpc_entry(struct mp_config_table *mc, u16 length)
-{
- mc->mpc_length += length;
- mc->mpc_entry_count++;
-}
-
-void *smp_next_mpe_entry(struct mp_config_table *mc)
-{
- void *v;
- v = (void *)(((char *)mc) + mc->mpc_length + mc->mpe_length);
-
- return v;
-}
-static void smp_add_mpe_entry(struct mp_config_table *mc, mpe_t mpe)
-{
- mc->mpe_length += mpe->mpe_length;
-}
-
-/*
- * Type 0: Processor Entries:
- * Entry Type, LAPIC ID, LAPIC Version, CPU Flags EN/BP,
- * CPU Signature (Stepping, Model, Family), Feature Flags
- */
-void smp_write_processor(struct mp_config_table *mc,
- u8 apicid, u8 apicver, u8 cpuflag,
- u32 cpufeature, u32 featureflag)
-{
- struct mpc_config_processor *mpc;
- mpc = smp_next_mpc_entry(mc);
- memset(mpc, '\0', sizeof(*mpc));
- mpc->mpc_type = MP_PROCESSOR;
- mpc->mpc_apicid = apicid;
- mpc->mpc_apicver = apicver;
- mpc->mpc_cpuflag = cpuflag;
- mpc->mpc_cpufeature = cpufeature;
- mpc->mpc_featureflag = featureflag;
- smp_add_mpc_entry(mc, sizeof(*mpc));
-}
-
-/*
- * If we assume a symmetric processor configuration we can
- * get all of the information we need to write the processor
- * entry from the bootstrap processor.
- * Plus I don't think linux really even cares.
- * Having the proper apicid's in the table so the non-bootstrap
- * processors can be woken up should be enough.
- */
-void smp_write_processors(struct mp_config_table *mc)
-{
- int boot_apic_id;
- int order_id;
- unsigned apic_version;
- unsigned cpu_features;
- unsigned cpu_feature_flags;
- struct cpuid_result result;
- struct device *cpu;
-
- boot_apic_id = lapicid();
- apic_version = lapic_read(LAPIC_LVR) & 0xff;
- result = cpuid(1);
- cpu_features = result.eax;
- cpu_feature_flags = result.edx;
- /* order the output of the cpus to fix a bug in kernel 2.6.11 */
- for(order_id = 0;order_id <256; order_id++) {
- for(cpu = all_devices; cpu; cpu = cpu->next) {
- unsigned long cpu_flag;
- if ((cpu->path.type != DEVICE_PATH_APIC) ||
- (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER))
- continue;
-
- if (!cpu->enabled)
- continue;
-
- cpu_flag = MPC_CPU_ENABLED;
-
- if (boot_apic_id == cpu->path.apic.apic_id)
- cpu_flag = MPC_CPU_ENABLED | MPC_CPU_BOOTPROCESSOR;
-
- if(cpu->path.apic.apic_id == order_id) {
- smp_write_processor(mc,
- cpu->path.apic.apic_id, apic_version,
- cpu_flag, cpu_features, cpu_feature_flags
- );
- break;
- }
- }
- }
-}
-
-/*
- * Type 1: Bus Entries:
- * Entry Type, Bus ID, Bus Type
- */
-static void smp_write_bus(struct mp_config_table *mc,
- u8 id, const char *bustype)
-{
- struct mpc_config_bus *mpc;
- mpc = smp_next_mpc_entry(mc);
- memset(mpc, '\0', sizeof(*mpc));
- mpc->mpc_type = MP_BUS;
- mpc->mpc_busid = id;
- memcpy(mpc->mpc_bustype, bustype, sizeof(mpc->mpc_bustype));
- smp_add_mpc_entry(mc, sizeof(*mpc));
-}
-
-/*
- * Type 2: I/O APIC Entries:
- * Entry Type, APIC ID, Version,
- * APIC Flags:EN, Address
- */
-void smp_write_ioapic(struct mp_config_table *mc,
- u8 id, u8 ver, void *apicaddr)
-{
- struct mpc_config_ioapic *mpc;
- mpc = smp_next_mpc_entry(mc);
- memset(mpc, '\0', sizeof(*mpc));
- mpc->mpc_type = MP_IOAPIC;
- mpc->mpc_apicid = id;
- mpc->mpc_apicver = ver;
- mpc->mpc_flags = MPC_APIC_USABLE;
- mpc->mpc_apicaddr = apicaddr;
- smp_add_mpc_entry(mc, sizeof(*mpc));
-}
-
-/*
- * Type 3: I/O Interrupt Table Entries:
- * Entry Type, Int Type, Int Polarity, Int Level,
- * Source Bus ID, Source Bus IRQ, Dest APIC ID, Dest PIN#
- */
-void smp_write_intsrc(struct mp_config_table *mc,
- u8 irqtype, u16 irqflag,
- u8 srcbus, u8 srcbusirq,
- u8 dstapic, u8 dstirq)
-{
- struct mpc_config_intsrc *mpc;
- mpc = smp_next_mpc_entry(mc);
- memset(mpc, '\0', sizeof(*mpc));
- mpc->mpc_type = MP_INTSRC;
- mpc->mpc_irqtype = irqtype;
- mpc->mpc_irqflag = irqflag;
- mpc->mpc_srcbus = srcbus;
- mpc->mpc_srcbusirq = srcbusirq;
- mpc->mpc_dstapic = dstapic;
- mpc->mpc_dstirq = dstirq;
- smp_add_mpc_entry(mc, sizeof(*mpc));
-#ifdef DEBUG_MPTABLE
- printk(BIOS_DEBUG, "add intsrc srcbus 0x%x srcbusirq 0x%x, dstapic 0x%x, dstirq 0x%x\n",
- srcbus, srcbusirq, dstapic, dstirq);
- hexdump(__func__, mpc, sizeof(*mpc));
-#endif
-}
-
-/*
- * Type 3: I/O Interrupt Table Entries for PCI Devices:
- * This has the same fields as 'Type 3: I/O Interrupt Table Entries'
- * but the Source Bus IRQ field has a slightly different
- * definition:
- * Bits 1-0: PIRQ pin: INT_A# = 0, INT_B# = 1, INT_C# = 2, INT_D# = 3
- * Bits 2-6: Originating PCI Device Number (Not its parent bridge device number)
- * Bit 7: Reserved
- */
-void smp_write_pci_intsrc(struct mp_config_table *mc,
- u8 irqtype, u8 srcbus, u8 dev, u8 pirq,
- u8 dstapic, u8 dstirq)
-{
- u8 srcbusirq = (dev << 2) | pirq;
- printk(BIOS_SPEW, "\tPCI srcbusirq = 0x%x from dev = 0x%x and pirq = %x\n", srcbusirq, dev, pirq);
- smp_write_intsrc(mc, irqtype, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, srcbus,
- srcbusirq, dstapic, dstirq);
-}
-
-void smp_write_intsrc_pci_bridge(struct mp_config_table *mc,
- u8 irqtype, u16 irqflag, struct device *dev,
- unsigned char dstapic, unsigned char *dstirq)
-{
- struct device *child;
-
- int i;
- int srcbus;
- int slot;
-
- struct bus *link;
- unsigned char dstirq_x[4];
-
- for (link = dev->link_list; link; link = link->next) {
-
- child = link->children;
- srcbus = link->secondary;
-
- while (child) {
- if (child->path.type != DEVICE_PATH_PCI)
- goto next;
-
- slot = (child->path.pci.devfn >> 3);
- /* round pins */
- for (i = 0; i < 4; i++)
- dstirq_x[i] = dstirq[(i + slot) % 4];
-
- if ((child->class >> 16) != PCI_BASE_CLASS_BRIDGE) {
- /* pci device */
- printk(BIOS_DEBUG, "route irq: %s\n", dev_path(child));
- for (i = 0; i < 4; i++)
- smp_write_intsrc(mc, irqtype, irqflag, srcbus, (slot<<2)|i, dstapic, dstirq_x[i]);
- goto next;
- }
-
- switch (child->class>>8) {
- case PCI_CLASS_BRIDGE_PCI:
- case PCI_CLASS_BRIDGE_PCMCIA:
- case PCI_CLASS_BRIDGE_CARDBUS:
- printk(BIOS_DEBUG, "route irq bridge: %s\n", dev_path(child));
- smp_write_intsrc_pci_bridge(mc, irqtype, irqflag, child, dstapic, dstirq_x);
- }
-
-next:
- child = child->sibling;
- }
-
- }
-}
-
-/*
- * Type 4: Local Interrupt Assignment Entries:
- * Entry Type, Int Type, Int Polarity, Int Level,
- * Source Bus ID, Source Bus IRQ, Dest LAPIC ID,
- * Dest LAPIC LINTIN#
- */
-void smp_write_lintsrc(struct mp_config_table *mc,
- u8 irqtype, u16 irqflag,
- u8 srcbusid, u8 srcbusirq,
- u8 destapic, u8 destapiclint)
-{
- struct mpc_config_lintsrc *mpc;
- mpc = smp_next_mpc_entry(mc);
- memset(mpc, '\0', sizeof(*mpc));
- mpc->mpc_type = MP_LINTSRC;
- mpc->mpc_irqtype = irqtype;
- mpc->mpc_irqflag = irqflag;
- mpc->mpc_srcbusid = srcbusid;
- mpc->mpc_srcbusirq = srcbusirq;
- mpc->mpc_destapic = destapic;
- mpc->mpc_destapiclint = destapiclint;
- smp_add_mpc_entry(mc, sizeof(*mpc));
-}
-
-/*
- * Type 128: System Address Space Mapping Entries
- * Entry Type, Entry Length, Bus ID, Address Type,
- * Address Base Lo/Hi, Address Length Lo/Hi
- */
-void smp_write_address_space(struct mp_config_table *mc,
- u8 busid, u8 address_type,
- u32 address_base_low, u32 address_base_high,
- u32 address_length_low, u32 address_length_high)
-{
- struct mp_exten_system_address_space *mpe;
- mpe = smp_next_mpe_entry(mc);
- memset(mpe, '\0', sizeof(*mpe));
- mpe->mpe_type = MPE_SYSTEM_ADDRESS_SPACE;
- mpe->mpe_length = sizeof(*mpe);
- mpe->mpe_busid = busid;
- mpe->mpe_address_type = address_type;
- mpe->mpe_address_base_low = address_base_low;
- mpe->mpe_address_base_high = address_base_high;
- mpe->mpe_address_length_low = address_length_low;
- mpe->mpe_address_length_high = address_length_high;
- smp_add_mpe_entry(mc, (mpe_t)mpe);
-}
-
-/*
- * Type 129: Bus Hierarchy Descriptor Entry
- * Entry Type, Entry Length, Bus ID, Bus Info,
- * Parent Bus ID
- */
-void smp_write_bus_hierarchy(struct mp_config_table *mc,
- u8 busid, u8 bus_info, u8 parent_busid)
-{
- struct mp_exten_bus_hierarchy *mpe;
- mpe = smp_next_mpe_entry(mc);
- memset(mpe, '\0', sizeof(*mpe));
- mpe->mpe_type = MPE_BUS_HIERARCHY;
- mpe->mpe_length = sizeof(*mpe);
- mpe->mpe_busid = busid;
- mpe->mpe_bus_info = bus_info;
- mpe->mpe_parent_busid = parent_busid;
- smp_add_mpe_entry(mc, (mpe_t)mpe);
-}
-
-/*
- * Type 130: Compatibility Bus Address Space Modifier Entry
- * Entry Type, Entry Length, Bus ID, Address Modifier
- * Predefined Range List
- */
-void smp_write_compatibility_address_space(struct mp_config_table *mc,
- u8 busid, u8 address_modifier,
- u32 range_list)
-{
- struct mp_exten_compatibility_address_space *mpe;
- mpe = smp_next_mpe_entry(mc);
- memset(mpe, '\0', sizeof(*mpe));
- mpe->mpe_type = MPE_COMPATIBILITY_ADDRESS_SPACE;
- mpe->mpe_length = sizeof(*mpe);
- mpe->mpe_busid = busid;
- mpe->mpe_address_modifier = address_modifier;
- mpe->mpe_range_list = range_list;
- smp_add_mpe_entry(mc, (mpe_t)mpe);
-}
-
-void mptable_lintsrc(struct mp_config_table *mc, unsigned long bus_isa)
-{
- smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x0);
- smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x1);
-}
-
-void mptable_add_isa_interrupts(struct mp_config_table *mc, unsigned long bus_isa, unsigned long apicid, int external_int2)
-{
-/*I/O Ints: Type Trigger Polarity Bus ID IRQ APIC ID PIN# */
- smp_write_intsrc(mc, external_int2?mp_INT:mp_ExtINT,
- MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, apicid, 0x0);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x1, apicid, 0x1);
- smp_write_intsrc(mc, external_int2?mp_ExtINT:mp_INT,
- MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, apicid, 0x2);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x3, apicid, 0x3);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x4, apicid, 0x4);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x6, apicid, 0x6);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x7, apicid, 0x7);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x8, apicid, 0x8);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x9, apicid, 0x9);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xa, apicid, 0xa);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xb, apicid, 0xb);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xc, apicid, 0xc);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xd, apicid, 0xd);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xe, apicid, 0xe);
- smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xf, apicid, 0xf);
-}
-
-void mptable_write_buses(struct mp_config_table *mc, int *max_pci_bus, int *isa_bus) {
- int dummy, i, highest;
- char buses[256];
- struct device *dev;
-
- if (!max_pci_bus) max_pci_bus = &dummy;
- if (!isa_bus) isa_bus = &dummy;
-
- *max_pci_bus = 0;
- highest = 0;
- memset(buses, 0, sizeof(buses));
-
- for (dev = all_devices; dev; dev = dev->next) {
- struct bus *bus;
- for (bus = dev->link_list; bus; bus = bus->next) {
- if (bus->secondary > 255) {
- printk(BIOS_ERR, "A bus claims to have a bus ID > 255?!? Aborting");
- return;
- }
- buses[bus->secondary] = 1;
- if (highest < bus->secondary) highest = bus->secondary;
- }
- }
- for (i=0; i <= highest; i++) {
- if (buses[i]) {
- smp_write_bus(mc, i, "PCI ");
- *max_pci_bus = i;
- }
- }
- *isa_bus = *max_pci_bus + 1;
- smp_write_bus(mc, *isa_bus, "ISA ");
-}
-
-void *mptable_finalize(struct mp_config_table *mc)
-{
- 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 __attribute__((weak)) write_smp_table(unsigned long addr)
-{
- struct drivers_generic_ioapic_config *ioapic_config;
- struct mp_config_table *mc;
- int isa_bus, pin, parentpin;
- struct device *dev;
- struct device *parent;
- struct device *oldparent;
- void *tmp, *v;
- int isaioapic = -1, have_fixed_entries;
-
- v = smp_write_floating_table(addr, 0);
- mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
-
- mptable_init(mc, LOCAL_APIC_ADDR);
-
- smp_write_processors(mc);
-
- mptable_write_buses(mc, NULL, &isa_bus);
-
- for(dev = all_devices; dev; dev = dev->next) {
- if (dev->path.type != DEVICE_PATH_IOAPIC)
- continue;
-
- if (!(ioapic_config = dev->chip_info)) {
- printk(BIOS_ERR, "%s has no config, ignoring\n", dev_path(dev));
- continue;
- }
- smp_write_ioapic(mc, dev->path.ioapic.ioapic_id,
- ioapic_config->version,
- ioapic_config->base);
-
- if (ioapic_config->have_isa_interrupts) {
- if (isaioapic >= 0)
- printk(BIOS_ERR, "More than one IOAPIC with ISA interrupts?\n");
- else
- isaioapic = dev->path.ioapic.ioapic_id;
- }
- }
-
- if (isaioapic >= 0) {
- /* Legacy Interrupts */
- printk(BIOS_DEBUG, "Writing ISA IRQs\n");
- mptable_add_isa_interrupts(mc, isa_bus, isaioapic, 0);
- }
-
- for(dev = all_devices; dev; dev = dev->next) {
-
- if (dev->path.type != DEVICE_PATH_PCI || !dev->enabled)
- continue;
-
- have_fixed_entries = 0;
- for (pin = 0; pin < 4; pin++) {
- if (dev->pci_irq_info[pin].ioapic_dst_id) {
- printk(BIOS_DEBUG, "fixed IRQ entry for: %s: INT%c# -> IOAPIC %d PIN %d\n", dev_path(dev),
- pin + 'A',
- dev->pci_irq_info[pin].ioapic_dst_id,
- dev->pci_irq_info[pin].ioapic_irq_pin);
- smp_write_intsrc(mc, mp_INT,
- dev->pci_irq_info[pin].ioapic_flags,
- dev->bus->secondary,
- ((dev->path.pci.devfn & 0xf8) >> 1) | pin,
- dev->pci_irq_info[pin].ioapic_dst_id,
- dev->pci_irq_info[pin].ioapic_irq_pin);
- have_fixed_entries = 1;
- }
- }
-
- if (!have_fixed_entries) {
- pin = (dev->path.pci.devfn & 7) % 4;
- oldparent = parent = dev;
- while((parent = parent->bus->dev)) {
- parentpin = (oldparent->path.pci.devfn >> 3) + (oldparent->path.pci.devfn & 7);
- parentpin += dev->path.pci.devfn & 7;
- parentpin += dev->path.pci.devfn >> 3;
- parentpin %= 4;
-
- if (parent->pci_irq_info[parentpin].ioapic_dst_id) {
- printk(BIOS_DEBUG, "automatic IRQ entry for %s: INT%c# -> IOAPIC %d PIN %d\n",
- dev_path(dev), pin + 'A',
- parent->pci_irq_info[parentpin].ioapic_dst_id,
- parent->pci_irq_info[parentpin].ioapic_irq_pin);
- smp_write_intsrc(mc, mp_INT,
- parent->pci_irq_info[parentpin].ioapic_flags,
- dev->bus->secondary,
- ((dev->path.pci.devfn & 0xf8) >> 1) | pin,
- parent->pci_irq_info[parentpin].ioapic_dst_id,
- parent->pci_irq_info[parentpin].ioapic_irq_pin);
-
- break;
- }
-
- if (parent->path.type == DEVICE_PATH_DOMAIN) {
- printk(BIOS_WARNING, "no IRQ found for %s\n", dev_path(dev));
- break;
- }
- oldparent = parent;
- }
- }
- }
-
- mptable_lintsrc(mc, isa_bus);
- tmp = mptable_finalize(mc);
- printk(BIOS_INFO, "MPTABLE len: %d\n", (unsigned int)((uintptr_t)tmp -
- (uintptr_t)v));
- return (unsigned long)tmp;
-}
diff --git a/src/arch/x86/boot/pirq_routing.c b/src/arch/x86/boot/pirq_routing.c
deleted file mode 100644
index 7fe20b2..0000000
--- a/src/arch/x86/boot/pirq_routing.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me at gmail.com>
- * Copyright (C) 2010 Stefan Reinauer <stepan at coreboot.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include <console/console.h>
-#include <arch/pirq_routing.h>
-#include <string.h>
-#include <device/pci.h>
-
-#if CONFIG_DEBUG_PIRQ
-static void check_pirq_routing_table(struct irq_routing_table *rt)
-{
- uint8_t *addr = (uint8_t *)rt;
- uint8_t sum=0;
- int i;
-
- printk(BIOS_INFO, "Checking Interrupt Routing Table consistency...\n");
-
- if (sizeof(struct irq_routing_table) != rt->size) {
- printk(BIOS_WARNING, "Inconsistent Interrupt Routing Table size (0x%x/0x%x).\n",
- (unsigned int) sizeof(struct irq_routing_table),
- rt->size
- );
- rt->size=sizeof(struct irq_routing_table);
- }
-
- for (i = 0; i < rt->size; i++)
- sum += addr[i];
-
- printk(BIOS_DEBUG, "%s(): Interrupt Routing Table located at %p.\n",
- __func__, addr);
-
-
- sum = rt->checksum - sum;
-
- if (sum != rt->checksum) {
- printk(BIOS_WARNING, "Interrupt Routing Table checksum is: 0x%02x but should be: 0x%02x.\n",
- rt->checksum, sum);
- rt->checksum = sum;
- }
-
- if (rt->signature != PIRQ_SIGNATURE || rt->version != PIRQ_VERSION ||
- rt->size % 16 ) {
- printk(BIOS_WARNING, "Interrupt Routing Table not valid.\n");
- return;
- }
-
- sum = 0;
- for (i=0; i<rt->size; i++)
- sum += addr[i];
-
- /* We're manually fixing the checksum above. This warning can probably
- * never happen because if the target location is read-only this
- * function would have bailed out earlier.
- */
- if (sum) {
- printk(BIOS_WARNING, "Checksum error in Interrupt Routing Table "
- "could not be fixed.\n");
- }
-
- printk(BIOS_INFO, "done.\n");
-}
-
-static int verify_copy_pirq_routing_table(unsigned long addr, const struct irq_routing_table *routing_table)
-{
- int i;
- uint8_t *rt_orig, *rt_curr;
-
- rt_curr = (uint8_t*)addr;
- rt_orig = (uint8_t*)routing_table;
- printk(BIOS_INFO, "Verifying copy of Interrupt Routing Table at 0x%08lx... ", addr);
- for (i = 0; i < routing_table->size; i++) {
- if (*(rt_curr + i) != *(rt_orig + i)) {
- printk(BIOS_INFO, "failed\n");
- return -1;
- }
- }
- printk(BIOS_INFO, "done\n");
-
- check_pirq_routing_table((struct irq_routing_table *)addr);
-
- return 0;
-}
-#endif
-
-#if CONFIG_PIRQ_ROUTE
-static u8 pirq_get_next_free_irq(u8* pirq, u16 bitmap)
-{
- int i, link;
- u8 irq = 0;
- for (i = 2; i <= 15; i++)
- {
- /* Can we assign this IRQ ? */
- if (!((bitmap >> i) & 1))
- continue;
- /* We can, Now let's assume we can use this IRQ */
- irq = i;
- /* And assume we have not yet routed it */
- int already_routed = 0;
- /* Have we already routed it ? */
- for(link = 0; link < CONFIG_MAX_PIRQ_LINKS; link++) {
- if (pirq[link] == irq) {
- already_routed = 1;
- break;
- }
- }
- /* If it's not yet routed, use it */
- if(!already_routed)
- break;
- /* But if it was already routed, try the next one */
- continue;
- }
- /* Now we got our IRQ */
- return irq;
-}
-
-static void pirq_route_irqs(unsigned long addr)
-{
- int i, intx, num_entries;
- unsigned char irq_slot[MAX_INTX_ENTRIES];
- unsigned char pirq[CONFIG_MAX_PIRQ_LINKS];
- struct irq_routing_table *pirq_tbl;
-
- memset(pirq, 0, CONFIG_MAX_PIRQ_LINKS);
-
- pirq_tbl = (struct irq_routing_table *)(addr);
- num_entries = (pirq_tbl->size - 32) / 16;
-
- /* Set PCI IRQs. */
- for (i = 0; i < num_entries; i++) {
-
- printk(BIOS_DEBUG, "PIRQ Entry %d Dev/Fn: %X Slot: %d\n", i,
- pirq_tbl->slots[i].devfn >> 3, pirq_tbl->slots[i].slot);
-
- for (intx = 0; intx < MAX_INTX_ENTRIES; intx++) {
-
- int link = pirq_tbl->slots[i].irq[intx].link;
- int bitmap = pirq_tbl->slots[i].irq[intx].bitmap;
- int irq = 0;
-
- printk(BIOS_DEBUG, "INT: %c link: %x bitmap: %x ",
- 'A' + intx, link, bitmap);
-
- if (!bitmap|| !link || link > CONFIG_MAX_PIRQ_LINKS) {
-
- printk(BIOS_DEBUG, "not routed\n");
- irq_slot[intx] = irq;
- continue;
- }
-
- /* yet not routed */
- if (!pirq[link - 1])
- {
- irq = pirq_get_next_free_irq(pirq, bitmap);
- if (irq)
- pirq[link - 1] = irq;
- }
- else
- irq = pirq[link - 1];
-
- printk(BIOS_DEBUG, "IRQ: %d\n", irq);
- irq_slot[intx] = irq;
- }
-
- /* Bus, device, slots IRQs for {A,B,C,D}. */
- pci_assign_irqs(pirq_tbl->slots[i].bus,
- pirq_tbl->slots[i].devfn >> 3, irq_slot);
- }
-
- for(i = 0; i < CONFIG_MAX_PIRQ_LINKS; i++)
- printk(BIOS_DEBUG, "PIRQ%c: %d\n", i + 'A', pirq[i]);
-
- pirq_assign_irqs(pirq);
-}
-#endif
-
-unsigned long copy_pirq_routing_table(unsigned long addr, const struct irq_routing_table *routing_table)
-{
- /* Align the table to be 16 byte aligned. */
- addr = ALIGN(addr, 16);
-
- /* This table must be between 0xf0000 & 0x100000 */
- printk(BIOS_INFO, "Copying Interrupt Routing Table to 0x%08lx... ", addr);
- memcpy((void *)addr, routing_table, routing_table->size);
- printk(BIOS_INFO, "done.\n");
-#if CONFIG_DEBUG_PIRQ
- verify_copy_pirq_routing_table(addr, routing_table);
-#endif
-#if CONFIG_PIRQ_ROUTE
- pirq_route_irqs(addr);
-#endif
- return addr + routing_table->size;
-}
diff --git a/src/arch/x86/boot/smbios.c b/src/arch/x86/boot/smbios.c
deleted file mode 100644
index a1f05da..0000000
--- a/src/arch/x86/boot/smbios.c
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2015 Timothy Pearson <tpearson at raptorengineeringinc.com>, Raptor Engineering
- * Copyright (C) 2011 Sven Schnelle <svens at stackframe.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; version 2 of
- * the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <smbios.h>
-#include <console/console.h>
-#include <version.h>
-#include <device/device.h>
-#include <arch/cpu.h>
-#include <cpu/x86/name.h>
-#include <elog.h>
-#include <endian.h>
-#include <memory_info.h>
-#include <spd.h>
-#include <cbmem.h>
-#if CONFIG_CHROMEOS
-#include <vendorcode/google/chromeos/gnvs.h>
-#endif
-
-static u8 smbios_checksum(u8 *p, u32 length)
-{
- u8 ret = 0;
- while (length--)
- ret += *p++;
- return -ret;
-}
-
-
-int smbios_add_string(char *start, const char *str)
-{
- int i = 1;
- char *p = start;
-
- for(;;) {
- if (!*p) {
- strcpy(p, str);
- p += strlen(str);
- *p++ = '\0';
- *p++ = '\0';
- return i;
- }
-
- if (!strcmp(p, str))
- return i;
-
- p += strlen(p)+1;
- i++;
- }
-}
-
-int smbios_string_table_len(char *start)
-{
- char *p = start;
- int i, len = 0;
-
- while(*p) {
- i = strlen(p) + 1;
- p += i;
- len += i;
- }
- return len + 1;
-}
-
-static int smbios_cpu_vendor(char *start)
-{
- char tmp[13] = "Unknown";
- u32 *_tmp = (u32 *)tmp;
- struct cpuid_result res;
-
- if (cpu_have_cpuid()) {
- res = cpuid(0);
- _tmp[0] = res.ebx;
- _tmp[1] = res.edx;
- _tmp[2] = res.ecx;
- tmp[12] = '\0';
- }
-
- return smbios_add_string(start, tmp);
-}
-
-static int smbios_processor_name(char *start)
-{
- char tmp[49] = "Unknown Processor Name";
- u32 *_tmp = (u32 *)tmp;
- struct cpuid_result res;
- int i;
-
- if (cpu_have_cpuid()) {
- res = cpuid(0x80000000);
- if (res.eax >= 0x80000004) {
- for (i = 0; i < 3; i++) {
- res = cpuid(0x80000002 + i);
- _tmp[i * 4 + 0] = res.eax;
- _tmp[i * 4 + 1] = res.ebx;
- _tmp[i * 4 + 2] = res.ecx;
- _tmp[i * 4 + 3] = res.edx;
- }
- tmp[48] = 0;
- }
- }
- return smbios_add_string(start, tmp);
-}
-
-/* this function will fill the corresponding manufacturer */
-void smbios_fill_dimm_manufacturer_from_id(uint16_t mod_id, struct smbios_type17 *t)
-{
- switch (mod_id) {
- case 0x987f:
- t->manufacturer = smbios_add_string(t->eos,
- "Hynix");
- break;
- case 0xad80:
- t->manufacturer = smbios_add_string(t->eos,
- "Hynix/Hyundai");
- break;
- case 0xce80:
- t->manufacturer = smbios_add_string(t->eos,
- "Samsung");
- break;
- case 0xfe02:
- t->manufacturer = smbios_add_string(t->eos,
- "Elpida");
- break;
- case 0xff2c:
- t->manufacturer = smbios_add_string(t->eos,
- "Micron");
- break;
- default: {
- char string_buffer[256];
- snprintf(string_buffer, sizeof(string_buffer),
- "Unknown (%x)", mod_id);
- t->manufacturer = smbios_add_string(t->eos,
- string_buffer);
- break;
- }
- }
-}
-
-static int create_smbios_type17_for_dimm(struct dimm_info *dimm,
- unsigned long *current, int *handle)
-{
- struct smbios_type17 *t = (struct smbios_type17 *)*current;
- uint8_t length;
- char locator[40];
-
- memset(t, 0, sizeof(struct smbios_type17));
- t->memory_type = dimm->ddr_type;
- t->clock_speed = dimm->ddr_frequency;
- t->speed = dimm->ddr_frequency;
- t->type = SMBIOS_MEMORY_DEVICE;
- t->size = dimm->dimm_size;
- t->data_width = 8 * (1 << (dimm->bus_width & 0x7));
- t->total_width = t->data_width + 8 * ((dimm->bus_width & 0x18) >> 3);
-
- switch (dimm->mod_type) {
- case SPD_RDIMM:
- case SPD_MINI_RDIMM:
- t->form_factor = MEMORY_FORMFACTOR_RIMM;
- break;
- case SPD_UDIMM:
- case SPD_MICRO_DIMM:
- case SPD_MINI_UDIMM:
- t->form_factor = MEMORY_FORMFACTOR_DIMM;
- break;
- case SPD_SODIMM:
- t->form_factor = MEMORY_FORMFACTOR_SODIMM;
- break;
- default:
- t->form_factor = MEMORY_FORMFACTOR_UNKNOWN;
- break;
- }
-
- smbios_fill_dimm_manufacturer_from_id(dimm->mod_id, t);
- /* put '\0' in the end of data */
- length = sizeof(dimm->serial);
- dimm->serial[length - 1] = '\0';
- if (dimm->serial[0] == 0)
- t->serial_number = smbios_add_string(t->eos, "None");
- else
- t->serial_number = smbios_add_string(t->eos,
- (const char *)dimm->serial);
-
- snprintf(locator, sizeof(locator), "Channel-%d-DIMM-%d",
- dimm->channel_num, dimm->dimm_num);
- t->device_locator = smbios_add_string(t->eos, locator);
-
- snprintf(locator, sizeof(locator), "BANK %d", dimm->bank_locator);
- t->bank_locator = smbios_add_string(t->eos, locator);
-
- /* put '\0' in the end of data */
- length = sizeof(dimm->module_part_number);
- dimm->module_part_number[length - 1] = '\0';
- t->part_number = smbios_add_string(t->eos,
- (const char *)dimm->module_part_number);
-
- /* Synchronous = 1 */
- t->type_detail = 0x0080;
- /* no handle for error information */
- t->memory_error_information_handle = 0xFFFE;
- t->attributes = dimm->rank_per_dimm;
- t->handle = *handle;
- *handle += 1;
- t->length = sizeof(struct smbios_type17) - 2;
- return t->length + smbios_string_table_len(t->eos);
-}
-
-const char *__attribute__((weak)) smbios_mainboard_bios_version(void)
-{
- if (strlen(CONFIG_LOCALVERSION))
- return CONFIG_LOCALVERSION;
- else
- return coreboot_version;
-}
-
-static int smbios_write_type0(unsigned long *current, int handle)
-{
- struct smbios_type0 *t = (struct smbios_type0 *)*current;
- int len = sizeof(struct smbios_type0);
-
- memset(t, 0, sizeof(struct smbios_type0));
- t->type = SMBIOS_BIOS_INFORMATION;
- t->handle = handle;
- t->length = len - 2;
-
- t->vendor = smbios_add_string(t->eos, "coreboot");
-#if !CONFIG_CHROMEOS
- t->bios_release_date = smbios_add_string(t->eos, coreboot_dmi_date);
-
- t->bios_version = smbios_add_string(t->eos, smbios_mainboard_bios_version());
-#else
-#define SPACES \
- " "
- t->bios_release_date = smbios_add_string(t->eos, coreboot_dmi_date);
-#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
- u32 version_offset = (u32)smbios_string_table_len(t->eos);
-#endif
- t->bios_version = smbios_add_string(t->eos, SPACES);
-
-#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
- /* SMBIOS offsets start at 1 rather than 0 */
- vboot_data->vbt10 = (u32)t->eos + (version_offset - 1);
-#endif
-#endif /* CONFIG_CHROMEOS */
-
- t->bios_rom_size = (CONFIG_ROM_SIZE / 65535) - 1;
-
- t->system_bios_major_release = 4;
- t->bios_characteristics =
- BIOS_CHARACTERISTICS_PCI_SUPPORTED |
-#if CONFIG_CARDBUS_PLUGIN_SUPPORT
- BIOS_CHARACTERISTICS_PC_CARD |
-#endif
- BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
- BIOS_CHARACTERISTICS_UPGRADEABLE;
-
-#if CONFIG_HAVE_ACPI_TABLES
- t->bios_characteristics_ext1 = BIOS_EXT1_CHARACTERISTICS_ACPI;
-#endif
- t->bios_characteristics_ext2 = BIOS_EXT2_CHARACTERISTICS_TARGET;
- len = t->length + smbios_string_table_len(t->eos);
- *current += len;
- return len;
-}
-
-#if !CONFIG_SMBIOS_PROVIDED_BY_MOBO
-
-const char *__attribute__((weak)) smbios_mainboard_serial_number(void)
-{
- return CONFIG_MAINBOARD_SERIAL_NUMBER;
-}
-
-const char *__attribute__((weak)) smbios_mainboard_version(void)
-{
- return CONFIG_MAINBOARD_VERSION;
-}
-
-const char *__attribute__((weak)) smbios_mainboard_manufacturer(void)
-{
- return CONFIG_MAINBOARD_SMBIOS_MANUFACTURER;
-}
-
-const char *__attribute__((weak)) smbios_mainboard_product_name(void)
-{
- return CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME;
-}
-
-void __attribute__((weak)) smbios_mainboard_set_uuid(u8 *uuid)
-{
- /* leave all zero */
-}
-#endif
-
-#ifdef CONFIG_MAINBOARD_FAMILY
-const char *smbios_mainboard_family(void)
-{
- return CONFIG_MAINBOARD_FAMILY;
-}
-#endif /* CONFIG_MAINBOARD_FAMILY */
-
-static int smbios_write_type1(unsigned long *current, int handle)
-{
- struct smbios_type1 *t = (struct smbios_type1 *)*current;
- int len = sizeof(struct smbios_type1);
-
- memset(t, 0, sizeof(struct smbios_type1));
- t->type = SMBIOS_SYSTEM_INFORMATION;
- t->handle = handle;
- t->length = len - 2;
- t->manufacturer = smbios_add_string(t->eos, smbios_mainboard_manufacturer());
- t->product_name = smbios_add_string(t->eos, smbios_mainboard_product_name());
- t->serial_number = smbios_add_string(t->eos, smbios_mainboard_serial_number());
- t->version = smbios_add_string(t->eos, smbios_mainboard_version());
-#ifdef CONFIG_MAINBOARD_FAMILY
- t->family = smbios_add_string(t->eos, smbios_mainboard_family());
-#endif
- smbios_mainboard_set_uuid(t->uuid);
- len = t->length + smbios_string_table_len(t->eos);
- *current += len;
- return len;
-}
-
-static int smbios_write_type2(unsigned long *current, int handle)
-{
- struct smbios_type2 *t = (struct smbios_type2 *)*current;
- int len = sizeof(struct smbios_type2);
-
- memset(t, 0, sizeof(struct smbios_type2));
- t->type = SMBIOS_BOARD_INFORMATION;
- t->handle = handle;
- t->length = len - 2;
- t->manufacturer = smbios_add_string(t->eos, smbios_mainboard_manufacturer());
- t->product_name = smbios_add_string(t->eos, smbios_mainboard_product_name());
- t->serial_number = smbios_add_string(t->eos, smbios_mainboard_serial_number());
- t->version = smbios_add_string(t->eos, smbios_mainboard_version());
- len = t->length + smbios_string_table_len(t->eos);
- *current += len;
- return len;
-}
-
-static int smbios_write_type3(unsigned long *current, int handle)
-{
- struct smbios_type3 *t = (struct smbios_type3 *)*current;
- int len = sizeof(struct smbios_type3);
-
- memset(t, 0, sizeof(struct smbios_type3));
- t->type = SMBIOS_SYSTEM_ENCLOSURE;
- t->handle = handle;
- t->length = len - 2;
- t->manufacturer = smbios_add_string(t->eos, smbios_mainboard_manufacturer());
- t->bootup_state = SMBIOS_STATE_SAFE;
- t->power_supply_state = SMBIOS_STATE_SAFE;
- t->thermal_state = SMBIOS_STATE_SAFE;
- if(IS_ENABLED(CONFIG_SYSTEM_TYPE_LAPTOP)) {
- t->_type = SMBIOS_ENCLOSURE_NOTEBOOK;
- } else {
- t->_type = SMBIOS_ENCLOSURE_DESKTOP;
- }
- t->security_status = SMBIOS_STATE_SAFE;
- len = t->length + smbios_string_table_len(t->eos);
- *current += len;
- return len;
-}
-
-static int smbios_write_type4(unsigned long *current, int handle)
-{
- struct cpuid_result res;
- struct smbios_type4 *t = (struct smbios_type4 *)*current;
- int len = sizeof(struct smbios_type4);
-
- /* Provide sane defaults even for CPU without CPUID */
- res.eax = res.edx = 0;
- res.ebx = 0x10000;
-
- if (cpu_have_cpuid()) {
- res = cpuid(1);
- }
-
- memset(t, 0, sizeof(struct smbios_type4));
- t->type = SMBIOS_PROCESSOR_INFORMATION;
- t->handle = handle;
- t->length = len - 2;
- t->processor_id[0] = res.eax;
- t->processor_id[1] = res.edx;
- t->processor_manufacturer = smbios_cpu_vendor(t->eos);
- t->processor_version = smbios_processor_name(t->eos);
- t->processor_family = (res.eax > 0) ? 0x0c : 0x6;
- t->processor_type = 3; /* System Processor */
- t->processor_upgrade = 0x06;
- t->core_count = (res.ebx >> 16) & 0xff;
- t->l1_cache_handle = 0xffff;
- t->l2_cache_handle = 0xffff;
- t->l3_cache_handle = 0xffff;
- t->processor_upgrade = 1;
- len = t->length + smbios_string_table_len(t->eos);
- *current += len;
- return len;
-}
-
-static int smbios_write_type11(unsigned long *current, int *handle)
-{
- struct smbios_type11 *t = (struct smbios_type11 *)*current;
- int len;
- struct device *dev;
-
- memset(t, 0, sizeof *t);
- t->type = SMBIOS_OEM_STRINGS;
- t->handle = *handle;
- t->length = len = sizeof *t - 2;
-
- for(dev = all_devices; dev; dev = dev->next) {
- if (dev->ops && dev->ops->get_smbios_strings)
- dev->ops->get_smbios_strings(dev, t);
- }
-
- if (t->count == 0) {
- memset(t, 0, sizeof *t);
- return 0;
- }
-
- len += smbios_string_table_len(t->eos);
-
- *current += len;
- (*handle)++;
- return len;
-}
-
-static int smbios_write_type17(unsigned long *current, int *handle)
-{
- int len = sizeof(struct smbios_type17);
- int i;
-
- struct memory_info *meminfo;
- meminfo = cbmem_find(CBMEM_ID_MEMINFO);
- if (meminfo == NULL)
- return 0; /* can't find mem info in cbmem */
-
- printk(BIOS_INFO, "Create SMBIOS type 17\n");
- for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
- struct dimm_info *dimm;
- dimm = &meminfo->dimm[i];
- len = create_smbios_type17_for_dimm(dimm, current, handle);
- *current += len;
- }
- return meminfo->dimm_cnt * len;
-}
-
-static int smbios_write_type32(unsigned long *current, int handle)
-{
- struct smbios_type32 *t = (struct smbios_type32 *)*current;
- int len = sizeof(struct smbios_type32);
-
- memset(t, 0, sizeof(struct smbios_type32));
- t->type = SMBIOS_SYSTEM_BOOT_INFORMATION;
- t->handle = handle;
- t->length = len - 2;
- *current += len;
- return len;
-}
-
-int smbios_write_type41(unsigned long *current, int *handle,
- const char *name, u8 instance, u16 segment,
- u8 bus, u8 device, u8 function)
-{
- struct smbios_type41 *t = (struct smbios_type41 *)*current;
- int len = sizeof(struct smbios_type41);
-
- memset(t, 0, sizeof(struct smbios_type41));
- t->type = SMBIOS_ONBOARD_DEVICES_EXTENDED_INFORMATION;
- t->handle = *handle;
- t->length = len - 2;
- t->reference_designation = smbios_add_string(t->eos, name);
- t->device_type = SMBIOS_DEVICE_TYPE_OTHER;
- t->device_status = 1;
- t->device_type_instance = instance;
- t->segment_group_number = segment;
- t->bus_number = bus;
- t->device_number = device;
- t->function_number = function;
-
- len = t->length + smbios_string_table_len(t->eos);
- *current += len;
- *handle += 1;
- return len;
-}
-
-static int smbios_write_type127(unsigned long *current, int handle)
-{
- struct smbios_type127 *t = (struct smbios_type127 *)*current;
- int len = sizeof(struct smbios_type127);
-
- memset(t, 0, sizeof(struct smbios_type127));
- t->type = SMBIOS_END_OF_TABLE;
- t->handle = handle;
- t->length = len - 2;
- *current += len;
- return len;
-}
-
-static int smbios_walk_device_tree(struct device *tree, int *handle, unsigned long *current)
-{
- struct device *dev;
- int len = 0;
-
- for(dev = tree; dev; dev = dev->next) {
- printk(BIOS_INFO, "%s (%s)\n", dev_path(dev), dev_name(dev));
-
- if (dev->ops && dev->ops->get_smbios_data)
- len += dev->ops->get_smbios_data(dev, handle, current);
- }
- return len;
-}
-
-#define update_max(len, max_len, stmt) do { int tmp = stmt; max_len = MAX(max_len, tmp); len += tmp; } while(0)
-unsigned long smbios_write_tables(unsigned long current)
-{
- struct smbios_entry *se;
- unsigned long tables;
- int len = 0;
- int max_struct_size = 0;
- int handle = 0;
-
- current = ALIGN(current, 16);
- printk(BIOS_DEBUG, "%s: %08lx\n", __func__, current);
-
- se = (struct smbios_entry *)current;
- current += sizeof(struct smbios_entry);
- current = ALIGN(current, 16);
-
- tables = current;
- update_max(len, max_struct_size, smbios_write_type0(¤t, handle++));
- update_max(len, max_struct_size, smbios_write_type1(¤t, handle++));
- update_max(len, max_struct_size, smbios_write_type2(¤t, handle++));
- update_max(len, max_struct_size, smbios_write_type3(¤t, handle++));
- update_max(len, max_struct_size, smbios_write_type4(¤t, handle++));
- update_max(len, max_struct_size, smbios_write_type11(¤t, &handle));
-#if CONFIG_ELOG
- update_max(len, max_struct_size, elog_smbios_write_type15(¤t, handle++));
-#endif
- update_max(len, max_struct_size, smbios_write_type17(¤t, &handle));
- update_max(len, max_struct_size, smbios_write_type32(¤t, handle++));
-
- update_max(len, max_struct_size, smbios_walk_device_tree(all_devices, &handle, ¤t));
-
- update_max(len, max_struct_size, smbios_write_type127(¤t, handle++));
-
- memset(se, 0, sizeof(struct smbios_entry));
- memcpy(se->anchor, "_SM_", 4);
- se->length = sizeof(struct smbios_entry);
- se->major_version = 2;
- se->minor_version = 7;
- se->max_struct_size = max_struct_size;
- se->struct_count = handle;
- memcpy(se->intermediate_anchor_string, "_DMI_", 5);
-
- se->struct_table_address = (u32)tables;
- se->struct_table_length = len;
-
- se->intermediate_checksum = smbios_checksum((u8 *)se + 0x10,
- sizeof(struct smbios_entry) - 0x10);
- se->checksum = smbios_checksum((u8 *)se, sizeof(struct smbios_entry));
- return current;
-}
diff --git a/src/arch/x86/boot/tables.c b/src/arch/x86/boot/tables.c
deleted file mode 100644
index 3d64563..0000000
--- a/src/arch/x86/boot/tables.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2003 Eric Biederman
- * Copyright (C) 2005 Steve Magnani
- * Copyright (C) 2008-2009 coresystems GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <console/console.h>
-#include <cpu/cpu.h>
-#include <boot/tables.h>
-#include <boot/coreboot_tables.h>
-#include <arch/pirq_routing.h>
-#include <arch/smp/mpspec.h>
-#include <arch/acpi.h>
-#include <string.h>
-#include <cbmem.h>
-#include <smbios.h>
-
-void write_tables(void)
-{
- unsigned long low_table_start, low_table_end;
- unsigned long rom_table_start, rom_table_end;
-
- /* Even if high tables are configured, some tables are copied both to
- * the low and the high area, so payloads and OSes don't need to know
- * about the high tables.
- */
- unsigned long high_table_pointer;
-
- rom_table_start = 0xf0000;
- rom_table_end = 0xf0000;
-
- /* Start low addr at 0x500, so we don't run into conflicts with the BDA
- * in case our data structures grow beyond 0x400. Only GDT
- * and the coreboot table use low_tables.
- */
- low_table_start = 0;
- low_table_end = 0x500;
-
-#if CONFIG_GENERATE_PIRQ_TABLE
-#define MAX_PIRQ_TABLE_SIZE (4 * 1024)
- post_code(0x9a);
-
- /* This table must be between 0x0f0000 and 0x100000 */
- rom_table_end = write_pirq_routing_table(rom_table_end);
- rom_table_end = ALIGN(rom_table_end, 1024);
-
- /* And add a high table version for those payloads that
- * want to live in the F segment
- */
- high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_PIRQ, MAX_PIRQ_TABLE_SIZE);
- if (high_table_pointer) {
- unsigned long new_high_table_pointer;
- new_high_table_pointer = write_pirq_routing_table(high_table_pointer);
- // FIXME make pirq table code intelligent enough to know how
- // much space it's going to need.
- if (new_high_table_pointer > (high_table_pointer + MAX_PIRQ_TABLE_SIZE)) {
- printk(BIOS_ERR, "ERROR: Increase PIRQ size.\n");
- }
- printk(BIOS_DEBUG, "PIRQ table: %ld bytes.\n",
- new_high_table_pointer - high_table_pointer);
- }
-
-#endif
-
-#if CONFIG_GENERATE_MP_TABLE
-#define MAX_MP_TABLE_SIZE (4 * 1024)
- post_code(0x9b);
-
- /* The smp table must be in 0-1K, 639K-640K, or 960K-1M */
- rom_table_end = write_smp_table(rom_table_end);
- rom_table_end = ALIGN(rom_table_end, 1024);
-
- high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_MPTABLE, MAX_MP_TABLE_SIZE);
- if (high_table_pointer) {
- unsigned long new_high_table_pointer;
- new_high_table_pointer = write_smp_table(high_table_pointer);
- // FIXME make mp table code intelligent enough to know how
- // much space it's going to need.
- if (new_high_table_pointer > (high_table_pointer + MAX_MP_TABLE_SIZE)) {
- printk(BIOS_ERR, "ERROR: Increase MP table size.\n");
- }
-
- printk(BIOS_DEBUG, "MP table: %ld bytes.\n",
- new_high_table_pointer - high_table_pointer);
- }
-#endif /* CONFIG_GENERATE_MP_TABLE */
-
-#if CONFIG_HAVE_ACPI_TABLES
-#define MAX_ACPI_SIZE (144 * 1024)
-
- post_code(0x9c);
-
- /* Write ACPI tables to F segment and high tables area */
-
- /* Ok, this is a bit hacky still, because some day we want to have this
- * completely dynamic. But right now we are setting fixed sizes.
- * It's probably still better than the old high_table_base code because
- * now at least we know when we have an overflow in the area.
- *
- * We want to use 1MB - 64K for Resume backup. We use 512B for TOC and
- * 512 byte for GDT, 4K for PIRQ and 4K for MP table and 8KB for the
- * coreboot table. This leaves us with 47KB for all of ACPI. Let's see
- * how far we get.
- */
- high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_ACPI, MAX_ACPI_SIZE);
- if (high_table_pointer) {
- unsigned long acpi_start = high_table_pointer;
- unsigned long new_high_table_pointer;
-
- rom_table_end = ALIGN(rom_table_end, 16);
- new_high_table_pointer = write_acpi_tables(high_table_pointer);
- if (new_high_table_pointer > ( high_table_pointer + MAX_ACPI_SIZE)) {
- printk(BIOS_ERR, "ERROR: Increase ACPI size\n");
- }
- printk(BIOS_DEBUG, "ACPI tables: %ld bytes.\n",
- new_high_table_pointer - high_table_pointer);
-
- /* Now we need to create a low table copy of the RSDP. */
-
- /* First we look for the high table RSDP */
- while (acpi_start < new_high_table_pointer) {
- if (memcmp(((acpi_rsdp_t *)acpi_start)->signature, RSDP_SIG, 8) == 0) {
- break;
- }
- acpi_start++;
- }
-
- /* Now, if we found the RSDP, we take the RSDT and XSDT pointer
- * from it in order to write the low RSDP
- */
- if (acpi_start < new_high_table_pointer) {
- acpi_rsdp_t *low_rsdp = (acpi_rsdp_t *)rom_table_end,
- *high_rsdp = (acpi_rsdp_t *)acpi_start;
-
- /* Technically rsdp length varies but coreboot always
- writes longest size available. */
- memcpy(low_rsdp, high_rsdp, sizeof(acpi_rsdp_t));
- } else {
- printk(BIOS_ERR, "ERROR: Didn't find RSDP in high table.\n");
- }
- rom_table_end = ALIGN(rom_table_end + sizeof(acpi_rsdp_t), 16);
- } else {
- rom_table_end = write_acpi_tables(rom_table_end);
- rom_table_end = ALIGN(rom_table_end, 1024);
- }
-
-#endif
-#define MAX_SMBIOS_SIZE 2048
-#if CONFIG_GENERATE_SMBIOS_TABLES
- high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_SMBIOS, MAX_SMBIOS_SIZE);
- if (high_table_pointer) {
- unsigned long new_high_table_pointer;
-
- new_high_table_pointer = smbios_write_tables(high_table_pointer);
- rom_table_end = ALIGN(rom_table_end, 16);
- memcpy((void *)rom_table_end, (void *)high_table_pointer, sizeof(struct smbios_entry));
- rom_table_end += sizeof(struct smbios_entry);
-
- if (new_high_table_pointer > ( high_table_pointer + MAX_SMBIOS_SIZE)) {
- printk(BIOS_ERR, "ERROR: Increase SMBIOS size\n");
- }
- printk(BIOS_DEBUG, "SMBIOS tables: %ld bytes.\n",
- new_high_table_pointer - high_table_pointer);
- } else {
- unsigned long new_rom_table_end = smbios_write_tables(rom_table_end);
- printk(BIOS_DEBUG, "SMBIOS size %ld bytes\n", new_rom_table_end - rom_table_end);
- rom_table_end = ALIGN(new_rom_table_end, 16);
- }
-#endif
-
- post_code(0x9e);
-
-#define MAX_COREBOOT_TABLE_SIZE (32 * 1024)
- post_code(0x9d);
-
- high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_CBTABLE, MAX_COREBOOT_TABLE_SIZE);
-
- if (high_table_pointer) {
- unsigned long new_high_table_pointer;
-
- /* FIXME: The high_table_base parameter is not reference when tables are high,
- * or high_table_pointer >1 MB.
- */
- u64 fixme_high_tables_base = 0;
-
- /* Also put a forwarder entry into 0-4K */
- new_high_table_pointer = write_coreboot_table(low_table_start, low_table_end,
- fixme_high_tables_base, high_table_pointer);
-
- if (new_high_table_pointer > (high_table_pointer +
- MAX_COREBOOT_TABLE_SIZE))
- printk(BIOS_ERR, "%s: coreboot table didn't fit (%lx)\n",
- __func__, new_high_table_pointer -
- high_table_pointer);
-
- printk(BIOS_DEBUG, "coreboot table: %ld bytes.\n",
- new_high_table_pointer - high_table_pointer);
- } else {
- /* The coreboot table must be in 0-4K or 960K-1M */
- write_coreboot_table(low_table_start, low_table_end,
- rom_table_start, rom_table_end);
- }
-
- /* Print CBMEM sections */
- cbmem_list();
-}
diff --git a/src/arch/x86/boot/wakeup.S b/src/arch/x86/boot/wakeup.S
deleted file mode 100644
index 38d6ea4..0000000
--- a/src/arch/x86/boot/wakeup.S
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2009 Rudolf Marek <r.marek at assembler.cz>
- * Copyright (C) 2009 coresystems GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#define WAKEUP_BASE 0x600
-#define RELOCATED(x) (x - __wakeup + WAKEUP_BASE)
-
-/* CR0 bits */
-#define PE (1 << 0)
-
-#ifdef __x86_64__
- .code64
-#else
- .code32
-#endif
-
- .globl __wakeup
-__wakeup:
- /* First prepare the jmp to the resume vector */
- mov 0x4(%esp), %eax /* vector */
- /* last 4 bits of linear addr are taken as offset */
- andw $0x0f, %ax
- movw %ax, (__wakeup_offset)
- mov 0x4(%esp), %eax
- /* the rest is taken as segment */
- shr $4, %eax
- movw %ax, (__wakeup_segment)
-
- /* Then overwrite coreboot with our backed up memory */
- cld
- movl 8(%esp), %esi
- movl 12(%esp), %edi
- movl 16(%esp), %ecx
- shrl $2, %ecx
- rep movsl
-
- /* Activate the right segment descriptor real mode. */
- ljmp $0x28, $RELOCATED(1f)
-1:
-.code16
- /* 16 bit code from here on... */
-
- /* Load the segment registers w/ properly configured
- * segment descriptors. They will retain these
- * configurations (limits, writability, etc.) once
- * protected mode is turned off.
- */
- mov $0x30, %ax
- mov %ax, %ds
- mov %ax, %es
- mov %ax, %fs
- mov %ax, %gs
- mov %ax, %ss
-
- /* Turn off protection */
- movl %cr0, %eax
- andl $~PE, %eax
- movl %eax, %cr0
-
- /* Now really going into real mode */
- ljmp $0, $RELOCATED(1f)
-1:
- movw $0x0, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss
- movw %ax, %fs
- movw %ax, %gs
-
- /* This is a FAR JMP to the OS waking vector. The C code changed
- * the address to be correct.
- */
- .byte 0xea
-
-__wakeup_offset = RELOCATED(.)
- .word 0x0000
-
-__wakeup_segment = RELOCATED(.)
- .word 0x0000
-
- .globl __wakeup_size
-__wakeup_size:
- .long . - __wakeup
diff --git a/src/arch/x86/bootblock_normal.c b/src/arch/x86/bootblock_normal.c
new file mode 100644
index 0000000..bde2535
--- /dev/null
+++ b/src/arch/x86/bootblock_normal.c
@@ -0,0 +1,52 @@
+#include <smp/node.h>
+#include <bootblock_common.h>
+#include <pc80/mc146818rtc.h>
+#include <halt.h>
+
+static const char *get_fallback(const char *stagelist) {
+ while (*stagelist) stagelist++;
+ return ++stagelist;
+}
+
+static void main(unsigned long bist)
+{
+ unsigned long entry;
+ int boot_mode;
+ const char *default_filenames = "normal/romstage\0fallback/romstage";
+
+ if (boot_cpu()) {
+ bootblock_mainboard_init();
+
+#if CONFIG_USE_OPTION_TABLE
+ sanitize_cmos();
+#endif
+ boot_mode = do_normal_boot();
+ } else {
+
+ /* Questionable single byte read from CMOS.
+ * Do not add any other CMOS access in the
+ * bootblock for AP CPUs.
+ */
+ boot_mode = last_boot_normal();
+ }
+
+ char *filenames = (char *)walkcbfs("coreboot-stages");
+ if (!filenames) {
+ filenames = default_filenames;
+ }
+ char *normal_candidate = filenames;
+
+ if (boot_mode)
+ entry = findstage(normal_candidate);
+ else
+ entry = findstage(get_fallback(normal_candidate));
+
+ if (entry) call(entry, bist);
+
+ /* run fallback if normal can't be found */
+ entry = findstage(get_fallback(normal_candidate));
+ if (entry) call(entry, bist);
+
+ /* duh. we're stuck */
+ halt();
+}
diff --git a/src/arch/x86/bootblock_simple.c b/src/arch/x86/bootblock_simple.c
new file mode 100644
index 0000000..adeecf7
--- /dev/null
+++ b/src/arch/x86/bootblock_simple.c
@@ -0,0 +1,23 @@
+#include <smp/node.h>
+#include <bootblock_common.h>
+#include <halt.h>
+
+static void main(unsigned long bist)
+{
+ if (boot_cpu()) {
+ bootblock_mainboard_init();
+
+#if CONFIG_USE_OPTION_TABLE
+ sanitize_cmos();
+#endif
+#if CONFIG_CMOS_POST
+ cmos_post_init();
+#endif
+ }
+
+ const char* target1 = "fallback/romstage";
+ unsigned long entry;
+ entry = findstage(target1);
+ if (entry) call(entry, bist);
+ halt();
+}
diff --git a/src/arch/x86/c_start.S b/src/arch/x86/c_start.S
new file mode 100644
index 0000000..582966b
--- /dev/null
+++ b/src/arch/x86/c_start.S
@@ -0,0 +1,421 @@
+#include <cpu/x86/post_code.h>
+
+/* Place the stack in the bss section. It's not necessary to define it in the
+ * the linker script. */
+ .section .bss, "aw", @nobits
+.global _stack
+.global _estack
+
+.align CONFIG_STACK_SIZE
+_stack:
+.space CONFIG_MAX_CPUS*CONFIG_STACK_SIZE
+_estack:
+#if CONFIG_COOP_MULTITASKING
+.global thread_stacks
+thread_stacks:
+.space CONFIG_STACK_SIZE*CONFIG_NUM_THREADS
+#endif
+
+ .section ".text._start", "ax", @progbits
+#ifdef __x86_64__
+ .code64
+#else
+ .code32
+#endif
+ .globl _start
+ .globl __rmodule_entry
+__rmodule_entry:
+_start:
+ cli
+ lgdt %cs:gdtaddr
+#ifndef __x86_64__
+ ljmp $0x10, $1f
+#endif
+1: movl $0x18, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+#ifdef __x86_64__
+ mov $0x48, %ecx
+ call SetCodeSelector
+#endif
+
+ post_code(POST_ENTRY_C_START) /* post 13 */
+
+ cld
+
+ /** poison the stack. Code should not count on the
+ * stack being full of zeros. This stack poisoning
+ * recently uncovered a bug in the broadcast SIPI
+ * code.
+ */
+ leal _stack, %edi
+ movl $_estack, %ecx
+ subl %edi, %ecx
+ shrl $2, %ecx /* it is 32 bit aligned, right? */
+ movl $0xDEADBEEF, %eax
+ rep
+ stosl
+
+ /* set new stack */
+ movl $_estack, %esp
+
+#if CONFIG_COOP_MULTITASKING
+ /* Push the thread pointer. */
+ push $0
+#endif
+ /* Push the cpu index and struct cpu */
+ push $0
+ push $0
+
+ /* Initialize the Interrupt Descriptor table */
+ leal _idt, %edi
+ leal vec0, %ebx
+ movl $(0x10 << 16), %eax /* cs selector */
+
+1: movw %bx, %ax
+ movl %ebx, %edx
+ movw $0x8E00, %dx /* Interrupt gate - dpl=0, present */
+ movl %eax, 0(%edi)
+ movl %edx, 4(%edi)
+ addl $6, %ebx
+ addl $8, %edi
+ cmpl $_idt_end, %edi
+ jne 1b
+
+ /* Load the Interrupt descriptor table */
+#ifndef __x86_64__
+ lidt idtarg
+#else
+ // FIXME port table to x64 - lidt idtarg
+#endif
+
+ /*
+ * Now we are finished. Memory is up, data is copied and
+ * bss is cleared. Now we call the main routine and
+ * let it do the rest.
+ */
+ post_code(POST_PRE_HARDWAREMAIN) /* post fe */
+
+#if CONFIG_GDB_WAIT
+ call gdb_hw_init
+ call gdb_stub_breakpoint
+#endif
+ call main
+ /* NOTREACHED */
+.Lhlt:
+ post_code(POST_DEAD_CODE) /* post ee */
+ hlt
+ jmp .Lhlt
+
+vec0:
+ push $0 /* error code */
+ push $0 /* vector */
+ jmp int_hand
+vec1:
+ push $0 /* error code */
+ push $1 /* vector */
+ jmp int_hand
+
+vec2:
+ push $0 /* error code */
+ push $2 /* vector */
+ jmp int_hand
+
+vec3:
+ push $0 /* error code */
+ push $3 /* vector */
+ jmp int_hand
+
+vec4:
+ push $0 /* error code */
+ push $4 /* vector */
+ jmp int_hand
+
+vec5:
+ push $0 /* error code */
+ push $5 /* vector */
+ jmp int_hand
+
+vec6:
+ push $0 /* error code */
+ push $6 /* vector */
+ jmp int_hand
+
+vec7:
+ push $0 /* error code */
+ push $7 /* vector */
+ jmp int_hand
+
+vec8:
+ /* error code */
+ push $8 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec9:
+ push $0 /* error code */
+ push $9 /* vector */
+ jmp int_hand
+
+vec10:
+ /* error code */
+ push $10 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec11:
+ /* error code */
+ push $11 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec12:
+ /* error code */
+ push $12 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec13:
+ /* error code */
+ push $13 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec14:
+ /* error code */
+ push $14 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec15:
+ push $0 /* error code */
+ push $15 /* vector */
+ jmp int_hand
+
+vec16:
+ push $0 /* error code */
+ push $16 /* vector */
+ jmp int_hand
+
+vec17:
+ /* error code */
+ push $17 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec18:
+ push $0 /* error code */
+ push $18 /* vector */
+ jmp int_hand
+
+vec19:
+ push $0 /* error code */
+ push $19 /* vector */
+ jmp int_hand
+
+int_hand:
+ /* At this point, on x86-32, on the stack there is:
+ * 0(%esp) vector
+ * 4(%esp) error code
+ * 8(%esp) eip
+ * 12(%esp) cs
+ * 16(%esp) eflags
+ */
+#ifdef __x86_64__
+ push %rdi
+ push %rsi
+ push %rbp
+ /* Original stack pointer */
+ lea 32(%rsp), %rbp
+ push %rbp
+ push %rbx
+ push %rdx
+ push %rcx
+ push %rax
+
+ push %rsp /* Pointer to structure on the stack */
+ call x86_exception
+ pop %rax /* Drop the pointer */
+
+ pop %rax
+ pop %rcx
+ pop %rdx
+ pop %rbx
+ pop %rbp /* Ignore saved %rsp value */
+ pop %rbp
+ pop %rsi
+ pop %rdi
+
+ add $8, %rsp /* pop of the vector and error code */
+#else
+ pushl %edi
+ pushl %esi
+ pushl %ebp
+
+ /* Original stack pointer */
+ leal 32(%esp), %ebp
+ pushl %ebp
+ pushl %ebx
+ pushl %edx
+ pushl %ecx
+ pushl %eax
+
+ pushl %esp /* Pointer to structure on the stack */
+ call x86_exception
+ pop %eax /* Drop the pointer */
+
+ popl %eax
+ popl %ecx
+ popl %edx
+ popl %ebx
+ popl %ebp /* Ignore saved %esp value */
+ popl %ebp
+ popl %esi
+ popl %edi
+
+ addl $8, %esp /* pop of the vector and error code */
+#endif
+
+ iret
+
+#if CONFIG_GDB_WAIT
+
+ .globl gdb_stub_breakpoint
+gdb_stub_breakpoint:
+#ifdef __x86_64__
+ pop %rax /* Return address */
+ pushfl
+ push %cs
+ push %rax /* Return address */
+ push $0 /* No error code */
+ push $32 /* vector 32 is user defined */
+#else
+ popl %eax /* Return address */
+ pushfl
+ pushl %cs
+ pushl %eax /* Return address */
+ pushl $0 /* No error code */
+ pushl $32 /* vector 32 is user defined */
+#endif
+ jmp int_hand
+#endif
+
+ .globl gdt, gdt_end, idtarg
+
+gdtaddr:
+ .word gdt_end - gdt - 1
+#ifdef __x86_64__
+ .quad gdt
+#else
+ .long gdt /* we know the offset */
+#endif
+
+ .data
+
+ /* This is the gdt for GCC part of coreboot.
+ * It is different from the gdt in ROMCC/ASM part of coreboot
+ * which is defined in entry32.inc
+ *
+ * When the machine is initially started, we use a very simple
+ * gdt from rom (that in entry32.inc) which only contains those
+ * entries we need for protected mode.
+ *
+ * When we're executing code from RAM, we want to do more complex
+ * stuff, like initializing PCI option roms in real mode, or doing
+ * a resume from a suspend to ram.
+ */
+gdt:
+ /* selgdt 0, unused */
+ .word 0x0000, 0x0000 /* dummy */
+ .byte 0x00, 0x00, 0x00, 0x00
+
+ /* selgdt 8, unused */
+ .word 0x0000, 0x0000 /* dummy */
+ .byte 0x00, 0x00, 0x00, 0x00
+
+ /* selgdt 0x10, flat code segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */
+
+ /* selgdt 0x18, flat data segment */
+ .word 0xffff, 0x0000
+#ifdef __x86_64__
+ .byte 0x00, 0x92, 0xcf, 0x00
+#else
+ .byte 0x00, 0x93, 0xcf, 0x00
+#endif
+
+ /* selgdt 0x20, unused */
+ .word 0x0000, 0x0000 /* dummy */
+ .byte 0x00, 0x00, 0x00, 0x00
+
+ /* The next two entries are used for executing VGA option ROMs */
+
+ /* selgdt 0x28 16 bit 64k code at 0x00000000 */
+ .word 0xffff, 0x0000
+ .byte 0, 0x9a, 0, 0
+
+ /* selgdt 0x30 16 bit 64k data at 0x00000000 */
+ .word 0xffff, 0x0000
+ .byte 0, 0x92, 0, 0
+
+ /* The next two entries are used for ACPI S3 RESUME */
+
+ /* selgdt 0x38, flat data segment 16 bit */
+ .word 0x0000, 0x0000 /* dummy */
+ .byte 0x00, 0x93, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */
+
+ /* selgdt 0x40, flat code segment 16 bit */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */
+
+#ifdef __x86_64__
+ /* selgdt 0x48, flat x64 code segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0xaf, 0x00
+#endif
+gdt_end:
+
+idtarg:
+ .word _idt_end - _idt - 1 /* limit */
+ .long _idt
+ .word 0
+_idt:
+ .fill 20, 8, 0 # idt is uninitialized
+_idt_end:
+
+#ifdef __x86_64__
+SetCodeSelector:
+.intel_syntax noprefix
+
+ # save rsp because iret will align it to a 16 byte boundary
+ mov rdx, rsp
+
+ # use iret to jump to a 64-bit offset in a new code segment
+ # iret will pop cs:rip, flags, then ss:rsp
+ mov ax, ss # need to push ss..
+ push rax # push ss instuction not valid in x64 mode, so use ax
+ push rsp
+ pushfq
+ push rcx # cx is code segment selector from caller
+ mov rax, offset setCodeSelectorLongJump
+ push rax
+
+ # the iret will continue at next instruction, with the new cs value loaded
+ iretq
+
+setCodeSelectorLongJump:
+ # restore rsp, it might not have been 16-byte aligned on entry
+ mov rsp, rdx
+ ret
+.att_syntax prefix
+
+ .previous
+.code64
+#else
+ .previous
+.code32
+#endif
diff --git a/src/arch/x86/cbfs_and_run.c b/src/arch/x86/cbfs_and_run.c
new file mode 100644
index 0000000..b6d3426
--- /dev/null
+++ b/src/arch/x86/cbfs_and_run.c
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <arch/stages.h>
+#include <program_loading.h>
+
+void asmlinkage copy_and_run(void)
+{
+ run_ramstage();
+}
diff --git a/src/arch/x86/cbmem.c b/src/arch/x86/cbmem.c
new file mode 100644
index 0000000..e279db9
--- /dev/null
+++ b/src/arch/x86/cbmem.c
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <stdlib.h>
+#include <console/console.h>
+#include <cbmem.h>
+#include <arch/acpi.h>
+
+#if IS_ENABLED(CONFIG_LATE_CBMEM_INIT)
+
+#if !defined(__PRE_RAM__)
+void __attribute__((weak)) backup_top_of_ram(uint64_t ramtop)
+{
+ /* Do nothing. Chipset may have implementation to save ramtop in NVRAM. */
+}
+
+static void *ramtop_pointer;
+
+void set_top_of_ram(uint64_t ramtop)
+{
+ backup_top_of_ram(ramtop);
+ ramtop_pointer = (void *)(uintptr_t)ramtop;
+}
+
+static inline void *saved_ramtop(void)
+{
+ return ramtop_pointer;
+}
+#else
+static inline void *saved_ramtop(void)
+{
+ return NULL;
+}
+#endif /* !__PRE_RAM__ */
+
+unsigned long __attribute__((weak)) get_top_of_ram(void)
+{
+ return 0;
+}
+
+void *cbmem_top(void)
+{
+ /* Top of cbmem is at lowest usable DRAM address below 4GiB. */
+ void *ptr = saved_ramtop();
+
+ if (ptr != NULL)
+ return ptr;
+
+ return (void *)get_top_of_ram();
+}
+
+#endif /* LATE_CBMEM_INIT */
+
+/* Something went wrong, our high memory area got wiped */
+void cbmem_fail_resume(void)
+{
+#if !defined(__PRE_RAM__) && IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
+ /* ACPI resume needs to be cleared in the fail-to-recover case, but that
+ * condition is only handled during ramstage. */
+ acpi_fail_wakeup();
+#endif
+}
diff --git a/src/arch/x86/cpu.c b/src/arch/x86/cpu.c
new file mode 100644
index 0000000..3eb7b94
--- /dev/null
+++ b/src/arch/x86/cpu.c
@@ -0,0 +1,273 @@
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <arch/io.h>
+#include <string.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/lapic.h>
+#include <arch/cpu.h>
+#include <device/path.h>
+#include <device/device.h>
+#include <smp/spinlock.h>
+
+#ifndef __x86_64__
+/* Standard macro to see if a specific flag is changeable */
+static inline int flag_is_changeable_p(uint32_t flag)
+{
+ uint32_t f1, f2;
+
+ asm(
+ "pushfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "movl %0,%1\n\t"
+ "xorl %2,%0\n\t"
+ "pushl %0\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "popfl\n\t"
+ : "=&r" (f1), "=&r" (f2)
+ : "ir" (flag));
+ return ((f1^f2) & flag) != 0;
+}
+
+/*
+ * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
+ * by the fact that they preserve the flags across the division of 5/2.
+ * PII and PPro exhibit this behavior too, but they have cpuid available.
+ */
+
+/*
+ * Perform the Cyrix 5/2 test. A Cyrix won't change
+ * the flags, while other 486 chips will.
+ */
+static inline int test_cyrix_52div(void)
+{
+ unsigned int test;
+
+ __asm__ __volatile__(
+ "sahf\n\t" /* clear flags (%eax = 0x0005) */
+ "div %b2\n\t" /* divide 5 by 2 */
+ "lahf" /* store flags into %ah */
+ : "=a" (test)
+ : "0" (5), "q" (2)
+ : "cc");
+
+ /* AH is 0x02 on Cyrix after the divide.. */
+ return (unsigned char) (test >> 8) == 0x02;
+}
+
+/*
+ * Detect a NexGen CPU running without BIOS hypercode new enough
+ * to have CPUID. (Thanks to Herbert Oppmann)
+ */
+
+static int deep_magic_nexgen_probe(void)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ " movw $0x5555, %%ax\n"
+ " xorw %%dx,%%dx\n"
+ " movw $2, %%cx\n"
+ " divw %%cx\n"
+ " movl $0, %%eax\n"
+ " jnz 1f\n"
+ " movl $1, %%eax\n"
+ "1:\n"
+ : "=a" (ret) : : "cx", "dx" );
+ return ret;
+}
+#endif
+
+/* List of cpu vendor strings along with their normalized
+ * id values.
+ */
+static struct {
+ int vendor;
+ const char *name;
+} x86_vendors[] = {
+ { X86_VENDOR_INTEL, "GenuineIntel", },
+ { X86_VENDOR_CYRIX, "CyrixInstead", },
+ { X86_VENDOR_AMD, "AuthenticAMD", },
+ { X86_VENDOR_UMC, "UMC UMC UMC ", },
+ { X86_VENDOR_NEXGEN, "NexGenDriven", },
+ { X86_VENDOR_CENTAUR, "CentaurHauls", },
+ { X86_VENDOR_RISE, "RiseRiseRise", },
+ { X86_VENDOR_TRANSMETA, "GenuineTMx86", },
+ { X86_VENDOR_TRANSMETA, "TransmetaCPU", },
+ { X86_VENDOR_NSC, "Geode by NSC", },
+ { X86_VENDOR_SIS, "SiS SiS SiS ", },
+};
+
+static const char *x86_vendor_name[] = {
+ [X86_VENDOR_INTEL] = "Intel",
+ [X86_VENDOR_CYRIX] = "Cyrix",
+ [X86_VENDOR_AMD] = "AMD",
+ [X86_VENDOR_UMC] = "UMC",
+ [X86_VENDOR_NEXGEN] = "NexGen",
+ [X86_VENDOR_CENTAUR] = "Centaur",
+ [X86_VENDOR_RISE] = "Rise",
+ [X86_VENDOR_TRANSMETA] = "Transmeta",
+ [X86_VENDOR_NSC] = "NSC",
+ [X86_VENDOR_SIS] = "SiS",
+};
+
+static const char *cpu_vendor_name(int vendor)
+{
+ const char *name;
+ name = "<invalid cpu vendor>";
+ if ((vendor < (ARRAY_SIZE(x86_vendor_name))) &&
+ (x86_vendor_name[vendor] != 0))
+ {
+ name = x86_vendor_name[vendor];
+ }
+ return name;
+}
+
+static void identify_cpu(struct device *cpu)
+{
+ char vendor_name[16];
+ int i;
+
+ vendor_name[0] = '\0'; /* Unset */
+
+#ifndef __x86_64__
+ /* Find the id and vendor_name */
+ if (!cpu_have_cpuid()) {
+ /* Its a 486 if we can modify the AC flag */
+ if (flag_is_changeable_p(X86_EFLAGS_AC)) {
+ cpu->device = 0x00000400; /* 486 */
+ } else {
+ cpu->device = 0x00000300; /* 386 */
+ }
+ if ((cpu->device == 0x00000400) && test_cyrix_52div()) {
+ memcpy(vendor_name, "CyrixInstead", 13);
+ /* If we ever care we can enable cpuid here */
+ }
+ /* Detect NexGen with old hypercode */
+ else if (deep_magic_nexgen_probe()) {
+ memcpy(vendor_name, "NexGenDriven", 13);
+ }
+ }
+#endif
+ if (cpu_have_cpuid()) {
+ int cpuid_level;
+ struct cpuid_result result;
+ result = cpuid(0x00000000);
+ cpuid_level = result.eax;
+ vendor_name[ 0] = (result.ebx >> 0) & 0xff;
+ vendor_name[ 1] = (result.ebx >> 8) & 0xff;
+ vendor_name[ 2] = (result.ebx >> 16) & 0xff;
+ vendor_name[ 3] = (result.ebx >> 24) & 0xff;
+ vendor_name[ 4] = (result.edx >> 0) & 0xff;
+ vendor_name[ 5] = (result.edx >> 8) & 0xff;
+ vendor_name[ 6] = (result.edx >> 16) & 0xff;
+ vendor_name[ 7] = (result.edx >> 24) & 0xff;
+ vendor_name[ 8] = (result.ecx >> 0) & 0xff;
+ vendor_name[ 9] = (result.ecx >> 8) & 0xff;
+ vendor_name[10] = (result.ecx >> 16) & 0xff;
+ vendor_name[11] = (result.ecx >> 24) & 0xff;
+ vendor_name[12] = '\0';
+
+ /* Intel-defined flags: level 0x00000001 */
+ if (cpuid_level >= 0x00000001) {
+ cpu->device = cpuid_eax(0x00000001);
+ }
+ else {
+ /* Have CPUID level 0 only unheard of */
+ cpu->device = 0x00000400;
+ }
+ }
+ cpu->vendor = X86_VENDOR_UNKNOWN;
+ for(i = 0; i < ARRAY_SIZE(x86_vendors); i++) {
+ if (memcmp(vendor_name, x86_vendors[i].name, 12) == 0) {
+ cpu->vendor = x86_vendors[i].vendor;
+ break;
+ }
+ }
+}
+
+struct cpu_driver *find_cpu_driver(struct device *cpu)
+{
+ struct cpu_driver *driver;
+ for (driver = cpu_drivers; driver < ecpu_drivers; driver++) {
+ struct cpu_device_id *id;
+ for (id = driver->id_table;
+ id->vendor != X86_VENDOR_INVALID; id++) {
+ if ((cpu->vendor == id->vendor) &&
+ (cpu->device == id->device))
+ {
+ return driver;
+ }
+ if (X86_VENDOR_ANY == id->vendor)
+ return driver;
+ }
+ }
+ return NULL;
+}
+
+static void set_cpu_ops(struct device *cpu)
+{
+ struct cpu_driver *driver = find_cpu_driver(cpu);
+ cpu->ops = driver ? driver->ops : NULL;
+}
+
+void cpu_initialize(unsigned int index)
+{
+ /* Because we busy wait at the printk spinlock.
+ * It is important to keep the number of printed messages
+ * from secondary cpus to a minimum, when debugging is
+ * disabled.
+ */
+ struct device *cpu;
+ struct cpu_info *info;
+ struct cpuinfo_x86 c;
+
+ info = cpu_info();
+
+ printk(BIOS_INFO, "Initializing CPU #%d\n", index);
+
+ cpu = info->cpu;
+ if (!cpu) {
+ die("CPU: missing cpu device structure");
+ }
+
+ post_log_path(cpu);
+
+ /* Find what type of cpu we are dealing with */
+ identify_cpu(cpu);
+ printk(BIOS_DEBUG, "CPU: vendor %s device %x\n",
+ cpu_vendor_name(cpu->vendor), cpu->device);
+
+ get_fms(&c, cpu->device);
+
+ printk(BIOS_DEBUG, "CPU: family %02x, model %02x, stepping %02x\n",
+ c.x86, c.x86_model, c.x86_mask);
+
+ /* Lookup the cpu's operations */
+ set_cpu_ops(cpu);
+
+ if(!cpu->ops) {
+ /* mask out the stepping and try again */
+ cpu->device -= c.x86_mask;
+ set_cpu_ops(cpu);
+ cpu->device += c.x86_mask;
+ if(!cpu->ops) die("Unknown cpu");
+ printk(BIOS_DEBUG, "Using generic cpu ops (good)\n");
+ }
+
+
+ /* Initialize the cpu */
+ if (cpu->ops && cpu->ops->init) {
+ cpu->enabled = 1;
+ cpu->initialized = 1;
+ cpu->ops->init(cpu);
+ }
+ post_log_clear();
+
+ printk(BIOS_INFO, "CPU #%d initialized\n", index);
+
+ return;
+}
diff --git a/src/arch/x86/cpu_common.c b/src/arch/x86/cpu_common.c
new file mode 100644
index 0000000..af0ab2a
--- /dev/null
+++ b/src/arch/x86/cpu_common.c
@@ -0,0 +1,65 @@
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <arch/io.h>
+#include <string.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/lapic.h>
+#include <arch/cpu.h>
+#include <device/path.h>
+#include <device/device.h>
+#include <smp/spinlock.h>
+
+#ifndef __x86_64__
+/* Standard macro to see if a specific flag is changeable */
+static inline int flag_is_changeable_p(uint32_t flag)
+{
+ uint32_t f1, f2;
+
+ asm(
+ "pushfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "movl %0,%1\n\t"
+ "xorl %2,%0\n\t"
+ "pushl %0\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "popfl\n\t"
+ : "=&r" (f1), "=&r" (f2)
+ : "ir" (flag));
+ return ((f1^f2) & flag) != 0;
+}
+
+/* Probe for the CPUID instruction */
+int cpu_have_cpuid(void)
+{
+ return flag_is_changeable_p(X86_EFLAGS_ID);
+}
+
+#else
+
+int cpu_have_cpuid(void)
+{
+ return 1;
+}
+#endif
+
+int cpu_cpuid_extended_level(void)
+{
+ return cpuid_eax(0x80000000);
+}
+
+int cpu_phys_address_size(void)
+{
+ if (!(cpu_have_cpuid()))
+ return 32;
+
+ if (cpu_cpuid_extended_level() >= 0x80000008)
+ return cpuid_eax(0x80000008) & 0xff;
+
+ if (cpuid_edx(1) & (CPUID_FEATURE_PAE | CPUID_FEATURE_PSE36))
+ return 36;
+ return 32;
+}
diff --git a/src/arch/x86/crt0_romcc_epilogue.inc b/src/arch/x86/crt0_romcc_epilogue.inc
new file mode 100644
index 0000000..ff93adb
--- /dev/null
+++ b/src/arch/x86/crt0_romcc_epilogue.inc
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2002 Eric Biederman
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of the License.
+ */
+#include <cpu/x86/post_code.h>
+
+__main:
+ post_code(POST_PREPARE_RAMSTAGE)
+ cld /* clear direction flag */
+
+ movl $CONFIG_RAMTOP, %esp
+ movl %esp, %ebp
+ call copy_and_run
+
+.Lhlt:
+ post_code(POST_DEAD_CODE)
+ hlt
+ jmp .Lhlt
diff --git a/src/arch/x86/ebda.c b/src/arch/x86/ebda.c
new file mode 100644
index 0000000..47dfbdb
--- /dev/null
+++ b/src/arch/x86/ebda.c
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 The Chromium OS Authors. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <arch/io.h>
+#include <arch/ebda.h>
+#include <arch/acpi.h>
+
+void setup_ebda(u32 low_memory_size, u16 ebda_segment, u16 ebda_size)
+{
+ /* Skip in S3 resume path */
+ if (acpi_is_wakeup_s3())
+ return;
+
+ if (!low_memory_size || !ebda_segment || !ebda_size)
+ return;
+
+ /* clear BIOS DATA AREA */
+ memset((void *)X86_BDA_BASE, 0, X86_BDA_SIZE);
+
+ write16(X86_EBDA_LOWMEM, (low_memory_size >> 10));
+ write16(X86_EBDA_SEGMENT, ebda_segment);
+
+ /* Set up EBDA */
+ memset((void *)((uintptr_t)ebda_segment << 4), 0, ebda_size);
+ write16((void*)((uintptr_t)ebda_segment << 4), (ebda_size >> 10));
+}
+
+void setup_default_ebda(void)
+{
+ setup_ebda(DEFAULT_EBDA_LOWMEM,
+ DEFAULT_EBDA_SEGMENT,
+ DEFAULT_EBDA_SIZE);
+}
diff --git a/src/arch/x86/exception.c b/src/arch/x86/exception.c
new file mode 100644
index 0000000..65181e2
--- /dev/null
+++ b/src/arch/x86/exception.c
@@ -0,0 +1,511 @@
+#include <console/console.h>
+#include <console/streams.h>
+#include <string.h>
+
+#if CONFIG_GDB_STUB
+
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers.
+ * At least NUM_REGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 400
+enum regnames {
+ EAX = 0, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
+ PC /* also known as eip */,
+ PS /* also known as eflags */,
+ CS, SS, DS, ES, FS, GS,
+ NUM_REGS /* Number of registers. */
+};
+
+static uint32_t gdb_stub_registers[NUM_REGS];
+
+#define GDB_SIG0 0 /* Signal 0 */
+#define GDB_SIGHUP 1 /* Hangup */
+#define GDB_SIGINT 2 /* Interrupt */
+#define GDB_SIGQUIT 3 /* Quit */
+#define GDB_SIGILL 4 /* Illegal instruction */
+#define GDB_SIGTRAP 5 /* Trace/breakpoint trap */
+#define GDB_SIGABRT 6 /* Aborted */
+#define GDB_SIGEMT 7 /* Emulation trap */
+#define GDB_SIGFPE 8 /* Arithmetic exception */
+#define GDB_SIGKILL 9 /* Killed */
+#define GDB_SIGBUS 10 /* Bus error */
+#define GDB_SIGSEGV 11 /* Segmentation fault */
+#define GDB_SIGSYS 12 /* Bad system call */
+#define GDB_SIGPIPE 13 /* Broken pipe */
+#define GDB_SIGALRM 14 /* Alarm clock */
+#define GDB_SIGTERM 15 /* Terminated */
+#define GDB_SIGURG 16 /* Urgent I/O condition */
+#define GDB_SIGSTOP 17 /* Stopped (signal) */
+#define GDB_SIGTSTP 18 /* Stopped (user) */
+#define GDB_SIGCONT 19 /* Continued */
+#define GDB_SIGCHLD 20 /* Child status changed */
+#define GDB_SIGTTIN 21 /* Stopped (tty input) */
+#define GDB_SIGTTOU 22 /* Stopped (tty output) */
+#define GDB_SIGIO 23 /* I/O possible */
+#define GDB_SIGXCPU 24 /* CPU time limit exceeded */
+#define GDB_SIGXFSZ 25 /* File size limit exceeded */
+#define GDB_SIGVTALRM 26 /* Virtual timer expired */
+#define GDB_SIGPROF 27 /* Profiling timer expired */
+#define GDB_SIGWINCH 28 /* Window size changed */
+#define GDB_SIGLOST 29 /* Resource lost */
+#define GDB_SIGUSR1 30 /* User defined signal 1 */
+#define GDB_SUGUSR2 31 /* User defined signal 2 */
+#define GDB_SIGPWR 32 /* Power fail/restart */
+#define GDB_SIGPOLL 33 /* Pollable event occurred */
+#define GDB_SIGWIND 34 /* SIGWIND */
+#define GDB_SIGPHONE 35 /* SIGPHONE */
+#define GDB_SIGWAITING 36 /* Process's LWPs are blocked */
+#define GDB_SIGLWP 37 /* Signal LWP */
+#define GDB_SIGDANGER 38 /* Swap space dangerously low */
+#define GDB_SIGGRANT 39 /* Monitor mode granted */
+#define GDB_SIGRETRACT 40 /* Need to relinquish monitor mode */
+#define GDB_SIGMSG 41 /* Monitor mode data available */
+#define GDB_SIGSOUND 42 /* Sound completed */
+#define GDB_SIGSAK 43 /* Secure attention */
+#define GDB_SIGPRIO 44 /* SIGPRIO */
+
+#define GDB_SIG33 45 /* Real-time event 33 */
+#define GDB_SIG34 46 /* Real-time event 34 */
+#define GDB_SIG35 47 /* Real-time event 35 */
+#define GDB_SIG36 48 /* Real-time event 36 */
+#define GDB_SIG37 49 /* Real-time event 37 */
+#define GDB_SIG38 50 /* Real-time event 38 */
+#define GDB_SIG39 51 /* Real-time event 39 */
+#define GDB_SIG40 52 /* Real-time event 40 */
+#define GDB_SIG41 53 /* Real-time event 41 */
+#define GDB_SIG42 54 /* Real-time event 42 */
+#define GDB_SIG43 55 /* Real-time event 43 */
+#define GDB_SIG44 56 /* Real-time event 44 */
+#define GDB_SIG45 57 /* Real-time event 45 */
+#define GDB_SIG46 58 /* Real-time event 46 */
+#define GDB_SIG47 59 /* Real-time event 47 */
+#define GDB_SIG48 60 /* Real-time event 48 */
+#define GDB_SIG49 61 /* Real-time event 49 */
+#define GDB_SIG50 62 /* Real-time event 50 */
+#define GDB_SIG51 63 /* Real-time event 51 */
+#define GDB_SIG52 64 /* Real-time event 52 */
+#define GDB_SIG53 65 /* Real-time event 53 */
+#define GDB_SIG54 66 /* Real-time event 54 */
+#define GDB_SIG55 67 /* Real-time event 55 */
+#define GDB_SIG56 68 /* Real-time event 56 */
+#define GDB_SIG57 69 /* Real-time event 57 */
+#define GDB_SIG58 70 /* Real-time event 58 */
+#define GDB_SIG59 71 /* Real-time event 59 */
+#define GDB_SIG60 72 /* Real-time event 60 */
+#define GDB_SIG61 73 /* Real-time event 61 */
+#define GDB_SIG62 74 /* Real-time event 62 */
+#define GDB_SIG63 75 /* Real-time event 63 */
+#define GDB_SIGCANCEL 76 /* LWP internal signal */
+#define GDB_SIG32 77 /* Real-time event 32 */
+#define GDB_SIG64 78 /* Real-time event 64 */
+#define GDB_SIG65 79 /* Real-time event 65 */
+#define GDB_SIG66 80 /* Real-time event 66 */
+#define GDB_SIG67 81 /* Real-time event 67 */
+#define GDB_SIG68 82 /* Real-time event 68 */
+#define GDB_SIG69 83 /* Real-time event 69 */
+#define GDB_SIG70 84 /* Real-time event 70 */
+#define GDB_SIG71 85 /* Real-time event 71 */
+#define GDB_SIG72 86 /* Real-time event 72 */
+#define GDB_SIG73 87 /* Real-time event 73 */
+#define GDB_SIG74 88 /* Real-time event 74 */
+#define GDB_SIG75 89 /* Real-time event 75 */
+#define GDB_SIG76 90 /* Real-time event 76 */
+#define GDB_SIG77 91 /* Real-time event 77 */
+#define GDB_SIG78 92 /* Real-time event 78 */
+#define GDB_SIG79 93 /* Real-time event 79 */
+#define GDB_SIG80 94 /* Real-time event 80 */
+#define GDB_SIG81 95 /* Real-time event 81 */
+#define GDB_SIG82 96 /* Real-time event 82 */
+#define GDB_SIG83 97 /* Real-time event 83 */
+#define GDB_SIG84 98 /* Real-time event 84 */
+#define GDB_SIG85 99 /* Real-time event 85 */
+#define GDB_SIG86 100 /* Real-time event 86 */
+#define GDB_SIG87 101 /* Real-time event 87 */
+#define GDB_SIG88 102 /* Real-time event 88 */
+#define GDB_SIG89 103 /* Real-time event 89 */
+#define GDB_SIG90 104 /* Real-time event 90 */
+#define GDB_SIG91 105 /* Real-time event 91 */
+#define GDB_SIG92 106 /* Real-time event 92 */
+#define GDB_SIG93 107 /* Real-time event 93 */
+#define GDB_SIG94 108 /* Real-time event 94 */
+#define GDB_SIG95 109 /* Real-time event 95 */
+#define GDB_SIG96 110 /* Real-time event 96 */
+#define GDB_SIG97 111 /* Real-time event 97 */
+#define GDB_SIG98 112 /* Real-time event 98 */
+#define GDB_SIG99 113 /* Real-time event 99 */
+#define GDB_SIG100 114 /* Real-time event 100 */
+#define GDB_SIG101 115 /* Real-time event 101 */
+#define GDB_SIG102 116 /* Real-time event 102 */
+#define GDB_SIG103 117 /* Real-time event 103 */
+#define GDB_SIG104 118 /* Real-time event 104 */
+#define GDB_SIG105 119 /* Real-time event 105 */
+#define GDB_SIG106 120 /* Real-time event 106 */
+#define GDB_SIG107 121 /* Real-time event 107 */
+#define GDB_SIG108 122 /* Real-time event 108 */
+#define GDB_SIG109 123 /* Real-time event 109 */
+#define GDB_SIG110 124 /* Real-time event 110 */
+#define GDB_SIG111 125 /* Real-time event 111 */
+#define GDB_SIG112 126 /* Real-time event 112 */
+#define GDB_SIG113 127 /* Real-time event 113 */
+#define GDB_SIG114 128 /* Real-time event 114 */
+#define GDB_SIG115 129 /* Real-time event 115 */
+#define GDB_SIG116 130 /* Real-time event 116 */
+#define GDB_SIG117 131 /* Real-time event 117 */
+#define GDB_SIG118 132 /* Real-time event 118 */
+#define GDB_SIG119 133 /* Real-time event 119 */
+#define GDB_SIG120 134 /* Real-time event 120 */
+#define GDB_SIG121 135 /* Real-time event 121 */
+#define GDB_SIG122 136 /* Real-time event 122 */
+#define GDB_SIG123 137 /* Real-time event 123 */
+#define GDB_SIG124 138 /* Real-time event 124 */
+#define GDB_SIG125 139 /* Real-time event 125 */
+#define GDB_SIG126 140 /* Real-time event 126 */
+#define GDB_SIG127 141 /* Real-time event 127 */
+#define GDB_SIGINFO 142 /* Information request */
+#define GDB_UNKNOWN 143 /* Unknown signal */
+#define GDB_DEFAULT 144 /* error: default signal */
+/* Mach exceptions */
+#define GDB_EXC_BAD_ACCESS 145 /* Could not access memory */
+#define GDB_EXC_BAD_INSTRCTION 146 /* Illegal instruction/operand */
+#define GDB_EXC_ARITHMETIC 147 /* Arithmetic exception */
+#define GDB_EXC_EMULATION 148 /* Emulation instruction */
+#define GDB_EXC_SOFTWARE 149 /* Software generated exception */
+#define GDB_EXC_BREAKPOINT 150 /* Breakpoint */
+
+
+
+static unsigned char exception_to_signal[] =
+{
+ [0] = GDB_SIGFPE, /* divide by zero */
+ [1] = GDB_SIGTRAP, /* debug exception */
+ [2] = GDB_SIGSEGV, /* NMI Interrupt */
+ [3] = GDB_SIGTRAP, /* Breakpoint */
+ [4] = GDB_SIGSEGV, /* into instruction (overflow) */
+ [5] = GDB_SIGSEGV, /* bound instruction */
+ [6] = GDB_SIGILL, /* Invalid opcode */
+ [7] = GDB_SIGSEGV, /* coprocessor not available */
+ [8] = GDB_SIGSEGV, /* double fault */
+ [9] = GDB_SIGFPE, /* coprocessor segment overrun */
+ [10] = GDB_SIGSEGV, /* Invalid TSS */
+ [11] = GDB_SIGBUS, /* Segment not present */
+ [12] = GDB_SIGBUS, /* stack exception */
+ [13] = GDB_SIGSEGV, /* general protection */
+ [14] = GDB_SIGSEGV, /* page fault */
+ [15] = GDB_UNKNOWN, /* reserved */
+ [16] = GDB_SIGEMT, /* coprocessor error */
+ [17] = GDB_SIGBUS, /* alignment check */
+ [18] = GDB_SIGSEGV, /* machine check */
+ [19] = GDB_SIGFPE, /* simd floating point exception */
+ [20] = GDB_UNKNOWN,
+ [21] = GDB_UNKNOWN,
+ [22] = GDB_UNKNOWN,
+ [23] = GDB_UNKNOWN,
+ [24] = GDB_UNKNOWN,
+ [25] = GDB_UNKNOWN,
+ [26] = GDB_UNKNOWN,
+ [27] = GDB_UNKNOWN,
+ [28] = GDB_UNKNOWN,
+ [29] = GDB_UNKNOWN,
+ [30] = GDB_UNKNOWN,
+ [31] = GDB_UNKNOWN,
+ [32] = GDB_SIGINT, /* User interrupt */
+};
+
+static const char hexchars[] = "0123456789abcdef";
+static char in_buffer[BUFMAX];
+static char out_buffer[BUFMAX];
+
+
+static inline void stub_putc(int ch)
+{
+ gdb_tx_byte(ch);
+}
+
+static inline void stub_flush(void)
+{
+ gdb_tx_flush();
+}
+
+static inline int stub_getc(void)
+{
+ return gdb_rx_byte();
+}
+
+static int hex(char ch)
+{
+ if ((ch >= 'a') && (ch <= 'f'))
+ return (ch - 'a' + 10);
+ if ((ch >= '0') && (ch <= '9'))
+ return (ch - '0');
+ if ((ch >= 'A') && (ch <= 'F'))
+ return (ch - 'A' + 10);
+ return (-1);
+}
+
+/*
+ * While we find hexadecimal digits, build an int.
+ * Fals is returned if nothing is parsed true otherwise.
+ */
+static int parse_ulong(char **ptr, unsigned long *value)
+{
+ int digit;
+ char *start;
+
+ start = *ptr;
+ *value = 0;
+
+ while((digit = hex(**ptr)) >= 0) {
+ *value = ((*value) << 4) | digit;
+ (*ptr)++;
+ }
+ return start != *ptr;
+}
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+static void copy_to_hex(char *buf, void *addr, unsigned long count)
+{
+ unsigned char ch;
+ char *mem = addr;
+
+ while(count--) {
+ ch = *mem++;
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch & 0x0f];
+ }
+ *buf = 0;
+ return;
+}
+
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+static void copy_from_hex(void *addr, char *buf, unsigned long count)
+{
+ unsigned char ch;
+ char *mem = addr;
+
+ while(count--) {
+ ch = hex (*buf++) << 4;
+ ch = ch + hex (*buf++);
+ *mem++ = ch;
+ }
+}
+
+
+/* scan for the sequence $<data>#<checksum> */
+
+static int get_packet(char *buffer)
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int count;
+ char ch;
+
+ /* Wishlit implement a timeout in get_packet */
+ do {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = (stub_getc() & 0x7f)) != '$');
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX) {
+ ch = stub_getc() & 0x7f;
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#') {
+ xmitcsum = hex(stub_getc() & 0x7f) << 4;
+ xmitcsum += hex(stub_getc() & 0x7f);
+
+ if (checksum != xmitcsum) {
+ stub_putc('-'); /* failed checksum */
+ stub_flush();
+ }
+ else {
+ stub_putc('+'); /* successful transfer */
+ stub_flush();
+ }
+ }
+ } while(checksum != xmitcsum);
+ return 1;
+}
+
+/* send the packet in buffer.*/
+static void put_packet(char *buffer)
+{
+ unsigned char checksum;
+ int count;
+ char ch;
+
+ /* $<packet info>#<checksum>. */
+ do {
+ stub_putc('$');
+ checksum = 0;
+ count = 0;
+
+ while ((ch = buffer[count])) {
+ stub_putc(ch);
+ checksum += ch;
+ count += 1;
+ }
+
+ stub_putc('#');
+ stub_putc(hexchars[checksum >> 4]);
+ stub_putc(hexchars[checksum % 16]);
+ stub_flush();
+
+ } while ((stub_getc() & 0x7f) != '+');
+
+}
+#endif /* CONFIG_GDB_STUB */
+
+#include <arch/registers.h>
+
+void x86_exception(struct eregs *info);
+
+void x86_exception(struct eregs *info)
+{
+#if CONFIG_GDB_STUB
+ int signo;
+ memcpy(gdb_stub_registers, info, 8*sizeof(uint32_t));
+ gdb_stub_registers[PC] = info->eip;
+ gdb_stub_registers[CS] = info->cs;
+ gdb_stub_registers[PS] = info->eflags;
+ signo = GDB_UNKNOWN;
+ if (info->vector < ARRAY_SIZE(exception_to_signal)) {
+ signo = exception_to_signal[info->vector];
+ }
+
+ /* reply to the host that an exception has occured */
+ out_buffer[0] = 'S';
+ out_buffer[1] = hexchars[(signo>>4) & 0xf];
+ out_buffer[2] = hexchars[signo & 0xf];
+ out_buffer[3] = '\0';
+ put_packet(out_buffer);
+
+ while(1) {
+ unsigned long addr, length;
+ char *ptr;
+ out_buffer[0] = '\0';
+ out_buffer[1] = '\0';
+ if (!get_packet(in_buffer)) {
+ break;
+ }
+ switch(in_buffer[0]) {
+ case '?': /* last signal */
+ out_buffer[0] = 'S';
+ out_buffer[1] = hexchars[(signo >> 4) & 0xf];
+ out_buffer[2] = hexchars[signo & 0xf];
+ out_buffer[3] = '\0';
+ break;
+ case 'g': /* return the value of the cpu registers */
+ copy_to_hex(out_buffer, &gdb_stub_registers, sizeof(gdb_stub_registers));
+ break;
+ case 'G': /* set the value of the CPU registers - return OK */
+ copy_from_hex(&gdb_stub_registers, in_buffer + 1, sizeof(gdb_stub_registers));
+ memcpy(info, gdb_stub_registers, 8*sizeof(uint32_t));
+ info->eip = gdb_stub_registers[PC];
+ info->cs = gdb_stub_registers[CS];
+ info->eflags = gdb_stub_registers[PS];
+ memcpy(out_buffer, "OK",3);
+ break;
+ case 'm':
+ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ ptr = &in_buffer[1];
+ if ( parse_ulong(&ptr, &addr) &&
+ (*ptr++ == ',') &&
+ parse_ulong(&ptr, &length)) {
+ copy_to_hex(out_buffer, (void *)addr, length);
+ } else {
+ memcpy(out_buffer, "E01", 4);
+ }
+ break;
+ case 'M':
+ /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ ptr = &in_buffer[1];
+ if ( parse_ulong(&ptr, &addr) &&
+ (*(ptr++) == ',') &&
+ parse_ulong(&ptr, &length) &&
+ (*(ptr++) == ':')) {
+ copy_from_hex((void *)addr, ptr, length);
+ memcpy(out_buffer, "OK", 3);
+ }
+ else {
+ memcpy(out_buffer, "E02", 4);
+ }
+ break;
+ case 's':
+ case 'c':
+ /* cAA..AA Continue at address AA..AA(optional) */
+ /* sAA..AA Step one instruction from AA..AA(optional) */
+ ptr = &in_buffer[1];
+ if (parse_ulong(&ptr, &addr)) {
+ info->eip = addr;
+ }
+
+ /* Clear the trace bit */
+ info->eflags &= ~(1 << 8);
+ /* Set the trace bit if we are single stepping */
+ if (in_buffer[0] == 's') {
+ info->eflags |= (1 << 8);
+ }
+ return;
+ break;
+ case 'D':
+ memcpy(out_buffer, "OK", 3);
+ break;
+ case 'k': /* kill request? */
+ break;
+ case 'q': /* query */
+ break;
+ case 'z': /* z0AAAA,LLLL remove memory breakpoint */
+ /* z1AAAA,LLLL remove hardware breakpoint */
+ /* z2AAAA,LLLL remove write watchpoint */
+ /* z3AAAA,LLLL remove read watchpoint */
+ /* z4AAAA,LLLL remove access watchpoint */
+ case 'Z': /* Z0AAAA,LLLL insert memory breakpoint */
+ /* Z1AAAA,LLLL insert hardware breakpoint */
+ /* Z2AAAA,LLLL insert write watchpoint */
+ /* Z3AAAA,LLLL insert read watchpoint */
+ /* Z4AAAA,LLLL insert access watchpoint */
+ break;
+ default:
+ break;
+ }
+ put_packet(out_buffer);
+ }
+#else /* !CONFIG_GDB_STUB */
+#define MDUMP_SIZE 0x80
+ printk(BIOS_EMERG,
+ "Unexpected Exception: %d @ %02x:%08x - Halting\n"
+ "Code: %d eflags: %08x\n"
+ "eax: %08x ebx: %08x ecx: %08x edx: %08x\n"
+ "edi: %08x esi: %08x ebp: %08x esp: %08x\n",
+ info->vector, info->cs, info->eip,
+ info->error_code, info->eflags,
+ info->eax, info->ebx, info->ecx, info->edx,
+ info->edi, info->esi, info->ebp, info->esp);
+ u8 *code = (u8*)((uintptr_t)info->eip - (MDUMP_SIZE >>1));
+ /* Align to 8-byte boundary please, and print eight bytes per row.
+ * This is done to make DRAM burst timing/reordering errors more
+ * evident from the looking at the dump */
+ code = (u8*)((uintptr_t)code & ~0x7);
+ int i;
+ for(i = 0; i < MDUMP_SIZE; i++)
+ {
+ if( (i & 0x07) == 0 )
+ printk(BIOS_EMERG, "\n%p:\t", code + i);
+ printk(BIOS_EMERG, "%.2x ", code[i]);
+ }
+ die("");
+#endif
+}
diff --git a/src/arch/x86/failover.ld b/src/arch/x86/failover.ld
new file mode 100644
index 0000000..d7aa47e
--- /dev/null
+++ b/src/arch/x86/failover.ld
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2006 Advanced Micro Devices, Inc.
+ * Copyright (C) 2008-2010 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+MEMORY {
+ rom : ORIGIN = 0xffff0000, LENGTH = 64K
+}
+
+TARGET(binary)
+SECTIONS
+{
+ /* Symbol ap_sipi_vector must be aligned to 4kB to start AP CPUs
+ * with Startup IPI message without RAM. Align .rom to next 4 byte
+ * boundary anyway, so no pad byte appears between _rom and _start.
+ */
+ .bogus ROMLOC_MIN : {
+ . = CONFIG_SIPI_VECTOR_IN_ROM ? ALIGN(4096) : ALIGN(4);
+ ROMLOC = .;
+ } >rom = 0xff
+
+ /* This section might be better named .setup */
+ .rom ROMLOC : {
+ _rom = .;
+ ap_sipi_vector = .;
+ *(.rom.text);
+ *(.rom.data);
+ *(.rom.data.*);
+ *(.rodata.*);
+ _erom = .;
+ } >rom = 0xff
+
+ /* Allocation reserves extra 16 bytes here. Alignment requirements
+ * may cause the total size of a section to change when the start
+ * address gets applied.
+ */
+ ROMLOC_MIN = 0xffffff00 - (_erom - _rom + 16) -
+ (CONFIG_SIPI_VECTOR_IN_ROM ? 4096 : 0);
+
+ /* Post-check proper SIPI vector. */
+ _bogus = ASSERT(!CONFIG_SIPI_VECTOR_IN_ROM || ((ap_sipi_vector & 0x0fff) == 0x0),
+ "Bad SIPI vector alignment");
+ _bogus = ASSERT(!CONFIG_SIPI_VECTOR_IN_ROM || (ap_sipi_vector == CONFIG_AP_SIPI_VECTOR),
+ "Address mismatch on AP_SIPI_VECTOR");
+
+ /DISCARD/ : {
+ *(.comment)
+ *(.note)
+ *(.comment.*)
+ *(.note.*)
+ *(.iplt)
+ *(.rel.*)
+ *(.igot.*)
+ }
+}
diff --git a/src/arch/x86/gdt.c b/src/arch/x86/gdt.c
new file mode 100644
index 0000000..a21fab2
--- /dev/null
+++ b/src/arch/x86/gdt.c
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <types.h>
+#include <string.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/x86/gdt.h>
+
+/* i386 lgdt argument */
+struct gdtarg {
+ u16 limit;
+#ifdef __x86_64__
+ u64 base;
+#else
+ u32 base;
+#endif
+} __attribute__((packed));
+
+/* Copy GDT to new location and reload it.
+ * FIXME: We only do this for BSP CPU.
+ */
+static void move_gdt(int is_recovery)
+{
+ void *newgdt;
+ u16 num_gdt_bytes = (uintptr_t)&gdt_end - (uintptr_t)&gdt;
+ struct gdtarg gdtarg;
+
+ newgdt = cbmem_find(CBMEM_ID_GDT);
+ if (!newgdt) {
+ newgdt = cbmem_add(CBMEM_ID_GDT, ALIGN(num_gdt_bytes, 512));
+ if (!newgdt) {
+ printk(BIOS_ERR, "Error: Could not relocate GDT.\n");
+ return;
+ }
+ printk(BIOS_DEBUG, "Moving GDT to %p...", newgdt);
+ memcpy((void*)newgdt, &gdt, num_gdt_bytes);
+ }
+
+ gdtarg.base = (uintptr_t)newgdt;
+ gdtarg.limit = num_gdt_bytes - 1;
+
+ __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg));
+ printk(BIOS_DEBUG, "ok\n");
+}
+RAMSTAGE_CBMEM_INIT_HOOK(move_gdt)
diff --git a/src/arch/x86/id.inc b/src/arch/x86/id.inc
new file mode 100644
index 0000000..f8aba0b
--- /dev/null
+++ b/src/arch/x86/id.inc
@@ -0,0 +1,18 @@
+ .section ".id", "a", @progbits
+
+ .globl __id_start
+__id_start:
+ver:
+ .asciz COREBOOT_VERSION
+vendor:
+ .asciz CONFIG_MAINBOARD_VENDOR
+part:
+ .asciz CONFIG_MAINBOARD_PART_NUMBER
+.long __id_end + CONFIG_ID_SECTION_OFFSET - ver /* Reverse offset to the vendor id */
+.long __id_end + CONFIG_ID_SECTION_OFFSET - vendor /* Reverse offset to the vendor id */
+.long __id_end + CONFIG_ID_SECTION_OFFSET - part /* Reverse offset to the part number */
+.long CONFIG_ROM_SIZE /* Size of this romimage */
+ .globl __id_end
+
+__id_end:
+.previous
diff --git a/src/arch/x86/id.ld b/src/arch/x86/id.ld
new file mode 100644
index 0000000..cfd091d
--- /dev/null
+++ b/src/arch/x86/id.ld
@@ -0,0 +1,6 @@
+SECTIONS {
+ . = (0xffffffff - CONFIG_ID_SECTION_OFFSET) - (__id_end - __id_start) + 1;
+ .id (.): {
+ *(.id)
+ }
+}
diff --git a/src/arch/x86/init/Makefile.inc b/src/arch/x86/init/Makefile.inc
deleted file mode 100644
index 263c58e..0000000
--- a/src/arch/x86/init/Makefile.inc
+++ /dev/null
@@ -1 +0,0 @@
-# If you add something to this file, enable it in src/arch/x86/Makefile.inc first.
diff --git a/src/arch/x86/init/bootblock_normal.c b/src/arch/x86/init/bootblock_normal.c
deleted file mode 100644
index bde2535..0000000
--- a/src/arch/x86/init/bootblock_normal.c
+++ /dev/null
@@ -1,52 +0,0 @@
-#include <smp/node.h>
-#include <bootblock_common.h>
-#include <pc80/mc146818rtc.h>
-#include <halt.h>
-
-static const char *get_fallback(const char *stagelist) {
- while (*stagelist) stagelist++;
- return ++stagelist;
-}
-
-static void main(unsigned long bist)
-{
- unsigned long entry;
- int boot_mode;
- const char *default_filenames = "normal/romstage\0fallback/romstage";
-
- if (boot_cpu()) {
- bootblock_mainboard_init();
-
-#if CONFIG_USE_OPTION_TABLE
- sanitize_cmos();
-#endif
- boot_mode = do_normal_boot();
- } else {
-
- /* Questionable single byte read from CMOS.
- * Do not add any other CMOS access in the
- * bootblock for AP CPUs.
- */
- boot_mode = last_boot_normal();
- }
-
- char *filenames = (char *)walkcbfs("coreboot-stages");
- if (!filenames) {
- filenames = default_filenames;
- }
- char *normal_candidate = filenames;
-
- if (boot_mode)
- entry = findstage(normal_candidate);
- else
- entry = findstage(get_fallback(normal_candidate));
-
- if (entry) call(entry, bist);
-
- /* run fallback if normal can't be found */
- entry = findstage(get_fallback(normal_candidate));
- if (entry) call(entry, bist);
-
- /* duh. we're stuck */
- halt();
-}
diff --git a/src/arch/x86/init/bootblock_simple.c b/src/arch/x86/init/bootblock_simple.c
deleted file mode 100644
index adeecf7..0000000
--- a/src/arch/x86/init/bootblock_simple.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <smp/node.h>
-#include <bootblock_common.h>
-#include <halt.h>
-
-static void main(unsigned long bist)
-{
- if (boot_cpu()) {
- bootblock_mainboard_init();
-
-#if CONFIG_USE_OPTION_TABLE
- sanitize_cmos();
-#endif
-#if CONFIG_CMOS_POST
- cmos_post_init();
-#endif
- }
-
- const char* target1 = "fallback/romstage";
- unsigned long entry;
- entry = findstage(target1);
- if (entry) call(entry, bist);
- halt();
-}
diff --git a/src/arch/x86/init/crt0_romcc_epilogue.inc b/src/arch/x86/init/crt0_romcc_epilogue.inc
deleted file mode 100644
index ff93adb..0000000
--- a/src/arch/x86/init/crt0_romcc_epilogue.inc
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2002 Eric Biederman
- *
- * This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; version 2 of the License.
- */
-#include <cpu/x86/post_code.h>
-
-__main:
- post_code(POST_PREPARE_RAMSTAGE)
- cld /* clear direction flag */
-
- movl $CONFIG_RAMTOP, %esp
- movl %esp, %ebp
- call copy_and_run
-
-.Lhlt:
- post_code(POST_DEAD_CODE)
- hlt
- jmp .Lhlt
diff --git a/src/arch/x86/init/failover.ld b/src/arch/x86/init/failover.ld
deleted file mode 100644
index d7aa47e..0000000
--- a/src/arch/x86/init/failover.ld
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2006 Advanced Micro Devices, Inc.
- * Copyright (C) 2008-2010 coresystems GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-MEMORY {
- rom : ORIGIN = 0xffff0000, LENGTH = 64K
-}
-
-TARGET(binary)
-SECTIONS
-{
- /* Symbol ap_sipi_vector must be aligned to 4kB to start AP CPUs
- * with Startup IPI message without RAM. Align .rom to next 4 byte
- * boundary anyway, so no pad byte appears between _rom and _start.
- */
- .bogus ROMLOC_MIN : {
- . = CONFIG_SIPI_VECTOR_IN_ROM ? ALIGN(4096) : ALIGN(4);
- ROMLOC = .;
- } >rom = 0xff
-
- /* This section might be better named .setup */
- .rom ROMLOC : {
- _rom = .;
- ap_sipi_vector = .;
- *(.rom.text);
- *(.rom.data);
- *(.rom.data.*);
- *(.rodata.*);
- _erom = .;
- } >rom = 0xff
-
- /* Allocation reserves extra 16 bytes here. Alignment requirements
- * may cause the total size of a section to change when the start
- * address gets applied.
- */
- ROMLOC_MIN = 0xffffff00 - (_erom - _rom + 16) -
- (CONFIG_SIPI_VECTOR_IN_ROM ? 4096 : 0);
-
- /* Post-check proper SIPI vector. */
- _bogus = ASSERT(!CONFIG_SIPI_VECTOR_IN_ROM || ((ap_sipi_vector & 0x0fff) == 0x0),
- "Bad SIPI vector alignment");
- _bogus = ASSERT(!CONFIG_SIPI_VECTOR_IN_ROM || (ap_sipi_vector == CONFIG_AP_SIPI_VECTOR),
- "Address mismatch on AP_SIPI_VECTOR");
-
- /DISCARD/ : {
- *(.comment)
- *(.note)
- *(.comment.*)
- *(.note.*)
- *(.iplt)
- *(.rel.*)
- *(.igot.*)
- }
-}
diff --git a/src/arch/x86/init/prologue.inc b/src/arch/x86/init/prologue.inc
deleted file mode 100644
index e0100b5..0000000
--- a/src/arch/x86/init/prologue.inc
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2002 Eric Biederman
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <cpu/x86/post_code.h>
-
-.section ".rom.data", "a", @progbits
-.section ".rom.text", "ax", @progbits
diff --git a/src/arch/x86/init/romstage.ld b/src/arch/x86/init/romstage.ld
deleted file mode 100644
index 951ca65..0000000
--- a/src/arch/x86/init/romstage.ld
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2006 Advanced Micro Devices, Inc.
- * Copyright (C) 2008-2010 coresystems GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-TARGET(binary)
-SECTIONS
-{
- . = ROMSTAGE_BASE;
-
- .rom . : {
- _rom = .;
- *(.rom.text);
- *(.rom.text.*);
- *(.text);
- *(.text.*);
- *(.rom.data);
- . = ALIGN(4);
- _cbmem_init_hooks = .;
- KEEP(*(.rodata.cbmem_init_hooks));
- _ecbmem_init_hooks = .;
- *(.rodata);
- *(.rodata.*);
- *(.rom.data.*);
- . = ALIGN(16);
- _erom = .;
- }
-
- /DISCARD/ : {
- *(.comment)
- *(.note)
- *(.comment.*)
- *(.note.*)
- *(.eh_frame);
- }
-
- . = CONFIG_DCACHE_RAM_BASE;
- .car.data . (NOLOAD) : {
- _car_data_start = .;
-#if IS_ENABLED(CONFIG_HAS_PRECBMEM_TIMESTAMP_REGION)
- _timestamp = .;
- . = . + 0x100;
- _etimestamp = .;
-#endif
- *(.car.global_data);
- _car_data_end = .;
- /* The preram cbmem console area comes last to take advantage
- * of a zero-sized array to hold the memconsole contents.
- * However, collisions within the cache-as-ram region cannot be
- * statically checked because the cache-as-ram region usage is
- * cpu/chipset dependent. */
- _preram_cbmem_console = .;
- _epreram_cbmem_console = . + (CONFIG_LATE_CBMEM_INIT ? 0 : 0xc00);
- }
-
- /* Global variables are not allowed in romstage
- * This section is checked during stage creation to ensure
- * that there are no global variables present
- */
-
- . = 0xffffff00;
- .illegal_globals . : {
- *(EXCLUDE_FILE ("*/libagesa.*.a:" "*/buildOpts.romstage.o" "*/agesawrapper.romstage.o" "*/vendorcode/amd/agesa/*" "*/vendorcode/amd/cimx/*") .data)
- *(EXCLUDE_FILE ("*/libagesa.*.a:" "*/buildOpts.romstage.o" "*/agesawrapper.romstage.o" "*/vendorcode/amd/agesa/*" "*/vendorcode/amd/cimx/*") .data.*)
- *(.bss)
- *(.bss.*)
- *(.sbss)
- *(.sbss.*)
- }
-
- _bogus = ASSERT((CONFIG_DCACHE_RAM_SIZE == 0) || (SIZEOF(.car.data) + 0xc00 <= CONFIG_DCACHE_RAM_SIZE), "Cache as RAM area is too full");
-}
diff --git a/src/arch/x86/ioapic.c b/src/arch/x86/ioapic.c
new file mode 100644
index 0000000..1b13127
--- /dev/null
+++ b/src/arch/x86/ioapic.c
@@ -0,0 +1,153 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <arch/io.h>
+#include <arch/ioapic.h>
+#include <console/console.h>
+#include <cpu/x86/lapic.h>
+
+u32 io_apic_read(void *ioapic_base, u32 reg)
+{
+ write32(ioapic_base, reg);
+ return read32(ioapic_base + 0x10);
+}
+
+void io_apic_write(void *ioapic_base, u32 reg, u32 value)
+{
+ write32(ioapic_base, reg);
+ write32(ioapic_base + 0x10, value);
+}
+
+static int ioapic_interrupt_count(void *ioapic_base)
+{
+ /* Read the available number of interrupts. */
+ int ioapic_interrupts = (io_apic_read(ioapic_base, 0x01) >> 16) & 0xff;
+ if (ioapic_interrupts == 0xff)
+ ioapic_interrupts = 23;
+ ioapic_interrupts += 1; /* Bits 23-16 specify the maximum redirection
+ entry, which is the number of interrupts
+ minus 1. */
+ printk(BIOS_DEBUG, "IOAPIC: %d interrupts\n", ioapic_interrupts);
+
+ return ioapic_interrupts;
+}
+
+void clear_ioapic(void *ioapic_base)
+{
+ u32 low, high;
+ u32 i, ioapic_interrupts;
+
+ printk(BIOS_DEBUG, "IOAPIC: Clearing IOAPIC at %p\n", ioapic_base);
+
+ ioapic_interrupts = ioapic_interrupt_count(ioapic_base);
+
+ low = DISABLED;
+ high = NONE;
+
+ for (i = 0; i < ioapic_interrupts; i++) {
+ io_apic_write(ioapic_base, i * 2 + 0x10, low);
+ io_apic_write(ioapic_base, i * 2 + 0x11, high);
+
+ printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
+ i, high, low);
+ }
+
+ if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
+ printk(BIOS_WARNING, "IOAPIC not responding.\n");
+ return;
+ }
+}
+
+void set_ioapic_id(void *ioapic_base, u8 ioapic_id)
+{
+ u32 bsp_lapicid = lapicid();
+ int i;
+
+ printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at 0x%p\n",
+ ioapic_base);
+ printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC = 0x%02x\n",
+ bsp_lapicid);
+
+ if (ioapic_id) {
+ printk(BIOS_DEBUG, "IOAPIC: ID = 0x%02x\n", ioapic_id);
+ /* Set IOAPIC ID if it has been specified. */
+ io_apic_write(ioapic_base, 0x00,
+ (io_apic_read(ioapic_base, 0x00) & 0xf0ffffff) |
+ (ioapic_id << 24));
+ }
+
+ printk(BIOS_SPEW, "IOAPIC: Dumping registers\n");
+ for (i = 0; i < 3; i++)
+ printk(BIOS_SPEW, " reg 0x%04x: 0x%08x\n", i,
+ io_apic_read(ioapic_base, i));
+
+}
+
+static void load_vectors(void *ioapic_base)
+{
+ u32 bsp_lapicid = lapicid();
+ u32 low, high;
+ u32 i, ioapic_interrupts;
+
+ ioapic_interrupts = ioapic_interrupt_count(ioapic_base);
+
+#if CONFIG_IOAPIC_INTERRUPTS_ON_FSB
+ /*
+ * For the Pentium 4 and above APICs deliver their interrupts
+ * on the front side bus, enable that.
+ */
+ printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on FSB\n");
+ io_apic_write(ioapic_base, 0x03,
+ io_apic_read(ioapic_base, 0x03) | (1 << 0));
+#endif
+#if CONFIG_IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
+ printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on APIC serial bus\n");
+ io_apic_write(ioapic_base, 0x03, 0);
+#endif
+
+ /* Enable Virtual Wire Mode. */
+ low = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
+ high = bsp_lapicid << (56 - 32);
+
+ io_apic_write(ioapic_base, 0x10, low);
+ io_apic_write(ioapic_base, 0x11, high);
+
+ if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
+ printk(BIOS_WARNING, "IOAPIC not responding.\n");
+ return;
+ }
+
+ printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
+ 0, high, low);
+ low = DISABLED;
+ high = NONE;
+ for (i = 1; i < ioapic_interrupts; i++) {
+ io_apic_write(ioapic_base, i * 2 + 0x10, low);
+ io_apic_write(ioapic_base, i * 2 + 0x11, high);
+
+ printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
+ i, high, low);
+ }
+}
+
+void setup_ioapic(void *ioapic_base, u8 ioapic_id)
+{
+ set_ioapic_id(ioapic_base, ioapic_id);
+ load_vectors(ioapic_base);
+}
diff --git a/src/arch/x86/lib/Makefile.inc b/src/arch/x86/lib/Makefile.inc
deleted file mode 100644
index ccfe30a..0000000
--- a/src/arch/x86/lib/Makefile.inc
+++ /dev/null
@@ -1,48 +0,0 @@
-
-ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32)$(CONFIG_ARCH_ROMSTAGE_X86_64),y)
-
-romstage-y += cbfs_and_run.c
-romstage-$(CONFIG_ARCH_RAMSTAGE_X86_32) += cpu_common.c
-romstage-y += memset.c
-romstage-y += memcpy.c
-romstage-y += memmove.c
-romstage-y += mmap_boot.c
-
-endif # CONFIG_ARCH_ROMSTAGE_X86_32 / CONFIG_ARCH_ROMSTAGE_X86_64
-
-ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32)$(CONFIG_ARCH_RAMSTAGE_X86_64),y)
-
-ramstage-y += c_start.S
-ramstage-y += cpu.c
-ramstage-y += cpu_common.c
-ramstage-y += pci_ops_conf1.c
-ramstage-$(CONFIG_MMCONF_SUPPORT) += pci_ops_mmconf.c
-ramstage-y += exception.c
-ramstage-$(CONFIG_IOAPIC) += ioapic.c
-ramstage-y += memset.c
-ramstage-y += memcpy.c
-ramstage-y += memmove.c
-ramstage-y += ebda.c
-ramstage-y += mmap_boot.c
-ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c
-ramstage-$(CONFIG_COOP_MULTITASKING) += thread_switch.S
-ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
-
-romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
-
-smm-y += memset.c
-smm-y += memcpy.c
-smm-y += memmove.c
-smm-y += mmap_boot.c
-
-ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y)
-rmodules_x86_32-y += memset.c
-rmodules_x86_32-y += memcpy.c
-rmodules_x86_32-y += memmove.c
-else
-rmodules_x86_64-y += memset.c
-rmodules_x86_64-y += memcpy.c
-rmodules_x86_64-y += memmove.c
-endif
-
-endif # CONFIG_ARCH_RAMSTAGE_X86_32 / CONFIG_ARCH_RAMSTAGE_X86_64
diff --git a/src/arch/x86/lib/c_start.S b/src/arch/x86/lib/c_start.S
deleted file mode 100644
index 582966b..0000000
--- a/src/arch/x86/lib/c_start.S
+++ /dev/null
@@ -1,421 +0,0 @@
-#include <cpu/x86/post_code.h>
-
-/* Place the stack in the bss section. It's not necessary to define it in the
- * the linker script. */
- .section .bss, "aw", @nobits
-.global _stack
-.global _estack
-
-.align CONFIG_STACK_SIZE
-_stack:
-.space CONFIG_MAX_CPUS*CONFIG_STACK_SIZE
-_estack:
-#if CONFIG_COOP_MULTITASKING
-.global thread_stacks
-thread_stacks:
-.space CONFIG_STACK_SIZE*CONFIG_NUM_THREADS
-#endif
-
- .section ".text._start", "ax", @progbits
-#ifdef __x86_64__
- .code64
-#else
- .code32
-#endif
- .globl _start
- .globl __rmodule_entry
-__rmodule_entry:
-_start:
- cli
- lgdt %cs:gdtaddr
-#ifndef __x86_64__
- ljmp $0x10, $1f
-#endif
-1: movl $0x18, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %ss
- movl %eax, %fs
- movl %eax, %gs
-#ifdef __x86_64__
- mov $0x48, %ecx
- call SetCodeSelector
-#endif
-
- post_code(POST_ENTRY_C_START) /* post 13 */
-
- cld
-
- /** poison the stack. Code should not count on the
- * stack being full of zeros. This stack poisoning
- * recently uncovered a bug in the broadcast SIPI
- * code.
- */
- leal _stack, %edi
- movl $_estack, %ecx
- subl %edi, %ecx
- shrl $2, %ecx /* it is 32 bit aligned, right? */
- movl $0xDEADBEEF, %eax
- rep
- stosl
-
- /* set new stack */
- movl $_estack, %esp
-
-#if CONFIG_COOP_MULTITASKING
- /* Push the thread pointer. */
- push $0
-#endif
- /* Push the cpu index and struct cpu */
- push $0
- push $0
-
- /* Initialize the Interrupt Descriptor table */
- leal _idt, %edi
- leal vec0, %ebx
- movl $(0x10 << 16), %eax /* cs selector */
-
-1: movw %bx, %ax
- movl %ebx, %edx
- movw $0x8E00, %dx /* Interrupt gate - dpl=0, present */
- movl %eax, 0(%edi)
- movl %edx, 4(%edi)
- addl $6, %ebx
- addl $8, %edi
- cmpl $_idt_end, %edi
- jne 1b
-
- /* Load the Interrupt descriptor table */
-#ifndef __x86_64__
- lidt idtarg
-#else
- // FIXME port table to x64 - lidt idtarg
-#endif
-
- /*
- * Now we are finished. Memory is up, data is copied and
- * bss is cleared. Now we call the main routine and
- * let it do the rest.
- */
- post_code(POST_PRE_HARDWAREMAIN) /* post fe */
-
-#if CONFIG_GDB_WAIT
- call gdb_hw_init
- call gdb_stub_breakpoint
-#endif
- call main
- /* NOTREACHED */
-.Lhlt:
- post_code(POST_DEAD_CODE) /* post ee */
- hlt
- jmp .Lhlt
-
-vec0:
- push $0 /* error code */
- push $0 /* vector */
- jmp int_hand
-vec1:
- push $0 /* error code */
- push $1 /* vector */
- jmp int_hand
-
-vec2:
- push $0 /* error code */
- push $2 /* vector */
- jmp int_hand
-
-vec3:
- push $0 /* error code */
- push $3 /* vector */
- jmp int_hand
-
-vec4:
- push $0 /* error code */
- push $4 /* vector */
- jmp int_hand
-
-vec5:
- push $0 /* error code */
- push $5 /* vector */
- jmp int_hand
-
-vec6:
- push $0 /* error code */
- push $6 /* vector */
- jmp int_hand
-
-vec7:
- push $0 /* error code */
- push $7 /* vector */
- jmp int_hand
-
-vec8:
- /* error code */
- push $8 /* vector */
- jmp int_hand
- .word 0x9090
-
-vec9:
- push $0 /* error code */
- push $9 /* vector */
- jmp int_hand
-
-vec10:
- /* error code */
- push $10 /* vector */
- jmp int_hand
- .word 0x9090
-
-vec11:
- /* error code */
- push $11 /* vector */
- jmp int_hand
- .word 0x9090
-
-vec12:
- /* error code */
- push $12 /* vector */
- jmp int_hand
- .word 0x9090
-
-vec13:
- /* error code */
- push $13 /* vector */
- jmp int_hand
- .word 0x9090
-
-vec14:
- /* error code */
- push $14 /* vector */
- jmp int_hand
- .word 0x9090
-
-vec15:
- push $0 /* error code */
- push $15 /* vector */
- jmp int_hand
-
-vec16:
- push $0 /* error code */
- push $16 /* vector */
- jmp int_hand
-
-vec17:
- /* error code */
- push $17 /* vector */
- jmp int_hand
- .word 0x9090
-
-vec18:
- push $0 /* error code */
- push $18 /* vector */
- jmp int_hand
-
-vec19:
- push $0 /* error code */
- push $19 /* vector */
- jmp int_hand
-
-int_hand:
- /* At this point, on x86-32, on the stack there is:
- * 0(%esp) vector
- * 4(%esp) error code
- * 8(%esp) eip
- * 12(%esp) cs
- * 16(%esp) eflags
- */
-#ifdef __x86_64__
- push %rdi
- push %rsi
- push %rbp
- /* Original stack pointer */
- lea 32(%rsp), %rbp
- push %rbp
- push %rbx
- push %rdx
- push %rcx
- push %rax
-
- push %rsp /* Pointer to structure on the stack */
- call x86_exception
- pop %rax /* Drop the pointer */
-
- pop %rax
- pop %rcx
- pop %rdx
- pop %rbx
- pop %rbp /* Ignore saved %rsp value */
- pop %rbp
- pop %rsi
- pop %rdi
-
- add $8, %rsp /* pop of the vector and error code */
-#else
- pushl %edi
- pushl %esi
- pushl %ebp
-
- /* Original stack pointer */
- leal 32(%esp), %ebp
- pushl %ebp
- pushl %ebx
- pushl %edx
- pushl %ecx
- pushl %eax
-
- pushl %esp /* Pointer to structure on the stack */
- call x86_exception
- pop %eax /* Drop the pointer */
-
- popl %eax
- popl %ecx
- popl %edx
- popl %ebx
- popl %ebp /* Ignore saved %esp value */
- popl %ebp
- popl %esi
- popl %edi
-
- addl $8, %esp /* pop of the vector and error code */
-#endif
-
- iret
-
-#if CONFIG_GDB_WAIT
-
- .globl gdb_stub_breakpoint
-gdb_stub_breakpoint:
-#ifdef __x86_64__
- pop %rax /* Return address */
- pushfl
- push %cs
- push %rax /* Return address */
- push $0 /* No error code */
- push $32 /* vector 32 is user defined */
-#else
- popl %eax /* Return address */
- pushfl
- pushl %cs
- pushl %eax /* Return address */
- pushl $0 /* No error code */
- pushl $32 /* vector 32 is user defined */
-#endif
- jmp int_hand
-#endif
-
- .globl gdt, gdt_end, idtarg
-
-gdtaddr:
- .word gdt_end - gdt - 1
-#ifdef __x86_64__
- .quad gdt
-#else
- .long gdt /* we know the offset */
-#endif
-
- .data
-
- /* This is the gdt for GCC part of coreboot.
- * It is different from the gdt in ROMCC/ASM part of coreboot
- * which is defined in entry32.inc
- *
- * When the machine is initially started, we use a very simple
- * gdt from rom (that in entry32.inc) which only contains those
- * entries we need for protected mode.
- *
- * When we're executing code from RAM, we want to do more complex
- * stuff, like initializing PCI option roms in real mode, or doing
- * a resume from a suspend to ram.
- */
-gdt:
- /* selgdt 0, unused */
- .word 0x0000, 0x0000 /* dummy */
- .byte 0x00, 0x00, 0x00, 0x00
-
- /* selgdt 8, unused */
- .word 0x0000, 0x0000 /* dummy */
- .byte 0x00, 0x00, 0x00, 0x00
-
- /* selgdt 0x10, flat code segment */
- .word 0xffff, 0x0000
- .byte 0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */
-
- /* selgdt 0x18, flat data segment */
- .word 0xffff, 0x0000
-#ifdef __x86_64__
- .byte 0x00, 0x92, 0xcf, 0x00
-#else
- .byte 0x00, 0x93, 0xcf, 0x00
-#endif
-
- /* selgdt 0x20, unused */
- .word 0x0000, 0x0000 /* dummy */
- .byte 0x00, 0x00, 0x00, 0x00
-
- /* The next two entries are used for executing VGA option ROMs */
-
- /* selgdt 0x28 16 bit 64k code at 0x00000000 */
- .word 0xffff, 0x0000
- .byte 0, 0x9a, 0, 0
-
- /* selgdt 0x30 16 bit 64k data at 0x00000000 */
- .word 0xffff, 0x0000
- .byte 0, 0x92, 0, 0
-
- /* The next two entries are used for ACPI S3 RESUME */
-
- /* selgdt 0x38, flat data segment 16 bit */
- .word 0x0000, 0x0000 /* dummy */
- .byte 0x00, 0x93, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */
-
- /* selgdt 0x40, flat code segment 16 bit */
- .word 0xffff, 0x0000
- .byte 0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */
-
-#ifdef __x86_64__
- /* selgdt 0x48, flat x64 code segment */
- .word 0xffff, 0x0000
- .byte 0x00, 0x9b, 0xaf, 0x00
-#endif
-gdt_end:
-
-idtarg:
- .word _idt_end - _idt - 1 /* limit */
- .long _idt
- .word 0
-_idt:
- .fill 20, 8, 0 # idt is uninitialized
-_idt_end:
-
-#ifdef __x86_64__
-SetCodeSelector:
-.intel_syntax noprefix
-
- # save rsp because iret will align it to a 16 byte boundary
- mov rdx, rsp
-
- # use iret to jump to a 64-bit offset in a new code segment
- # iret will pop cs:rip, flags, then ss:rsp
- mov ax, ss # need to push ss..
- push rax # push ss instuction not valid in x64 mode, so use ax
- push rsp
- pushfq
- push rcx # cx is code segment selector from caller
- mov rax, offset setCodeSelectorLongJump
- push rax
-
- # the iret will continue at next instruction, with the new cs value loaded
- iretq
-
-setCodeSelectorLongJump:
- # restore rsp, it might not have been 16-byte aligned on entry
- mov rsp, rdx
- ret
-.att_syntax prefix
-
- .previous
-.code64
-#else
- .previous
-.code32
-#endif
diff --git a/src/arch/x86/lib/cbfs_and_run.c b/src/arch/x86/lib/cbfs_and_run.c
deleted file mode 100644
index b6d3426..0000000
--- a/src/arch/x86/lib/cbfs_and_run.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2008-2009 coresystems GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <arch/stages.h>
-#include <program_loading.h>
-
-void asmlinkage copy_and_run(void)
-{
- run_ramstage();
-}
diff --git a/src/arch/x86/lib/cpu.c b/src/arch/x86/lib/cpu.c
deleted file mode 100644
index 3eb7b94..0000000
--- a/src/arch/x86/lib/cpu.c
+++ /dev/null
@@ -1,273 +0,0 @@
-#include <console/console.h>
-#include <cpu/cpu.h>
-#include <arch/io.h>
-#include <string.h>
-#include <cpu/x86/mtrr.h>
-#include <cpu/x86/msr.h>
-#include <cpu/x86/lapic.h>
-#include <arch/cpu.h>
-#include <device/path.h>
-#include <device/device.h>
-#include <smp/spinlock.h>
-
-#ifndef __x86_64__
-/* Standard macro to see if a specific flag is changeable */
-static inline int flag_is_changeable_p(uint32_t flag)
-{
- uint32_t f1, f2;
-
- asm(
- "pushfl\n\t"
- "pushfl\n\t"
- "popl %0\n\t"
- "movl %0,%1\n\t"
- "xorl %2,%0\n\t"
- "pushl %0\n\t"
- "popfl\n\t"
- "pushfl\n\t"
- "popl %0\n\t"
- "popfl\n\t"
- : "=&r" (f1), "=&r" (f2)
- : "ir" (flag));
- return ((f1^f2) & flag) != 0;
-}
-
-/*
- * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
- * by the fact that they preserve the flags across the division of 5/2.
- * PII and PPro exhibit this behavior too, but they have cpuid available.
- */
-
-/*
- * Perform the Cyrix 5/2 test. A Cyrix won't change
- * the flags, while other 486 chips will.
- */
-static inline int test_cyrix_52div(void)
-{
- unsigned int test;
-
- __asm__ __volatile__(
- "sahf\n\t" /* clear flags (%eax = 0x0005) */
- "div %b2\n\t" /* divide 5 by 2 */
- "lahf" /* store flags into %ah */
- : "=a" (test)
- : "0" (5), "q" (2)
- : "cc");
-
- /* AH is 0x02 on Cyrix after the divide.. */
- return (unsigned char) (test >> 8) == 0x02;
-}
-
-/*
- * Detect a NexGen CPU running without BIOS hypercode new enough
- * to have CPUID. (Thanks to Herbert Oppmann)
- */
-
-static int deep_magic_nexgen_probe(void)
-{
- int ret;
-
- __asm__ __volatile__ (
- " movw $0x5555, %%ax\n"
- " xorw %%dx,%%dx\n"
- " movw $2, %%cx\n"
- " divw %%cx\n"
- " movl $0, %%eax\n"
- " jnz 1f\n"
- " movl $1, %%eax\n"
- "1:\n"
- : "=a" (ret) : : "cx", "dx" );
- return ret;
-}
-#endif
-
-/* List of cpu vendor strings along with their normalized
- * id values.
- */
-static struct {
- int vendor;
- const char *name;
-} x86_vendors[] = {
- { X86_VENDOR_INTEL, "GenuineIntel", },
- { X86_VENDOR_CYRIX, "CyrixInstead", },
- { X86_VENDOR_AMD, "AuthenticAMD", },
- { X86_VENDOR_UMC, "UMC UMC UMC ", },
- { X86_VENDOR_NEXGEN, "NexGenDriven", },
- { X86_VENDOR_CENTAUR, "CentaurHauls", },
- { X86_VENDOR_RISE, "RiseRiseRise", },
- { X86_VENDOR_TRANSMETA, "GenuineTMx86", },
- { X86_VENDOR_TRANSMETA, "TransmetaCPU", },
- { X86_VENDOR_NSC, "Geode by NSC", },
- { X86_VENDOR_SIS, "SiS SiS SiS ", },
-};
-
-static const char *x86_vendor_name[] = {
- [X86_VENDOR_INTEL] = "Intel",
- [X86_VENDOR_CYRIX] = "Cyrix",
- [X86_VENDOR_AMD] = "AMD",
- [X86_VENDOR_UMC] = "UMC",
- [X86_VENDOR_NEXGEN] = "NexGen",
- [X86_VENDOR_CENTAUR] = "Centaur",
- [X86_VENDOR_RISE] = "Rise",
- [X86_VENDOR_TRANSMETA] = "Transmeta",
- [X86_VENDOR_NSC] = "NSC",
- [X86_VENDOR_SIS] = "SiS",
-};
-
-static const char *cpu_vendor_name(int vendor)
-{
- const char *name;
- name = "<invalid cpu vendor>";
- if ((vendor < (ARRAY_SIZE(x86_vendor_name))) &&
- (x86_vendor_name[vendor] != 0))
- {
- name = x86_vendor_name[vendor];
- }
- return name;
-}
-
-static void identify_cpu(struct device *cpu)
-{
- char vendor_name[16];
- int i;
-
- vendor_name[0] = '\0'; /* Unset */
-
-#ifndef __x86_64__
- /* Find the id and vendor_name */
- if (!cpu_have_cpuid()) {
- /* Its a 486 if we can modify the AC flag */
- if (flag_is_changeable_p(X86_EFLAGS_AC)) {
- cpu->device = 0x00000400; /* 486 */
- } else {
- cpu->device = 0x00000300; /* 386 */
- }
- if ((cpu->device == 0x00000400) && test_cyrix_52div()) {
- memcpy(vendor_name, "CyrixInstead", 13);
- /* If we ever care we can enable cpuid here */
- }
- /* Detect NexGen with old hypercode */
- else if (deep_magic_nexgen_probe()) {
- memcpy(vendor_name, "NexGenDriven", 13);
- }
- }
-#endif
- if (cpu_have_cpuid()) {
- int cpuid_level;
- struct cpuid_result result;
- result = cpuid(0x00000000);
- cpuid_level = result.eax;
- vendor_name[ 0] = (result.ebx >> 0) & 0xff;
- vendor_name[ 1] = (result.ebx >> 8) & 0xff;
- vendor_name[ 2] = (result.ebx >> 16) & 0xff;
- vendor_name[ 3] = (result.ebx >> 24) & 0xff;
- vendor_name[ 4] = (result.edx >> 0) & 0xff;
- vendor_name[ 5] = (result.edx >> 8) & 0xff;
- vendor_name[ 6] = (result.edx >> 16) & 0xff;
- vendor_name[ 7] = (result.edx >> 24) & 0xff;
- vendor_name[ 8] = (result.ecx >> 0) & 0xff;
- vendor_name[ 9] = (result.ecx >> 8) & 0xff;
- vendor_name[10] = (result.ecx >> 16) & 0xff;
- vendor_name[11] = (result.ecx >> 24) & 0xff;
- vendor_name[12] = '\0';
-
- /* Intel-defined flags: level 0x00000001 */
- if (cpuid_level >= 0x00000001) {
- cpu->device = cpuid_eax(0x00000001);
- }
- else {
- /* Have CPUID level 0 only unheard of */
- cpu->device = 0x00000400;
- }
- }
- cpu->vendor = X86_VENDOR_UNKNOWN;
- for(i = 0; i < ARRAY_SIZE(x86_vendors); i++) {
- if (memcmp(vendor_name, x86_vendors[i].name, 12) == 0) {
- cpu->vendor = x86_vendors[i].vendor;
- break;
- }
- }
-}
-
-struct cpu_driver *find_cpu_driver(struct device *cpu)
-{
- struct cpu_driver *driver;
- for (driver = cpu_drivers; driver < ecpu_drivers; driver++) {
- struct cpu_device_id *id;
- for (id = driver->id_table;
- id->vendor != X86_VENDOR_INVALID; id++) {
- if ((cpu->vendor == id->vendor) &&
- (cpu->device == id->device))
- {
- return driver;
- }
- if (X86_VENDOR_ANY == id->vendor)
- return driver;
- }
- }
- return NULL;
-}
-
-static void set_cpu_ops(struct device *cpu)
-{
- struct cpu_driver *driver = find_cpu_driver(cpu);
- cpu->ops = driver ? driver->ops : NULL;
-}
-
-void cpu_initialize(unsigned int index)
-{
- /* Because we busy wait at the printk spinlock.
- * It is important to keep the number of printed messages
- * from secondary cpus to a minimum, when debugging is
- * disabled.
- */
- struct device *cpu;
- struct cpu_info *info;
- struct cpuinfo_x86 c;
-
- info = cpu_info();
-
- printk(BIOS_INFO, "Initializing CPU #%d\n", index);
-
- cpu = info->cpu;
- if (!cpu) {
- die("CPU: missing cpu device structure");
- }
-
- post_log_path(cpu);
-
- /* Find what type of cpu we are dealing with */
- identify_cpu(cpu);
- printk(BIOS_DEBUG, "CPU: vendor %s device %x\n",
- cpu_vendor_name(cpu->vendor), cpu->device);
-
- get_fms(&c, cpu->device);
-
- printk(BIOS_DEBUG, "CPU: family %02x, model %02x, stepping %02x\n",
- c.x86, c.x86_model, c.x86_mask);
-
- /* Lookup the cpu's operations */
- set_cpu_ops(cpu);
-
- if(!cpu->ops) {
- /* mask out the stepping and try again */
- cpu->device -= c.x86_mask;
- set_cpu_ops(cpu);
- cpu->device += c.x86_mask;
- if(!cpu->ops) die("Unknown cpu");
- printk(BIOS_DEBUG, "Using generic cpu ops (good)\n");
- }
-
-
- /* Initialize the cpu */
- if (cpu->ops && cpu->ops->init) {
- cpu->enabled = 1;
- cpu->initialized = 1;
- cpu->ops->init(cpu);
- }
- post_log_clear();
-
- printk(BIOS_INFO, "CPU #%d initialized\n", index);
-
- return;
-}
diff --git a/src/arch/x86/lib/cpu_common.c b/src/arch/x86/lib/cpu_common.c
deleted file mode 100644
index af0ab2a..0000000
--- a/src/arch/x86/lib/cpu_common.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#include <console/console.h>
-#include <cpu/cpu.h>
-#include <arch/io.h>
-#include <string.h>
-#include <cpu/x86/mtrr.h>
-#include <cpu/x86/msr.h>
-#include <cpu/x86/lapic.h>
-#include <arch/cpu.h>
-#include <device/path.h>
-#include <device/device.h>
-#include <smp/spinlock.h>
-
-#ifndef __x86_64__
-/* Standard macro to see if a specific flag is changeable */
-static inline int flag_is_changeable_p(uint32_t flag)
-{
- uint32_t f1, f2;
-
- asm(
- "pushfl\n\t"
- "pushfl\n\t"
- "popl %0\n\t"
- "movl %0,%1\n\t"
- "xorl %2,%0\n\t"
- "pushl %0\n\t"
- "popfl\n\t"
- "pushfl\n\t"
- "popl %0\n\t"
- "popfl\n\t"
- : "=&r" (f1), "=&r" (f2)
- : "ir" (flag));
- return ((f1^f2) & flag) != 0;
-}
-
-/* Probe for the CPUID instruction */
-int cpu_have_cpuid(void)
-{
- return flag_is_changeable_p(X86_EFLAGS_ID);
-}
-
-#else
-
-int cpu_have_cpuid(void)
-{
- return 1;
-}
-#endif
-
-int cpu_cpuid_extended_level(void)
-{
- return cpuid_eax(0x80000000);
-}
-
-int cpu_phys_address_size(void)
-{
- if (!(cpu_have_cpuid()))
- return 32;
-
- if (cpu_cpuid_extended_level() >= 0x80000008)
- return cpuid_eax(0x80000008) & 0xff;
-
- if (cpuid_edx(1) & (CPUID_FEATURE_PAE | CPUID_FEATURE_PSE36))
- return 36;
- return 32;
-}
diff --git a/src/arch/x86/lib/ebda.c b/src/arch/x86/lib/ebda.c
deleted file mode 100644
index 47dfbdb..0000000
--- a/src/arch/x86/lib/ebda.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 The Chromium OS Authors. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; version 2 of
- * the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <stdint.h>
-#include <string.h>
-#include <arch/io.h>
-#include <arch/ebda.h>
-#include <arch/acpi.h>
-
-void setup_ebda(u32 low_memory_size, u16 ebda_segment, u16 ebda_size)
-{
- /* Skip in S3 resume path */
- if (acpi_is_wakeup_s3())
- return;
-
- if (!low_memory_size || !ebda_segment || !ebda_size)
- return;
-
- /* clear BIOS DATA AREA */
- memset((void *)X86_BDA_BASE, 0, X86_BDA_SIZE);
-
- write16(X86_EBDA_LOWMEM, (low_memory_size >> 10));
- write16(X86_EBDA_SEGMENT, ebda_segment);
-
- /* Set up EBDA */
- memset((void *)((uintptr_t)ebda_segment << 4), 0, ebda_size);
- write16((void*)((uintptr_t)ebda_segment << 4), (ebda_size >> 10));
-}
-
-void setup_default_ebda(void)
-{
- setup_ebda(DEFAULT_EBDA_LOWMEM,
- DEFAULT_EBDA_SEGMENT,
- DEFAULT_EBDA_SIZE);
-}
diff --git a/src/arch/x86/lib/exception.c b/src/arch/x86/lib/exception.c
deleted file mode 100644
index 65181e2..0000000
--- a/src/arch/x86/lib/exception.c
+++ /dev/null
@@ -1,511 +0,0 @@
-#include <console/console.h>
-#include <console/streams.h>
-#include <string.h>
-
-#if CONFIG_GDB_STUB
-
-/* BUFMAX defines the maximum number of characters in inbound/outbound buffers.
- * At least NUM_REGBYTES*2 are needed for register packets
- */
-#define BUFMAX 400
-enum regnames {
- EAX = 0, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
- PC /* also known as eip */,
- PS /* also known as eflags */,
- CS, SS, DS, ES, FS, GS,
- NUM_REGS /* Number of registers. */
-};
-
-static uint32_t gdb_stub_registers[NUM_REGS];
-
-#define GDB_SIG0 0 /* Signal 0 */
-#define GDB_SIGHUP 1 /* Hangup */
-#define GDB_SIGINT 2 /* Interrupt */
-#define GDB_SIGQUIT 3 /* Quit */
-#define GDB_SIGILL 4 /* Illegal instruction */
-#define GDB_SIGTRAP 5 /* Trace/breakpoint trap */
-#define GDB_SIGABRT 6 /* Aborted */
-#define GDB_SIGEMT 7 /* Emulation trap */
-#define GDB_SIGFPE 8 /* Arithmetic exception */
-#define GDB_SIGKILL 9 /* Killed */
-#define GDB_SIGBUS 10 /* Bus error */
-#define GDB_SIGSEGV 11 /* Segmentation fault */
-#define GDB_SIGSYS 12 /* Bad system call */
-#define GDB_SIGPIPE 13 /* Broken pipe */
-#define GDB_SIGALRM 14 /* Alarm clock */
-#define GDB_SIGTERM 15 /* Terminated */
-#define GDB_SIGURG 16 /* Urgent I/O condition */
-#define GDB_SIGSTOP 17 /* Stopped (signal) */
-#define GDB_SIGTSTP 18 /* Stopped (user) */
-#define GDB_SIGCONT 19 /* Continued */
-#define GDB_SIGCHLD 20 /* Child status changed */
-#define GDB_SIGTTIN 21 /* Stopped (tty input) */
-#define GDB_SIGTTOU 22 /* Stopped (tty output) */
-#define GDB_SIGIO 23 /* I/O possible */
-#define GDB_SIGXCPU 24 /* CPU time limit exceeded */
-#define GDB_SIGXFSZ 25 /* File size limit exceeded */
-#define GDB_SIGVTALRM 26 /* Virtual timer expired */
-#define GDB_SIGPROF 27 /* Profiling timer expired */
-#define GDB_SIGWINCH 28 /* Window size changed */
-#define GDB_SIGLOST 29 /* Resource lost */
-#define GDB_SIGUSR1 30 /* User defined signal 1 */
-#define GDB_SUGUSR2 31 /* User defined signal 2 */
-#define GDB_SIGPWR 32 /* Power fail/restart */
-#define GDB_SIGPOLL 33 /* Pollable event occurred */
-#define GDB_SIGWIND 34 /* SIGWIND */
-#define GDB_SIGPHONE 35 /* SIGPHONE */
-#define GDB_SIGWAITING 36 /* Process's LWPs are blocked */
-#define GDB_SIGLWP 37 /* Signal LWP */
-#define GDB_SIGDANGER 38 /* Swap space dangerously low */
-#define GDB_SIGGRANT 39 /* Monitor mode granted */
-#define GDB_SIGRETRACT 40 /* Need to relinquish monitor mode */
-#define GDB_SIGMSG 41 /* Monitor mode data available */
-#define GDB_SIGSOUND 42 /* Sound completed */
-#define GDB_SIGSAK 43 /* Secure attention */
-#define GDB_SIGPRIO 44 /* SIGPRIO */
-
-#define GDB_SIG33 45 /* Real-time event 33 */
-#define GDB_SIG34 46 /* Real-time event 34 */
-#define GDB_SIG35 47 /* Real-time event 35 */
-#define GDB_SIG36 48 /* Real-time event 36 */
-#define GDB_SIG37 49 /* Real-time event 37 */
-#define GDB_SIG38 50 /* Real-time event 38 */
-#define GDB_SIG39 51 /* Real-time event 39 */
-#define GDB_SIG40 52 /* Real-time event 40 */
-#define GDB_SIG41 53 /* Real-time event 41 */
-#define GDB_SIG42 54 /* Real-time event 42 */
-#define GDB_SIG43 55 /* Real-time event 43 */
-#define GDB_SIG44 56 /* Real-time event 44 */
-#define GDB_SIG45 57 /* Real-time event 45 */
-#define GDB_SIG46 58 /* Real-time event 46 */
-#define GDB_SIG47 59 /* Real-time event 47 */
-#define GDB_SIG48 60 /* Real-time event 48 */
-#define GDB_SIG49 61 /* Real-time event 49 */
-#define GDB_SIG50 62 /* Real-time event 50 */
-#define GDB_SIG51 63 /* Real-time event 51 */
-#define GDB_SIG52 64 /* Real-time event 52 */
-#define GDB_SIG53 65 /* Real-time event 53 */
-#define GDB_SIG54 66 /* Real-time event 54 */
-#define GDB_SIG55 67 /* Real-time event 55 */
-#define GDB_SIG56 68 /* Real-time event 56 */
-#define GDB_SIG57 69 /* Real-time event 57 */
-#define GDB_SIG58 70 /* Real-time event 58 */
-#define GDB_SIG59 71 /* Real-time event 59 */
-#define GDB_SIG60 72 /* Real-time event 60 */
-#define GDB_SIG61 73 /* Real-time event 61 */
-#define GDB_SIG62 74 /* Real-time event 62 */
-#define GDB_SIG63 75 /* Real-time event 63 */
-#define GDB_SIGCANCEL 76 /* LWP internal signal */
-#define GDB_SIG32 77 /* Real-time event 32 */
-#define GDB_SIG64 78 /* Real-time event 64 */
-#define GDB_SIG65 79 /* Real-time event 65 */
-#define GDB_SIG66 80 /* Real-time event 66 */
-#define GDB_SIG67 81 /* Real-time event 67 */
-#define GDB_SIG68 82 /* Real-time event 68 */
-#define GDB_SIG69 83 /* Real-time event 69 */
-#define GDB_SIG70 84 /* Real-time event 70 */
-#define GDB_SIG71 85 /* Real-time event 71 */
-#define GDB_SIG72 86 /* Real-time event 72 */
-#define GDB_SIG73 87 /* Real-time event 73 */
-#define GDB_SIG74 88 /* Real-time event 74 */
-#define GDB_SIG75 89 /* Real-time event 75 */
-#define GDB_SIG76 90 /* Real-time event 76 */
-#define GDB_SIG77 91 /* Real-time event 77 */
-#define GDB_SIG78 92 /* Real-time event 78 */
-#define GDB_SIG79 93 /* Real-time event 79 */
-#define GDB_SIG80 94 /* Real-time event 80 */
-#define GDB_SIG81 95 /* Real-time event 81 */
-#define GDB_SIG82 96 /* Real-time event 82 */
-#define GDB_SIG83 97 /* Real-time event 83 */
-#define GDB_SIG84 98 /* Real-time event 84 */
-#define GDB_SIG85 99 /* Real-time event 85 */
-#define GDB_SIG86 100 /* Real-time event 86 */
-#define GDB_SIG87 101 /* Real-time event 87 */
-#define GDB_SIG88 102 /* Real-time event 88 */
-#define GDB_SIG89 103 /* Real-time event 89 */
-#define GDB_SIG90 104 /* Real-time event 90 */
-#define GDB_SIG91 105 /* Real-time event 91 */
-#define GDB_SIG92 106 /* Real-time event 92 */
-#define GDB_SIG93 107 /* Real-time event 93 */
-#define GDB_SIG94 108 /* Real-time event 94 */
-#define GDB_SIG95 109 /* Real-time event 95 */
-#define GDB_SIG96 110 /* Real-time event 96 */
-#define GDB_SIG97 111 /* Real-time event 97 */
-#define GDB_SIG98 112 /* Real-time event 98 */
-#define GDB_SIG99 113 /* Real-time event 99 */
-#define GDB_SIG100 114 /* Real-time event 100 */
-#define GDB_SIG101 115 /* Real-time event 101 */
-#define GDB_SIG102 116 /* Real-time event 102 */
-#define GDB_SIG103 117 /* Real-time event 103 */
-#define GDB_SIG104 118 /* Real-time event 104 */
-#define GDB_SIG105 119 /* Real-time event 105 */
-#define GDB_SIG106 120 /* Real-time event 106 */
-#define GDB_SIG107 121 /* Real-time event 107 */
-#define GDB_SIG108 122 /* Real-time event 108 */
-#define GDB_SIG109 123 /* Real-time event 109 */
-#define GDB_SIG110 124 /* Real-time event 110 */
-#define GDB_SIG111 125 /* Real-time event 111 */
-#define GDB_SIG112 126 /* Real-time event 112 */
-#define GDB_SIG113 127 /* Real-time event 113 */
-#define GDB_SIG114 128 /* Real-time event 114 */
-#define GDB_SIG115 129 /* Real-time event 115 */
-#define GDB_SIG116 130 /* Real-time event 116 */
-#define GDB_SIG117 131 /* Real-time event 117 */
-#define GDB_SIG118 132 /* Real-time event 118 */
-#define GDB_SIG119 133 /* Real-time event 119 */
-#define GDB_SIG120 134 /* Real-time event 120 */
-#define GDB_SIG121 135 /* Real-time event 121 */
-#define GDB_SIG122 136 /* Real-time event 122 */
-#define GDB_SIG123 137 /* Real-time event 123 */
-#define GDB_SIG124 138 /* Real-time event 124 */
-#define GDB_SIG125 139 /* Real-time event 125 */
-#define GDB_SIG126 140 /* Real-time event 126 */
-#define GDB_SIG127 141 /* Real-time event 127 */
-#define GDB_SIGINFO 142 /* Information request */
-#define GDB_UNKNOWN 143 /* Unknown signal */
-#define GDB_DEFAULT 144 /* error: default signal */
-/* Mach exceptions */
-#define GDB_EXC_BAD_ACCESS 145 /* Could not access memory */
-#define GDB_EXC_BAD_INSTRCTION 146 /* Illegal instruction/operand */
-#define GDB_EXC_ARITHMETIC 147 /* Arithmetic exception */
-#define GDB_EXC_EMULATION 148 /* Emulation instruction */
-#define GDB_EXC_SOFTWARE 149 /* Software generated exception */
-#define GDB_EXC_BREAKPOINT 150 /* Breakpoint */
-
-
-
-static unsigned char exception_to_signal[] =
-{
- [0] = GDB_SIGFPE, /* divide by zero */
- [1] = GDB_SIGTRAP, /* debug exception */
- [2] = GDB_SIGSEGV, /* NMI Interrupt */
- [3] = GDB_SIGTRAP, /* Breakpoint */
- [4] = GDB_SIGSEGV, /* into instruction (overflow) */
- [5] = GDB_SIGSEGV, /* bound instruction */
- [6] = GDB_SIGILL, /* Invalid opcode */
- [7] = GDB_SIGSEGV, /* coprocessor not available */
- [8] = GDB_SIGSEGV, /* double fault */
- [9] = GDB_SIGFPE, /* coprocessor segment overrun */
- [10] = GDB_SIGSEGV, /* Invalid TSS */
- [11] = GDB_SIGBUS, /* Segment not present */
- [12] = GDB_SIGBUS, /* stack exception */
- [13] = GDB_SIGSEGV, /* general protection */
- [14] = GDB_SIGSEGV, /* page fault */
- [15] = GDB_UNKNOWN, /* reserved */
- [16] = GDB_SIGEMT, /* coprocessor error */
- [17] = GDB_SIGBUS, /* alignment check */
- [18] = GDB_SIGSEGV, /* machine check */
- [19] = GDB_SIGFPE, /* simd floating point exception */
- [20] = GDB_UNKNOWN,
- [21] = GDB_UNKNOWN,
- [22] = GDB_UNKNOWN,
- [23] = GDB_UNKNOWN,
- [24] = GDB_UNKNOWN,
- [25] = GDB_UNKNOWN,
- [26] = GDB_UNKNOWN,
- [27] = GDB_UNKNOWN,
- [28] = GDB_UNKNOWN,
- [29] = GDB_UNKNOWN,
- [30] = GDB_UNKNOWN,
- [31] = GDB_UNKNOWN,
- [32] = GDB_SIGINT, /* User interrupt */
-};
-
-static const char hexchars[] = "0123456789abcdef";
-static char in_buffer[BUFMAX];
-static char out_buffer[BUFMAX];
-
-
-static inline void stub_putc(int ch)
-{
- gdb_tx_byte(ch);
-}
-
-static inline void stub_flush(void)
-{
- gdb_tx_flush();
-}
-
-static inline int stub_getc(void)
-{
- return gdb_rx_byte();
-}
-
-static int hex(char ch)
-{
- if ((ch >= 'a') && (ch <= 'f'))
- return (ch - 'a' + 10);
- if ((ch >= '0') && (ch <= '9'))
- return (ch - '0');
- if ((ch >= 'A') && (ch <= 'F'))
- return (ch - 'A' + 10);
- return (-1);
-}
-
-/*
- * While we find hexadecimal digits, build an int.
- * Fals is returned if nothing is parsed true otherwise.
- */
-static int parse_ulong(char **ptr, unsigned long *value)
-{
- int digit;
- char *start;
-
- start = *ptr;
- *value = 0;
-
- while((digit = hex(**ptr)) >= 0) {
- *value = ((*value) << 4) | digit;
- (*ptr)++;
- }
- return start != *ptr;
-}
-
-/* convert the memory pointed to by mem into hex, placing result in buf */
-/* return a pointer to the last char put in buf (null) */
-static void copy_to_hex(char *buf, void *addr, unsigned long count)
-{
- unsigned char ch;
- char *mem = addr;
-
- while(count--) {
- ch = *mem++;
- *buf++ = hexchars[ch >> 4];
- *buf++ = hexchars[ch & 0x0f];
- }
- *buf = 0;
- return;
-}
-
-
-/* convert the hex array pointed to by buf into binary to be placed in mem */
-/* return a pointer to the character AFTER the last byte written */
-static void copy_from_hex(void *addr, char *buf, unsigned long count)
-{
- unsigned char ch;
- char *mem = addr;
-
- while(count--) {
- ch = hex (*buf++) << 4;
- ch = ch + hex (*buf++);
- *mem++ = ch;
- }
-}
-
-
-/* scan for the sequence $<data>#<checksum> */
-
-static int get_packet(char *buffer)
-{
- unsigned char checksum;
- unsigned char xmitcsum;
- int count;
- char ch;
-
- /* Wishlit implement a timeout in get_packet */
- do {
- /* wait around for the start character, ignore all other characters */
- while ((ch = (stub_getc() & 0x7f)) != '$');
- checksum = 0;
- xmitcsum = -1;
-
- count = 0;
-
- /* now, read until a # or end of buffer is found */
- while (count < BUFMAX) {
- ch = stub_getc() & 0x7f;
- if (ch == '#')
- break;
- checksum = checksum + ch;
- buffer[count] = ch;
- count = count + 1;
- }
- buffer[count] = 0;
-
- if (ch == '#') {
- xmitcsum = hex(stub_getc() & 0x7f) << 4;
- xmitcsum += hex(stub_getc() & 0x7f);
-
- if (checksum != xmitcsum) {
- stub_putc('-'); /* failed checksum */
- stub_flush();
- }
- else {
- stub_putc('+'); /* successful transfer */
- stub_flush();
- }
- }
- } while(checksum != xmitcsum);
- return 1;
-}
-
-/* send the packet in buffer.*/
-static void put_packet(char *buffer)
-{
- unsigned char checksum;
- int count;
- char ch;
-
- /* $<packet info>#<checksum>. */
- do {
- stub_putc('$');
- checksum = 0;
- count = 0;
-
- while ((ch = buffer[count])) {
- stub_putc(ch);
- checksum += ch;
- count += 1;
- }
-
- stub_putc('#');
- stub_putc(hexchars[checksum >> 4]);
- stub_putc(hexchars[checksum % 16]);
- stub_flush();
-
- } while ((stub_getc() & 0x7f) != '+');
-
-}
-#endif /* CONFIG_GDB_STUB */
-
-#include <arch/registers.h>
-
-void x86_exception(struct eregs *info);
-
-void x86_exception(struct eregs *info)
-{
-#if CONFIG_GDB_STUB
- int signo;
- memcpy(gdb_stub_registers, info, 8*sizeof(uint32_t));
- gdb_stub_registers[PC] = info->eip;
- gdb_stub_registers[CS] = info->cs;
- gdb_stub_registers[PS] = info->eflags;
- signo = GDB_UNKNOWN;
- if (info->vector < ARRAY_SIZE(exception_to_signal)) {
- signo = exception_to_signal[info->vector];
- }
-
- /* reply to the host that an exception has occured */
- out_buffer[0] = 'S';
- out_buffer[1] = hexchars[(signo>>4) & 0xf];
- out_buffer[2] = hexchars[signo & 0xf];
- out_buffer[3] = '\0';
- put_packet(out_buffer);
-
- while(1) {
- unsigned long addr, length;
- char *ptr;
- out_buffer[0] = '\0';
- out_buffer[1] = '\0';
- if (!get_packet(in_buffer)) {
- break;
- }
- switch(in_buffer[0]) {
- case '?': /* last signal */
- out_buffer[0] = 'S';
- out_buffer[1] = hexchars[(signo >> 4) & 0xf];
- out_buffer[2] = hexchars[signo & 0xf];
- out_buffer[3] = '\0';
- break;
- case 'g': /* return the value of the cpu registers */
- copy_to_hex(out_buffer, &gdb_stub_registers, sizeof(gdb_stub_registers));
- break;
- case 'G': /* set the value of the CPU registers - return OK */
- copy_from_hex(&gdb_stub_registers, in_buffer + 1, sizeof(gdb_stub_registers));
- memcpy(info, gdb_stub_registers, 8*sizeof(uint32_t));
- info->eip = gdb_stub_registers[PC];
- info->cs = gdb_stub_registers[CS];
- info->eflags = gdb_stub_registers[PS];
- memcpy(out_buffer, "OK",3);
- break;
- case 'm':
- /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
- ptr = &in_buffer[1];
- if ( parse_ulong(&ptr, &addr) &&
- (*ptr++ == ',') &&
- parse_ulong(&ptr, &length)) {
- copy_to_hex(out_buffer, (void *)addr, length);
- } else {
- memcpy(out_buffer, "E01", 4);
- }
- break;
- case 'M':
- /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
- ptr = &in_buffer[1];
- if ( parse_ulong(&ptr, &addr) &&
- (*(ptr++) == ',') &&
- parse_ulong(&ptr, &length) &&
- (*(ptr++) == ':')) {
- copy_from_hex((void *)addr, ptr, length);
- memcpy(out_buffer, "OK", 3);
- }
- else {
- memcpy(out_buffer, "E02", 4);
- }
- break;
- case 's':
- case 'c':
- /* cAA..AA Continue at address AA..AA(optional) */
- /* sAA..AA Step one instruction from AA..AA(optional) */
- ptr = &in_buffer[1];
- if (parse_ulong(&ptr, &addr)) {
- info->eip = addr;
- }
-
- /* Clear the trace bit */
- info->eflags &= ~(1 << 8);
- /* Set the trace bit if we are single stepping */
- if (in_buffer[0] == 's') {
- info->eflags |= (1 << 8);
- }
- return;
- break;
- case 'D':
- memcpy(out_buffer, "OK", 3);
- break;
- case 'k': /* kill request? */
- break;
- case 'q': /* query */
- break;
- case 'z': /* z0AAAA,LLLL remove memory breakpoint */
- /* z1AAAA,LLLL remove hardware breakpoint */
- /* z2AAAA,LLLL remove write watchpoint */
- /* z3AAAA,LLLL remove read watchpoint */
- /* z4AAAA,LLLL remove access watchpoint */
- case 'Z': /* Z0AAAA,LLLL insert memory breakpoint */
- /* Z1AAAA,LLLL insert hardware breakpoint */
- /* Z2AAAA,LLLL insert write watchpoint */
- /* Z3AAAA,LLLL insert read watchpoint */
- /* Z4AAAA,LLLL insert access watchpoint */
- break;
- default:
- break;
- }
- put_packet(out_buffer);
- }
-#else /* !CONFIG_GDB_STUB */
-#define MDUMP_SIZE 0x80
- printk(BIOS_EMERG,
- "Unexpected Exception: %d @ %02x:%08x - Halting\n"
- "Code: %d eflags: %08x\n"
- "eax: %08x ebx: %08x ecx: %08x edx: %08x\n"
- "edi: %08x esi: %08x ebp: %08x esp: %08x\n",
- info->vector, info->cs, info->eip,
- info->error_code, info->eflags,
- info->eax, info->ebx, info->ecx, info->edx,
- info->edi, info->esi, info->ebp, info->esp);
- u8 *code = (u8*)((uintptr_t)info->eip - (MDUMP_SIZE >>1));
- /* Align to 8-byte boundary please, and print eight bytes per row.
- * This is done to make DRAM burst timing/reordering errors more
- * evident from the looking at the dump */
- code = (u8*)((uintptr_t)code & ~0x7);
- int i;
- for(i = 0; i < MDUMP_SIZE; i++)
- {
- if( (i & 0x07) == 0 )
- printk(BIOS_EMERG, "\n%p:\t", code + i);
- printk(BIOS_EMERG, "%.2x ", code[i]);
- }
- die("");
-#endif
-}
diff --git a/src/arch/x86/lib/id.inc b/src/arch/x86/lib/id.inc
deleted file mode 100644
index f8aba0b..0000000
--- a/src/arch/x86/lib/id.inc
+++ /dev/null
@@ -1,18 +0,0 @@
- .section ".id", "a", @progbits
-
- .globl __id_start
-__id_start:
-ver:
- .asciz COREBOOT_VERSION
-vendor:
- .asciz CONFIG_MAINBOARD_VENDOR
-part:
- .asciz CONFIG_MAINBOARD_PART_NUMBER
-.long __id_end + CONFIG_ID_SECTION_OFFSET - ver /* Reverse offset to the vendor id */
-.long __id_end + CONFIG_ID_SECTION_OFFSET - vendor /* Reverse offset to the vendor id */
-.long __id_end + CONFIG_ID_SECTION_OFFSET - part /* Reverse offset to the part number */
-.long CONFIG_ROM_SIZE /* Size of this romimage */
- .globl __id_end
-
-__id_end:
-.previous
diff --git a/src/arch/x86/lib/id.ld b/src/arch/x86/lib/id.ld
deleted file mode 100644
index cfd091d..0000000
--- a/src/arch/x86/lib/id.ld
+++ /dev/null
@@ -1,6 +0,0 @@
-SECTIONS {
- . = (0xffffffff - CONFIG_ID_SECTION_OFFSET) - (__id_end - __id_start) + 1;
- .id (.): {
- *(.id)
- }
-}
diff --git a/src/arch/x86/lib/ioapic.c b/src/arch/x86/lib/ioapic.c
deleted file mode 100644
index 1b13127..0000000
--- a/src/arch/x86/lib/ioapic.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2010 coresystems GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <arch/io.h>
-#include <arch/ioapic.h>
-#include <console/console.h>
-#include <cpu/x86/lapic.h>
-
-u32 io_apic_read(void *ioapic_base, u32 reg)
-{
- write32(ioapic_base, reg);
- return read32(ioapic_base + 0x10);
-}
-
-void io_apic_write(void *ioapic_base, u32 reg, u32 value)
-{
- write32(ioapic_base, reg);
- write32(ioapic_base + 0x10, value);
-}
-
-static int ioapic_interrupt_count(void *ioapic_base)
-{
- /* Read the available number of interrupts. */
- int ioapic_interrupts = (io_apic_read(ioapic_base, 0x01) >> 16) & 0xff;
- if (ioapic_interrupts == 0xff)
- ioapic_interrupts = 23;
- ioapic_interrupts += 1; /* Bits 23-16 specify the maximum redirection
- entry, which is the number of interrupts
- minus 1. */
- printk(BIOS_DEBUG, "IOAPIC: %d interrupts\n", ioapic_interrupts);
-
- return ioapic_interrupts;
-}
-
-void clear_ioapic(void *ioapic_base)
-{
- u32 low, high;
- u32 i, ioapic_interrupts;
-
- printk(BIOS_DEBUG, "IOAPIC: Clearing IOAPIC at %p\n", ioapic_base);
-
- ioapic_interrupts = ioapic_interrupt_count(ioapic_base);
-
- low = DISABLED;
- high = NONE;
-
- for (i = 0; i < ioapic_interrupts; i++) {
- io_apic_write(ioapic_base, i * 2 + 0x10, low);
- io_apic_write(ioapic_base, i * 2 + 0x11, high);
-
- printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
- i, high, low);
- }
-
- if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
- printk(BIOS_WARNING, "IOAPIC not responding.\n");
- return;
- }
-}
-
-void set_ioapic_id(void *ioapic_base, u8 ioapic_id)
-{
- u32 bsp_lapicid = lapicid();
- int i;
-
- printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at 0x%p\n",
- ioapic_base);
- printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC = 0x%02x\n",
- bsp_lapicid);
-
- if (ioapic_id) {
- printk(BIOS_DEBUG, "IOAPIC: ID = 0x%02x\n", ioapic_id);
- /* Set IOAPIC ID if it has been specified. */
- io_apic_write(ioapic_base, 0x00,
- (io_apic_read(ioapic_base, 0x00) & 0xf0ffffff) |
- (ioapic_id << 24));
- }
-
- printk(BIOS_SPEW, "IOAPIC: Dumping registers\n");
- for (i = 0; i < 3; i++)
- printk(BIOS_SPEW, " reg 0x%04x: 0x%08x\n", i,
- io_apic_read(ioapic_base, i));
-
-}
-
-static void load_vectors(void *ioapic_base)
-{
- u32 bsp_lapicid = lapicid();
- u32 low, high;
- u32 i, ioapic_interrupts;
-
- ioapic_interrupts = ioapic_interrupt_count(ioapic_base);
-
-#if CONFIG_IOAPIC_INTERRUPTS_ON_FSB
- /*
- * For the Pentium 4 and above APICs deliver their interrupts
- * on the front side bus, enable that.
- */
- printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on FSB\n");
- io_apic_write(ioapic_base, 0x03,
- io_apic_read(ioapic_base, 0x03) | (1 << 0));
-#endif
-#if CONFIG_IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
- printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on APIC serial bus\n");
- io_apic_write(ioapic_base, 0x03, 0);
-#endif
-
- /* Enable Virtual Wire Mode. */
- low = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
- high = bsp_lapicid << (56 - 32);
-
- io_apic_write(ioapic_base, 0x10, low);
- io_apic_write(ioapic_base, 0x11, high);
-
- if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
- printk(BIOS_WARNING, "IOAPIC not responding.\n");
- return;
- }
-
- printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
- 0, high, low);
- low = DISABLED;
- high = NONE;
- for (i = 1; i < ioapic_interrupts; i++) {
- io_apic_write(ioapic_base, i * 2 + 0x10, low);
- io_apic_write(ioapic_base, i * 2 + 0x11, high);
-
- printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
- i, high, low);
- }
-}
-
-void setup_ioapic(void *ioapic_base, u8 ioapic_id)
-{
- set_ioapic_id(ioapic_base, ioapic_id);
- load_vectors(ioapic_base);
-}
diff --git a/src/arch/x86/lib/memcpy.c b/src/arch/x86/lib/memcpy.c
deleted file mode 100644
index 4915a9e..0000000
--- a/src/arch/x86/lib/memcpy.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <string.h>
-
-void *memcpy(void *dest, const void *src, size_t n)
-{
- unsigned long d0, d1, d2;
-
- asm volatile(
-#ifdef __x86_64__
- "rep ; movsd\n\t"
- "mov %4,%%rcx\n\t"
-#else
- "rep ; movsl\n\t"
- "movl %4,%%ecx\n\t"
-#endif
- "rep ; movsb\n\t"
- : "=&c" (d0), "=&D" (d1), "=&S" (d2)
- : "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src)
- : "memory"
- );
-
- return dest;
-}
diff --git a/src/arch/x86/lib/memmove.c b/src/arch/x86/lib/memmove.c
deleted file mode 100644
index ba12127..0000000
--- a/src/arch/x86/lib/memmove.c
+++ /dev/null
@@ -1,187 +0,0 @@
-#include <string.h>
-
-void *memmove(void *dest, const void *src, size_t n)
-{
- int d0,d1,d2,d3,d4,d5;
- char *ret = dest;
-
- __asm__ __volatile__(
- /* Handle more 16bytes in loop */
- "cmp $0x10, %0\n\t"
- "jb 1f\n\t"
-
- /* Decide forward/backward copy mode */
- "cmp %2, %1\n\t"
- "jb 2f\n\t"
-
- /*
- * movs instruction have many startup latency
- * so we handle small size by general register.
- */
- "cmp $680, %0\n\t"
- "jb 3f\n\t"
- /*
- * movs instruction is only good for aligned case.
- */
- "mov %1, %3\n\t"
- "xor %2, %3\n\t"
- "and $0xff, %3\n\t"
- "jz 4f\n\t"
- "3:\n\t"
- "sub $0x10, %0\n\t"
-
- /*
- * We gobble 16byts forward in each loop.
- */
- "3:\n\t"
- "sub $0x10, %0\n\t"
- "mov 0*4(%1), %3\n\t"
- "mov 1*4(%1), %4\n\t"
- "mov %3, 0*4(%2)\n\t"
- "mov %4, 1*4(%2)\n\t"
- "mov 2*4(%1), %3\n\t"
- "mov 3*4(%1), %4\n\t"
- "mov %3, 2*4(%2)\n\t"
- "mov %4, 3*4(%2)\n\t"
- "lea 0x10(%1), %1\n\t"
- "lea 0x10(%2), %2\n\t"
- "jae 3b\n\t"
- "add $0x10, %0\n\t"
- "jmp 1f\n\t"
-
- /*
- * Handle data forward by movs.
- */
- ".p2align 4\n\t"
- "4:\n\t"
- "mov -4(%1, %0), %3\n\t"
- "lea -4(%2, %0), %4\n\t"
- "shr $2, %0\n\t"
- "rep movsl\n\t"
- "mov %3, (%4)\n\t"
- "jmp 11f\n\t"
- /*
- * Handle data backward by movs.
- */
- ".p2align 4\n\t"
- "6:\n\t"
- "mov (%1), %3\n\t"
- "mov %2, %4\n\t"
- "lea -4(%1, %0), %1\n\t"
- "lea -4(%2, %0), %2\n\t"
- "shr $2, %0\n\t"
- "std\n\t"
- "rep movsl\n\t"
- "mov %3,(%4)\n\t"
- "cld\n\t"
- "jmp 11f\n\t"
-
- /*
- * Start to prepare for backward copy.
- */
- ".p2align 4\n\t"
- "2:\n\t"
- "cmp $680, %0\n\t"
- "jb 5f\n\t"
- "mov %1, %3\n\t"
- "xor %2, %3\n\t"
- "and $0xff, %3\n\t"
- "jz 6b\n\t"
-
- /*
- * Calculate copy position to tail.
- */
- "5:\n\t"
- "add %0, %1\n\t"
- "add %0, %2\n\t"
- "sub $0x10, %0\n\t"
-
- /*
- * We gobble 16byts backward in each loop.
- */
- "7:\n\t"
- "sub $0x10, %0\n\t"
-
- "mov -1*4(%1), %3\n\t"
- "mov -2*4(%1), %4\n\t"
- "mov %3, -1*4(%2)\n\t"
- "mov %4, -2*4(%2)\n\t"
- "mov -3*4(%1), %3\n\t"
- "mov -4*4(%1), %4\n\t"
- "mov %3, -3*4(%2)\n\t"
- "mov %4, -4*4(%2)\n\t"
- "lea -0x10(%1), %1\n\t"
- "lea -0x10(%2), %2\n\t"
- "jae 7b\n\t"
- /*
- * Calculate copy position to head.
- */
- "add $0x10, %0\n\t"
- "sub %0, %1\n\t"
- "sub %0, %2\n\t"
-
- /*
- * Move data from 8 bytes to 15 bytes.
- */
- ".p2align 4\n\t"
- "1:\n\t"
- "cmp $8, %0\n\t"
- "jb 8f\n\t"
- "mov 0*4(%1), %3\n\t"
- "mov 1*4(%1), %4\n\t"
- "mov -2*4(%1, %0), %5\n\t"
- "mov -1*4(%1, %0), %1\n\t"
-
- "mov %3, 0*4(%2)\n\t"
- "mov %4, 1*4(%2)\n\t"
- "mov %5, -2*4(%2, %0)\n\t"
- "mov %1, -1*4(%2, %0)\n\t"
- "jmp 11f\n\t"
-
- /*
- * Move data from 4 bytes to 7 bytes.
- */
- ".p2align 4\n\t"
- "8:\n\t"
- "cmp $4, %0\n\t"
- "jb 9f\n\t"
- "mov 0*4(%1), %3\n\t"
- "mov -1*4(%1, %0), %4\n\t"
- "mov %3, 0*4(%2)\n\t"
- "mov %4, -1*4(%2, %0)\n\t"
- "jmp 11f\n\t"
-
- /*
- * Move data from 2 bytes to 3 bytes.
- */
- ".p2align 4\n\t"
- "9:\n\t"
- "cmp $2, %0\n\t"
- "jb 10f\n\t"
- "movw 0*2(%1), %%dx\n\t"
- "movw -1*2(%1, %0), %%bx\n\t"
- "movw %%dx, 0*2(%2)\n\t"
- "movw %%bx, -1*2(%2, %0)\n\t"
- "jmp 11f\n\t"
-
- /*
- * Move data for 1 byte.
- */
- ".p2align 4\n\t"
- "10:\n\t"
- "cmp $1, %0\n\t"
- "jb 11f\n\t"
- "movb (%1), %%cl\n\t"
- "movb %%cl, (%2)\n\t"
- ".p2align 4\n\t"
- "11:"
- : "=&c" (d0), "=&S" (d1), "=&D" (d2),
- "=r" (d3),"=r" (d4), "=r"(d5)
- :"0" (n),
- "1" (src),
- "2" (dest)
- :"memory");
-
- return ret;
-
-}
diff --git a/src/arch/x86/lib/memset.c b/src/arch/x86/lib/memset.c
deleted file mode 100644
index d534556..0000000
--- a/src/arch/x86/lib/memset.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 1991,1992,1993,1997,1998,2003, 2005 Free Software Foundation, Inc.
- * This file is part of the GNU C Library.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-/* From glibc-2.14, sysdeps/i386/memset.c */
-
-#include <string.h>
-#include <stdint.h>
-
-typedef uint32_t op_t;
-
-void *memset(void *dstpp, int c, size_t len)
-{
- int d0;
- unsigned long int dstp = (unsigned long int) dstpp;
-
- /* This explicit register allocation improves code very much indeed. */
- register op_t x asm("ax");
-
- x = (unsigned char) c;
-
- /* Clear the direction flag, so filling will move forward. */
- asm volatile("cld");
-
- /* This threshold value is optimal. */
- if (len >= 12) {
- /* Fill X with four copies of the char we want to fill with. */
- x |= (x << 8);
- x |= (x << 16);
-
- /* Adjust LEN for the bytes handled in the first loop. */
- len -= (-dstp) % sizeof(op_t);
-
- /*
- * There are at least some bytes to set. No need to test for
- * LEN == 0 in this alignment loop.
- */
-
- /* Fill bytes until DSTP is aligned on a longword boundary. */
- asm volatile(
- "rep\n"
- "stosb" /* %0, %2, %3 */ :
- "=D" (dstp), "=c" (d0) :
- "0" (dstp), "1" ((-dstp) % sizeof(op_t)), "a" (x) :
- "memory");
-
- /* Fill longwords. */
- asm volatile(
- "rep\n"
- "stosl" /* %0, %2, %3 */ :
- "=D" (dstp), "=c" (d0) :
- "0" (dstp), "1" (len / sizeof(op_t)), "a" (x) :
- "memory");
- len %= sizeof(op_t);
- }
-
- /* Write the last few bytes. */
- asm volatile(
- "rep\n"
- "stosb" /* %0, %2, %3 */ :
- "=D" (dstp), "=c" (d0) :
- "0" (dstp), "1" (len), "a" (x) :
- "memory");
-
- return dstpp;
-}
diff --git a/src/arch/x86/lib/mmap_boot.c b/src/arch/x86/lib/mmap_boot.c
deleted file mode 100644
index 4dd269b..0000000
--- a/src/arch/x86/lib/mmap_boot.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2015 Google Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <boot_device.h>
-#include <console/console.h>
-#include <cbfs.h>
-#include <endian.h>
-#include <stdlib.h>
-
-/* The ROM is memory mapped just below 4GiB. Form a pointer for the base. */
-#define rom_base ((void *)(uintptr_t)(-(int32_t)CONFIG_ROM_SIZE))
-
-static const struct mem_region_device boot_dev =
- MEM_REGION_DEV_INIT(rom_base, CONFIG_ROM_SIZE);
-
-const struct region_device *boot_device_ro(void)
-{
- return &boot_dev.rdev;
-}
-
-int cbfs_boot_region_properties(struct cbfs_props *props)
-{
- struct cbfs_header header;
- int32_t offset;
- const struct region_device *bdev;
-
- bdev = boot_device_ro();
-
- rdev_readat(bdev, &offset, CONFIG_ROM_SIZE - sizeof(offset),
- sizeof(offset));
-
- /* The offset is relative to the end of the media. */
- offset += CONFIG_ROM_SIZE;
-
- rdev_readat(bdev, &header , offset, sizeof(header));
-
- header.magic = ntohl(header.magic);
- header.romsize = ntohl(header.romsize);
- header.bootblocksize = ntohl(header.bootblocksize);
- header.align = ntohl(header.align);
- header.offset = ntohl(header.offset);
-
- if (header.magic != CBFS_HEADER_MAGIC)
- return -1;
-
- props->align = header.align;
- props->offset = header.offset;
- if (CONFIG_ROM_SIZE != header.romsize)
- props->size = CONFIG_ROM_SIZE;
- else
- props->size = header.romsize;
- props->size -= props->offset;
- props->size -= header.bootblocksize;
- props->size = ALIGN_DOWN(props->size, props->align);
-
- printk(BIOS_DEBUG, "CBFS @ %zx size %zx\n", props->offset, props->size);
-
- return 0;
-}
diff --git a/src/arch/x86/lib/pci_ops_conf1.c b/src/arch/x86/lib/pci_ops_conf1.c
deleted file mode 100644
index 77df4b3..0000000
--- a/src/arch/x86/lib/pci_ops_conf1.c
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <console/console.h>
-#include <arch/io.h>
-#include <arch/pciconf.h>
-#include <device/pci.h>
-#include <device/pci_ids.h>
-#include <device/pci_ops.h>
-/*
- * Functions for accessing PCI configuration space with type 1 accesses
- */
-
-#if !CONFIG_PCI_IO_CFG_EXT
-#define CONFIG_CMD(bus,devfn, where) (0x80000000 | (bus << 16) | \
- (devfn << 8) | (where & ~3))
-#else
-#define CONFIG_CMD(bus,devfn, where) (0x80000000 | (bus << 16) | \
- (devfn << 8) | ((where & 0xff) & ~3) |\
- ((where & 0xf00)<<16))
-#endif
-
-static uint8_t pci_conf1_read_config8(struct bus *pbus, int bus, int devfn,
- int where)
-{
- outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
- return inb(0xCFC + (where & 3));
-}
-
-static uint16_t pci_conf1_read_config16(struct bus *pbus, int bus, int devfn,
- int where)
-{
- outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
- return inw(0xCFC + (where & 2));
-}
-
-static uint32_t pci_conf1_read_config32(struct bus *pbus, int bus, int devfn,
- int where)
-{
- outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
- return inl(0xCFC);
-}
-
-static void pci_conf1_write_config8(struct bus *pbus, int bus, int devfn,
- int where, uint8_t value)
-{
- outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
- outb(value, 0xCFC + (where & 3));
-}
-
-static void pci_conf1_write_config16(struct bus *pbus, int bus, int devfn,
- int where, uint16_t value)
-{
- outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
- outw(value, 0xCFC + (where & 2));
-}
-
-static void pci_conf1_write_config32(struct bus *pbus, int bus, int devfn,
- int where, uint32_t value)
-{
- outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
- outl(value, 0xCFC);
-}
-
-#undef CONFIG_CMD
-
-const struct pci_bus_operations pci_cf8_conf1 = {
- .read8 = pci_conf1_read_config8,
- .read16 = pci_conf1_read_config16,
- .read32 = pci_conf1_read_config32,
- .write8 = pci_conf1_write_config8,
- .write16 = pci_conf1_write_config16,
- .write32 = pci_conf1_write_config32,
-};
diff --git a/src/arch/x86/lib/pci_ops_mmconf.c b/src/arch/x86/lib/pci_ops_mmconf.c
deleted file mode 100644
index e4fa128..0000000
--- a/src/arch/x86/lib/pci_ops_mmconf.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <console/console.h>
-#include <arch/io.h>
-#include <arch/pciconf.h>
-#include <device/pci.h>
-#include <device/pci_ids.h>
-#include <device/pci_ops.h>
-
-/*
- * Functions for accessing PCI configuration space with mmconf accesses
- */
-
-#define PCI_MMIO_ADDR(SEGBUS, DEVFN, WHERE, MASK) \
- ((void *)(((uintptr_t)CONFIG_MMCONF_BASE_ADDRESS |\
- (((SEGBUS) & 0xFFF) << 20) |\
- (((DEVFN) & 0xFF) << 12) |\
- ((WHERE) & 0xFFF)) & ~MASK))
-
-static uint8_t pci_mmconf_read_config8(struct bus *pbus, int bus, int devfn,
- int where)
-{
- return read8(PCI_MMIO_ADDR(bus, devfn, where, 0));
-}
-
-static uint16_t pci_mmconf_read_config16(struct bus *pbus, int bus, int devfn,
- int where)
-{
- return read16(PCI_MMIO_ADDR(bus, devfn, where, 1));
-}
-
-static uint32_t pci_mmconf_read_config32(struct bus *pbus, int bus, int devfn,
- int where)
-{
- return read32(PCI_MMIO_ADDR(bus, devfn, where, 3));
-}
-
-static void pci_mmconf_write_config8(struct bus *pbus, int bus, int devfn,
- int where, uint8_t value)
-{
- write8(PCI_MMIO_ADDR(bus, devfn, where, 0), value);
-}
-
-static void pci_mmconf_write_config16(struct bus *pbus, int bus, int devfn,
- int where, uint16_t value)
-{
- write16(PCI_MMIO_ADDR(bus, devfn, where, 1), value);
-}
-
-static void pci_mmconf_write_config32(struct bus *pbus, int bus, int devfn,
- int where, uint32_t value)
-{
- write32(PCI_MMIO_ADDR(bus, devfn, where, 3), value);
-}
-
-const struct pci_bus_operations pci_ops_mmconf = {
- .read8 = pci_mmconf_read_config8,
- .read16 = pci_mmconf_read_config16,
- .read32 = pci_mmconf_read_config32,
- .write8 = pci_mmconf_write_config8,
- .write16 = pci_mmconf_write_config16,
- .write32 = pci_mmconf_write_config32,
-};
diff --git a/src/arch/x86/lib/romcc_console.c b/src/arch/x86/lib/romcc_console.c
deleted file mode 100644
index bfc35bc..0000000
--- a/src/arch/x86/lib/romcc_console.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2003 Eric Biederman
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <build.h>
-#include <console/streams.h>
-#include <console/early_print.h>
-#include <console/loglevel.h>
-
-/* Include the sources. */
-#if CONFIG_CONSOLE_SERIAL && CONFIG_DRIVERS_UART_8250IO
-#include "drivers/uart/util.c"
-#include "drivers/uart/uart8250io.c"
-#endif
-#if CONFIG_CONSOLE_NE2K
-#include "drivers/net/ne2k.c"
-#endif
-
-void console_hw_init(void)
-{
-#if CONFIG_CONSOLE_SERIAL
- uart_init(CONFIG_UART_FOR_CONSOLE);
-#endif
-#if CONFIG_CONSOLE_NE2K
- ne2k_init(CONFIG_CONSOLE_NE2K_IO_PORT);
-#endif
-}
-
-void console_tx_byte(unsigned char byte)
-{
-#if CONFIG_CONSOLE_SERIAL
- uart_tx_byte(CONFIG_UART_FOR_CONSOLE, byte);
-#endif
-#if CONFIG_CONSOLE_NE2K
- ne2k_append_data_byte(byte, CONFIG_CONSOLE_NE2K_IO_PORT);
-#endif
-}
-
-void console_tx_flush(void)
-{
-#if CONFIG_CONSOLE_SERIAL
- uart_tx_flush(CONFIG_UART_FOR_CONSOLE);
-#endif
-#if CONFIG_CONSOLE_NE2K
- ne2k_transmit(CONFIG_CONSOLE_NE2K_IO_PORT);
-#endif
-}
-
-#include <console/early_print.c>
-#include <console/post.c>
-#include <console/die.c>
-
-void console_init(void)
-{
- static const char console_test[] =
- "\n\ncoreboot-"
- COREBOOT_VERSION
- COREBOOT_EXTRA_VERSION
- " "
- COREBOOT_BUILD
- " romstage starting...\n";
-
- console_hw_init();
-
- print_info(console_test);
-}
-
-void die(const char *msg)
-{
- print_emerg(msg);
- halt();
-}
diff --git a/src/arch/x86/lib/stages.c b/src/arch/x86/lib/stages.c
deleted file mode 100644
index c06abe6..0000000
--- a/src/arch/x86/lib/stages.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2010 coresystems GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-static void skip_romstage(void)
-{
- asm volatile (
- "jmp __main\n"
- );
-}
diff --git a/src/arch/x86/lib/thread.c b/src/arch/x86/lib/thread.c
deleted file mode 100644
index f81a2d2..0000000
--- a/src/arch/x86/lib/thread.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2013 Google, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <thread.h>
-
-/* The stack frame looks like the following after a pushad instruction. */
-struct pushad_regs {
- uint32_t edi; /* Offset 0x00 */
- uint32_t esi; /* Offset 0x04 */
- uint32_t ebp; /* Offset 0x08 */
- uint32_t esp; /* Offset 0x0c */
- uint32_t ebx; /* Offset 0x10 */
- uint32_t edx; /* Offset 0x14 */
- uint32_t ecx; /* Offset 0x18 */
- uint32_t eax; /* Offset 0x1c */
-};
-
-static inline uintptr_t push_stack(uintptr_t cur_stack, uintptr_t value)
-{
- uintptr_t *addr;
-
- cur_stack -= sizeof(value);
- addr = (uintptr_t *)cur_stack;
- *addr = value;
- return cur_stack;
-}
-
-void arch_prepare_thread(struct thread *t,
- void asmlinkage (*thread_entry)(void *), void *arg)
-{
- uintptr_t stack = t->stack_current;
-
- /* Imitate thread_entry(t) with return address of 0. thread_entry()
- * is assumed to never return. */
- stack = push_stack(stack, (uintptr_t)arg);
- stack = push_stack(stack, (uintptr_t)0);
- stack = push_stack(stack, (uintptr_t)thread_entry);
- /* Make room for the registers. Ignore intial values. */
- stack -= sizeof(struct pushad_regs);
-
- t->stack_current = stack;
-}
-
-void *arch_get_thread_stackbase(void)
-{
- /* defined in c_start.S */
- extern u8 thread_stacks[];
- return &thread_stacks[0];
-}
diff --git a/src/arch/x86/lib/thread_switch.S b/src/arch/x86/lib/thread_switch.S
deleted file mode 100644
index 52d4d30..0000000
--- a/src/arch/x86/lib/thread_switch.S
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2013 Google, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-.code32
-.text
-
-/*
- * stack layout after pushad:
- * +------------+
- * | save stack | <-- esp + 0x28
- * +------------+
- * | new stack | <-- esp + 0x24
- * +------------+
- * | ret addr | <-- esp + 0x20
- * +------------+
- * | eax | <-- esp + 0x1c
- * +------------+
- * | ecx | <-- esp + 0x18
- * +------------+
- * | edx | <-- esp + 0x14
- * +------------+
- * | ebx | <-- esp + 0x10
- * +------------+
- * | orig esp | <-- esp + 0x0c
- * +------------+
- * | ebp | <-- esp + 0x08
- * +------------+
- * | esi | <-- esp + 0x04
- * +------------+
- * | edi | <-- esp + 0x00
- * +------------+
- */
-.globl switch_to_thread
-switch_to_thread:
- pusha
- /* Save the current stack */
- movl 0x28(%esp), %ebx
- movl %esp, (%ebx)
- /* Switch to the new stack. */
- movl 0x24(%esp), %eax
- movl %eax, %esp
- popa
- ret
diff --git a/src/arch/x86/lib/timestamp.c b/src/arch/x86/lib/timestamp.c
deleted file mode 100644
index 9df505a..0000000
--- a/src/arch/x86/lib/timestamp.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2013 Google Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- */
-
-#include <cpu/x86/tsc.h>
-#include <timestamp.h>
-
-uint64_t timestamp_get(void)
-{
- return rdtscll();
-}
diff --git a/src/arch/x86/lib/walkcbfs.S b/src/arch/x86/lib/walkcbfs.S
deleted file mode 100644
index 60eb8b5..0000000
--- a/src/arch/x86/lib/walkcbfs.S
+++ /dev/null
@@ -1,117 +0,0 @@
-#define CBFS_HEADER_PTR 0xfffffffc
-
-#define CBFS_HEADER_MAGIC 0
-#define CBFS_HEADER_VERSION (CBFS_HEADER_MAGIC + 4)
-#define CBFS_HEADER_ROMSIZE (CBFS_HEADER_VERSION + 4)
-#define CBFS_HEADER_BOOTBLOCKSIZE (CBFS_HEADER_ROMSIZE + 4)
-#define CBFS_HEADER_ALIGN (CBFS_HEADER_BOOTBLOCKSIZE + 4)
-#define CBFS_HEADER_OFFSET (CBFS_HEADER_ALIGN + 4)
-
-#define CBFS_FILE_MAGIC 0
-#define CBFS_FILE_LEN (CBFS_FILE_MAGIC + 8)
-#define CBFS_FILE_TYPE (CBFS_FILE_LEN + 4)
-#define CBFS_FILE_CHECKSUM (CBFS_FILE_TYPE + 4)
-#define CBFS_FILE_OFFSET (CBFS_FILE_CHECKSUM + 4)
-
-#define CBFS_FILE_STRUCTSIZE (CBFS_FILE_OFFSET + 4)
-
-/*
- * input %esi: filename
- * input %esp: return address (not pointer to return address!)
- * output %eax: pointer to CBFS header
- * clobbers %ebx, %ecx, %edi
- */
-walkcbfs_asm:
- cld
-
- mov CBFS_HEADER_PTR, %eax
- mov CBFS_HEADER_ROMSIZE(%eax), %ecx
- bswap %ecx
- mov $0, %ebx
- sub %ecx, %ebx /* rom base address in ebx */
- mov CBFS_HEADER_OFFSET(%eax), %ecx
- bswap %ecx
- add %ecx, %ebx /* address where we start looking for LARCHIVEs */
-
- /* determine filename length */
- mov $0, %eax
-1:
- cmpb $0, (%eax,%esi)
- jz 2f
- add $1, %eax
- jmp 1b
-2:
- add $1, %eax
-walker:
- mov 0(%ebx), %edi /* Check for LARCHIVE header */
- cmp %edi, filemagic
- jne searchfile
- mov 4(%ebx), %edi
- cmp %edi, filemagic+4
- jne searchfile
-
- /* LARCHIVE header found */
- mov %ebx, %edi
- add $CBFS_FILE_STRUCTSIZE, %edi /* edi = address of first byte after struct cbfs_file */
- mov %eax, %ecx
- repe cmpsb
- /* zero flag set if strings are equal */
- jnz tryharder
-
- /* we found it! */
- mov %ebx, %eax
- jmp *%esp
-
-tryharder:
- sub %ebx, %edi
- sub $CBFS_FILE_STRUCTSIZE, %edi /* edi = # of walked bytes */
- sub %edi, %esi /* esi = start of filename */
-
- /* ebx = ecx = (current+offset+len+ALIGN-1) & ~(ALIGN-1) */
- mov CBFS_FILE_OFFSET(%ebx), %ecx
- bswap %ecx
- add %ebx, %ecx
- mov CBFS_FILE_LEN(%ebx), %edi
- bswap %edi
- add %edi, %ecx
- mov CBFS_HEADER_PTR, %edi
- mov CBFS_HEADER_ALIGN(%edi), %edi
- bswap %edi
- sub $1, %edi
- add %edi, %ecx
- not %edi
- and %edi, %ecx
-
- /* if oldaddr >= addr, leave */
- cmp %ebx, %ecx
- jbe out
-
- mov %ecx, %ebx
-
-check_for_exit:
- /* look if we should exit: did we pass into the bootblock already? */
- mov CBFS_HEADER_PTR, %ecx
- mov CBFS_HEADER_BOOTBLOCKSIZE(%ecx), %ecx
- bswap %ecx
- not %ecx
- add $1, %ecx
-
- cmp %ecx, %ebx
- /* if bootblockstart >= addr (==we're still in the data area) , jump back */
- jbe walker
-
-out:
- mov $0, %eax
- jmp *%esp
-
-
-searchfile:
- /* if filemagic isn't found, move forward cbfs_header->align bytes */
- mov CBFS_HEADER_PTR, %edi
- mov CBFS_HEADER_ALIGN(%edi), %edi
- bswap %edi
- add %edi, %ebx
- jmp check_for_exit
-
-filemagic:
- .ascii "LARCHIVE"
diff --git a/src/arch/x86/memcpy.c b/src/arch/x86/memcpy.c
new file mode 100644
index 0000000..4915a9e
--- /dev/null
+++ b/src/arch/x86/memcpy.c
@@ -0,0 +1,22 @@
+#include <string.h>
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+ unsigned long d0, d1, d2;
+
+ asm volatile(
+#ifdef __x86_64__
+ "rep ; movsd\n\t"
+ "mov %4,%%rcx\n\t"
+#else
+ "rep ; movsl\n\t"
+ "movl %4,%%ecx\n\t"
+#endif
+ "rep ; movsb\n\t"
+ : "=&c" (d0), "=&D" (d1), "=&S" (d2)
+ : "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src)
+ : "memory"
+ );
+
+ return dest;
+}
diff --git a/src/arch/x86/memmove.c b/src/arch/x86/memmove.c
new file mode 100644
index 0000000..ba12127
--- /dev/null
+++ b/src/arch/x86/memmove.c
@@ -0,0 +1,187 @@
+#include <string.h>
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+ int d0,d1,d2,d3,d4,d5;
+ char *ret = dest;
+
+ __asm__ __volatile__(
+ /* Handle more 16bytes in loop */
+ "cmp $0x10, %0\n\t"
+ "jb 1f\n\t"
+
+ /* Decide forward/backward copy mode */
+ "cmp %2, %1\n\t"
+ "jb 2f\n\t"
+
+ /*
+ * movs instruction have many startup latency
+ * so we handle small size by general register.
+ */
+ "cmp $680, %0\n\t"
+ "jb 3f\n\t"
+ /*
+ * movs instruction is only good for aligned case.
+ */
+ "mov %1, %3\n\t"
+ "xor %2, %3\n\t"
+ "and $0xff, %3\n\t"
+ "jz 4f\n\t"
+ "3:\n\t"
+ "sub $0x10, %0\n\t"
+
+ /*
+ * We gobble 16byts forward in each loop.
+ */
+ "3:\n\t"
+ "sub $0x10, %0\n\t"
+ "mov 0*4(%1), %3\n\t"
+ "mov 1*4(%1), %4\n\t"
+ "mov %3, 0*4(%2)\n\t"
+ "mov %4, 1*4(%2)\n\t"
+ "mov 2*4(%1), %3\n\t"
+ "mov 3*4(%1), %4\n\t"
+ "mov %3, 2*4(%2)\n\t"
+ "mov %4, 3*4(%2)\n\t"
+ "lea 0x10(%1), %1\n\t"
+ "lea 0x10(%2), %2\n\t"
+ "jae 3b\n\t"
+ "add $0x10, %0\n\t"
+ "jmp 1f\n\t"
+
+ /*
+ * Handle data forward by movs.
+ */
+ ".p2align 4\n\t"
+ "4:\n\t"
+ "mov -4(%1, %0), %3\n\t"
+ "lea -4(%2, %0), %4\n\t"
+ "shr $2, %0\n\t"
+ "rep movsl\n\t"
+ "mov %3, (%4)\n\t"
+ "jmp 11f\n\t"
+ /*
+ * Handle data backward by movs.
+ */
+ ".p2align 4\n\t"
+ "6:\n\t"
+ "mov (%1), %3\n\t"
+ "mov %2, %4\n\t"
+ "lea -4(%1, %0), %1\n\t"
+ "lea -4(%2, %0), %2\n\t"
+ "shr $2, %0\n\t"
+ "std\n\t"
+ "rep movsl\n\t"
+ "mov %3,(%4)\n\t"
+ "cld\n\t"
+ "jmp 11f\n\t"
+
+ /*
+ * Start to prepare for backward copy.
+ */
+ ".p2align 4\n\t"
+ "2:\n\t"
+ "cmp $680, %0\n\t"
+ "jb 5f\n\t"
+ "mov %1, %3\n\t"
+ "xor %2, %3\n\t"
+ "and $0xff, %3\n\t"
+ "jz 6b\n\t"
+
+ /*
+ * Calculate copy position to tail.
+ */
+ "5:\n\t"
+ "add %0, %1\n\t"
+ "add %0, %2\n\t"
+ "sub $0x10, %0\n\t"
+
+ /*
+ * We gobble 16byts backward in each loop.
+ */
+ "7:\n\t"
+ "sub $0x10, %0\n\t"
+
+ "mov -1*4(%1), %3\n\t"
+ "mov -2*4(%1), %4\n\t"
+ "mov %3, -1*4(%2)\n\t"
+ "mov %4, -2*4(%2)\n\t"
+ "mov -3*4(%1), %3\n\t"
+ "mov -4*4(%1), %4\n\t"
+ "mov %3, -3*4(%2)\n\t"
+ "mov %4, -4*4(%2)\n\t"
+ "lea -0x10(%1), %1\n\t"
+ "lea -0x10(%2), %2\n\t"
+ "jae 7b\n\t"
+ /*
+ * Calculate copy position to head.
+ */
+ "add $0x10, %0\n\t"
+ "sub %0, %1\n\t"
+ "sub %0, %2\n\t"
+
+ /*
+ * Move data from 8 bytes to 15 bytes.
+ */
+ ".p2align 4\n\t"
+ "1:\n\t"
+ "cmp $8, %0\n\t"
+ "jb 8f\n\t"
+ "mov 0*4(%1), %3\n\t"
+ "mov 1*4(%1), %4\n\t"
+ "mov -2*4(%1, %0), %5\n\t"
+ "mov -1*4(%1, %0), %1\n\t"
+
+ "mov %3, 0*4(%2)\n\t"
+ "mov %4, 1*4(%2)\n\t"
+ "mov %5, -2*4(%2, %0)\n\t"
+ "mov %1, -1*4(%2, %0)\n\t"
+ "jmp 11f\n\t"
+
+ /*
+ * Move data from 4 bytes to 7 bytes.
+ */
+ ".p2align 4\n\t"
+ "8:\n\t"
+ "cmp $4, %0\n\t"
+ "jb 9f\n\t"
+ "mov 0*4(%1), %3\n\t"
+ "mov -1*4(%1, %0), %4\n\t"
+ "mov %3, 0*4(%2)\n\t"
+ "mov %4, -1*4(%2, %0)\n\t"
+ "jmp 11f\n\t"
+
+ /*
+ * Move data from 2 bytes to 3 bytes.
+ */
+ ".p2align 4\n\t"
+ "9:\n\t"
+ "cmp $2, %0\n\t"
+ "jb 10f\n\t"
+ "movw 0*2(%1), %%dx\n\t"
+ "movw -1*2(%1, %0), %%bx\n\t"
+ "movw %%dx, 0*2(%2)\n\t"
+ "movw %%bx, -1*2(%2, %0)\n\t"
+ "jmp 11f\n\t"
+
+ /*
+ * Move data for 1 byte.
+ */
+ ".p2align 4\n\t"
+ "10:\n\t"
+ "cmp $1, %0\n\t"
+ "jb 11f\n\t"
+ "movb (%1), %%cl\n\t"
+ "movb %%cl, (%2)\n\t"
+ ".p2align 4\n\t"
+ "11:"
+ : "=&c" (d0), "=&S" (d1), "=&D" (d2),
+ "=r" (d3),"=r" (d4), "=r"(d5)
+ :"0" (n),
+ "1" (src),
+ "2" (dest)
+ :"memory");
+
+ return ret;
+
+}
diff --git a/src/arch/x86/memset.c b/src/arch/x86/memset.c
new file mode 100644
index 0000000..d534556
--- /dev/null
+++ b/src/arch/x86/memset.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 1991,1992,1993,1997,1998,2003, 2005 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+/* From glibc-2.14, sysdeps/i386/memset.c */
+
+#include <string.h>
+#include <stdint.h>
+
+typedef uint32_t op_t;
+
+void *memset(void *dstpp, int c, size_t len)
+{
+ int d0;
+ unsigned long int dstp = (unsigned long int) dstpp;
+
+ /* This explicit register allocation improves code very much indeed. */
+ register op_t x asm("ax");
+
+ x = (unsigned char) c;
+
+ /* Clear the direction flag, so filling will move forward. */
+ asm volatile("cld");
+
+ /* This threshold value is optimal. */
+ if (len >= 12) {
+ /* Fill X with four copies of the char we want to fill with. */
+ x |= (x << 8);
+ x |= (x << 16);
+
+ /* Adjust LEN for the bytes handled in the first loop. */
+ len -= (-dstp) % sizeof(op_t);
+
+ /*
+ * There are at least some bytes to set. No need to test for
+ * LEN == 0 in this alignment loop.
+ */
+
+ /* Fill bytes until DSTP is aligned on a longword boundary. */
+ asm volatile(
+ "rep\n"
+ "stosb" /* %0, %2, %3 */ :
+ "=D" (dstp), "=c" (d0) :
+ "0" (dstp), "1" ((-dstp) % sizeof(op_t)), "a" (x) :
+ "memory");
+
+ /* Fill longwords. */
+ asm volatile(
+ "rep\n"
+ "stosl" /* %0, %2, %3 */ :
+ "=D" (dstp), "=c" (d0) :
+ "0" (dstp), "1" (len / sizeof(op_t)), "a" (x) :
+ "memory");
+ len %= sizeof(op_t);
+ }
+
+ /* Write the last few bytes. */
+ asm volatile(
+ "rep\n"
+ "stosb" /* %0, %2, %3 */ :
+ "=D" (dstp), "=c" (d0) :
+ "0" (dstp), "1" (len), "a" (x) :
+ "memory");
+
+ return dstpp;
+}
diff --git a/src/arch/x86/mmap_boot.c b/src/arch/x86/mmap_boot.c
new file mode 100644
index 0000000..4dd269b
--- /dev/null
+++ b/src/arch/x86/mmap_boot.c
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <boot_device.h>
+#include <console/console.h>
+#include <cbfs.h>
+#include <endian.h>
+#include <stdlib.h>
+
+/* The ROM is memory mapped just below 4GiB. Form a pointer for the base. */
+#define rom_base ((void *)(uintptr_t)(-(int32_t)CONFIG_ROM_SIZE))
+
+static const struct mem_region_device boot_dev =
+ MEM_REGION_DEV_INIT(rom_base, CONFIG_ROM_SIZE);
+
+const struct region_device *boot_device_ro(void)
+{
+ return &boot_dev.rdev;
+}
+
+int cbfs_boot_region_properties(struct cbfs_props *props)
+{
+ struct cbfs_header header;
+ int32_t offset;
+ const struct region_device *bdev;
+
+ bdev = boot_device_ro();
+
+ rdev_readat(bdev, &offset, CONFIG_ROM_SIZE - sizeof(offset),
+ sizeof(offset));
+
+ /* The offset is relative to the end of the media. */
+ offset += CONFIG_ROM_SIZE;
+
+ rdev_readat(bdev, &header , offset, sizeof(header));
+
+ header.magic = ntohl(header.magic);
+ header.romsize = ntohl(header.romsize);
+ header.bootblocksize = ntohl(header.bootblocksize);
+ header.align = ntohl(header.align);
+ header.offset = ntohl(header.offset);
+
+ if (header.magic != CBFS_HEADER_MAGIC)
+ return -1;
+
+ props->align = header.align;
+ props->offset = header.offset;
+ if (CONFIG_ROM_SIZE != header.romsize)
+ props->size = CONFIG_ROM_SIZE;
+ else
+ props->size = header.romsize;
+ props->size -= props->offset;
+ props->size -= header.bootblocksize;
+ props->size = ALIGN_DOWN(props->size, props->align);
+
+ printk(BIOS_DEBUG, "CBFS @ %zx size %zx\n", props->offset, props->size);
+
+ return 0;
+}
diff --git a/src/arch/x86/mpspec.c b/src/arch/x86/mpspec.c
new file mode 100644
index 0000000..1a0ac31
--- /dev/null
+++ b/src/arch/x86/mpspec.c
@@ -0,0 +1,597 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Sage Electronic Engineering, LLC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <console/console.h>
+#include <device/path.h>
+#include <device/pci_ids.h>
+#include <cpu/cpu.h>
+#include <arch/smp/mpspec.h>
+#include <string.h>
+#include <arch/cpu.h>
+#include <cpu/x86/lapic.h>
+#include <drivers/generic/ioapic/chip.h>
+
+/* Initialize the specified "mc" struct with initial values. */
+void mptable_init(struct mp_config_table *mc, u32 lapic_addr)
+{
+ int i;
+
+ memset(mc, 0, sizeof(*mc));
+
+ memcpy(mc->mpc_signature, MPC_SIGNATURE, 4);
+
+ mc->mpc_length = sizeof(*mc); /* Initially just the header size. */
+ mc->mpc_spec = 0x04; /* MultiProcessor specification 1.4 */
+ mc->mpc_checksum = 0; /* Not yet computed. */
+ mc->mpc_oemptr = 0;
+ mc->mpc_oemsize = 0;
+ mc->mpc_entry_count = 0; /* No entries yet... */
+ mc->mpc_lapic = lapic_addr;
+ mc->mpe_length = 0;
+ mc->mpe_checksum = 0;
+ mc->reserved = 0;
+
+ strncpy(mc->mpc_oem, CONFIG_MAINBOARD_VENDOR, 8);
+ strncpy(mc->mpc_productid, CONFIG_MAINBOARD_PART_NUMBER, 12);
+
+ /*
+ * The oem/productid fields are exactly 8/12 bytes long. If the resp.
+ * entry is shorter, the remaining bytes are filled with spaces.
+ */
+ for (i = MIN(strlen(CONFIG_MAINBOARD_VENDOR), 8); i < 8; i++)
+ mc->mpc_oem[i] = ' ';
+ for (i = MIN(strlen(CONFIG_MAINBOARD_PART_NUMBER), 12); i < 12; i++)
+ mc->mpc_productid[i] = ' ';
+}
+
+static unsigned char smp_compute_checksum(void *v, int len)
+{
+ unsigned char *bytes;
+ unsigned char checksum;
+ int i;
+ bytes = v;
+ checksum = 0;
+ for(i = 0; i < len; i++) {
+ checksum -= bytes[i];
+ }
+ return checksum;
+}
+
+static void *smp_write_floating_table_physaddr(uintptr_t addr, uintptr_t mpf_physptr, unsigned int virtualwire)
+{
+ struct intel_mp_floating *mf;
+ void *v;
+
+ v = (void *)addr;
+ mf = v;
+ mf->mpf_signature[0] = '_';
+ mf->mpf_signature[1] = 'M';
+ mf->mpf_signature[2] = 'P';
+ mf->mpf_signature[3] = '_';
+ mf->mpf_physptr = mpf_physptr;
+ mf->mpf_length = 1;
+ mf->mpf_specification = 4;
+ mf->mpf_checksum = 0;
+ mf->mpf_feature1 = 0;
+ mf->mpf_feature2 = virtualwire?MP_FEATURE_PIC:MP_FEATURE_VIRTUALWIRE;
+ mf->mpf_feature3 = 0;
+ mf->mpf_feature4 = 0;
+ mf->mpf_feature5 = 0;
+ mf->mpf_checksum = smp_compute_checksum(mf, mf->mpf_length*16);
+ return v;
+}
+
+void *smp_write_floating_table(unsigned long addr, unsigned int virtualwire)
+{
+ /* 16 byte align the table address */
+ addr = (addr + 0xf) & (~0xf);
+ return smp_write_floating_table_physaddr(addr, addr + SMP_FLOATING_TABLE_LEN, virtualwire);
+}
+
+void *smp_next_mpc_entry(struct mp_config_table *mc)
+{
+ void *v;
+ v = (void *)(((char *)mc) + mc->mpc_length);
+
+ return v;
+}
+static void smp_add_mpc_entry(struct mp_config_table *mc, u16 length)
+{
+ mc->mpc_length += length;
+ mc->mpc_entry_count++;
+}
+
+void *smp_next_mpe_entry(struct mp_config_table *mc)
+{
+ void *v;
+ v = (void *)(((char *)mc) + mc->mpc_length + mc->mpe_length);
+
+ return v;
+}
+static void smp_add_mpe_entry(struct mp_config_table *mc, mpe_t mpe)
+{
+ mc->mpe_length += mpe->mpe_length;
+}
+
+/*
+ * Type 0: Processor Entries:
+ * Entry Type, LAPIC ID, LAPIC Version, CPU Flags EN/BP,
+ * CPU Signature (Stepping, Model, Family), Feature Flags
+ */
+void smp_write_processor(struct mp_config_table *mc,
+ u8 apicid, u8 apicver, u8 cpuflag,
+ u32 cpufeature, u32 featureflag)
+{
+ struct mpc_config_processor *mpc;
+ mpc = smp_next_mpc_entry(mc);
+ memset(mpc, '\0', sizeof(*mpc));
+ mpc->mpc_type = MP_PROCESSOR;
+ mpc->mpc_apicid = apicid;
+ mpc->mpc_apicver = apicver;
+ mpc->mpc_cpuflag = cpuflag;
+ mpc->mpc_cpufeature = cpufeature;
+ mpc->mpc_featureflag = featureflag;
+ smp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+/*
+ * If we assume a symmetric processor configuration we can
+ * get all of the information we need to write the processor
+ * entry from the bootstrap processor.
+ * Plus I don't think linux really even cares.
+ * Having the proper apicid's in the table so the non-bootstrap
+ * processors can be woken up should be enough.
+ */
+void smp_write_processors(struct mp_config_table *mc)
+{
+ int boot_apic_id;
+ int order_id;
+ unsigned apic_version;
+ unsigned cpu_features;
+ unsigned cpu_feature_flags;
+ struct cpuid_result result;
+ struct device *cpu;
+
+ boot_apic_id = lapicid();
+ apic_version = lapic_read(LAPIC_LVR) & 0xff;
+ result = cpuid(1);
+ cpu_features = result.eax;
+ cpu_feature_flags = result.edx;
+ /* order the output of the cpus to fix a bug in kernel 2.6.11 */
+ for(order_id = 0;order_id <256; order_id++) {
+ for(cpu = all_devices; cpu; cpu = cpu->next) {
+ unsigned long cpu_flag;
+ if ((cpu->path.type != DEVICE_PATH_APIC) ||
+ (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER))
+ continue;
+
+ if (!cpu->enabled)
+ continue;
+
+ cpu_flag = MPC_CPU_ENABLED;
+
+ if (boot_apic_id == cpu->path.apic.apic_id)
+ cpu_flag = MPC_CPU_ENABLED | MPC_CPU_BOOTPROCESSOR;
+
+ if(cpu->path.apic.apic_id == order_id) {
+ smp_write_processor(mc,
+ cpu->path.apic.apic_id, apic_version,
+ cpu_flag, cpu_features, cpu_feature_flags
+ );
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * Type 1: Bus Entries:
+ * Entry Type, Bus ID, Bus Type
+ */
+static void smp_write_bus(struct mp_config_table *mc,
+ u8 id, const char *bustype)
+{
+ struct mpc_config_bus *mpc;
+ mpc = smp_next_mpc_entry(mc);
+ memset(mpc, '\0', sizeof(*mpc));
+ mpc->mpc_type = MP_BUS;
+ mpc->mpc_busid = id;
+ memcpy(mpc->mpc_bustype, bustype, sizeof(mpc->mpc_bustype));
+ smp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+/*
+ * Type 2: I/O APIC Entries:
+ * Entry Type, APIC ID, Version,
+ * APIC Flags:EN, Address
+ */
+void smp_write_ioapic(struct mp_config_table *mc,
+ u8 id, u8 ver, void *apicaddr)
+{
+ struct mpc_config_ioapic *mpc;
+ mpc = smp_next_mpc_entry(mc);
+ memset(mpc, '\0', sizeof(*mpc));
+ mpc->mpc_type = MP_IOAPIC;
+ mpc->mpc_apicid = id;
+ mpc->mpc_apicver = ver;
+ mpc->mpc_flags = MPC_APIC_USABLE;
+ mpc->mpc_apicaddr = apicaddr;
+ smp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+/*
+ * Type 3: I/O Interrupt Table Entries:
+ * Entry Type, Int Type, Int Polarity, Int Level,
+ * Source Bus ID, Source Bus IRQ, Dest APIC ID, Dest PIN#
+ */
+void smp_write_intsrc(struct mp_config_table *mc,
+ u8 irqtype, u16 irqflag,
+ u8 srcbus, u8 srcbusirq,
+ u8 dstapic, u8 dstirq)
+{
+ struct mpc_config_intsrc *mpc;
+ mpc = smp_next_mpc_entry(mc);
+ memset(mpc, '\0', sizeof(*mpc));
+ mpc->mpc_type = MP_INTSRC;
+ mpc->mpc_irqtype = irqtype;
+ mpc->mpc_irqflag = irqflag;
+ mpc->mpc_srcbus = srcbus;
+ mpc->mpc_srcbusirq = srcbusirq;
+ mpc->mpc_dstapic = dstapic;
+ mpc->mpc_dstirq = dstirq;
+ smp_add_mpc_entry(mc, sizeof(*mpc));
+#ifdef DEBUG_MPTABLE
+ printk(BIOS_DEBUG, "add intsrc srcbus 0x%x srcbusirq 0x%x, dstapic 0x%x, dstirq 0x%x\n",
+ srcbus, srcbusirq, dstapic, dstirq);
+ hexdump(__func__, mpc, sizeof(*mpc));
+#endif
+}
+
+/*
+ * Type 3: I/O Interrupt Table Entries for PCI Devices:
+ * This has the same fields as 'Type 3: I/O Interrupt Table Entries'
+ * but the Source Bus IRQ field has a slightly different
+ * definition:
+ * Bits 1-0: PIRQ pin: INT_A# = 0, INT_B# = 1, INT_C# = 2, INT_D# = 3
+ * Bits 2-6: Originating PCI Device Number (Not its parent bridge device number)
+ * Bit 7: Reserved
+ */
+void smp_write_pci_intsrc(struct mp_config_table *mc,
+ u8 irqtype, u8 srcbus, u8 dev, u8 pirq,
+ u8 dstapic, u8 dstirq)
+{
+ u8 srcbusirq = (dev << 2) | pirq;
+ printk(BIOS_SPEW, "\tPCI srcbusirq = 0x%x from dev = 0x%x and pirq = %x\n", srcbusirq, dev, pirq);
+ smp_write_intsrc(mc, irqtype, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, srcbus,
+ srcbusirq, dstapic, dstirq);
+}
+
+void smp_write_intsrc_pci_bridge(struct mp_config_table *mc,
+ u8 irqtype, u16 irqflag, struct device *dev,
+ unsigned char dstapic, unsigned char *dstirq)
+{
+ struct device *child;
+
+ int i;
+ int srcbus;
+ int slot;
+
+ struct bus *link;
+ unsigned char dstirq_x[4];
+
+ for (link = dev->link_list; link; link = link->next) {
+
+ child = link->children;
+ srcbus = link->secondary;
+
+ while (child) {
+ if (child->path.type != DEVICE_PATH_PCI)
+ goto next;
+
+ slot = (child->path.pci.devfn >> 3);
+ /* round pins */
+ for (i = 0; i < 4; i++)
+ dstirq_x[i] = dstirq[(i + slot) % 4];
+
+ if ((child->class >> 16) != PCI_BASE_CLASS_BRIDGE) {
+ /* pci device */
+ printk(BIOS_DEBUG, "route irq: %s\n", dev_path(child));
+ for (i = 0; i < 4; i++)
+ smp_write_intsrc(mc, irqtype, irqflag, srcbus, (slot<<2)|i, dstapic, dstirq_x[i]);
+ goto next;
+ }
+
+ switch (child->class>>8) {
+ case PCI_CLASS_BRIDGE_PCI:
+ case PCI_CLASS_BRIDGE_PCMCIA:
+ case PCI_CLASS_BRIDGE_CARDBUS:
+ printk(BIOS_DEBUG, "route irq bridge: %s\n", dev_path(child));
+ smp_write_intsrc_pci_bridge(mc, irqtype, irqflag, child, dstapic, dstirq_x);
+ }
+
+next:
+ child = child->sibling;
+ }
+
+ }
+}
+
+/*
+ * Type 4: Local Interrupt Assignment Entries:
+ * Entry Type, Int Type, Int Polarity, Int Level,
+ * Source Bus ID, Source Bus IRQ, Dest LAPIC ID,
+ * Dest LAPIC LINTIN#
+ */
+void smp_write_lintsrc(struct mp_config_table *mc,
+ u8 irqtype, u16 irqflag,
+ u8 srcbusid, u8 srcbusirq,
+ u8 destapic, u8 destapiclint)
+{
+ struct mpc_config_lintsrc *mpc;
+ mpc = smp_next_mpc_entry(mc);
+ memset(mpc, '\0', sizeof(*mpc));
+ mpc->mpc_type = MP_LINTSRC;
+ mpc->mpc_irqtype = irqtype;
+ mpc->mpc_irqflag = irqflag;
+ mpc->mpc_srcbusid = srcbusid;
+ mpc->mpc_srcbusirq = srcbusirq;
+ mpc->mpc_destapic = destapic;
+ mpc->mpc_destapiclint = destapiclint;
+ smp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+/*
+ * Type 128: System Address Space Mapping Entries
+ * Entry Type, Entry Length, Bus ID, Address Type,
+ * Address Base Lo/Hi, Address Length Lo/Hi
+ */
+void smp_write_address_space(struct mp_config_table *mc,
+ u8 busid, u8 address_type,
+ u32 address_base_low, u32 address_base_high,
+ u32 address_length_low, u32 address_length_high)
+{
+ struct mp_exten_system_address_space *mpe;
+ mpe = smp_next_mpe_entry(mc);
+ memset(mpe, '\0', sizeof(*mpe));
+ mpe->mpe_type = MPE_SYSTEM_ADDRESS_SPACE;
+ mpe->mpe_length = sizeof(*mpe);
+ mpe->mpe_busid = busid;
+ mpe->mpe_address_type = address_type;
+ mpe->mpe_address_base_low = address_base_low;
+ mpe->mpe_address_base_high = address_base_high;
+ mpe->mpe_address_length_low = address_length_low;
+ mpe->mpe_address_length_high = address_length_high;
+ smp_add_mpe_entry(mc, (mpe_t)mpe);
+}
+
+/*
+ * Type 129: Bus Hierarchy Descriptor Entry
+ * Entry Type, Entry Length, Bus ID, Bus Info,
+ * Parent Bus ID
+ */
+void smp_write_bus_hierarchy(struct mp_config_table *mc,
+ u8 busid, u8 bus_info, u8 parent_busid)
+{
+ struct mp_exten_bus_hierarchy *mpe;
+ mpe = smp_next_mpe_entry(mc);
+ memset(mpe, '\0', sizeof(*mpe));
+ mpe->mpe_type = MPE_BUS_HIERARCHY;
+ mpe->mpe_length = sizeof(*mpe);
+ mpe->mpe_busid = busid;
+ mpe->mpe_bus_info = bus_info;
+ mpe->mpe_parent_busid = parent_busid;
+ smp_add_mpe_entry(mc, (mpe_t)mpe);
+}
+
+/*
+ * Type 130: Compatibility Bus Address Space Modifier Entry
+ * Entry Type, Entry Length, Bus ID, Address Modifier
+ * Predefined Range List
+ */
+void smp_write_compatibility_address_space(struct mp_config_table *mc,
+ u8 busid, u8 address_modifier,
+ u32 range_list)
+{
+ struct mp_exten_compatibility_address_space *mpe;
+ mpe = smp_next_mpe_entry(mc);
+ memset(mpe, '\0', sizeof(*mpe));
+ mpe->mpe_type = MPE_COMPATIBILITY_ADDRESS_SPACE;
+ mpe->mpe_length = sizeof(*mpe);
+ mpe->mpe_busid = busid;
+ mpe->mpe_address_modifier = address_modifier;
+ mpe->mpe_range_list = range_list;
+ smp_add_mpe_entry(mc, (mpe_t)mpe);
+}
+
+void mptable_lintsrc(struct mp_config_table *mc, unsigned long bus_isa)
+{
+ smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x0);
+ smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x1);
+}
+
+void mptable_add_isa_interrupts(struct mp_config_table *mc, unsigned long bus_isa, unsigned long apicid, int external_int2)
+{
+/*I/O Ints: Type Trigger Polarity Bus ID IRQ APIC ID PIN# */
+ smp_write_intsrc(mc, external_int2?mp_INT:mp_ExtINT,
+ MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, apicid, 0x0);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x1, apicid, 0x1);
+ smp_write_intsrc(mc, external_int2?mp_ExtINT:mp_INT,
+ MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, apicid, 0x2);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x3, apicid, 0x3);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x4, apicid, 0x4);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x6, apicid, 0x6);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x7, apicid, 0x7);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x8, apicid, 0x8);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x9, apicid, 0x9);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xa, apicid, 0xa);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xb, apicid, 0xb);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xc, apicid, 0xc);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xd, apicid, 0xd);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xe, apicid, 0xe);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0xf, apicid, 0xf);
+}
+
+void mptable_write_buses(struct mp_config_table *mc, int *max_pci_bus, int *isa_bus) {
+ int dummy, i, highest;
+ char buses[256];
+ struct device *dev;
+
+ if (!max_pci_bus) max_pci_bus = &dummy;
+ if (!isa_bus) isa_bus = &dummy;
+
+ *max_pci_bus = 0;
+ highest = 0;
+ memset(buses, 0, sizeof(buses));
+
+ for (dev = all_devices; dev; dev = dev->next) {
+ struct bus *bus;
+ for (bus = dev->link_list; bus; bus = bus->next) {
+ if (bus->secondary > 255) {
+ printk(BIOS_ERR, "A bus claims to have a bus ID > 255?!? Aborting");
+ return;
+ }
+ buses[bus->secondary] = 1;
+ if (highest < bus->secondary) highest = bus->secondary;
+ }
+ }
+ for (i=0; i <= highest; i++) {
+ if (buses[i]) {
+ smp_write_bus(mc, i, "PCI ");
+ *max_pci_bus = i;
+ }
+ }
+ *isa_bus = *max_pci_bus + 1;
+ smp_write_bus(mc, *isa_bus, "ISA ");
+}
+
+void *mptable_finalize(struct mp_config_table *mc)
+{
+ 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 __attribute__((weak)) write_smp_table(unsigned long addr)
+{
+ struct drivers_generic_ioapic_config *ioapic_config;
+ struct mp_config_table *mc;
+ int isa_bus, pin, parentpin;
+ struct device *dev;
+ struct device *parent;
+ struct device *oldparent;
+ void *tmp, *v;
+ int isaioapic = -1, have_fixed_entries;
+
+ v = smp_write_floating_table(addr, 0);
+ mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
+
+ mptable_init(mc, LOCAL_APIC_ADDR);
+
+ smp_write_processors(mc);
+
+ mptable_write_buses(mc, NULL, &isa_bus);
+
+ for(dev = all_devices; dev; dev = dev->next) {
+ if (dev->path.type != DEVICE_PATH_IOAPIC)
+ continue;
+
+ if (!(ioapic_config = dev->chip_info)) {
+ printk(BIOS_ERR, "%s has no config, ignoring\n", dev_path(dev));
+ continue;
+ }
+ smp_write_ioapic(mc, dev->path.ioapic.ioapic_id,
+ ioapic_config->version,
+ ioapic_config->base);
+
+ if (ioapic_config->have_isa_interrupts) {
+ if (isaioapic >= 0)
+ printk(BIOS_ERR, "More than one IOAPIC with ISA interrupts?\n");
+ else
+ isaioapic = dev->path.ioapic.ioapic_id;
+ }
+ }
+
+ if (isaioapic >= 0) {
+ /* Legacy Interrupts */
+ printk(BIOS_DEBUG, "Writing ISA IRQs\n");
+ mptable_add_isa_interrupts(mc, isa_bus, isaioapic, 0);
+ }
+
+ for(dev = all_devices; dev; dev = dev->next) {
+
+ if (dev->path.type != DEVICE_PATH_PCI || !dev->enabled)
+ continue;
+
+ have_fixed_entries = 0;
+ for (pin = 0; pin < 4; pin++) {
+ if (dev->pci_irq_info[pin].ioapic_dst_id) {
+ printk(BIOS_DEBUG, "fixed IRQ entry for: %s: INT%c# -> IOAPIC %d PIN %d\n", dev_path(dev),
+ pin + 'A',
+ dev->pci_irq_info[pin].ioapic_dst_id,
+ dev->pci_irq_info[pin].ioapic_irq_pin);
+ smp_write_intsrc(mc, mp_INT,
+ dev->pci_irq_info[pin].ioapic_flags,
+ dev->bus->secondary,
+ ((dev->path.pci.devfn & 0xf8) >> 1) | pin,
+ dev->pci_irq_info[pin].ioapic_dst_id,
+ dev->pci_irq_info[pin].ioapic_irq_pin);
+ have_fixed_entries = 1;
+ }
+ }
+
+ if (!have_fixed_entries) {
+ pin = (dev->path.pci.devfn & 7) % 4;
+ oldparent = parent = dev;
+ while((parent = parent->bus->dev)) {
+ parentpin = (oldparent->path.pci.devfn >> 3) + (oldparent->path.pci.devfn & 7);
+ parentpin += dev->path.pci.devfn & 7;
+ parentpin += dev->path.pci.devfn >> 3;
+ parentpin %= 4;
+
+ if (parent->pci_irq_info[parentpin].ioapic_dst_id) {
+ printk(BIOS_DEBUG, "automatic IRQ entry for %s: INT%c# -> IOAPIC %d PIN %d\n",
+ dev_path(dev), pin + 'A',
+ parent->pci_irq_info[parentpin].ioapic_dst_id,
+ parent->pci_irq_info[parentpin].ioapic_irq_pin);
+ smp_write_intsrc(mc, mp_INT,
+ parent->pci_irq_info[parentpin].ioapic_flags,
+ dev->bus->secondary,
+ ((dev->path.pci.devfn & 0xf8) >> 1) | pin,
+ parent->pci_irq_info[parentpin].ioapic_dst_id,
+ parent->pci_irq_info[parentpin].ioapic_irq_pin);
+
+ break;
+ }
+
+ if (parent->path.type == DEVICE_PATH_DOMAIN) {
+ printk(BIOS_WARNING, "no IRQ found for %s\n", dev_path(dev));
+ break;
+ }
+ oldparent = parent;
+ }
+ }
+ }
+
+ mptable_lintsrc(mc, isa_bus);
+ tmp = mptable_finalize(mc);
+ printk(BIOS_INFO, "MPTABLE len: %d\n", (unsigned int)((uintptr_t)tmp -
+ (uintptr_t)v));
+ return (unsigned long)tmp;
+}
diff --git a/src/arch/x86/pci_ops_conf1.c b/src/arch/x86/pci_ops_conf1.c
new file mode 100644
index 0000000..77df4b3
--- /dev/null
+++ b/src/arch/x86/pci_ops_conf1.c
@@ -0,0 +1,71 @@
+#include <console/console.h>
+#include <arch/io.h>
+#include <arch/pciconf.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+
+#if !CONFIG_PCI_IO_CFG_EXT
+#define CONFIG_CMD(bus,devfn, where) (0x80000000 | (bus << 16) | \
+ (devfn << 8) | (where & ~3))
+#else
+#define CONFIG_CMD(bus,devfn, where) (0x80000000 | (bus << 16) | \
+ (devfn << 8) | ((where & 0xff) & ~3) |\
+ ((where & 0xf00)<<16))
+#endif
+
+static uint8_t pci_conf1_read_config8(struct bus *pbus, int bus, int devfn,
+ int where)
+{
+ outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
+ return inb(0xCFC + (where & 3));
+}
+
+static uint16_t pci_conf1_read_config16(struct bus *pbus, int bus, int devfn,
+ int where)
+{
+ outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
+ return inw(0xCFC + (where & 2));
+}
+
+static uint32_t pci_conf1_read_config32(struct bus *pbus, int bus, int devfn,
+ int where)
+{
+ outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
+ return inl(0xCFC);
+}
+
+static void pci_conf1_write_config8(struct bus *pbus, int bus, int devfn,
+ int where, uint8_t value)
+{
+ outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
+ outb(value, 0xCFC + (where & 3));
+}
+
+static void pci_conf1_write_config16(struct bus *pbus, int bus, int devfn,
+ int where, uint16_t value)
+{
+ outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
+ outw(value, 0xCFC + (where & 2));
+}
+
+static void pci_conf1_write_config32(struct bus *pbus, int bus, int devfn,
+ int where, uint32_t value)
+{
+ outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
+ outl(value, 0xCFC);
+}
+
+#undef CONFIG_CMD
+
+const struct pci_bus_operations pci_cf8_conf1 = {
+ .read8 = pci_conf1_read_config8,
+ .read16 = pci_conf1_read_config16,
+ .read32 = pci_conf1_read_config32,
+ .write8 = pci_conf1_write_config8,
+ .write16 = pci_conf1_write_config16,
+ .write32 = pci_conf1_write_config32,
+};
diff --git a/src/arch/x86/pci_ops_mmconf.c b/src/arch/x86/pci_ops_mmconf.c
new file mode 100644
index 0000000..e4fa128
--- /dev/null
+++ b/src/arch/x86/pci_ops_mmconf.c
@@ -0,0 +1,61 @@
+#include <console/console.h>
+#include <arch/io.h>
+#include <arch/pciconf.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+
+/*
+ * Functions for accessing PCI configuration space with mmconf accesses
+ */
+
+#define PCI_MMIO_ADDR(SEGBUS, DEVFN, WHERE, MASK) \
+ ((void *)(((uintptr_t)CONFIG_MMCONF_BASE_ADDRESS |\
+ (((SEGBUS) & 0xFFF) << 20) |\
+ (((DEVFN) & 0xFF) << 12) |\
+ ((WHERE) & 0xFFF)) & ~MASK))
+
+static uint8_t pci_mmconf_read_config8(struct bus *pbus, int bus, int devfn,
+ int where)
+{
+ return read8(PCI_MMIO_ADDR(bus, devfn, where, 0));
+}
+
+static uint16_t pci_mmconf_read_config16(struct bus *pbus, int bus, int devfn,
+ int where)
+{
+ return read16(PCI_MMIO_ADDR(bus, devfn, where, 1));
+}
+
+static uint32_t pci_mmconf_read_config32(struct bus *pbus, int bus, int devfn,
+ int where)
+{
+ return read32(PCI_MMIO_ADDR(bus, devfn, where, 3));
+}
+
+static void pci_mmconf_write_config8(struct bus *pbus, int bus, int devfn,
+ int where, uint8_t value)
+{
+ write8(PCI_MMIO_ADDR(bus, devfn, where, 0), value);
+}
+
+static void pci_mmconf_write_config16(struct bus *pbus, int bus, int devfn,
+ int where, uint16_t value)
+{
+ write16(PCI_MMIO_ADDR(bus, devfn, where, 1), value);
+}
+
+static void pci_mmconf_write_config32(struct bus *pbus, int bus, int devfn,
+ int where, uint32_t value)
+{
+ write32(PCI_MMIO_ADDR(bus, devfn, where, 3), value);
+}
+
+const struct pci_bus_operations pci_ops_mmconf = {
+ .read8 = pci_mmconf_read_config8,
+ .read16 = pci_mmconf_read_config16,
+ .read32 = pci_mmconf_read_config32,
+ .write8 = pci_mmconf_write_config8,
+ .write16 = pci_mmconf_write_config16,
+ .write32 = pci_mmconf_write_config32,
+};
diff --git a/src/arch/x86/pirq_routing.c b/src/arch/x86/pirq_routing.c
new file mode 100644
index 0000000..7fe20b2
--- /dev/null
+++ b/src/arch/x86/pirq_routing.c
@@ -0,0 +1,208 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ * Copyright (C) 2010 Stefan Reinauer <stepan at coreboot.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <console/console.h>
+#include <arch/pirq_routing.h>
+#include <string.h>
+#include <device/pci.h>
+
+#if CONFIG_DEBUG_PIRQ
+static void check_pirq_routing_table(struct irq_routing_table *rt)
+{
+ uint8_t *addr = (uint8_t *)rt;
+ uint8_t sum=0;
+ int i;
+
+ printk(BIOS_INFO, "Checking Interrupt Routing Table consistency...\n");
+
+ if (sizeof(struct irq_routing_table) != rt->size) {
+ printk(BIOS_WARNING, "Inconsistent Interrupt Routing Table size (0x%x/0x%x).\n",
+ (unsigned int) sizeof(struct irq_routing_table),
+ rt->size
+ );
+ rt->size=sizeof(struct irq_routing_table);
+ }
+
+ for (i = 0; i < rt->size; i++)
+ sum += addr[i];
+
+ printk(BIOS_DEBUG, "%s(): Interrupt Routing Table located at %p.\n",
+ __func__, addr);
+
+
+ sum = rt->checksum - sum;
+
+ if (sum != rt->checksum) {
+ printk(BIOS_WARNING, "Interrupt Routing Table checksum is: 0x%02x but should be: 0x%02x.\n",
+ rt->checksum, sum);
+ rt->checksum = sum;
+ }
+
+ if (rt->signature != PIRQ_SIGNATURE || rt->version != PIRQ_VERSION ||
+ rt->size % 16 ) {
+ printk(BIOS_WARNING, "Interrupt Routing Table not valid.\n");
+ return;
+ }
+
+ sum = 0;
+ for (i=0; i<rt->size; i++)
+ sum += addr[i];
+
+ /* We're manually fixing the checksum above. This warning can probably
+ * never happen because if the target location is read-only this
+ * function would have bailed out earlier.
+ */
+ if (sum) {
+ printk(BIOS_WARNING, "Checksum error in Interrupt Routing Table "
+ "could not be fixed.\n");
+ }
+
+ printk(BIOS_INFO, "done.\n");
+}
+
+static int verify_copy_pirq_routing_table(unsigned long addr, const struct irq_routing_table *routing_table)
+{
+ int i;
+ uint8_t *rt_orig, *rt_curr;
+
+ rt_curr = (uint8_t*)addr;
+ rt_orig = (uint8_t*)routing_table;
+ printk(BIOS_INFO, "Verifying copy of Interrupt Routing Table at 0x%08lx... ", addr);
+ for (i = 0; i < routing_table->size; i++) {
+ if (*(rt_curr + i) != *(rt_orig + i)) {
+ printk(BIOS_INFO, "failed\n");
+ return -1;
+ }
+ }
+ printk(BIOS_INFO, "done\n");
+
+ check_pirq_routing_table((struct irq_routing_table *)addr);
+
+ return 0;
+}
+#endif
+
+#if CONFIG_PIRQ_ROUTE
+static u8 pirq_get_next_free_irq(u8* pirq, u16 bitmap)
+{
+ int i, link;
+ u8 irq = 0;
+ for (i = 2; i <= 15; i++)
+ {
+ /* Can we assign this IRQ ? */
+ if (!((bitmap >> i) & 1))
+ continue;
+ /* We can, Now let's assume we can use this IRQ */
+ irq = i;
+ /* And assume we have not yet routed it */
+ int already_routed = 0;
+ /* Have we already routed it ? */
+ for(link = 0; link < CONFIG_MAX_PIRQ_LINKS; link++) {
+ if (pirq[link] == irq) {
+ already_routed = 1;
+ break;
+ }
+ }
+ /* If it's not yet routed, use it */
+ if(!already_routed)
+ break;
+ /* But if it was already routed, try the next one */
+ continue;
+ }
+ /* Now we got our IRQ */
+ return irq;
+}
+
+static void pirq_route_irqs(unsigned long addr)
+{
+ int i, intx, num_entries;
+ unsigned char irq_slot[MAX_INTX_ENTRIES];
+ unsigned char pirq[CONFIG_MAX_PIRQ_LINKS];
+ struct irq_routing_table *pirq_tbl;
+
+ memset(pirq, 0, CONFIG_MAX_PIRQ_LINKS);
+
+ pirq_tbl = (struct irq_routing_table *)(addr);
+ num_entries = (pirq_tbl->size - 32) / 16;
+
+ /* Set PCI IRQs. */
+ for (i = 0; i < num_entries; i++) {
+
+ printk(BIOS_DEBUG, "PIRQ Entry %d Dev/Fn: %X Slot: %d\n", i,
+ pirq_tbl->slots[i].devfn >> 3, pirq_tbl->slots[i].slot);
+
+ for (intx = 0; intx < MAX_INTX_ENTRIES; intx++) {
+
+ int link = pirq_tbl->slots[i].irq[intx].link;
+ int bitmap = pirq_tbl->slots[i].irq[intx].bitmap;
+ int irq = 0;
+
+ printk(BIOS_DEBUG, "INT: %c link: %x bitmap: %x ",
+ 'A' + intx, link, bitmap);
+
+ if (!bitmap|| !link || link > CONFIG_MAX_PIRQ_LINKS) {
+
+ printk(BIOS_DEBUG, "not routed\n");
+ irq_slot[intx] = irq;
+ continue;
+ }
+
+ /* yet not routed */
+ if (!pirq[link - 1])
+ {
+ irq = pirq_get_next_free_irq(pirq, bitmap);
+ if (irq)
+ pirq[link - 1] = irq;
+ }
+ else
+ irq = pirq[link - 1];
+
+ printk(BIOS_DEBUG, "IRQ: %d\n", irq);
+ irq_slot[intx] = irq;
+ }
+
+ /* Bus, device, slots IRQs for {A,B,C,D}. */
+ pci_assign_irqs(pirq_tbl->slots[i].bus,
+ pirq_tbl->slots[i].devfn >> 3, irq_slot);
+ }
+
+ for(i = 0; i < CONFIG_MAX_PIRQ_LINKS; i++)
+ printk(BIOS_DEBUG, "PIRQ%c: %d\n", i + 'A', pirq[i]);
+
+ pirq_assign_irqs(pirq);
+}
+#endif
+
+unsigned long copy_pirq_routing_table(unsigned long addr, const struct irq_routing_table *routing_table)
+{
+ /* Align the table to be 16 byte aligned. */
+ addr = ALIGN(addr, 16);
+
+ /* This table must be between 0xf0000 & 0x100000 */
+ printk(BIOS_INFO, "Copying Interrupt Routing Table to 0x%08lx... ", addr);
+ memcpy((void *)addr, routing_table, routing_table->size);
+ printk(BIOS_INFO, "done.\n");
+#if CONFIG_DEBUG_PIRQ
+ verify_copy_pirq_routing_table(addr, routing_table);
+#endif
+#if CONFIG_PIRQ_ROUTE
+ pirq_route_irqs(addr);
+#endif
+ return addr + routing_table->size;
+}
diff --git a/src/arch/x86/prologue.inc b/src/arch/x86/prologue.inc
new file mode 100644
index 0000000..e0100b5
--- /dev/null
+++ b/src/arch/x86/prologue.inc
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2002 Eric Biederman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <cpu/x86/post_code.h>
+
+.section ".rom.data", "a", @progbits
+.section ".rom.text", "ax", @progbits
diff --git a/src/arch/x86/romcc_console.c b/src/arch/x86/romcc_console.c
new file mode 100644
index 0000000..bfc35bc
--- /dev/null
+++ b/src/arch/x86/romcc_console.c
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2003 Eric Biederman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <build.h>
+#include <console/streams.h>
+#include <console/early_print.h>
+#include <console/loglevel.h>
+
+/* Include the sources. */
+#if CONFIG_CONSOLE_SERIAL && CONFIG_DRIVERS_UART_8250IO
+#include "drivers/uart/util.c"
+#include "drivers/uart/uart8250io.c"
+#endif
+#if CONFIG_CONSOLE_NE2K
+#include "drivers/net/ne2k.c"
+#endif
+
+void console_hw_init(void)
+{
+#if CONFIG_CONSOLE_SERIAL
+ uart_init(CONFIG_UART_FOR_CONSOLE);
+#endif
+#if CONFIG_CONSOLE_NE2K
+ ne2k_init(CONFIG_CONSOLE_NE2K_IO_PORT);
+#endif
+}
+
+void console_tx_byte(unsigned char byte)
+{
+#if CONFIG_CONSOLE_SERIAL
+ uart_tx_byte(CONFIG_UART_FOR_CONSOLE, byte);
+#endif
+#if CONFIG_CONSOLE_NE2K
+ ne2k_append_data_byte(byte, CONFIG_CONSOLE_NE2K_IO_PORT);
+#endif
+}
+
+void console_tx_flush(void)
+{
+#if CONFIG_CONSOLE_SERIAL
+ uart_tx_flush(CONFIG_UART_FOR_CONSOLE);
+#endif
+#if CONFIG_CONSOLE_NE2K
+ ne2k_transmit(CONFIG_CONSOLE_NE2K_IO_PORT);
+#endif
+}
+
+#include <console/early_print.c>
+#include <console/post.c>
+#include <console/die.c>
+
+void console_init(void)
+{
+ static const char console_test[] =
+ "\n\ncoreboot-"
+ COREBOOT_VERSION
+ COREBOOT_EXTRA_VERSION
+ " "
+ COREBOOT_BUILD
+ " romstage starting...\n";
+
+ console_hw_init();
+
+ print_info(console_test);
+}
+
+void die(const char *msg)
+{
+ print_emerg(msg);
+ halt();
+}
diff --git a/src/arch/x86/romstage.ld b/src/arch/x86/romstage.ld
new file mode 100644
index 0000000..951ca65
--- /dev/null
+++ b/src/arch/x86/romstage.ld
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2006 Advanced Micro Devices, Inc.
+ * Copyright (C) 2008-2010 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+TARGET(binary)
+SECTIONS
+{
+ . = ROMSTAGE_BASE;
+
+ .rom . : {
+ _rom = .;
+ *(.rom.text);
+ *(.rom.text.*);
+ *(.text);
+ *(.text.*);
+ *(.rom.data);
+ . = ALIGN(4);
+ _cbmem_init_hooks = .;
+ KEEP(*(.rodata.cbmem_init_hooks));
+ _ecbmem_init_hooks = .;
+ *(.rodata);
+ *(.rodata.*);
+ *(.rom.data.*);
+ . = ALIGN(16);
+ _erom = .;
+ }
+
+ /DISCARD/ : {
+ *(.comment)
+ *(.note)
+ *(.comment.*)
+ *(.note.*)
+ *(.eh_frame);
+ }
+
+ . = CONFIG_DCACHE_RAM_BASE;
+ .car.data . (NOLOAD) : {
+ _car_data_start = .;
+#if IS_ENABLED(CONFIG_HAS_PRECBMEM_TIMESTAMP_REGION)
+ _timestamp = .;
+ . = . + 0x100;
+ _etimestamp = .;
+#endif
+ *(.car.global_data);
+ _car_data_end = .;
+ /* The preram cbmem console area comes last to take advantage
+ * of a zero-sized array to hold the memconsole contents.
+ * However, collisions within the cache-as-ram region cannot be
+ * statically checked because the cache-as-ram region usage is
+ * cpu/chipset dependent. */
+ _preram_cbmem_console = .;
+ _epreram_cbmem_console = . + (CONFIG_LATE_CBMEM_INIT ? 0 : 0xc00);
+ }
+
+ /* Global variables are not allowed in romstage
+ * This section is checked during stage creation to ensure
+ * that there are no global variables present
+ */
+
+ . = 0xffffff00;
+ .illegal_globals . : {
+ *(EXCLUDE_FILE ("*/libagesa.*.a:" "*/buildOpts.romstage.o" "*/agesawrapper.romstage.o" "*/vendorcode/amd/agesa/*" "*/vendorcode/amd/cimx/*") .data)
+ *(EXCLUDE_FILE ("*/libagesa.*.a:" "*/buildOpts.romstage.o" "*/agesawrapper.romstage.o" "*/vendorcode/amd/agesa/*" "*/vendorcode/amd/cimx/*") .data.*)
+ *(.bss)
+ *(.bss.*)
+ *(.sbss)
+ *(.sbss.*)
+ }
+
+ _bogus = ASSERT((CONFIG_DCACHE_RAM_SIZE == 0) || (SIZEOF(.car.data) + 0xc00 <= CONFIG_DCACHE_RAM_SIZE), "Cache as RAM area is too full");
+}
diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c
new file mode 100644
index 0000000..a1f05da
--- /dev/null
+++ b/src/arch/x86/smbios.c
@@ -0,0 +1,581 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Timothy Pearson <tpearson at raptorengineeringinc.com>, Raptor Engineering
+ * Copyright (C) 2011 Sven Schnelle <svens at stackframe.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <smbios.h>
+#include <console/console.h>
+#include <version.h>
+#include <device/device.h>
+#include <arch/cpu.h>
+#include <cpu/x86/name.h>
+#include <elog.h>
+#include <endian.h>
+#include <memory_info.h>
+#include <spd.h>
+#include <cbmem.h>
+#if CONFIG_CHROMEOS
+#include <vendorcode/google/chromeos/gnvs.h>
+#endif
+
+static u8 smbios_checksum(u8 *p, u32 length)
+{
+ u8 ret = 0;
+ while (length--)
+ ret += *p++;
+ return -ret;
+}
+
+
+int smbios_add_string(char *start, const char *str)
+{
+ int i = 1;
+ char *p = start;
+
+ for(;;) {
+ if (!*p) {
+ strcpy(p, str);
+ p += strlen(str);
+ *p++ = '\0';
+ *p++ = '\0';
+ return i;
+ }
+
+ if (!strcmp(p, str))
+ return i;
+
+ p += strlen(p)+1;
+ i++;
+ }
+}
+
+int smbios_string_table_len(char *start)
+{
+ char *p = start;
+ int i, len = 0;
+
+ while(*p) {
+ i = strlen(p) + 1;
+ p += i;
+ len += i;
+ }
+ return len + 1;
+}
+
+static int smbios_cpu_vendor(char *start)
+{
+ char tmp[13] = "Unknown";
+ u32 *_tmp = (u32 *)tmp;
+ struct cpuid_result res;
+
+ if (cpu_have_cpuid()) {
+ res = cpuid(0);
+ _tmp[0] = res.ebx;
+ _tmp[1] = res.edx;
+ _tmp[2] = res.ecx;
+ tmp[12] = '\0';
+ }
+
+ return smbios_add_string(start, tmp);
+}
+
+static int smbios_processor_name(char *start)
+{
+ char tmp[49] = "Unknown Processor Name";
+ u32 *_tmp = (u32 *)tmp;
+ struct cpuid_result res;
+ int i;
+
+ if (cpu_have_cpuid()) {
+ res = cpuid(0x80000000);
+ if (res.eax >= 0x80000004) {
+ for (i = 0; i < 3; i++) {
+ res = cpuid(0x80000002 + i);
+ _tmp[i * 4 + 0] = res.eax;
+ _tmp[i * 4 + 1] = res.ebx;
+ _tmp[i * 4 + 2] = res.ecx;
+ _tmp[i * 4 + 3] = res.edx;
+ }
+ tmp[48] = 0;
+ }
+ }
+ return smbios_add_string(start, tmp);
+}
+
+/* this function will fill the corresponding manufacturer */
+void smbios_fill_dimm_manufacturer_from_id(uint16_t mod_id, struct smbios_type17 *t)
+{
+ switch (mod_id) {
+ case 0x987f:
+ t->manufacturer = smbios_add_string(t->eos,
+ "Hynix");
+ break;
+ case 0xad80:
+ t->manufacturer = smbios_add_string(t->eos,
+ "Hynix/Hyundai");
+ break;
+ case 0xce80:
+ t->manufacturer = smbios_add_string(t->eos,
+ "Samsung");
+ break;
+ case 0xfe02:
+ t->manufacturer = smbios_add_string(t->eos,
+ "Elpida");
+ break;
+ case 0xff2c:
+ t->manufacturer = smbios_add_string(t->eos,
+ "Micron");
+ break;
+ default: {
+ char string_buffer[256];
+ snprintf(string_buffer, sizeof(string_buffer),
+ "Unknown (%x)", mod_id);
+ t->manufacturer = smbios_add_string(t->eos,
+ string_buffer);
+ break;
+ }
+ }
+}
+
+static int create_smbios_type17_for_dimm(struct dimm_info *dimm,
+ unsigned long *current, int *handle)
+{
+ struct smbios_type17 *t = (struct smbios_type17 *)*current;
+ uint8_t length;
+ char locator[40];
+
+ memset(t, 0, sizeof(struct smbios_type17));
+ t->memory_type = dimm->ddr_type;
+ t->clock_speed = dimm->ddr_frequency;
+ t->speed = dimm->ddr_frequency;
+ t->type = SMBIOS_MEMORY_DEVICE;
+ t->size = dimm->dimm_size;
+ t->data_width = 8 * (1 << (dimm->bus_width & 0x7));
+ t->total_width = t->data_width + 8 * ((dimm->bus_width & 0x18) >> 3);
+
+ switch (dimm->mod_type) {
+ case SPD_RDIMM:
+ case SPD_MINI_RDIMM:
+ t->form_factor = MEMORY_FORMFACTOR_RIMM;
+ break;
+ case SPD_UDIMM:
+ case SPD_MICRO_DIMM:
+ case SPD_MINI_UDIMM:
+ t->form_factor = MEMORY_FORMFACTOR_DIMM;
+ break;
+ case SPD_SODIMM:
+ t->form_factor = MEMORY_FORMFACTOR_SODIMM;
+ break;
+ default:
+ t->form_factor = MEMORY_FORMFACTOR_UNKNOWN;
+ break;
+ }
+
+ smbios_fill_dimm_manufacturer_from_id(dimm->mod_id, t);
+ /* put '\0' in the end of data */
+ length = sizeof(dimm->serial);
+ dimm->serial[length - 1] = '\0';
+ if (dimm->serial[0] == 0)
+ t->serial_number = smbios_add_string(t->eos, "None");
+ else
+ t->serial_number = smbios_add_string(t->eos,
+ (const char *)dimm->serial);
+
+ snprintf(locator, sizeof(locator), "Channel-%d-DIMM-%d",
+ dimm->channel_num, dimm->dimm_num);
+ t->device_locator = smbios_add_string(t->eos, locator);
+
+ snprintf(locator, sizeof(locator), "BANK %d", dimm->bank_locator);
+ t->bank_locator = smbios_add_string(t->eos, locator);
+
+ /* put '\0' in the end of data */
+ length = sizeof(dimm->module_part_number);
+ dimm->module_part_number[length - 1] = '\0';
+ t->part_number = smbios_add_string(t->eos,
+ (const char *)dimm->module_part_number);
+
+ /* Synchronous = 1 */
+ t->type_detail = 0x0080;
+ /* no handle for error information */
+ t->memory_error_information_handle = 0xFFFE;
+ t->attributes = dimm->rank_per_dimm;
+ t->handle = *handle;
+ *handle += 1;
+ t->length = sizeof(struct smbios_type17) - 2;
+ return t->length + smbios_string_table_len(t->eos);
+}
+
+const char *__attribute__((weak)) smbios_mainboard_bios_version(void)
+{
+ if (strlen(CONFIG_LOCALVERSION))
+ return CONFIG_LOCALVERSION;
+ else
+ return coreboot_version;
+}
+
+static int smbios_write_type0(unsigned long *current, int handle)
+{
+ struct smbios_type0 *t = (struct smbios_type0 *)*current;
+ int len = sizeof(struct smbios_type0);
+
+ memset(t, 0, sizeof(struct smbios_type0));
+ t->type = SMBIOS_BIOS_INFORMATION;
+ t->handle = handle;
+ t->length = len - 2;
+
+ t->vendor = smbios_add_string(t->eos, "coreboot");
+#if !CONFIG_CHROMEOS
+ t->bios_release_date = smbios_add_string(t->eos, coreboot_dmi_date);
+
+ t->bios_version = smbios_add_string(t->eos, smbios_mainboard_bios_version());
+#else
+#define SPACES \
+ " "
+ t->bios_release_date = smbios_add_string(t->eos, coreboot_dmi_date);
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+ u32 version_offset = (u32)smbios_string_table_len(t->eos);
+#endif
+ t->bios_version = smbios_add_string(t->eos, SPACES);
+
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+ /* SMBIOS offsets start at 1 rather than 0 */
+ vboot_data->vbt10 = (u32)t->eos + (version_offset - 1);
+#endif
+#endif /* CONFIG_CHROMEOS */
+
+ t->bios_rom_size = (CONFIG_ROM_SIZE / 65535) - 1;
+
+ t->system_bios_major_release = 4;
+ t->bios_characteristics =
+ BIOS_CHARACTERISTICS_PCI_SUPPORTED |
+#if CONFIG_CARDBUS_PLUGIN_SUPPORT
+ BIOS_CHARACTERISTICS_PC_CARD |
+#endif
+ BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
+ BIOS_CHARACTERISTICS_UPGRADEABLE;
+
+#if CONFIG_HAVE_ACPI_TABLES
+ t->bios_characteristics_ext1 = BIOS_EXT1_CHARACTERISTICS_ACPI;
+#endif
+ t->bios_characteristics_ext2 = BIOS_EXT2_CHARACTERISTICS_TARGET;
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ return len;
+}
+
+#if !CONFIG_SMBIOS_PROVIDED_BY_MOBO
+
+const char *__attribute__((weak)) smbios_mainboard_serial_number(void)
+{
+ return CONFIG_MAINBOARD_SERIAL_NUMBER;
+}
+
+const char *__attribute__((weak)) smbios_mainboard_version(void)
+{
+ return CONFIG_MAINBOARD_VERSION;
+}
+
+const char *__attribute__((weak)) smbios_mainboard_manufacturer(void)
+{
+ return CONFIG_MAINBOARD_SMBIOS_MANUFACTURER;
+}
+
+const char *__attribute__((weak)) smbios_mainboard_product_name(void)
+{
+ return CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME;
+}
+
+void __attribute__((weak)) smbios_mainboard_set_uuid(u8 *uuid)
+{
+ /* leave all zero */
+}
+#endif
+
+#ifdef CONFIG_MAINBOARD_FAMILY
+const char *smbios_mainboard_family(void)
+{
+ return CONFIG_MAINBOARD_FAMILY;
+}
+#endif /* CONFIG_MAINBOARD_FAMILY */
+
+static int smbios_write_type1(unsigned long *current, int handle)
+{
+ struct smbios_type1 *t = (struct smbios_type1 *)*current;
+ int len = sizeof(struct smbios_type1);
+
+ memset(t, 0, sizeof(struct smbios_type1));
+ t->type = SMBIOS_SYSTEM_INFORMATION;
+ t->handle = handle;
+ t->length = len - 2;
+ t->manufacturer = smbios_add_string(t->eos, smbios_mainboard_manufacturer());
+ t->product_name = smbios_add_string(t->eos, smbios_mainboard_product_name());
+ t->serial_number = smbios_add_string(t->eos, smbios_mainboard_serial_number());
+ t->version = smbios_add_string(t->eos, smbios_mainboard_version());
+#ifdef CONFIG_MAINBOARD_FAMILY
+ t->family = smbios_add_string(t->eos, smbios_mainboard_family());
+#endif
+ smbios_mainboard_set_uuid(t->uuid);
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ return len;
+}
+
+static int smbios_write_type2(unsigned long *current, int handle)
+{
+ struct smbios_type2 *t = (struct smbios_type2 *)*current;
+ int len = sizeof(struct smbios_type2);
+
+ memset(t, 0, sizeof(struct smbios_type2));
+ t->type = SMBIOS_BOARD_INFORMATION;
+ t->handle = handle;
+ t->length = len - 2;
+ t->manufacturer = smbios_add_string(t->eos, smbios_mainboard_manufacturer());
+ t->product_name = smbios_add_string(t->eos, smbios_mainboard_product_name());
+ t->serial_number = smbios_add_string(t->eos, smbios_mainboard_serial_number());
+ t->version = smbios_add_string(t->eos, smbios_mainboard_version());
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ return len;
+}
+
+static int smbios_write_type3(unsigned long *current, int handle)
+{
+ struct smbios_type3 *t = (struct smbios_type3 *)*current;
+ int len = sizeof(struct smbios_type3);
+
+ memset(t, 0, sizeof(struct smbios_type3));
+ t->type = SMBIOS_SYSTEM_ENCLOSURE;
+ t->handle = handle;
+ t->length = len - 2;
+ t->manufacturer = smbios_add_string(t->eos, smbios_mainboard_manufacturer());
+ t->bootup_state = SMBIOS_STATE_SAFE;
+ t->power_supply_state = SMBIOS_STATE_SAFE;
+ t->thermal_state = SMBIOS_STATE_SAFE;
+ if(IS_ENABLED(CONFIG_SYSTEM_TYPE_LAPTOP)) {
+ t->_type = SMBIOS_ENCLOSURE_NOTEBOOK;
+ } else {
+ t->_type = SMBIOS_ENCLOSURE_DESKTOP;
+ }
+ t->security_status = SMBIOS_STATE_SAFE;
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ return len;
+}
+
+static int smbios_write_type4(unsigned long *current, int handle)
+{
+ struct cpuid_result res;
+ struct smbios_type4 *t = (struct smbios_type4 *)*current;
+ int len = sizeof(struct smbios_type4);
+
+ /* Provide sane defaults even for CPU without CPUID */
+ res.eax = res.edx = 0;
+ res.ebx = 0x10000;
+
+ if (cpu_have_cpuid()) {
+ res = cpuid(1);
+ }
+
+ memset(t, 0, sizeof(struct smbios_type4));
+ t->type = SMBIOS_PROCESSOR_INFORMATION;
+ t->handle = handle;
+ t->length = len - 2;
+ t->processor_id[0] = res.eax;
+ t->processor_id[1] = res.edx;
+ t->processor_manufacturer = smbios_cpu_vendor(t->eos);
+ t->processor_version = smbios_processor_name(t->eos);
+ t->processor_family = (res.eax > 0) ? 0x0c : 0x6;
+ t->processor_type = 3; /* System Processor */
+ t->processor_upgrade = 0x06;
+ t->core_count = (res.ebx >> 16) & 0xff;
+ t->l1_cache_handle = 0xffff;
+ t->l2_cache_handle = 0xffff;
+ t->l3_cache_handle = 0xffff;
+ t->processor_upgrade = 1;
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ return len;
+}
+
+static int smbios_write_type11(unsigned long *current, int *handle)
+{
+ struct smbios_type11 *t = (struct smbios_type11 *)*current;
+ int len;
+ struct device *dev;
+
+ memset(t, 0, sizeof *t);
+ t->type = SMBIOS_OEM_STRINGS;
+ t->handle = *handle;
+ t->length = len = sizeof *t - 2;
+
+ for(dev = all_devices; dev; dev = dev->next) {
+ if (dev->ops && dev->ops->get_smbios_strings)
+ dev->ops->get_smbios_strings(dev, t);
+ }
+
+ if (t->count == 0) {
+ memset(t, 0, sizeof *t);
+ return 0;
+ }
+
+ len += smbios_string_table_len(t->eos);
+
+ *current += len;
+ (*handle)++;
+ return len;
+}
+
+static int smbios_write_type17(unsigned long *current, int *handle)
+{
+ int len = sizeof(struct smbios_type17);
+ int i;
+
+ struct memory_info *meminfo;
+ meminfo = cbmem_find(CBMEM_ID_MEMINFO);
+ if (meminfo == NULL)
+ return 0; /* can't find mem info in cbmem */
+
+ printk(BIOS_INFO, "Create SMBIOS type 17\n");
+ for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
+ struct dimm_info *dimm;
+ dimm = &meminfo->dimm[i];
+ len = create_smbios_type17_for_dimm(dimm, current, handle);
+ *current += len;
+ }
+ return meminfo->dimm_cnt * len;
+}
+
+static int smbios_write_type32(unsigned long *current, int handle)
+{
+ struct smbios_type32 *t = (struct smbios_type32 *)*current;
+ int len = sizeof(struct smbios_type32);
+
+ memset(t, 0, sizeof(struct smbios_type32));
+ t->type = SMBIOS_SYSTEM_BOOT_INFORMATION;
+ t->handle = handle;
+ t->length = len - 2;
+ *current += len;
+ return len;
+}
+
+int smbios_write_type41(unsigned long *current, int *handle,
+ const char *name, u8 instance, u16 segment,
+ u8 bus, u8 device, u8 function)
+{
+ struct smbios_type41 *t = (struct smbios_type41 *)*current;
+ int len = sizeof(struct smbios_type41);
+
+ memset(t, 0, sizeof(struct smbios_type41));
+ t->type = SMBIOS_ONBOARD_DEVICES_EXTENDED_INFORMATION;
+ t->handle = *handle;
+ t->length = len - 2;
+ t->reference_designation = smbios_add_string(t->eos, name);
+ t->device_type = SMBIOS_DEVICE_TYPE_OTHER;
+ t->device_status = 1;
+ t->device_type_instance = instance;
+ t->segment_group_number = segment;
+ t->bus_number = bus;
+ t->device_number = device;
+ t->function_number = function;
+
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ *handle += 1;
+ return len;
+}
+
+static int smbios_write_type127(unsigned long *current, int handle)
+{
+ struct smbios_type127 *t = (struct smbios_type127 *)*current;
+ int len = sizeof(struct smbios_type127);
+
+ memset(t, 0, sizeof(struct smbios_type127));
+ t->type = SMBIOS_END_OF_TABLE;
+ t->handle = handle;
+ t->length = len - 2;
+ *current += len;
+ return len;
+}
+
+static int smbios_walk_device_tree(struct device *tree, int *handle, unsigned long *current)
+{
+ struct device *dev;
+ int len = 0;
+
+ for(dev = tree; dev; dev = dev->next) {
+ printk(BIOS_INFO, "%s (%s)\n", dev_path(dev), dev_name(dev));
+
+ if (dev->ops && dev->ops->get_smbios_data)
+ len += dev->ops->get_smbios_data(dev, handle, current);
+ }
+ return len;
+}
+
+#define update_max(len, max_len, stmt) do { int tmp = stmt; max_len = MAX(max_len, tmp); len += tmp; } while(0)
+unsigned long smbios_write_tables(unsigned long current)
+{
+ struct smbios_entry *se;
+ unsigned long tables;
+ int len = 0;
+ int max_struct_size = 0;
+ int handle = 0;
+
+ current = ALIGN(current, 16);
+ printk(BIOS_DEBUG, "%s: %08lx\n", __func__, current);
+
+ se = (struct smbios_entry *)current;
+ current += sizeof(struct smbios_entry);
+ current = ALIGN(current, 16);
+
+ tables = current;
+ update_max(len, max_struct_size, smbios_write_type0(¤t, handle++));
+ update_max(len, max_struct_size, smbios_write_type1(¤t, handle++));
+ update_max(len, max_struct_size, smbios_write_type2(¤t, handle++));
+ update_max(len, max_struct_size, smbios_write_type3(¤t, handle++));
+ update_max(len, max_struct_size, smbios_write_type4(¤t, handle++));
+ update_max(len, max_struct_size, smbios_write_type11(¤t, &handle));
+#if CONFIG_ELOG
+ update_max(len, max_struct_size, elog_smbios_write_type15(¤t, handle++));
+#endif
+ update_max(len, max_struct_size, smbios_write_type17(¤t, &handle));
+ update_max(len, max_struct_size, smbios_write_type32(¤t, handle++));
+
+ update_max(len, max_struct_size, smbios_walk_device_tree(all_devices, &handle, ¤t));
+
+ update_max(len, max_struct_size, smbios_write_type127(¤t, handle++));
+
+ memset(se, 0, sizeof(struct smbios_entry));
+ memcpy(se->anchor, "_SM_", 4);
+ se->length = sizeof(struct smbios_entry);
+ se->major_version = 2;
+ se->minor_version = 7;
+ se->max_struct_size = max_struct_size;
+ se->struct_count = handle;
+ memcpy(se->intermediate_anchor_string, "_DMI_", 5);
+
+ se->struct_table_address = (u32)tables;
+ se->struct_table_length = len;
+
+ se->intermediate_checksum = smbios_checksum((u8 *)se + 0x10,
+ sizeof(struct smbios_entry) - 0x10);
+ se->checksum = smbios_checksum((u8 *)se, sizeof(struct smbios_entry));
+ return current;
+}
diff --git a/src/arch/x86/stages.c b/src/arch/x86/stages.c
new file mode 100644
index 0000000..c06abe6
--- /dev/null
+++ b/src/arch/x86/stages.c
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+static void skip_romstage(void)
+{
+ asm volatile (
+ "jmp __main\n"
+ );
+}
diff --git a/src/arch/x86/tables.c b/src/arch/x86/tables.c
new file mode 100644
index 0000000..3d64563
--- /dev/null
+++ b/src/arch/x86/tables.c
@@ -0,0 +1,221 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2003 Eric Biederman
+ * Copyright (C) 2005 Steve Magnani
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <boot/tables.h>
+#include <boot/coreboot_tables.h>
+#include <arch/pirq_routing.h>
+#include <arch/smp/mpspec.h>
+#include <arch/acpi.h>
+#include <string.h>
+#include <cbmem.h>
+#include <smbios.h>
+
+void write_tables(void)
+{
+ unsigned long low_table_start, low_table_end;
+ unsigned long rom_table_start, rom_table_end;
+
+ /* Even if high tables are configured, some tables are copied both to
+ * the low and the high area, so payloads and OSes don't need to know
+ * about the high tables.
+ */
+ unsigned long high_table_pointer;
+
+ rom_table_start = 0xf0000;
+ rom_table_end = 0xf0000;
+
+ /* Start low addr at 0x500, so we don't run into conflicts with the BDA
+ * in case our data structures grow beyond 0x400. Only GDT
+ * and the coreboot table use low_tables.
+ */
+ low_table_start = 0;
+ low_table_end = 0x500;
+
+#if CONFIG_GENERATE_PIRQ_TABLE
+#define MAX_PIRQ_TABLE_SIZE (4 * 1024)
+ post_code(0x9a);
+
+ /* This table must be between 0x0f0000 and 0x100000 */
+ rom_table_end = write_pirq_routing_table(rom_table_end);
+ rom_table_end = ALIGN(rom_table_end, 1024);
+
+ /* And add a high table version for those payloads that
+ * want to live in the F segment
+ */
+ high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_PIRQ, MAX_PIRQ_TABLE_SIZE);
+ if (high_table_pointer) {
+ unsigned long new_high_table_pointer;
+ new_high_table_pointer = write_pirq_routing_table(high_table_pointer);
+ // FIXME make pirq table code intelligent enough to know how
+ // much space it's going to need.
+ if (new_high_table_pointer > (high_table_pointer + MAX_PIRQ_TABLE_SIZE)) {
+ printk(BIOS_ERR, "ERROR: Increase PIRQ size.\n");
+ }
+ printk(BIOS_DEBUG, "PIRQ table: %ld bytes.\n",
+ new_high_table_pointer - high_table_pointer);
+ }
+
+#endif
+
+#if CONFIG_GENERATE_MP_TABLE
+#define MAX_MP_TABLE_SIZE (4 * 1024)
+ post_code(0x9b);
+
+ /* The smp table must be in 0-1K, 639K-640K, or 960K-1M */
+ rom_table_end = write_smp_table(rom_table_end);
+ rom_table_end = ALIGN(rom_table_end, 1024);
+
+ high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_MPTABLE, MAX_MP_TABLE_SIZE);
+ if (high_table_pointer) {
+ unsigned long new_high_table_pointer;
+ new_high_table_pointer = write_smp_table(high_table_pointer);
+ // FIXME make mp table code intelligent enough to know how
+ // much space it's going to need.
+ if (new_high_table_pointer > (high_table_pointer + MAX_MP_TABLE_SIZE)) {
+ printk(BIOS_ERR, "ERROR: Increase MP table size.\n");
+ }
+
+ printk(BIOS_DEBUG, "MP table: %ld bytes.\n",
+ new_high_table_pointer - high_table_pointer);
+ }
+#endif /* CONFIG_GENERATE_MP_TABLE */
+
+#if CONFIG_HAVE_ACPI_TABLES
+#define MAX_ACPI_SIZE (144 * 1024)
+
+ post_code(0x9c);
+
+ /* Write ACPI tables to F segment and high tables area */
+
+ /* Ok, this is a bit hacky still, because some day we want to have this
+ * completely dynamic. But right now we are setting fixed sizes.
+ * It's probably still better than the old high_table_base code because
+ * now at least we know when we have an overflow in the area.
+ *
+ * We want to use 1MB - 64K for Resume backup. We use 512B for TOC and
+ * 512 byte for GDT, 4K for PIRQ and 4K for MP table and 8KB for the
+ * coreboot table. This leaves us with 47KB for all of ACPI. Let's see
+ * how far we get.
+ */
+ high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_ACPI, MAX_ACPI_SIZE);
+ if (high_table_pointer) {
+ unsigned long acpi_start = high_table_pointer;
+ unsigned long new_high_table_pointer;
+
+ rom_table_end = ALIGN(rom_table_end, 16);
+ new_high_table_pointer = write_acpi_tables(high_table_pointer);
+ if (new_high_table_pointer > ( high_table_pointer + MAX_ACPI_SIZE)) {
+ printk(BIOS_ERR, "ERROR: Increase ACPI size\n");
+ }
+ printk(BIOS_DEBUG, "ACPI tables: %ld bytes.\n",
+ new_high_table_pointer - high_table_pointer);
+
+ /* Now we need to create a low table copy of the RSDP. */
+
+ /* First we look for the high table RSDP */
+ while (acpi_start < new_high_table_pointer) {
+ if (memcmp(((acpi_rsdp_t *)acpi_start)->signature, RSDP_SIG, 8) == 0) {
+ break;
+ }
+ acpi_start++;
+ }
+
+ /* Now, if we found the RSDP, we take the RSDT and XSDT pointer
+ * from it in order to write the low RSDP
+ */
+ if (acpi_start < new_high_table_pointer) {
+ acpi_rsdp_t *low_rsdp = (acpi_rsdp_t *)rom_table_end,
+ *high_rsdp = (acpi_rsdp_t *)acpi_start;
+
+ /* Technically rsdp length varies but coreboot always
+ writes longest size available. */
+ memcpy(low_rsdp, high_rsdp, sizeof(acpi_rsdp_t));
+ } else {
+ printk(BIOS_ERR, "ERROR: Didn't find RSDP in high table.\n");
+ }
+ rom_table_end = ALIGN(rom_table_end + sizeof(acpi_rsdp_t), 16);
+ } else {
+ rom_table_end = write_acpi_tables(rom_table_end);
+ rom_table_end = ALIGN(rom_table_end, 1024);
+ }
+
+#endif
+#define MAX_SMBIOS_SIZE 2048
+#if CONFIG_GENERATE_SMBIOS_TABLES
+ high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_SMBIOS, MAX_SMBIOS_SIZE);
+ if (high_table_pointer) {
+ unsigned long new_high_table_pointer;
+
+ new_high_table_pointer = smbios_write_tables(high_table_pointer);
+ rom_table_end = ALIGN(rom_table_end, 16);
+ memcpy((void *)rom_table_end, (void *)high_table_pointer, sizeof(struct smbios_entry));
+ rom_table_end += sizeof(struct smbios_entry);
+
+ if (new_high_table_pointer > ( high_table_pointer + MAX_SMBIOS_SIZE)) {
+ printk(BIOS_ERR, "ERROR: Increase SMBIOS size\n");
+ }
+ printk(BIOS_DEBUG, "SMBIOS tables: %ld bytes.\n",
+ new_high_table_pointer - high_table_pointer);
+ } else {
+ unsigned long new_rom_table_end = smbios_write_tables(rom_table_end);
+ printk(BIOS_DEBUG, "SMBIOS size %ld bytes\n", new_rom_table_end - rom_table_end);
+ rom_table_end = ALIGN(new_rom_table_end, 16);
+ }
+#endif
+
+ post_code(0x9e);
+
+#define MAX_COREBOOT_TABLE_SIZE (32 * 1024)
+ post_code(0x9d);
+
+ high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_CBTABLE, MAX_COREBOOT_TABLE_SIZE);
+
+ if (high_table_pointer) {
+ unsigned long new_high_table_pointer;
+
+ /* FIXME: The high_table_base parameter is not reference when tables are high,
+ * or high_table_pointer >1 MB.
+ */
+ u64 fixme_high_tables_base = 0;
+
+ /* Also put a forwarder entry into 0-4K */
+ new_high_table_pointer = write_coreboot_table(low_table_start, low_table_end,
+ fixme_high_tables_base, high_table_pointer);
+
+ if (new_high_table_pointer > (high_table_pointer +
+ MAX_COREBOOT_TABLE_SIZE))
+ printk(BIOS_ERR, "%s: coreboot table didn't fit (%lx)\n",
+ __func__, new_high_table_pointer -
+ high_table_pointer);
+
+ printk(BIOS_DEBUG, "coreboot table: %ld bytes.\n",
+ new_high_table_pointer - high_table_pointer);
+ } else {
+ /* The coreboot table must be in 0-4K or 960K-1M */
+ write_coreboot_table(low_table_start, low_table_end,
+ rom_table_start, rom_table_end);
+ }
+
+ /* Print CBMEM sections */
+ cbmem_list();
+}
diff --git a/src/arch/x86/thread.c b/src/arch/x86/thread.c
new file mode 100644
index 0000000..f81a2d2
--- /dev/null
+++ b/src/arch/x86/thread.c
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <thread.h>
+
+/* The stack frame looks like the following after a pushad instruction. */
+struct pushad_regs {
+ uint32_t edi; /* Offset 0x00 */
+ uint32_t esi; /* Offset 0x04 */
+ uint32_t ebp; /* Offset 0x08 */
+ uint32_t esp; /* Offset 0x0c */
+ uint32_t ebx; /* Offset 0x10 */
+ uint32_t edx; /* Offset 0x14 */
+ uint32_t ecx; /* Offset 0x18 */
+ uint32_t eax; /* Offset 0x1c */
+};
+
+static inline uintptr_t push_stack(uintptr_t cur_stack, uintptr_t value)
+{
+ uintptr_t *addr;
+
+ cur_stack -= sizeof(value);
+ addr = (uintptr_t *)cur_stack;
+ *addr = value;
+ return cur_stack;
+}
+
+void arch_prepare_thread(struct thread *t,
+ void asmlinkage (*thread_entry)(void *), void *arg)
+{
+ uintptr_t stack = t->stack_current;
+
+ /* Imitate thread_entry(t) with return address of 0. thread_entry()
+ * is assumed to never return. */
+ stack = push_stack(stack, (uintptr_t)arg);
+ stack = push_stack(stack, (uintptr_t)0);
+ stack = push_stack(stack, (uintptr_t)thread_entry);
+ /* Make room for the registers. Ignore intial values. */
+ stack -= sizeof(struct pushad_regs);
+
+ t->stack_current = stack;
+}
+
+void *arch_get_thread_stackbase(void)
+{
+ /* defined in c_start.S */
+ extern u8 thread_stacks[];
+ return &thread_stacks[0];
+}
diff --git a/src/arch/x86/thread_switch.S b/src/arch/x86/thread_switch.S
new file mode 100644
index 0000000..52d4d30
--- /dev/null
+++ b/src/arch/x86/thread_switch.S
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+.code32
+.text
+
+/*
+ * stack layout after pushad:
+ * +------------+
+ * | save stack | <-- esp + 0x28
+ * +------------+
+ * | new stack | <-- esp + 0x24
+ * +------------+
+ * | ret addr | <-- esp + 0x20
+ * +------------+
+ * | eax | <-- esp + 0x1c
+ * +------------+
+ * | ecx | <-- esp + 0x18
+ * +------------+
+ * | edx | <-- esp + 0x14
+ * +------------+
+ * | ebx | <-- esp + 0x10
+ * +------------+
+ * | orig esp | <-- esp + 0x0c
+ * +------------+
+ * | ebp | <-- esp + 0x08
+ * +------------+
+ * | esi | <-- esp + 0x04
+ * +------------+
+ * | edi | <-- esp + 0x00
+ * +------------+
+ */
+.globl switch_to_thread
+switch_to_thread:
+ pusha
+ /* Save the current stack */
+ movl 0x28(%esp), %ebx
+ movl %esp, (%ebx)
+ /* Switch to the new stack. */
+ movl 0x24(%esp), %eax
+ movl %eax, %esp
+ popa
+ ret
diff --git a/src/arch/x86/timestamp.c b/src/arch/x86/timestamp.c
new file mode 100644
index 0000000..9df505a
--- /dev/null
+++ b/src/arch/x86/timestamp.c
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <cpu/x86/tsc.h>
+#include <timestamp.h>
+
+uint64_t timestamp_get(void)
+{
+ return rdtscll();
+}
diff --git a/src/arch/x86/wakeup.S b/src/arch/x86/wakeup.S
new file mode 100644
index 0000000..38d6ea4
--- /dev/null
+++ b/src/arch/x86/wakeup.S
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 Rudolf Marek <r.marek at assembler.cz>
+ * Copyright (C) 2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#define WAKEUP_BASE 0x600
+#define RELOCATED(x) (x - __wakeup + WAKEUP_BASE)
+
+/* CR0 bits */
+#define PE (1 << 0)
+
+#ifdef __x86_64__
+ .code64
+#else
+ .code32
+#endif
+
+ .globl __wakeup
+__wakeup:
+ /* First prepare the jmp to the resume vector */
+ mov 0x4(%esp), %eax /* vector */
+ /* last 4 bits of linear addr are taken as offset */
+ andw $0x0f, %ax
+ movw %ax, (__wakeup_offset)
+ mov 0x4(%esp), %eax
+ /* the rest is taken as segment */
+ shr $4, %eax
+ movw %ax, (__wakeup_segment)
+
+ /* Then overwrite coreboot with our backed up memory */
+ cld
+ movl 8(%esp), %esi
+ movl 12(%esp), %edi
+ movl 16(%esp), %ecx
+ shrl $2, %ecx
+ rep movsl
+
+ /* Activate the right segment descriptor real mode. */
+ ljmp $0x28, $RELOCATED(1f)
+1:
+.code16
+ /* 16 bit code from here on... */
+
+ /* Load the segment registers w/ properly configured
+ * segment descriptors. They will retain these
+ * configurations (limits, writability, etc.) once
+ * protected mode is turned off.
+ */
+ mov $0x30, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+
+ /* Turn off protection */
+ movl %cr0, %eax
+ andl $~PE, %eax
+ movl %eax, %cr0
+
+ /* Now really going into real mode */
+ ljmp $0, $RELOCATED(1f)
+1:
+ movw $0x0, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movw %ax, %fs
+ movw %ax, %gs
+
+ /* This is a FAR JMP to the OS waking vector. The C code changed
+ * the address to be correct.
+ */
+ .byte 0xea
+
+__wakeup_offset = RELOCATED(.)
+ .word 0x0000
+
+__wakeup_segment = RELOCATED(.)
+ .word 0x0000
+
+ .globl __wakeup_size
+__wakeup_size:
+ .long . - __wakeup
diff --git a/src/arch/x86/walkcbfs.S b/src/arch/x86/walkcbfs.S
new file mode 100644
index 0000000..60eb8b5
--- /dev/null
+++ b/src/arch/x86/walkcbfs.S
@@ -0,0 +1,117 @@
+#define CBFS_HEADER_PTR 0xfffffffc
+
+#define CBFS_HEADER_MAGIC 0
+#define CBFS_HEADER_VERSION (CBFS_HEADER_MAGIC + 4)
+#define CBFS_HEADER_ROMSIZE (CBFS_HEADER_VERSION + 4)
+#define CBFS_HEADER_BOOTBLOCKSIZE (CBFS_HEADER_ROMSIZE + 4)
+#define CBFS_HEADER_ALIGN (CBFS_HEADER_BOOTBLOCKSIZE + 4)
+#define CBFS_HEADER_OFFSET (CBFS_HEADER_ALIGN + 4)
+
+#define CBFS_FILE_MAGIC 0
+#define CBFS_FILE_LEN (CBFS_FILE_MAGIC + 8)
+#define CBFS_FILE_TYPE (CBFS_FILE_LEN + 4)
+#define CBFS_FILE_CHECKSUM (CBFS_FILE_TYPE + 4)
+#define CBFS_FILE_OFFSET (CBFS_FILE_CHECKSUM + 4)
+
+#define CBFS_FILE_STRUCTSIZE (CBFS_FILE_OFFSET + 4)
+
+/*
+ * input %esi: filename
+ * input %esp: return address (not pointer to return address!)
+ * output %eax: pointer to CBFS header
+ * clobbers %ebx, %ecx, %edi
+ */
+walkcbfs_asm:
+ cld
+
+ mov CBFS_HEADER_PTR, %eax
+ mov CBFS_HEADER_ROMSIZE(%eax), %ecx
+ bswap %ecx
+ mov $0, %ebx
+ sub %ecx, %ebx /* rom base address in ebx */
+ mov CBFS_HEADER_OFFSET(%eax), %ecx
+ bswap %ecx
+ add %ecx, %ebx /* address where we start looking for LARCHIVEs */
+
+ /* determine filename length */
+ mov $0, %eax
+1:
+ cmpb $0, (%eax,%esi)
+ jz 2f
+ add $1, %eax
+ jmp 1b
+2:
+ add $1, %eax
+walker:
+ mov 0(%ebx), %edi /* Check for LARCHIVE header */
+ cmp %edi, filemagic
+ jne searchfile
+ mov 4(%ebx), %edi
+ cmp %edi, filemagic+4
+ jne searchfile
+
+ /* LARCHIVE header found */
+ mov %ebx, %edi
+ add $CBFS_FILE_STRUCTSIZE, %edi /* edi = address of first byte after struct cbfs_file */
+ mov %eax, %ecx
+ repe cmpsb
+ /* zero flag set if strings are equal */
+ jnz tryharder
+
+ /* we found it! */
+ mov %ebx, %eax
+ jmp *%esp
+
+tryharder:
+ sub %ebx, %edi
+ sub $CBFS_FILE_STRUCTSIZE, %edi /* edi = # of walked bytes */
+ sub %edi, %esi /* esi = start of filename */
+
+ /* ebx = ecx = (current+offset+len+ALIGN-1) & ~(ALIGN-1) */
+ mov CBFS_FILE_OFFSET(%ebx), %ecx
+ bswap %ecx
+ add %ebx, %ecx
+ mov CBFS_FILE_LEN(%ebx), %edi
+ bswap %edi
+ add %edi, %ecx
+ mov CBFS_HEADER_PTR, %edi
+ mov CBFS_HEADER_ALIGN(%edi), %edi
+ bswap %edi
+ sub $1, %edi
+ add %edi, %ecx
+ not %edi
+ and %edi, %ecx
+
+ /* if oldaddr >= addr, leave */
+ cmp %ebx, %ecx
+ jbe out
+
+ mov %ecx, %ebx
+
+check_for_exit:
+ /* look if we should exit: did we pass into the bootblock already? */
+ mov CBFS_HEADER_PTR, %ecx
+ mov CBFS_HEADER_BOOTBLOCKSIZE(%ecx), %ecx
+ bswap %ecx
+ not %ecx
+ add $1, %ecx
+
+ cmp %ecx, %ebx
+ /* if bootblockstart >= addr (==we're still in the data area) , jump back */
+ jbe walker
+
+out:
+ mov $0, %eax
+ jmp *%esp
+
+
+searchfile:
+ /* if filemagic isn't found, move forward cbfs_header->align bytes */
+ mov CBFS_HEADER_PTR, %edi
+ mov CBFS_HEADER_ALIGN(%edi), %edi
+ bswap %edi
+ add %edi, %ebx
+ jmp check_for_exit
+
+filemagic:
+ .ascii "LARCHIVE"
More information about the coreboot-gerrit
mailing list