diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2008-06-08 13:48:06 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2008-06-08 13:48:06 -0400 |
commit | da4a6482c94dbae35064be24cd71f1b22de6d50c (patch) | |
tree | 0f4eedfeec0be5e7b0b6095f52bc81a4d49702fc /src/shadow.c | |
parent | b3c28be1815ad846dbb04de359a84545b8db76fe (diff) | |
download | seabios-da4a6482c94dbae35064be24cd71f1b22de6d50c.tar.gz |
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.
Diffstat (limited to 'src/shadow.c')
-rw-r--r-- | src/shadow.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/shadow.c b/src/shadow.c new file mode 100644 index 00000000..6500029c --- /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); +} |