diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2009-07-26 19:16:09 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2009-07-26 19:16:09 -0400 |
commit | e773930ea4f37bca9334a157e86e70f14234888f (patch) | |
tree | cc55909121ff77e44b31097f37a78f73e597cc37 /src/shadow.c | |
parent | 98571bee61e23bcfe1400d9ceaf432d8a84a77bb (diff) | |
download | seabios-e773930ea4f37bca9334a157e86e70f14234888f.tar.gz |
Add support for enabling ram in 0xc0000-0xf0000 area.
Enhance shadow ram support to enable read/write of option rom area.
This enables support for option roms that modify themselves.
Support copying the roms before enabling shadowing, to work around the
qemu implementation of ram shadowing.
Rename next_rom to RomEnd and export it.
Support locking ram being used for optionroms before booting.
Don't bother and'ing/or'ing 0x59 register - it's usage is well defined.
Diffstat (limited to 'src/shadow.c')
-rw-r--r-- | src/shadow.c | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/src/shadow.c b/src/shadow.c index 1c389f44..daa2e213 100644 --- a/src/shadow.c +++ b/src/shadow.c @@ -1,6 +1,6 @@ // Support for enabling/disabling BIOS ram shadowing. // -// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net> +// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net> // Copyright (C) 2006 Fabrice Bellard // // This file may be distributed under the terms of the GNU LGPLv3 license. @@ -23,13 +23,13 @@ // Enable shadowing and copy bios. static void -copy_bios(u16 bdf, int reg) +copy_bios(u16 bdf) { - pci_config_writeb(bdf, 0x59, reg | 0x30); + pci_config_writeb(bdf, 0x59, 0x30); memcpy((void*)BUILD_BIOS_ADDR, (void*)BIOS_SRC_ADDR, BUILD_BIOS_SIZE); } -// Make the BIOS code segment area (0xf0000) writable. +// Make the 0xc0000-0x100000 area read/writable. void make_bios_writable() { @@ -45,10 +45,33 @@ make_bios_writable() return; } + // Make ram from 0xc0000-0xf0000 writable + int clear = 0; + int i; + for (i=0; i<6; i++) { + if (CONFIG_OPTIONROMS_DEPLOYED) { + int reg = pci_config_readb(bdf, 0x5a + i); + if ((reg & 0x11) != 0x11) { + // Need to copy optionroms to work around qemu implementation + void *mem = (void*)(BUILD_ROM_START + i * 32*1024); + memcpy((void*)BUILD_BIOS_TMP_ADDR, mem, 32*1024); + pci_config_writeb(bdf, 0x5a + i, 0x33); + memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024); + clear = 1; + } else { + pci_config_writeb(bdf, 0x5a + i, 0x33); + } + } else { + pci_config_writeb(bdf, 0x5a + i, 0x33); + } + } + if (clear) + memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024); + int reg = pci_config_readb(bdf, 0x59); - if (reg & 0x30) { + if (reg & 0x10) { // Ram already present - just enable writes - pci_config_writeb(bdf, 0x59, reg | 0x30); + pci_config_writeb(bdf, 0x59, 0x30); return; } @@ -58,10 +81,10 @@ make_bios_writable() // temporary storage area so that memory does not change under // the executing code. u32 pos = (u32)copy_bios - BUILD_BIOS_ADDR + BIOS_SRC_ADDR; - void (*func)(u16 bdf, int reg) = (void*)pos; - func(bdf, reg); + void (*func)(u16 bdf) = (void*)pos; + func(bdf); } else { - copy_bios(bdf, reg); + copy_bios(bdf); } } @@ -80,8 +103,21 @@ make_bios_readonly() return; } + // Flush any pending writes before locking memory. wbinvd(); - int v = pci_config_readb(bdf, 0x59); - v = (v & 0x0f) | (0x10); - pci_config_writeb(bdf, 0x59, v); + + // Write protect roms from 0xc0000-0xf0000 + int i; + for (i=0; i<6; i++) { + u32 mem = BUILD_ROM_START + i * 32*1024; + if (RomEnd <= mem + 16*1024) { + if (RomEnd > mem) + pci_config_writeb(bdf, 0x5a + i, 0x31); + break; + } + pci_config_writeb(bdf, 0x5a + i, 0x11); + } + + // Write protect 0xf0000-0x100000 + pci_config_writeb(bdf, 0x59, 0x10); } |