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