From e773930ea4f37bca9334a157e86e70f14234888f Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sun, 26 Jul 2009 19:16:09 -0400 Subject: 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. --- src/shadow.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 12 deletions(-) (limited to 'src/shadow.c') 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 +// Copyright (C) 2008,2009 Kevin O'Connor // 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); } -- cgit