1 // Support for enabling/disabling BIOS ram shadowing.
3 // Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2006 Fabrice Bellard
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
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
12 #include "dev-i440fx.h"
14 // On the emulators, the bios at 0xf0000 is also at 0xffff0000
15 #define BIOS_SRC_OFFSET 0xfff00000
17 // Enable shadowing and copy bios.
19 __make_bios_writable_intel(u16 bdf, u32 pam0)
21 // Make ram from 0xc0000-0xf0000 writable
25 u32 pam = pam0 + 1 + i;
26 int reg = pci_config_readb(bdf, pam);
27 if (CONFIG_OPTIONROMS_DEPLOYED && (reg & 0x11) != 0x11) {
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);
31 pci_config_writeb(bdf, pam, 0x33);
32 memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024);
35 pci_config_writeb(bdf, pam, 0x33);
39 memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024);
41 // Make ram from 0xf0000-0x100000 writable
42 int reg = pci_config_readb(bdf, pam0);
43 pci_config_writeb(bdf, pam0, 0x30);
45 // Ram already present.
49 extern u8 code32flat_start[], code32flat_end[];
50 memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET
51 , code32flat_end - code32flat_start);
55 make_bios_writable_intel(u16 bdf, u32 pam0)
57 int reg = pci_config_readb(bdf, pam0);
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.
63 u32 pos = (u32)__make_bios_writable_intel + BIOS_SRC_OFFSET;
64 void (*func)(u16 bdf, u32 pam0) = (void*)pos;
68 // Ram already present - just enable writes
69 __make_bios_writable_intel(bdf, pam0);
73 make_bios_readonly_intel(u16 bdf, u32 pam0)
75 // Flush any pending writes before locking memory.
78 // Write protect roms from 0xc0000-0xf0000
81 u32 mem = BUILD_ROM_START + i * 32*1024;
82 u32 pam = pam0 + 1 + i;
83 if (RomEnd <= mem + 16*1024) {
85 pci_config_writeb(bdf, pam, 0x31);
88 pci_config_writeb(bdf, pam, 0x11);
91 // Write protect 0xf0000-0x100000
92 pci_config_writeb(bdf, pam0, 0x10);
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),
101 // Make the 0xc0000-0x100000 area read/writable.
103 make_bios_writable(void)
108 dprintf(3, "enabling shadow ram\n");
110 // at this point, statically allocated variables can't be written.
111 // so stack should be used.
113 // Locate chip controlling ram shadowing.
114 int bdf = pci_find_init_device(dram_controller_make_writable_tbl, NULL);
116 dprintf(1, "Unable to unlock ram - bridge not found\n");
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),
126 // Make the BIOS code segment area (0xf0000) read-only.
128 make_bios_readonly(void)
133 dprintf(3, "locking shadow ram\n");
134 int bdf = pci_find_init_device(dram_controller_make_readonly_tbl, NULL);
136 dprintf(1, "Unable to lock ram - bridge not found\n");
141 qemu_prep_reset(void)
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);