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