summaryrefslogtreecommitdiffstats
path: root/src/mainboard/emulation/qemu-i440fx
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2013-06-07 15:46:23 +0200
committerRonald G. Minnich <rminnich@gmail.com>2013-06-14 18:19:26 +0200
commit00cc7f4355ca1bdd621d4618f24f3336b29463cb (patch)
tree4dbd332fef5a39b55fb95d424e8a5e712ff48ed5 /src/mainboard/emulation/qemu-i440fx
parente49679d5a1e6a6225980a9ae8455fef47e56ab12 (diff)
downloadcoreboot-00cc7f4355ca1bdd621d4618f24f3336b29463cb.tar.gz
coreboot-00cc7f4355ca1bdd621d4618f24f3336b29463cb.tar.bz2
coreboot-00cc7f4355ca1bdd621d4618f24f3336b29463cb.zip
qemu: move i440fx bits
Prepare tree for adding q35 support: Move emulation/qemu-x86 to emulation/qemu-i440fx. Rename some stuff to include 'i440fx'. Change-Id: Ib8c58175c5734cfcda1b22404ef52c09d38f0462 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-on: http://review.coreboot.org/3429 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Diffstat (limited to 'src/mainboard/emulation/qemu-i440fx')
-rw-r--r--src/mainboard/emulation/qemu-i440fx/Kconfig37
-rw-r--r--src/mainboard/emulation/qemu-i440fx/Makefile.inc3
-rw-r--r--src/mainboard/emulation/qemu-i440fx/acpi/cpu-hotplug.asl78
-rw-r--r--src/mainboard/emulation/qemu-i440fx/acpi/dbug.asl26
-rw-r--r--src/mainboard/emulation/qemu-i440fx/acpi/hpet.asl36
-rw-r--r--src/mainboard/emulation/qemu-i440fx/acpi/isa.asl102
-rw-r--r--src/mainboard/emulation/qemu-i440fx/acpi/pci-crs.asl94
-rw-r--r--src/mainboard/emulation/qemu-i440fx/acpi_tables.c189
-rw-r--r--src/mainboard/emulation/qemu-i440fx/cache_as_ram.inc95
-rw-r--r--src/mainboard/emulation/qemu-i440fx/cmos.layout74
-rw-r--r--src/mainboard/emulation/qemu-i440fx/devicetree.cb18
-rw-r--r--src/mainboard/emulation/qemu-i440fx/dsdt.asl347
-rw-r--r--src/mainboard/emulation/qemu-i440fx/fw_cfg.c59
-rw-r--r--src/mainboard/emulation/qemu-i440fx/fw_cfg.h19
-rw-r--r--src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h53
-rw-r--r--src/mainboard/emulation/qemu-i440fx/irq_tables.c35
-rw-r--r--src/mainboard/emulation/qemu-i440fx/mainboard.c65
-rw-r--r--src/mainboard/emulation/qemu-i440fx/memory.c47
-rw-r--r--src/mainboard/emulation/qemu-i440fx/northbridge.c191
-rw-r--r--src/mainboard/emulation/qemu-i440fx/romstage.c61
20 files changed, 1629 insertions, 0 deletions
diff --git a/src/mainboard/emulation/qemu-i440fx/Kconfig b/src/mainboard/emulation/qemu-i440fx/Kconfig
new file mode 100644
index 000000000000..a61050a7554a
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/Kconfig
@@ -0,0 +1,37 @@
+if BOARD_EMULATION_QEMU_X86_I440FX
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+ select ARCH_X86
+ select CPU_QEMU_X86
+ select SOUTHBRIDGE_INTEL_I82371EB
+ select CACHE_AS_RAM
+ select HAVE_OPTION_TABLE
+ select HAVE_PIRQ_TABLE
+ select HAVE_ACPI_TABLES
+ select HAVE_ACPI_RESUME
+ select BOARD_ROMSIZE_KB_256
+ select EARLY_CBMEM_INIT
+
+config MAINBOARD_DIR
+ string
+ default emulation/qemu-i440fx
+
+config MAINBOARD_PART_NUMBER
+ string
+ default "QEMU x86 i440fx/piix4"
+
+config IRQ_SLOT_COUNT
+ int
+ default 6
+
+config DCACHE_RAM_BASE
+ hex
+ default 0xd0000
+
+config DCACHE_RAM_SIZE
+ hex
+ default 0x10000
+
+
+endif # BOARD_EMULATION_QEMU_X86
diff --git a/src/mainboard/emulation/qemu-i440fx/Makefile.inc b/src/mainboard/emulation/qemu-i440fx/Makefile.inc
new file mode 100644
index 000000000000..7423b2b84b42
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/Makefile.inc
@@ -0,0 +1,3 @@
+cpu_incs += $(src)/mainboard/emulation/qemu-i440fx/cache_as_ram.inc
+ramstage-y += northbridge.c
+ramstage-y += fw_cfg.c
diff --git a/src/mainboard/emulation/qemu-i440fx/acpi/cpu-hotplug.asl b/src/mainboard/emulation/qemu-i440fx/acpi/cpu-hotplug.asl
new file mode 100644
index 000000000000..0f3e83b14d9e
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/acpi/cpu-hotplug.asl
@@ -0,0 +1,78 @@
+/****************************************************************
+ * CPU hotplug
+ ****************************************************************/
+
+Scope(\_SB) {
+ /* Objects filled in by run-time generated SSDT */
+ External(NTFY, MethodObj)
+ External(CPON, PkgObj)
+
+ /* Methods called by run-time generated SSDT Processor objects */
+ Method(CPMA, 1, NotSerialized) {
+ // _MAT method - create an madt apic buffer
+ // Arg0 = Processor ID = Local APIC ID
+ // Local0 = CPON flag for this cpu
+ Store(DerefOf(Index(CPON, Arg0)), Local0)
+ // Local1 = Buffer (in madt apic form) to return
+ Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1)
+ // Update the processor id, lapic id, and enable/disable status
+ Store(Arg0, Index(Local1, 2))
+ Store(Arg0, Index(Local1, 3))
+ Store(Local0, Index(Local1, 4))
+ Return (Local1)
+ }
+ Method(CPST, 1, NotSerialized) {
+ // _STA method - return ON status of cpu
+ // Arg0 = Processor ID = Local APIC ID
+ // Local0 = CPON flag for this cpu
+ Store(DerefOf(Index(CPON, Arg0)), Local0)
+ If (Local0) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+ Method(CPEJ, 2, NotSerialized) {
+ // _EJ0 method - eject callback
+ Sleep(200)
+ }
+
+ /* CPU hotplug notify method */
+ OperationRegion(PRST, SystemIO, 0xaf00, 32)
+ Field(PRST, ByteAcc, NoLock, Preserve) {
+ PRS, 256
+ }
+ Method(PRSC, 0) {
+ // Local5 = active cpu bitmap
+ Store(PRS, Local5)
+ // Local2 = last read byte from bitmap
+ Store(Zero, Local2)
+ // Local0 = Processor ID / APIC ID iterator
+ Store(Zero, Local0)
+ While (LLess(Local0, SizeOf(CPON))) {
+ // Local1 = CPON flag for this cpu
+ Store(DerefOf(Index(CPON, Local0)), Local1)
+ If (And(Local0, 0x07)) {
+ // Shift down previously read bitmap byte
+ ShiftRight(Local2, 1, Local2)
+ } Else {
+ // Read next byte from cpu bitmap
+ Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
+ }
+ // Local3 = active state for this cpu
+ Store(And(Local2, 1), Local3)
+
+ If (LNotEqual(Local1, Local3)) {
+ // State change - update CPON with new state
+ Store(Local3, Index(CPON, Local0))
+ // Do CPU notify
+ If (LEqual(Local3, 1)) {
+ NTFY(Local0, 1)
+ } Else {
+ NTFY(Local0, 3)
+ }
+ }
+ Increment(Local0)
+ }
+ }
+}
diff --git a/src/mainboard/emulation/qemu-i440fx/acpi/dbug.asl b/src/mainboard/emulation/qemu-i440fx/acpi/dbug.asl
new file mode 100644
index 000000000000..276321f61787
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/acpi/dbug.asl
@@ -0,0 +1,26 @@
+/****************************************************************
+ * Debugging
+ ****************************************************************/
+
+Scope(\) {
+ /* Debug Output */
+ OperationRegion(DBG, SystemIO, 0x0402, 0x01)
+ Field(DBG, ByteAcc, NoLock, Preserve) {
+ DBGB, 8,
+ }
+
+ /* Debug method - use this method to send output to the QEMU
+ * BIOS debug port. This method handles strings, integers,
+ * and buffers. For example: DBUG("abc") DBUG(0x123) */
+ Method(DBUG, 1) {
+ ToHexString(Arg0, Local0)
+ ToBuffer(Local0, Local0)
+ Subtract(SizeOf(Local0), 1, Local1)
+ Store(Zero, Local2)
+ While (LLess(Local2, Local1)) {
+ Store(DerefOf(Index(Local0, Local2)), DBGB)
+ Increment(Local2)
+ }
+ Store(0x0A, DBGB)
+ }
+}
diff --git a/src/mainboard/emulation/qemu-i440fx/acpi/hpet.asl b/src/mainboard/emulation/qemu-i440fx/acpi/hpet.asl
new file mode 100644
index 000000000000..f33e52795f8d
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/acpi/hpet.asl
@@ -0,0 +1,36 @@
+/****************************************************************
+ * HPET
+ ****************************************************************/
+
+Scope(\_SB) {
+ Device(HPET) {
+ Name(_HID, EISAID("PNP0103"))
+ Name(_UID, 0)
+ OperationRegion(HPTM, SystemMemory, 0xFED00000, 0x400)
+ Field(HPTM, DWordAcc, Lock, Preserve) {
+ VEND, 32,
+ PRD, 32,
+ }
+ Method(_STA, 0, NotSerialized) {
+ Store(VEND, Local0)
+ Store(PRD, Local1)
+ ShiftRight(Local0, 16, Local0)
+ If (LOr(LEqual(Local0, 0), LEqual(Local0, 0xffff))) {
+ Return (0x0)
+ }
+ If (LOr(LEqual(Local1, 0), LGreater(Local1, 100000000))) {
+ Return (0x0)
+ }
+ Return (0x0F)
+ }
+ Name(_CRS, ResourceTemplate() {
+#if 0 /* This makes WinXP BSOD for not yet figured reasons. */
+ IRQNoFlags() {2, 8}
+#endif
+ Memory32Fixed(ReadOnly,
+ 0xFED00000, // Address Base
+ 0x00000400, // Address Length
+ )
+ })
+ }
+}
diff --git a/src/mainboard/emulation/qemu-i440fx/acpi/isa.asl b/src/mainboard/emulation/qemu-i440fx/acpi/isa.asl
new file mode 100644
index 000000000000..23761dbbac88
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/acpi/isa.asl
@@ -0,0 +1,102 @@
+/* Common legacy ISA style devices. */
+Scope(\_SB.PCI0.ISA) {
+
+ Device(RTC) {
+ Name(_HID, EisaId("PNP0B00"))
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x0070, 0x0070, 0x10, 0x02)
+ IRQNoFlags() { 8 }
+ IO(Decode16, 0x0072, 0x0072, 0x02, 0x06)
+ })
+ }
+
+ Device(KBD) {
+ Name(_HID, EisaId("PNP0303"))
+ Method(_STA, 0, NotSerialized) {
+ Return (0x0f)
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x0060, 0x0060, 0x01, 0x01)
+ IO(Decode16, 0x0064, 0x0064, 0x01, 0x01)
+ IRQNoFlags() { 1 }
+ })
+ }
+
+ Device(MOU) {
+ Name(_HID, EisaId("PNP0F13"))
+ Method(_STA, 0, NotSerialized) {
+ Return (0x0f)
+ }
+ Name(_CRS, ResourceTemplate() {
+ IRQNoFlags() { 12 }
+ })
+ }
+
+ Device(FDC0) {
+ Name(_HID, EisaId("PNP0700"))
+ Method(_STA, 0, NotSerialized) {
+ Store(FDEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0F)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
+ IO(Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
+ IRQNoFlags() { 6 }
+ DMA(Compatibility, NotBusMaster, Transfer8) { 2 }
+ })
+ }
+
+ Device(LPT) {
+ Name(_HID, EisaId("PNP0400"))
+ Method(_STA, 0, NotSerialized) {
+ Store(LPEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0F)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x0378, 0x0378, 0x08, 0x08)
+ IRQNoFlags() { 7 }
+ })
+ }
+
+ Device(COM1) {
+ Name(_HID, EisaId("PNP0501"))
+ Name(_UID, 0x01)
+ Method(_STA, 0, NotSerialized) {
+ Store(CAEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0F)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
+ IRQNoFlags() { 4 }
+ })
+ }
+
+ Device(COM2) {
+ Name(_HID, EisaId("PNP0501"))
+ Name(_UID, 0x02)
+ Method(_STA, 0, NotSerialized) {
+ Store(CBEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0F)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
+ IRQNoFlags() { 3 }
+ })
+ }
+}
diff --git a/src/mainboard/emulation/qemu-i440fx/acpi/pci-crs.asl b/src/mainboard/emulation/qemu-i440fx/acpi/pci-crs.asl
new file mode 100644
index 000000000000..63d1fd5dde5d
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/acpi/pci-crs.asl
@@ -0,0 +1,94 @@
+/* PCI CRS (current resources) definition. */
+Scope(\_SB.PCI0) {
+
+ Name(CRES, ResourceTemplate() {
+ WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
+ 0x0000, // Address Space Granularity
+ 0x0000, // Address Range Minimum
+ 0x00FF, // Address Range Maximum
+ 0x0000, // Address Translation Offset
+ 0x0100, // Address Length
+ ,, )
+ IO(Decode16,
+ 0x0CF8, // Address Range Minimum
+ 0x0CF8, // Address Range Maximum
+ 0x01, // Address Alignment
+ 0x08, // Address Length
+ )
+ WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, // Address Space Granularity
+ 0x0000, // Address Range Minimum
+ 0x0CF7, // Address Range Maximum
+ 0x0000, // Address Translation Offset
+ 0x0CF8, // Address Length
+ ,, , TypeStatic)
+ WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, // Address Space Granularity
+ 0x0D00, // Address Range Minimum
+ 0xFFFF, // Address Range Maximum
+ 0x0000, // Address Translation Offset
+ 0xF300, // Address Length
+ ,, , TypeStatic)
+ DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+ 0x00000000, // Address Space Granularity
+ 0x000A0000, // Address Range Minimum
+ 0x000BFFFF, // Address Range Maximum
+ 0x00000000, // Address Translation Offset
+ 0x00020000, // Address Length
+ ,, , AddressRangeMemory, TypeStatic)
+ DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+ 0x00000000, // Address Space Granularity
+ 0xE0000000, // Address Range Minimum
+ 0xFEBFFFFF, // Address Range Maximum
+ 0x00000000, // Address Translation Offset
+ 0x1EC00000, // Address Length
+ ,, PW32, AddressRangeMemory, TypeStatic)
+ })
+
+ Name(CR64, ResourceTemplate() {
+ QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+ 0x00000000, // Address Space Granularity
+ 0x8000000000, // Address Range Minimum
+ 0xFFFFFFFFFF, // Address Range Maximum
+ 0x00000000, // Address Translation Offset
+ 0x8000000000, // Address Length
+ ,, PW64, AddressRangeMemory, TypeStatic)
+ })
+
+ Method(_CRS, 0) {
+#if 0
+ /* Fields provided by dynamically created ssdt */
+ External(P0S, IntObj)
+ External(P0E, IntObj)
+ External(P1V, IntObj)
+ External(P1S, BuffObj)
+ External(P1E, BuffObj)
+ External(P1L, BuffObj)
+
+ /* fixup 32bit pci io window */
+ CreateDWordField(CRES, \_SB.PCI0.PW32._MIN, PS32)
+ CreateDWordField(CRES, \_SB.PCI0.PW32._MAX, PE32)
+ CreateDWordField(CRES, \_SB.PCI0.PW32._LEN, PL32)
+ Store(P0S, PS32)
+ Store(P0E, PE32)
+ Store(Add(Subtract(P0E, P0S), 1), PL32)
+
+ If (LEqual(P1V, Zero)) {
+ Return (CRES)
+ }
+
+ /* fixup 64bit pci io window */
+ CreateQWordField(CR64, \_SB.PCI0.PW64._MIN, PS64)
+ CreateQWordField(CR64, \_SB.PCI0.PW64._MAX, PE64)
+ CreateQWordField(CR64, \_SB.PCI0.PW64._LEN, PL64)
+ Store(P1S, PS64)
+ Store(P1E, PE64)
+ Store(P1L, PL64)
+ /* add window and return result */
+ ConcatenateResTemplate(CRES, CR64, Local0)
+ Return (Local0)
+#else
+ Return (CRES)
+#endif
+ }
+}
diff --git a/src/mainboard/emulation/qemu-i440fx/acpi_tables.c b/src/mainboard/emulation/qemu-i440fx/acpi_tables.c
new file mode 100644
index 000000000000..904fe0fdd222
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/acpi_tables.c
@@ -0,0 +1,189 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <types.h>
+#include <string.h>
+#include <console/console.h>
+#include <arch/acpi.h>
+#include <arch/ioapic.h>
+#include <arch/acpigen.h>
+#include <arch/smp/mpspec.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <cpu/x86/msr.h>
+
+extern const unsigned char AmlCode[];
+#if CONFIG_HAVE_ACPI_SLIC
+unsigned long acpi_create_slic(unsigned long current);
+#endif
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+ /* Local APICs */
+ current = acpi_create_madt_lapics(current);
+
+ /* IOAPIC */
+ current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
+ 2, IO_APIC_ADDR, 0);
+
+ /* INT_SRC_OVR */
+ current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
+ current, 0, 0, 2, 0);
+ current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
+ current, 0, 9, 9, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH);
+
+ return current;
+}
+
+unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id)
+{
+ generate_cpu_entries();
+ return (unsigned long) (acpigen_get_current());
+}
+
+unsigned long acpi_fill_slit(unsigned long current)
+{
+ // Not implemented
+ return current;
+}
+
+unsigned long acpi_fill_srat(unsigned long current)
+{
+ /* No NUMA, no SRAT */
+ return current;
+}
+
+#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_hpet_t *hpet;
+ acpi_madt_t *madt;
+ acpi_mcfg_t *mcfg;
+ acpi_fadt_t *fadt;
+ acpi_facs_t *facs;
+#if CONFIG_HAVE_ACPI_SLIC
+ acpi_header_t *slic;
+#endif
+ acpi_header_t *ssdt;
+ acpi_header_t *dsdt;
+
+ current = start;
+
+ /* Align ACPI tables to 16byte */
+ ALIGN_CURRENT;
+
+ 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);
+ acpi_write_rsdt(rsdt);
+ acpi_write_xsdt(xsdt);
+
+ /*
+ * We explicitly add these tables later on:
+ */
+ printk(BIOS_DEBUG, "ACPI: * HPET\n");
+
+ hpet = (acpi_hpet_t *) current;
+ current += sizeof(acpi_hpet_t);
+ ALIGN_CURRENT;
+ acpi_create_hpet(hpet);
+ acpi_add_table(rsdp, hpet);
+
+ /* If we want to use HPET Timers Linux wants an MADT */
+ printk(BIOS_DEBUG, "ACPI: * MADT\n");
+
+ madt = (acpi_madt_t *) current;
+ acpi_create_madt(madt);
+ current += madt->header.length;
+ ALIGN_CURRENT;
+ acpi_add_table(rsdp, madt);
+
+ printk(BIOS_DEBUG, "ACPI: * MCFG\n");
+ mcfg = (acpi_mcfg_t *) current;
+ acpi_create_mcfg(mcfg);
+ current += mcfg->header.length;
+ ALIGN_CURRENT;
+ acpi_add_table(rsdp, mcfg);
+
+ printk(BIOS_DEBUG, "ACPI: * FACS\n");
+ facs = (acpi_facs_t *) current;
+ current += sizeof(acpi_facs_t);
+ ALIGN_CURRENT;
+ acpi_create_facs(facs);
+
+ dsdt = (acpi_header_t *) current;
+ memcpy(dsdt, &AmlCode, sizeof(acpi_header_t));
+ current += dsdt->length;
+ memcpy(dsdt, &AmlCode, dsdt->length);
+
+ ALIGN_CURRENT;
+
+ /* We patched up the DSDT, so we need to recalculate the checksum */
+ dsdt->checksum = 0;
+ dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length);
+
+ printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt,
+ dsdt->length);
+
+#if CONFIG_HAVE_ACPI_SLIC
+ printk(BIOS_DEBUG, "ACPI: * SLIC\n");
+ slic = (acpi_header_t *)current;
+ current += acpi_create_slic(current);
+ ALIGN_CURRENT;
+ acpi_add_table(rsdp, slic);
+#endif
+
+ 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);
+
+ printk(BIOS_DEBUG, "ACPI: * SSDT\n");
+ ssdt = (acpi_header_t *)current;
+ acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR);
+ current += ssdt->length;
+ acpi_add_table(rsdp, ssdt);
+ ALIGN_CURRENT;
+
+ printk(BIOS_DEBUG, "current = %lx\n", current);
+ printk(BIOS_INFO, "ACPI: done.\n");
+ return current;
+}
diff --git a/src/mainboard/emulation/qemu-i440fx/cache_as_ram.inc b/src/mainboard/emulation/qemu-i440fx/cache_as_ram.inc
new file mode 100644
index 000000000000..11ac91d049f8
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/cache_as_ram.inc
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
+ * Copyright (C) 2007-2008 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <cpu/x86/stack.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/post_code.h>
+#include <cbmem.h>
+
+#define CACHE_AS_RAM_SIZE 0x10000
+#define CACHE_AS_RAM_BASE 0xd0000
+
+#define CPU_PHYSMASK_HI (1 << (CONFIG_CPU_ADDR_BITS - 32) - 1)
+
+ /* Save the BIST result. */
+ movl %eax, %ebp
+
+cache_as_ram:
+ post_code(0x20)
+ /* Clear the cache memory region. This will also fill up the cache */
+ movl $CACHE_AS_RAM_BASE, %esi
+ movl %esi, %edi
+ movl $(CACHE_AS_RAM_SIZE / 4), %ecx
+ // movl $0x23322332, %eax
+ xorl %eax, %eax
+ rep stosl
+
+ post_code(0x21)
+ /* Set up the stack pointer. */
+ movl $(CACHE_AS_RAM_SIZE + CACHE_AS_RAM_BASE - 4), %eax
+ movl %eax, %esp
+
+ /* Restore the BIST result. */
+ movl %ebp, %eax
+ movl %esp, %ebp
+ pushl %eax
+
+before_romstage:
+ post_code(0x29)
+ /* Call romstage.c main function. */
+ call main
+
+ post_code(0x30)
+
+#if CONFIG_HAVE_ACPI_RESUME
+ movl CBMEM_BOOT_MODE, %eax
+ cmpl $0x2, %eax // Resume?
+ jne __acpi_resume_backup_done
+
+ /* copy 1MB - 64K to high tables ram_base to prevent memory corruption
+ * through stage 2. We could keep stuff like stack and heap in high
+ * tables memory completely, but that's a wonderful clean up task for
+ * another day.
+ */
+ cld
+ movl $CONFIG_RAMBASE, %esi
+ movl CBMEM_RESUME_BACKUP, %edi
+ movl $HIGH_MEMORY_SAVE / 4, %ecx
+ rep movsl
+
+__acpi_resume_backup_done:
+#endif
+
+ post_code(0x3d)
+
+__main:
+ post_code(POST_PREPARE_RAMSTAGE)
+ cld /* Clear direction flag. */
+
+ movl $ROMSTAGE_STACK, %esp
+ movl %esp, %ebp
+ call copy_and_run
+
+.Lhlt:
+ post_code(POST_DEAD_CODE)
+ hlt
+ jmp .Lhlt
+
diff --git a/src/mainboard/emulation/qemu-i440fx/cmos.layout b/src/mainboard/emulation/qemu-i440fx/cmos.layout
new file mode 100644
index 000000000000..c1354a2866fe
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/cmos.layout
@@ -0,0 +1,74 @@
+entries
+
+#start-bit length config config-ID name
+#0 8 r 0 seconds
+#8 8 r 0 alarm_seconds
+#16 8 r 0 minutes
+#24 8 r 0 alarm_minutes
+#32 8 r 0 hours
+#40 8 r 0 alarm_hours
+#48 8 r 0 day_of_week
+#56 8 r 0 day_of_month
+#64 8 r 0 month
+#72 8 r 0 year
+#80 4 r 0 rate_select
+#84 3 r 0 REF_Clock
+#87 1 r 0 UIP
+#88 1 r 0 auto_switch_DST
+#89 1 r 0 24_hour_mode
+#90 1 r 0 binary_values_enable
+#91 1 r 0 square-wave_out_enable
+#92 1 r 0 update_finished_enable
+#93 1 r 0 alarm_interrupt_enable
+#94 1 r 0 periodic_interrupt_enable
+#95 1 r 0 disable_clock_updates
+#96 288 r 0 temporary_filler
+0 384 r 0 reserved_memory
+384 1 e 4 boot_option
+385 1 e 4 last_boot
+386 1 e 1 ECC_memory
+388 4 r 0 reboot_bits
+392 3 e 5 baud_rate
+400 1 e 1 power_on_after_fail
+412 4 e 6 debug_level
+416 4 e 7 boot_first
+420 4 e 7 boot_second
+424 4 e 7 boot_third
+428 4 h 0 boot_index
+432 8 h 0 boot_countdown
+1008 16 h 0 check_sum
+
+enumerations
+
+#ID value text
+1 0 Disable
+1 1 Enable
+2 0 Enable
+2 1 Disable
+4 0 Fallback
+4 1 Normal
+5 0 115200
+5 1 57600
+5 2 38400
+5 3 19200
+5 4 9600
+5 5 4800
+5 6 2400
+5 7 1200
+6 6 Notice
+6 7 Info
+6 8 Debug
+6 9 Spew
+7 0 Network
+7 1 HDD
+7 2 Floppy
+7 8 Fallback_Network
+7 9 Fallback_HDD
+7 10 Fallback_Floppy
+#7 3 ROM
+
+checksums
+
+checksum 392 1007 1008
+
+
diff --git a/src/mainboard/emulation/qemu-i440fx/devicetree.cb b/src/mainboard/emulation/qemu-i440fx/devicetree.cb
new file mode 100644
index 000000000000..a4fcef1fd91e
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/devicetree.cb
@@ -0,0 +1,18 @@
+chip mainboard/emulation/qemu-i440fx
+ device cpu_cluster 0 on
+ chip cpu/qemu-x86
+ device lapic 0 on end
+ end
+ end
+ device domain 0 on
+ device pci 0.0 on end # northbridge (i440fx)
+ chip southbridge/intel/i82371eb # southbridge
+ device pci 01.0 on end # ISA bridge
+ device pci 01.1 on end # IDE
+ device pci 01.3 on end # ACPI
+ register "ide0_enable" = "1"
+ register "ide1_enable" = "1"
+ register "gpo" = "0x7fffbbff"
+ end
+ end
+end
diff --git a/src/mainboard/emulation/qemu-i440fx/dsdt.asl b/src/mainboard/emulation/qemu-i440fx/dsdt.asl
new file mode 100644
index 000000000000..e63d10fb42fd
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/dsdt.asl
@@ -0,0 +1,347 @@
+/*
+ * Bochs/QEMU ACPI DSDT ASL definition
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+DefinitionBlock (
+ "dsdt.aml", // Output Filename
+ "DSDT", // Signature
+ 0x01, // DSDT Compliance Revision
+ "CORE", // OEMID
+ "COREBOOT", // TABLE ID
+ 0x1 // OEM Revision
+ )
+{
+
+#include "acpi/dbug.asl"
+
+
+/****************************************************************
+ * PCI Bus definition
+ ****************************************************************/
+
+ Scope(\_SB) {
+ Device(PCI0) {
+ Name(_HID, EisaId("PNP0A03"))
+ Name(_ADR, 0x00)
+ Name(_UID, 1)
+ }
+ }
+
+#include "acpi/pci-crs.asl"
+#include "acpi/hpet.asl"
+
+
+/****************************************************************
+ * VGA
+ ****************************************************************/
+
+ Scope(\_SB.PCI0) {
+ Device(VGA) {
+ Name(_ADR, 0x00020000)
+ OperationRegion(PCIC, PCI_Config, Zero, 0x4)
+ Field(PCIC, DWordAcc, NoLock, Preserve) {
+ VEND, 32
+ }
+ Method(_S1D, 0, NotSerialized) {
+ Return (0x00)
+ }
+ Method(_S2D, 0, NotSerialized) {
+ Return (0x00)
+ }
+ Method(_S3D, 0, NotSerialized) {
+ If (LEqual(VEND, 0x1001b36)) {
+ Return (0x03) // QXL
+ } Else {
+ Return (0x00)
+ }
+ }
+ }
+ }
+
+
+/****************************************************************
+ * PIIX4 PM
+ ****************************************************************/
+
+ Scope(\_SB.PCI0) {
+ Device(PX13) {
+ Name(_ADR, 0x00010003)
+ OperationRegion(P13C, PCI_Config, 0x00, 0xff)
+ }
+ }
+
+
+/****************************************************************
+ * PIIX3 ISA bridge
+ ****************************************************************/
+
+ Scope(\_SB.PCI0) {
+ Device(ISA) {
+ Name(_ADR, 0x00010000)
+
+ /* PIIX PCI to ISA irq remapping */
+ OperationRegion(P40C, PCI_Config, 0x60, 0x04)
+
+ /* enable bits */
+ Field(\_SB.PCI0.PX13.P13C, AnyAcc, NoLock, Preserve) {
+ Offset(0x5f),
+ , 7,
+ LPEN, 1, // LPT
+ Offset(0x67),
+ , 3,
+ CAEN, 1, // COM1
+ , 3,
+ CBEN, 1, // COM2
+ }
+ Name(FDEN, 1)
+ }
+ }
+
+#include "acpi/isa.asl"
+
+
+/****************************************************************
+ * PCI hotplug
+ ****************************************************************/
+
+ Scope(\_SB.PCI0) {
+ OperationRegion(PCST, SystemIO, 0xae00, 0x08)
+ Field(PCST, DWordAcc, NoLock, WriteAsZeros) {
+ PCIU, 32,
+ PCID, 32,
+ }
+
+ OperationRegion(SEJ, SystemIO, 0xae08, 0x04)
+ Field(SEJ, DWordAcc, NoLock, WriteAsZeros) {
+ B0EJ, 32,
+ }
+
+ /* Methods called by bulk generated PCI devices below */
+
+ /* Methods called by hotplug devices */
+ Method(PCEJ, 1, NotSerialized) {
+ // _EJ0 method - eject callback
+ Store(ShiftLeft(1, Arg0), B0EJ)
+ Return (0x0)
+ }
+
+ /* Hotplug notification method supplied by SSDT */
+ External(\_SB.PCI0.PCNT, MethodObj)
+
+ /* PCI hotplug notify method */
+ Method(PCNF, 0) {
+ // Local0 = iterator
+ Store(Zero, Local0)
+ While (LLess(Local0, 31)) {
+ Increment(Local0)
+ If (And(PCIU, ShiftLeft(1, Local0))) {
+ PCNT(Local0, 1)
+ }
+ If (And(PCID, ShiftLeft(1, Local0))) {
+ PCNT(Local0, 3)
+ }
+ }
+ }
+ }
+
+
+/****************************************************************
+ * PCI IRQs
+ ****************************************************************/
+
+ Scope(\_SB) {
+ Scope(PCI0) {
+ Name(_PRT, Package() {
+ /* PCI IRQ routing table, example from ACPI 2.0a specification,
+ section 6.2.8.1 */
+ /* Note: we provide the same info as the PCI routing
+ table of the Bochs BIOS */
+
+#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \
+ Package() { nr##ffff, 0, lnk0, 0 }, \
+ Package() { nr##ffff, 1, lnk1, 0 }, \
+ Package() { nr##ffff, 2, lnk2, 0 }, \
+ Package() { nr##ffff, 3, lnk3, 0 }
+
+#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC)
+#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD)
+#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA)
+#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB)
+
+ prt_slot0(0x0000),
+ /* Device 1 is power mgmt device, and can only use irq 9 */
+ prt_slot(0x0001, LNKS, LNKB, LNKC, LNKD),
+ prt_slot2(0x0002),
+ prt_slot3(0x0003),
+ prt_slot0(0x0004),
+ prt_slot1(0x0005),
+ prt_slot2(0x0006),
+ prt_slot3(0x0007),
+ prt_slot0(0x0008),
+ prt_slot1(0x0009),
+ prt_slot2(0x000a),
+ prt_slot3(0x000b),
+ prt_slot0(0x000c),
+ prt_slot1(0x000d),
+ prt_slot2(0x000e),
+ prt_slot3(0x000f),
+ prt_slot0(0x0010),
+ prt_slot1(0x0011),
+ prt_slot2(0x0012),
+ prt_slot3(0x0013),
+ prt_slot0(0x0014),
+ prt_slot1(0x0015),
+ prt_slot2(0x0016),
+ prt_slot3(0x0017),
+ prt_slot0(0x0018),
+ prt_slot1(0x0019),
+ prt_slot2(0x001a),
+ prt_slot3(0x001b),
+ prt_slot0(0x001c),
+ prt_slot1(0x001d),
+ prt_slot2(0x001e),
+ prt_slot3(0x001f),
+ })
+ }
+
+ Field(PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) {
+ PRQ0, 8,
+ PRQ1, 8,
+ PRQ2, 8,
+ PRQ3, 8
+ }
+
+ Method(IQST, 1, NotSerialized) {
+ // _STA method - get status
+ If (And(0x80, Arg0)) {
+ Return (0x09)
+ }
+ Return (0x0B)
+ }
+ Method(IQCR, 1, NotSerialized) {
+ // _CRS method - get current settings
+ Name(PRR0, ResourceTemplate() {
+ Interrupt(, Level, ActiveHigh, Shared) { 0 }
+ })
+ CreateDWordField(PRR0, 0x05, PRRI)
+ If (LLess(Arg0, 0x80)) {
+ Store(Arg0, PRRI)
+ }
+ Return (PRR0)
+ }
+
+#define define_link(link, uid, reg) \
+ Device(link) { \
+ Name(_HID, EISAID("PNP0C0F")) \
+ Name(_UID, uid) \
+ Name(_PRS, ResourceTemplate() { \
+ Interrupt(, Level, ActiveHigh, Shared) { \
+ 5, 10, 11 \
+ } \
+ }) \
+ Method(_STA, 0, NotSerialized) { \
+ Return (IQST(reg)) \
+ } \
+ Method(_DIS, 0, NotSerialized) { \
+ Or(reg, 0x80, reg) \
+ } \
+ Method(_CRS, 0, NotSerialized) { \
+ Return (IQCR(reg)) \
+ } \
+ Method(_SRS, 1, NotSerialized) { \
+ CreateDWordField(Arg0, 0x05, PRRI) \
+ Store(PRRI, reg) \
+ } \
+ }
+
+ define_link(LNKA, 0, PRQ0)
+ define_link(LNKB, 1, PRQ1)
+ define_link(LNKC, 2, PRQ2)
+ define_link(LNKD, 3, PRQ3)
+
+ Device(LNKS) {
+ Name(_HID, EISAID("PNP0C0F"))
+ Name(_UID, 4)
+ Name(_PRS, ResourceTemplate() {
+ Interrupt(, Level, ActiveHigh, Shared) { 9 }
+ })
+
+ // The SCI cannot be disabled and is always attached to GSI 9,
+ // so these are no-ops. We only need this link to override the
+ // polarity to active high and match the content of the MADT.
+ Method(_STA, 0, NotSerialized) { Return (0x0b) }
+ Method(_DIS, 0, NotSerialized) { }
+ Method(_CRS, 0, NotSerialized) { Return (_PRS) }
+ Method(_SRS, 1, NotSerialized) { }
+ }
+ }
+
+#if 0
+#include "acpi/cpu-hotplug.asl"
+#endif
+
+
+/****************************************************************
+ * General purpose events
+ ****************************************************************/
+
+ Scope(\_GPE) {
+ Name(_HID, "ACPI0006")
+
+ Method(_L00) {
+ }
+ Method(_E01) {
+#if 0
+ // PCI hotplug event
+ \_SB.PCI0.PCNF()
+#endif
+ }
+ Method(_E02) {
+#if 0
+ // CPU hotplug event
+ \_SB.PRSC()
+#endif
+ }
+ Method(_L03) {
+ }
+ Method(_L04) {
+ }
+ Method(_L05) {
+ }
+ Method(_L06) {
+ }
+ Method(_L07) {
+ }
+ Method(_L08) {
+ }
+ Method(_L09) {
+ }
+ Method(_L0A) {
+ }
+ Method(_L0B) {
+ }
+ Method(_L0C) {
+ }
+ Method(_L0D) {
+ }
+ Method(_L0E) {
+ }
+ Method(_L0F) {
+ }
+ }
+}
diff --git a/src/mainboard/emulation/qemu-i440fx/fw_cfg.c b/src/mainboard/emulation/qemu-i440fx/fw_cfg.c
new file mode 100644
index 000000000000..5166f830921a
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/fw_cfg.c
@@ -0,0 +1,59 @@
+/*
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+#include <console/console.h>
+#include <arch/io.h>
+
+#include "fw_cfg.h"
+#include "fw_cfg_if.h"
+
+#define FW_CFG_PORT_CTL 0x0510
+#define FW_CFG_PORT_DATA 0x0511
+
+static unsigned char fw_cfg_detected = 0xff;
+
+static int fw_cfg_present(void)
+{
+ static const char qsig[] = "QEMU";
+ unsigned char sig[4];
+
+ if (fw_cfg_detected == 0xff) {
+ fw_cfg_get(FW_CFG_SIGNATURE, sig, sizeof(sig));
+ fw_cfg_detected = (memcmp(sig, qsig, 4) == 0) ? 1 : 0;
+ printk(BIOS_INFO, "QEMU: firmware config interface %s\n",
+ fw_cfg_detected ? "detected" : "not found");
+ }
+ return fw_cfg_detected;
+}
+
+void fw_cfg_get(int entry, void *dst, int dstlen)
+{
+ outw(entry, FW_CFG_PORT_CTL);
+ insb(FW_CFG_PORT_DATA, dst, dstlen);
+}
+
+int fw_cfg_max_cpus(void)
+{
+ unsigned short max_cpus;
+
+ if (!fw_cfg_present())
+ return -1;
+
+ fw_cfg_get(FW_CFG_MAX_CPUS, &max_cpus, sizeof(max_cpus));
+ return max_cpus;
+}
diff --git a/src/mainboard/emulation/qemu-i440fx/fw_cfg.h b/src/mainboard/emulation/qemu-i440fx/fw_cfg.h
new file mode 100644
index 000000000000..063e48f838ad
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/fw_cfg.h
@@ -0,0 +1,19 @@
+/*
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+void fw_cfg_get(int entry, void *dst, int dstlen);
+int fw_cfg_max_cpus(void);
diff --git a/src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h b/src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h
new file mode 100644
index 000000000000..d159f12d09ec
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h
@@ -0,0 +1,53 @@
+/*
+ * This are the qemu firmware config interface defines and structs.
+ * Copyed over from qemu soure tree, include/hw/nvram/fw_cfg.h
+ */
+
+#define FW_CFG_SIGNATURE 0x00
+#define FW_CFG_ID 0x01
+#define FW_CFG_UUID 0x02
+#define FW_CFG_RAM_SIZE 0x03
+#define FW_CFG_NOGRAPHIC 0x04
+#define FW_CFG_NB_CPUS 0x05
+#define FW_CFG_MACHINE_ID 0x06
+#define FW_CFG_KERNEL_ADDR 0x07
+#define FW_CFG_KERNEL_SIZE 0x08
+#define FW_CFG_KERNEL_CMDLINE 0x09
+#define FW_CFG_INITRD_ADDR 0x0a
+#define FW_CFG_INITRD_SIZE 0x0b
+#define FW_CFG_BOOT_DEVICE 0x0c
+#define FW_CFG_NUMA 0x0d
+#define FW_CFG_BOOT_MENU 0x0e
+#define FW_CFG_MAX_CPUS 0x0f
+#define FW_CFG_KERNEL_ENTRY 0x10
+#define FW_CFG_KERNEL_DATA 0x11
+#define FW_CFG_INITRD_DATA 0x12
+#define FW_CFG_CMDLINE_ADDR 0x13
+#define FW_CFG_CMDLINE_SIZE 0x14
+#define FW_CFG_CMDLINE_DATA 0x15
+#define FW_CFG_SETUP_ADDR 0x16
+#define FW_CFG_SETUP_SIZE 0x17
+#define FW_CFG_SETUP_DATA 0x18
+#define FW_CFG_FILE_DIR 0x19
+
+#define FW_CFG_FILE_FIRST 0x20
+#define FW_CFG_FILE_SLOTS 0x10
+#define FW_CFG_MAX_ENTRY (FW_CFG_FILE_FIRST+FW_CFG_FILE_SLOTS)
+
+#define FW_CFG_WRITE_CHANNEL 0x4000
+#define FW_CFG_ARCH_LOCAL 0x8000
+#define FW_CFG_ENTRY_MASK ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL)
+
+#define FW_CFG_INVALID 0xffff
+
+typedef struct FWCfgFile {
+ uint32_t size; /* file size */
+ uint16_t select; /* write this to 0x510 to read it */
+ uint16_t reserved;
+ char name[56];
+} FWCfgFile;
+
+typedef struct FWCfgFiles {
+ uint32_t count;
+ FWCfgFile f[];
+} FWCfgFiles;
diff --git a/src/mainboard/emulation/qemu-i440fx/irq_tables.c b/src/mainboard/emulation/qemu-i440fx/irq_tables.c
new file mode 100644
index 000000000000..21eeabf33114
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/irq_tables.c
@@ -0,0 +1,35 @@
+/* This file was generated by getpir.c, do not modify!
+ (but if you do, please run checkpir on it to verify)
+ * Contains the IRQ Routing Table dumped directly from your memory, which BIOS sets up
+ *
+ * Documentation at : http://www.microsoft.com/hwdev/busbios/PCIIRQ.HTM
+*/
+
+#include <arch/pirq_routing.h>
+
+static const struct irq_routing_table intel_irq_routing_table = {
+ PIRQ_SIGNATURE, /* u32 signature */
+ PIRQ_VERSION, /* u16 version */
+ 32+16*CONFIG_IRQ_SLOT_COUNT, /* there can be total CONFIG_IRQ_SLOT_COUNT devices on the bus */
+ 0x00, /* Where the interrupt router lies (bus) */
+ (0x01<<3)|0x0, /* Where the interrupt router lies (dev) */
+ 0, /* IRQs devoted exclusively to PCI usage */
+ 0x8086, /* Vendor */
+ 0x7000, /* Device */
+ 0, /* Miniport data */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
+ 0x7, /* u8 checksum , this hase to set to some value that would give 0 after the sum of all bytes for this structure (including checksum) */
+ {
+ /* bus, dev|fn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */
+ {0x00,(0x01<<3)|0x0, {{0x60, 0xdef8}, {0x61, 0xdef8}, {0x62, 0xdef8}, {0x63, 0x0def8}}, 0x0, 0x0},
+ {0x00,(0x02<<3)|0x0, {{0x61, 0xdef8}, {0x62, 0xdef8}, {0x63, 0xdef8}, {0x60, 0x0def8}}, 0x1, 0x0},
+ {0x00,(0x03<<3)|0x0, {{0x62, 0xdef8}, {0x63, 0xdef8}, {0x60, 0xdef8}, {0x61, 0x0def8}}, 0x2, 0x0},
+ {0x00,(0x04<<3)|0x0, {{0x63, 0xdef8}, {0x60, 0xdef8}, {0x61, 0xdef8}, {0x62, 0x0def8}}, 0x3, 0x0},
+ {0x00,(0x05<<3)|0x0, {{0x60, 0xdef8}, {0x61, 0xdef8}, {0x62, 0xdef8}, {0x63, 0x0def8}}, 0x4, 0x0},
+ {0x00,(0x06<<3)|0x0, {{0x61, 0xdef8}, {0x62, 0xdef8}, {0x63, 0xdef8}, {0x60, 0x0def8}}, 0x5, 0x0},
+ }
+};
+unsigned long write_pirq_routing_table(unsigned long addr)
+{
+ return copy_pirq_routing_table(addr, &intel_irq_routing_table);
+}
diff --git a/src/mainboard/emulation/qemu-i440fx/mainboard.c b/src/mainboard/emulation/qemu-i440fx/mainboard.c
new file mode 100644
index 000000000000..f651b9909414
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/mainboard.c
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2004 Stefan Reinauer <stefan.reinauer@coreboot.org>
+ * Copyright (C) 2010 Kevin O'Connor <kevin@koconnor.net>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <pc80/keyboard.h>
+#include <arch/io.h>
+
+static const unsigned char qemu_i440fx_irqs[] = {
+ 11, 10, 10, 11,
+ 11, 10, 10, 11,
+};
+
+static void qemu_nb_init(device_t dev)
+{
+ /* Map memory at 0xc0000 - 0xfffff */
+ int i;
+ uint8_t v = pci_read_config8(dev, 0x59);
+ v |= 0x30;
+ pci_write_config8(dev, 0x59, v);
+ for (i=0; i<6; i++)
+ pci_write_config8(dev, 0x5a + i, 0x33);
+
+ /* This sneaked in here, because Qemu does not
+ * emulate a SuperIO chip
+ */
+ pc_keyboard_init(0);
+
+ /* setup IRQ routing */
+ for (i = 0; i < 32; i++)
+ pci_assign_irqs(0, i, qemu_i440fx_irqs + (i % 4));
+}
+
+static struct device_operations nb_operations = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = qemu_nb_init,
+ .ops_pci = 0,
+};
+
+static const struct pci_driver nb_driver __pci_driver = {
+ .ops = &nb_operations,
+ .vendor = 0x8086,
+ .device = 0x1237,
+};
diff --git a/src/mainboard/emulation/qemu-i440fx/memory.c b/src/mainboard/emulation/qemu-i440fx/memory.c
new file mode 100644
index 000000000000..322fc492ec34
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/memory.c
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2004 Stefan Reinauer <stefan.reinauer@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; 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <cbmem.h>
+
+#define CMOS_ADDR_PORT 0x70
+#define CMOS_DATA_PORT 0x71
+#define HIGH_RAM_ADDR 0x35
+#define LOW_RAM_ADDR 0x34
+
+static unsigned long qemu_get_memory_size(void)
+{
+ unsigned long tomk;
+ outb (HIGH_RAM_ADDR, CMOS_ADDR_PORT);
+ tomk = ((unsigned long) inb(CMOS_DATA_PORT)) << 14;
+ outb (LOW_RAM_ADDR, CMOS_ADDR_PORT);
+ tomk |= ((unsigned long) inb(CMOS_DATA_PORT)) << 6;
+ tomk += 16 * 1024;
+ return tomk;
+}
+
+unsigned long get_top_of_ram(void);
+unsigned long get_top_of_ram(void)
+{
+ return qemu_get_memory_size() * 1024;
+}
+
+struct cbmem_entry *get_cbmem_toc(void)
+{
+ return (struct cbmem_entry *)(get_top_of_ram() - HIGH_MEMORY_SIZE);
+}
diff --git a/src/mainboard/emulation/qemu-i440fx/northbridge.c b/src/mainboard/emulation/qemu-i440fx/northbridge.c
new file mode 100644
index 000000000000..c2e4ba22b3ff
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/northbridge.c
@@ -0,0 +1,191 @@
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/lapic_def.h>
+#include <arch/io.h>
+#include <arch/ioapic.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <stdlib.h>
+#include <string.h>
+#include <delay.h>
+#include <smbios.h>
+#include <cbmem.h>
+
+#include "fw_cfg.h"
+
+#include "memory.c"
+
+static void cpu_pci_domain_set_resources(device_t dev)
+{
+ u32 pci_tolm = find_pci_tolm(dev->link_list);
+ unsigned long tomk = 0, tolmk;
+ int idx;
+
+ tomk = qemu_get_memory_size();
+ printk(BIOS_DEBUG, "Detected %lu Kbytes (%lu MiB) RAM.\n",
+ tomk, tomk / 1024);
+
+ /* Compute the top of Low memory */
+ tolmk = pci_tolm >> 10;
+ if (tolmk >= tomk) {
+ /* The PCI hole does not overlap the memory. */
+ tolmk = tomk;
+ }
+
+ /* Report the memory regions. */
+ idx = 10;
+ ram_resource(dev, idx++, 0, 640);
+ ram_resource(dev, idx++, 768, tolmk - 768);
+
+ /* Leave some space for ACPI, PIRQ and MP tables */
+ high_tables_base = (tomk * 1024) - HIGH_MEMORY_SIZE;
+ high_tables_size = HIGH_MEMORY_SIZE;
+
+ assign_resources(dev->link_list);
+}
+
+static void cpu_pci_domain_read_resources(struct device *dev)
+{
+ struct resource *res;
+
+ pci_domain_read_resources(dev);
+
+ /* Reserve space for the IOAPIC. This should be in the Southbridge,
+ * but I couldn't tell which device to put it in. */
+ res = new_resource(dev, 2);
+ res->base = IO_APIC_ADDR;
+ res->size = 0x100000UL;
+ res->limit = 0xffffffffUL;
+ res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
+ IORESOURCE_ASSIGNED;
+
+ /* Reserve space for the LAPIC. There's one in every processor, but
+ * the space only needs to be reserved once, so we do it here. */
+ res = new_resource(dev, 3);
+ res->base = LOCAL_APIC_ADDR;
+ res->size = 0x10000UL;
+ res->limit = 0xffffffffUL;
+ res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
+ IORESOURCE_ASSIGNED;
+}
+
+#if CONFIG_GENERATE_SMBIOS_TABLES
+static int qemu_get_smbios_data16(int handle, unsigned long *current)
+{
+ struct smbios_type16 *t = (struct smbios_type16 *)*current;
+ int len = sizeof(struct smbios_type16);
+
+ memset(t, 0, sizeof(struct smbios_type16));
+ t->type = SMBIOS_PHYS_MEMORY_ARRAY;
+ t->handle = handle;
+ t->length = len - 2;
+ t->location = 3; /* Location: System Board */
+ t->use = 3; /* System memory */
+ t->memory_error_correction = 3; /* No error correction */
+ t->maximum_capacity = qemu_get_memory_size();
+ *current += len;
+ return len;
+}
+
+static int qemu_get_smbios_data17(int handle, int parent_handle, unsigned long *current)
+{
+ struct smbios_type17 *t = (struct smbios_type17 *)*current;
+ int len;
+
+ memset(t, 0, sizeof(struct smbios_type17));
+ t->type = SMBIOS_MEMORY_DEVICE;
+ t->handle = handle;
+ t->phys_memory_array_handle = parent_handle;
+ t->length = sizeof(struct smbios_type17) - 2;
+ t->size = qemu_get_memory_size() / 1024;
+ t->data_width = 64;
+ t->total_width = 64;
+ t->form_factor = 9; /* DIMM */
+ t->device_locator = smbios_add_string(t->eos, "Virtual");
+ t->memory_type = 0x12; /* DDR */
+ t->type_detail = 0x80; /* Synchronous */
+ t->speed = 200;
+ t->clock_speed = 200;
+ t->manufacturer = smbios_add_string(t->eos, CONFIG_MAINBOARD_VENDOR);
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ return len;
+}
+
+static int qemu_get_smbios_data(device_t dev, int *handle, unsigned long *current)
+{
+ int len;
+ len = qemu_get_smbios_data16(*handle, current);
+ len += qemu_get_smbios_data17(*handle+1, *handle, current);
+ *handle += 2;
+ return len;
+}
+#endif
+static struct device_operations pci_domain_ops = {
+ .read_resources = cpu_pci_domain_read_resources,
+ .set_resources = cpu_pci_domain_set_resources,
+ .enable_resources = NULL,
+ .init = NULL,
+ .scan_bus = pci_domain_scan_bus,
+#if CONFIG_GENERATE_SMBIOS_TABLES
+ .get_smbios_data = qemu_get_smbios_data,
+#endif
+};
+
+static void cpu_bus_init(device_t dev)
+{
+ initialize_cpus(dev->link_list);
+}
+
+static unsigned int cpu_bus_scan(device_t bus, unsigned int max)
+{
+ int max_cpus = fw_cfg_max_cpus();
+ device_t cpu;
+ int i;
+
+ if (max_cpus < 0)
+ return 0;
+
+ /*
+ * TODO: This only handles the simple "qemu -smp $nr" case
+ * correctly. qemu also allows to specify the number of
+ * cores, threads & sockets.
+ */
+ printk(BIOS_INFO, "QEMU: max_cpus is %d\n", max_cpus);
+ for (i = 0; i < max_cpus; i++) {
+ cpu = add_cpu_device(bus->link_list, i, 1);
+ if (cpu)
+ set_cpu_topology(cpu, 1, 0, i, 0);
+ }
+ return max_cpus;
+}
+
+static void cpu_bus_noop(device_t dev)
+{
+}
+
+static struct device_operations cpu_bus_ops = {
+ .read_resources = cpu_bus_noop,
+ .set_resources = cpu_bus_noop,
+ .enable_resources = cpu_bus_noop,
+ .init = cpu_bus_init,
+ .scan_bus = cpu_bus_scan,
+};
+
+static void northbridge_enable(struct device *dev)
+{
+ /* Set the operations if it is a special bus type */
+ if (dev->path.type == DEVICE_PATH_DOMAIN) {
+ dev->ops = &pci_domain_ops;
+ pci_set_method(dev);
+ }
+ else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
+ dev->ops = &cpu_bus_ops;
+ }
+}
+
+struct chip_operations mainboard_emulation_qemu_i440fx_ops = {
+ CHIP_NAME("QEMU Northbridge i440fx")
+ .enable_dev = northbridge_enable,
+};
diff --git a/src/mainboard/emulation/qemu-i440fx/romstage.c b/src/mainboard/emulation/qemu-i440fx/romstage.c
new file mode 100644
index 000000000000..3faf947e001c
--- /dev/null
+++ b/src/mainboard/emulation/qemu-i440fx/romstage.c
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <arch/io.h>
+#include <device/pnp_def.h>
+#include <arch/hlt.h>
+#include <pc80/mc146818rtc.h>
+#include <console/console.h>
+#include <cpu/x86/bist.h>
+#include <timestamp.h>
+#include "drivers/pc80/udelay_io.c"
+#include "lib/delay.c"
+#include "cpu/x86/lapic/boot_cpu.c"
+
+#include "memory.c"
+
+void main(unsigned long bist)
+{
+ int cbmem_was_initted;
+
+ /* init_timer(); */
+ post_code(0x05);
+
+ console_init();
+
+ /* Halt if there was a built in self test failure */
+ report_bist_failure(bist);
+
+ //print_pci_devices();
+ //dump_pci_devices();
+
+ cbmem_was_initted = !cbmem_initialize();
+#if CONFIG_COLLECT_TIMESTAMPS
+ timestamp_init(rdtsc());
+ timestamp_add_now(TS_START_ROMSTAGE);
+#endif
+#if CONFIG_CONSOLE_CBMEM
+ /* Keep this the last thing this function does. */
+ cbmemc_reinit();
+#endif
+
+}