|
|
1.1 root 1: // Support for enabling/disabling BIOS ram shadowing.
2: //
1.1.1.4 root 3: // Copyright (C) 2008-2010 Kevin O'Connor <[email protected]>
1.1 root 4: // Copyright (C) 2006 Fabrice Bellard
5: //
6: // This file may be distributed under the terms of the GNU LGPLv3 license.
7:
8: #include "util.h" // memcpy
9: #include "pci.h" // pci_config_writeb
10: #include "config.h" // CONFIG_*
11: #include "pci_ids.h" // PCI_VENDOR_ID_INTEL
1.1.1.5 ! root 12: #include "pci_regs.h" // PCI_VENDOR_ID
! 13: #include "xen.h" // usingXen
1.1 root 14:
15: // On the emulators, the bios at 0xf0000 is also at 0xffff0000
1.1.1.4 root 16: #define BIOS_SRC_OFFSET 0xfff00000
1.1 root 17:
1.1.1.5 ! root 18: #define I440FX_PAM0 0x59
! 19:
1.1 root 20: // Enable shadowing and copy bios.
21: static void
1.1.1.3 root 22: __make_bios_writable_intel(u16 bdf, u32 pam0)
1.1 root 23: {
24: // Make ram from 0xc0000-0xf0000 writable
25: int clear = 0;
26: int i;
27: for (i=0; i<6; i++) {
1.1.1.4 root 28: u32 pam = pam0 + 1 + i;
29: int reg = pci_config_readb(bdf, pam);
30: if (CONFIG_OPTIONROMS_DEPLOYED && (reg & 0x11) != 0x11) {
1.1 root 31: // Need to copy optionroms to work around qemu implementation
32: void *mem = (void*)(BUILD_ROM_START + i * 32*1024);
33: memcpy((void*)BUILD_BIOS_TMP_ADDR, mem, 32*1024);
1.1.1.3 root 34: pci_config_writeb(bdf, pam, 0x33);
1.1 root 35: memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024);
36: clear = 1;
37: } else {
1.1.1.3 root 38: pci_config_writeb(bdf, pam, 0x33);
1.1 root 39: }
40: }
41: if (clear)
42: memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024);
43:
44: // Make ram from 0xf0000-0x100000 writable
1.1.1.3 root 45: int reg = pci_config_readb(bdf, pam0);
46: pci_config_writeb(bdf, pam0, 0x30);
1.1 root 47: if (reg & 0x10)
48: // Ram already present.
49: return;
50:
51: // Copy bios.
1.1.1.4 root 52: extern u8 code32flat_start[], code32flat_end[];
53: memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET
54: , code32flat_end - code32flat_start);
1.1 root 55: }
56:
1.1.1.5 ! root 57: static void
1.1.1.3 root 58: make_bios_writable_intel(u16 bdf, u32 pam0)
1.1 root 59: {
1.1.1.3 root 60: int reg = pci_config_readb(bdf, pam0);
1.1 root 61: if (!(reg & 0x10)) {
62: // QEMU doesn't fully implement the piix shadow capabilities -
63: // if ram isn't backing the bios segment when shadowing is
64: // disabled, the code itself wont be in memory. So, run the
65: // code from the high-memory flash location.
1.1.1.4 root 66: u32 pos = (u32)__make_bios_writable_intel + BIOS_SRC_OFFSET;
1.1.1.3 root 67: void (*func)(u16 bdf, u32 pam0) = (void*)pos;
68: func(bdf, pam0);
1.1 root 69: return;
70: }
71: // Ram already present - just enable writes
1.1.1.3 root 72: __make_bios_writable_intel(bdf, pam0);
1.1 root 73: }
74:
1.1.1.5 ! root 75: static void
1.1.1.3 root 76: make_bios_readonly_intel(u16 bdf, u32 pam0)
1.1 root 77: {
78: // Flush any pending writes before locking memory.
79: wbinvd();
80:
81: // Write protect roms from 0xc0000-0xf0000
82: int i;
83: for (i=0; i<6; i++) {
84: u32 mem = BUILD_ROM_START + i * 32*1024;
1.1.1.3 root 85: u32 pam = pam0 + 1 + i;
1.1 root 86: if (RomEnd <= mem + 16*1024) {
87: if (RomEnd > mem)
1.1.1.3 root 88: pci_config_writeb(bdf, pam, 0x31);
1.1 root 89: break;
90: }
1.1.1.3 root 91: pci_config_writeb(bdf, pam, 0x11);
1.1 root 92: }
93:
94: // Write protect 0xf0000-0x100000
1.1.1.3 root 95: pci_config_writeb(bdf, pam0, 0x10);
96: }
97:
1.1.1.5 ! root 98: static void i440fx_bios_make_readonly(struct pci_device *pci, void *arg)
! 99: {
! 100: make_bios_readonly_intel(pci->bdf, I440FX_PAM0);
! 101: }
! 102:
! 103: static const struct pci_device_id dram_controller_make_readonly_tbl[] = {
1.1.1.3 root 104: PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441,
1.1.1.5 ! root 105: i440fx_bios_make_readonly),
1.1.1.3 root 106: PCI_DEVICE_END
107: };
108:
109: // Make the 0xc0000-0x100000 area read/writable.
110: void
111: make_bios_writable(void)
112: {
1.1.1.5 ! root 113: if (CONFIG_COREBOOT || usingXen())
1.1.1.3 root 114: return;
115:
116: dprintf(3, "enabling shadow ram\n");
117:
1.1.1.5 ! root 118: // At this point, statically allocated variables can't be written,
! 119: // so do this search manually.
! 120: int bdf;
! 121: foreachbdf(bdf, 0) {
! 122: u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID);
! 123: u16 vendor = vendev & 0xffff, device = vendev >> 16;
! 124: if (vendor == PCI_VENDOR_ID_INTEL
! 125: && device == PCI_DEVICE_ID_INTEL_82441) {
! 126: make_bios_writable_intel(bdf, I440FX_PAM0);
! 127: return;
! 128: }
1.1.1.3 root 129: }
1.1.1.5 ! root 130: dprintf(1, "Unable to unlock ram - bridge not found\n");
1.1.1.3 root 131: }
132:
133: // Make the BIOS code segment area (0xf0000) read-only.
134: void
135: make_bios_readonly(void)
136: {
1.1.1.5 ! root 137: if (CONFIG_COREBOOT || usingXen())
1.1.1.3 root 138: return;
139:
140: dprintf(3, "locking shadow ram\n");
1.1.1.5 ! root 141: struct pci_device *pci = pci_find_init_device(
! 142: dram_controller_make_readonly_tbl, NULL);
! 143: if (!pci)
1.1.1.3 root 144: dprintf(1, "Unable to lock ram - bridge not found\n");
1.1 root 145: }
1.1.1.4 root 146:
147: void
148: qemu_prep_reset(void)
149: {
150: if (CONFIG_COREBOOT)
151: return;
152: // QEMU doesn't map 0xc0000-0xfffff back to the original rom on a
153: // reset, so do that manually before invoking a hard reset.
154: make_bios_writable();
155: extern u8 code32flat_start[], code32flat_end[];
156: memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET
157: , code32flat_end - code32flat_start);
158: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.