Separate out ram shadow code and permit more code to write to bios.
Extract shadow code from rombios32.c to its own file - shadow.c.
Reorg post.c so that shadow enable happens early and ram lock happens
late in boot process.
Also, improve some comments in post.c and reorg code slightly.
diff --git a/Makefile b/Makefile
index c465120..7e5fa6b 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@
# Source files
SRCBOTH=output.c util.c floppy.c ata.c kbd.c pci.c boot.c serial.c clock.c
SRC16=$(SRCBOTH) disk.c system.c mouse.c cdrom.c apm.c pcibios.c
-SRC32=$(SRCBOTH) post.c rombios32.c post_menu.c
+SRC32=$(SRCBOTH) post.c shadow.c rombios32.c post_menu.c
TABLESRC=font.c cbt.c floppy_dbt.c
cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
diff --git a/src/post.c b/src/post.c
index 4b56551..9b54953 100644
--- a/src/post.c
+++ b/src/post.c
@@ -151,6 +151,7 @@
}
}
+// Execute a given option rom.
static void
callrom(u16 seg, u16 offset)
{
@@ -163,6 +164,7 @@
call16(&br);
}
+// Find and run any "option roms" found in the given address range.
static void
rom_scan(u32 start, u32 end)
{
@@ -211,11 +213,10 @@
}
}
+// Main setup code.
static void
post()
{
- dprintf(1, "Start bios\n");
-
dprintf(3, "init bda\n");
init_bda();
init_ebda();
@@ -239,10 +240,6 @@
printf("BIOS - begin\n\n");
- // clear bss section -- XXX - shouldn't use globals
- extern char __bss_start[], __bss_end[];
- memset(__bss_start, 0, __bss_end - __bss_start);
-
dprintf(3, "rombios32 init\n");
rombios32_init();
@@ -256,20 +253,18 @@
dprintf(1, "Scan for option roms\n");
rom_scan(0xc8000, 0xe0000);
-
- interactive_bootmenu();
-
- // reset the memory (some boot loaders such as syslinux suppose
- // that the memory is set to zero)
- memset((void*)0x40000, 0, 0x40000); // XXX - shouldn't use globals
-
- // Invoke int 19 to start boot process.
- dprintf(3, "Jump to int19\n");
- struct bregs br;
- memset(&br, 0, sizeof(br));
- call16_int(0x19, &br);
}
+// Clear .bss section for C code.
+static void
+clear_bss()
+{
+ dprintf(3, "clearing .bss section\n");
+ extern char __bss_start[], __bss_end[];
+ memset(__bss_start, 0, __bss_end - __bss_start);
+}
+
+// Reset DMA controller
static void
init_dma()
{
@@ -282,6 +277,7 @@
outb(0x00, PORT_DMA2_MASK_REG);
}
+// Check if the machine was setup with a special restart vector.
static void
check_restart_status()
{
@@ -308,13 +304,34 @@
call16(&br);
}
+// 32-bit entry point.
void VISIBLE32
_start()
{
init_dma();
check_restart_status();
+ dprintf(1, "Start bios\n");
+
+ // Setup for .bss and .data sections
+ clear_bss();
+ make_bios_writable();
+
+ // Perform main setup code.
post();
+
+ // Present the user with a bootup menu.
+ interactive_bootmenu();
+
+ // Prep for boot process.
+ make_bios_readonly();
+ clear_bss();
+
+ // Invoke int 19 to start boot process.
+ dprintf(3, "Jump to int19\n");
+ struct bregs br;
+ memset(&br, 0, sizeof(br));
+ call16_int(0x19, &br);
}
// Externally visible 32bit entry point.
diff --git a/src/rombios32.c b/src/rombios32.c
index 3e73323..74c4563 100644
--- a/src/rombios32.c
+++ b/src/rombios32.c
@@ -26,7 +26,6 @@
// are at 0x40000).
#define CPU_COUNT_ADDR 0xf000
#define AP_BOOT_ADDR 0x10000
-#define BIOS_TMP_STORAGE 0x30000 /* 64 KB used to copy the BIOS to shadow RAM */
#define PM_IO_BASE 0xb000
#define SMB_IO_BASE 0xb100
@@ -36,8 +35,6 @@
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
: "0" (index))
-#define wbinvd() asm volatile("wbinvd")
-
#define CPUID_APIC (1 << 9)
#define APIC_BASE ((u8 *)0xfee00000)
@@ -234,63 +231,6 @@
return (irq_num + slot_addend) & 3;
}
-static void
-copy_bios(PCIDevice d, int v)
-{
- pci_config_writeb(d, 0x59, v);
- memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE, 0x10000);
-}
-
-// Test if 'addr' is in the range from 'start'..'start+size'
-#define IN_RANGE(addr, start, size) ({ \
- u32 __addr = (addr); \
- u32 __start = (start); \
- u32 __size = (size); \
- (__addr - __start < __size); \
- })
-
-static void bios_shadow_init(PCIDevice d)
-{
- bios_table_cur_addr = 0xf0000 | OFFSET_freespace2_start;
- bios_table_end_addr = 0xf0000 | OFFSET_freespace2_end;
- dprintf(1, "bios_table_addr: 0x%08lx end=0x%08lx\n",
- bios_table_cur_addr, bios_table_end_addr);
-
- /* remap the BIOS to shadow RAM an keep it read/write while we
- are writing tables */
- int v = pci_config_readb(d, 0x59);
- v &= 0xcf;
- pci_config_writeb(d, 0x59, v);
- memcpy((void *)BIOS_TMP_STORAGE, (void *)0x000f0000, 0x10000);
- v |= 0x30;
-
- if (IN_RANGE((u32)copy_bios, 0xf0000, 0x10000)) {
- // Current code is in shadowed area. Perform the copy from
- // the code that is in the temporary location.
- u32 pos = (u32)copy_bios - 0xf0000 + BIOS_TMP_STORAGE;
- void (*func)(PCIDevice, int) = (void*)pos;
- func(d, v);
- } else {
- copy_bios(d, v);
- }
-
- // Clear the area just copied.
- memset((void *)BIOS_TMP_STORAGE, 0, 0x10000);
-
- i440_pcidev = d;
-}
-
-static void bios_lock_shadow_ram(void)
-{
- PCIDevice d = i440_pcidev;
- int v;
-
- wbinvd();
- v = pci_config_readb(d, 0x59);
- v = (v & 0x0f) | (0x10);
- pci_config_writeb(d, 0x59, v);
-}
-
static void pci_bios_init_bridges(PCIDevice d)
{
u16 vendor_id, device_id;
@@ -319,7 +259,7 @@
elcr[0], elcr[1]);
} else if (vendor_id == 0x8086 && device_id == 0x1237) {
/* i440 PCI bridge */
- bios_shadow_init(d);
+ i440_pcidev = d;
}
}
@@ -1677,6 +1617,11 @@
dprintf(1, "ebda_cur_addr: 0x%08lx\n", ebda_cur_addr);
#endif
+ bios_table_cur_addr = 0xf0000 | OFFSET_freespace2_start;
+ bios_table_end_addr = 0xf0000 | OFFSET_freespace2_end;
+ dprintf(1, "bios_table_addr: 0x%08lx end=0x%08lx\n",
+ bios_table_cur_addr, bios_table_end_addr);
+
cpu_probe();
smp_probe();
@@ -1694,8 +1639,6 @@
if (acpi_enabled)
acpi_bios_init();
- bios_lock_shadow_ram();
-
dprintf(1, "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");
diff --git a/src/shadow.c b/src/shadow.c
new file mode 100644
index 0000000..6500029
--- /dev/null
+++ b/src/shadow.c
@@ -0,0 +1,87 @@
+// Support for enabling/disabling BIOS ram shadowing.
+//
+// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include "util.h" // memcpy
+#include "pci.h" // pci_config_writeb
+
+#define BIOS_TMP_STORAGE 0x30000 /* 64 KB used to copy the BIOS to shadow RAM */
+
+// Test if 'addr' is in the range from 'start'..'start+size'
+#define IN_RANGE(addr, start, size) ({ \
+ u32 __addr = (addr); \
+ u32 __start = (start); \
+ u32 __size = (size); \
+ (__addr - __start < __size); \
+ })
+
+// Enable shadowing and copy bios.
+static void
+copy_bios(PCIDevice d)
+{
+ int v = pci_config_readb(d, 0x59);
+ v |= 0x30;
+ pci_config_writeb(d, 0x59, v);
+ memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE, 0x10000);
+}
+
+// Make the BIOS code segment area (0xf0000) writable.
+void
+make_bios_writable()
+{
+ if (CONFIG_COREBOOT)
+ return;
+
+ dprintf(3, "enabling shadow ram\n");
+
+ // Locate chip controlling ram shadowing.
+ PCIDevice d;
+ int ret = pci_find_device(0x8086, 0x1237, 0, &d);
+ if (ret) {
+ dprintf(1, "Unable to unlock ram - bridge not found\n");
+ return;
+ }
+
+ // Copy the bios to a temporary area.
+ memcpy((void *)BIOS_TMP_STORAGE, (void *)0x000f0000, 0x10000);
+
+ // Enable shadowing and copy bios.
+ if (IN_RANGE((u32)copy_bios, 0xf0000, 0x10000)) {
+ // Jump to shadow enable function - use the copy in the
+ // temporary storage area so that memory does not change under
+ // the executing code.
+ u32 pos = (u32)copy_bios - 0xf0000 + BIOS_TMP_STORAGE;
+ void (*func)(PCIDevice) = (void*)pos;
+ func(d);
+ } else {
+ copy_bios(d);
+ }
+
+ // Clear the temporary area.
+ memset((void *)BIOS_TMP_STORAGE, 0, 0x10000);
+}
+
+// Make the BIOS code segment area (0xf0000) read-only.
+void
+make_bios_readonly()
+{
+ if (CONFIG_COREBOOT)
+ return;
+
+ dprintf(3, "locking shadow ram\n");
+
+ PCIDevice d;
+ int ret = pci_find_device(0x8086, 0x1237, 0, &d);
+ if (ret) {
+ dprintf(1, "Unable to lock ram - bridge not found\n");
+ return;
+ }
+
+ wbinvd();
+ int v = pci_config_readb(d, 0x59);
+ v = (v & 0x0f) | (0x10);
+ pci_config_writeb(d, 0x59, v);
+}
diff --git a/src/util.h b/src/util.h
index 172308a..5c37100 100644
--- a/src/util.h
+++ b/src/util.h
@@ -47,6 +47,11 @@
asm volatile("hlt");
}
+static inline void wbinvd(void)
+{
+ asm volatile("wbinvd");
+}
+
void *memset(void *s, int c, size_t n);
void *memcpy(void *d1, const void *s1, size_t len);
@@ -179,6 +184,10 @@
// util.c
u8 checksum(u8 *far_data, u32 len);
+// shadow.c
+void make_bios_writable();
+void make_bios_readonly();
+
// rombios32.c
void rombios32_init(void);