This patch adds the BIOS support for SMP, ACPI, PCI, SMM, SMBIOS.

Signed-off-by: Nguyen Anh Quynh

Several compile fixes provided by Kevin O'Connor
diff --git a/Makefile b/Makefile
index bb078f4..7b9caed 100644
--- a/Makefile
+++ b/Makefile
@@ -4,13 +4,19 @@
 #
 # This file may be distributed under the terms of the GNU GPLv3 license.
 
+# Don't compile ACPI DSDT by default
+# Uncomment the below line in case you want to compile DSDT yourself.
+# Note: "iasl" package is required to compile.
+#BUILD_ACPI = 1
+BUILD_ACPI = 0
+
 # Output directory
 OUT=out/
 
 # Source files
 SRC16=floppy.c disk.c system.c clock.c serial.c kbd.c mouse.c output.c \
       boot.c ata.c cdrom.c apm.c
-SRC32=post.c output.c
+SRC32=post.c output.c smbios.c acpi.c smm.c smp.c pci.c
 TABLESRC=font.c cbt.c floppy_dbt.c
 
 cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
@@ -28,6 +34,7 @@
 CFLAGS16 = $(CFLAGS16INC) -g
 
 TABLETMP=$(addprefix $(OUT), $(patsubst %.c,%.16.s,$(TABLESRC)))
+
 all: $(OUT) $(OUT)rom.bin $(TABLETMP)
 
 # Run with "make V=1" to see the actual compile commands
@@ -99,7 +106,15 @@
 	@echo "  Extracting binary $@"
 	$(Q)objcopy -O binary $< $@
 
-$(OUT)romlayout32.o: $(OUT)rom16.offset.auto.h ; $(call whole-compile, $(CFLAGS), $(addprefix src/, $(SRC32)),$@)
+$(OUT)romlayout32.o: $(OUT)acpi-dsdt.hex $(OUT)rom16.offset.auto.h ; $(call whole-compile, $(CFLAGS), $(addprefix src/, $(SRC32)),$@)
+
+ifeq ($(BUILD_ACPI), 1)
+$(OUT)acpi-dsdt.hex: src/acpi-dsdt.dsl
+	iasl -tc -p $@ $<
+else
+$(OUT)acpi-dsdt.hex: src/acpi-dsdt.hex
+	cp src/acpi-dsdt.hex $(OUT)
+endif
 
 $(OUT)rom32.o: $(OUT)romlayout32.o $(OUT)rombios32.lds
 	@echo "  Linking $@"
@@ -110,6 +125,7 @@
 	$(Q)./tools/buildrom.py
 
 ####### Generic rules
+.PHONY : clean
 clean:
 	rm -rf $(OUT)
 
diff --git a/src/config.h b/src/config.h
index 199627e..e896ceb 100644
--- a/src/config.h
+++ b/src/config.h
@@ -2,6 +2,14 @@
 #define __CONFIG_H
 // Configuration definitions.
 
+//#define QEMU_SUPPORT
+
+#ifdef QEMU_SUPPORT
+#define CONFIG_BIOS_NAME "QEMU"
+#else
+#define CONFIG_BIOS_NAME "Bochs"
+#endif
+
 #define CONFIG_FLOPPY_SUPPORT 1
 #define CONFIG_PS2_MOUSE 1
 #define CONFIG_ATA 1
@@ -18,4 +26,12 @@
 #define CONFIG_SUBMODEL_ID   0x00
 #define CONFIG_BIOS_REVISION 0x01
 
+/* define it if the (emulated) hardware supports SMM mode */
+#define CONFIG_SMM 1
+
+/* if true, put the MP float table and ACPI RSDT in EBDA and the MP
+   table in RAM. Unfortunately, Linux has bugs with that, so we prefer
+   to modify the BIOS in shadow RAM */
+#define CONFIG_USE_EBDA_TABLES 0
+
 #endif // config.h
diff --git a/src/post.c b/src/post.c
index a1c71ee..b157a98 100644
--- a/src/post.c
+++ b/src/post.c
@@ -12,6 +12,27 @@
 #include "util.h" // memset
 #include "biosvar.h" // struct bios_data_area_s
 
+#include "acpi.h"
+#include "smbios.h"
+#include "smp.h"
+#include "pci.h"
+
+u32 cpuid_signature;
+u32 cpuid_features;
+u32 cpuid_ext_features;
+unsigned long ram_size;
+unsigned long bios_table_cur_addr;
+unsigned long bios_table_end_addr;
+
+#ifdef CONFIG_USE_EBDA_TABLES
+unsigned long ebda_cur_addr;
+#endif
+
+#define cpuid(index, eax, ebx, ecx, edx) \
+  asm volatile ("cpuid" \
+                : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
+                : "0" (index))
+
 #define bda ((struct bios_data_area_s *)0)
 #define ebda ((struct extended_bios_data_area_s *)(EBDA_SEG<<4))
 #define ipl ((struct ipl_s *)(IPL_SEG<<4))
@@ -502,6 +523,32 @@
 }
 
 static void
+ram_probe(void)
+{
+    if (inb_cmos(0x34) | inb_cmos(0x35))
+        ram_size = (inb_cmos(0x34) | (inb_cmos(0x35) << 8)) * 65536 +
+                   16 * 1024 * 1024;
+    else
+        ram_size = (inb_cmos(0x17) | (inb_cmos(0x18) << 8)) * 1024;
+#ifdef CONFIG_USE_EBDA_TABLES
+    ebda_cur_addr = ((*(u16 *)(0x40e)) << 4) + 0x380;
+#endif
+
+    BX_INFO("ram_size=0x%08lx\n", ram_size);
+}
+
+static void
+cpu_probe(void)
+{
+    u32 eax, ebx, ecx, edx;
+
+    cpuid(1, eax, ebx, ecx, edx);
+    cpuid_signature = eax;
+    cpuid_features = edx;
+    cpuid_ext_features = ecx;
+}
+
+static void
 post()
 {
     BX_INFO("Start bios\n");
@@ -533,6 +580,26 @@
     init_boot_vectors();
     rom_scan(0xc8000, 0xe0000);
 
+    ram_probe();
+    cpu_probe();
+    smp_probe();
+    //pci_bios_init();
+
+    if (bios_table_cur_addr != 0) {
+        mptable_init();
+
+        smbios_init();
+
+        if (acpi_enabled)
+            acpi_bios_init();
+
+        bios_lock_shadow_ram();
+
+        BX_INFO("bios_table_cur_addr: 0x%08lx\n", bios_table_cur_addr);
+        if (bios_table_cur_addr > bios_table_end_addr)
+            BX_PANIC("bios_table_end_addr overflow!\n");
+    }
+
     callrom(SEG_BIOS, OFFSET_begin_boot);
 }
 
diff --git a/src/system.c b/src/system.c
index 29f0052..6f581ef 100644
--- a/src/system.c
+++ b/src/system.c
@@ -5,6 +5,7 @@
 //
 // This file may be distributed under the terms of the GNU GPLv3 license.
 
+#include "acpi.h"
 #include "util.h" // irq_restore
 #include "biosvar.h" // CONFIG_BIOS_TABLE
 #include "ioport.h" // inb
@@ -282,8 +283,6 @@
     set_cf(regs, 0);
 }
 
-#define ACPI_DATA_SIZE    0x00010000L
-
 static void
 set_e820_range(u16 DI, u32 start, u32 end, u16 type)
 {
diff --git a/src/types.h b/src/types.h
index eb10a7b..10c3dfe 100644
--- a/src/types.h
+++ b/src/types.h
@@ -13,6 +13,7 @@
 typedef unsigned int u32;
 typedef signed int s32;
 typedef u32 size_t;
+typedef unsigned long long u64;
 
 #define VISIBLE __attribute__((externally_visible))
 
diff --git a/src/util.h b/src/util.h
index e84c7d8..488267d 100644
--- a/src/util.h
+++ b/src/util.h
@@ -53,6 +53,15 @@
 }
 
 static inline void
+memcpy(void *d, void *s, size_t n)
+{
+    while (n) {
+        ((char *)d)[n-1] = ((char *)s)[n-1];
+		n--;
+	}
+}
+
+static inline void
 eoi_master_pic()
 {
     outb(PIC1_IRQ5, PORT_PIC1);
@@ -138,4 +147,10 @@
     set_cf(regs, code);
 }
 
+unsigned long
+align(unsigned long addr, unsigned long v)
+{
+    return (addr + v - 1) & ~(v - 1);
+}
+
 #endif // util.h