blob: daa2e213f43ede8330e7a3f65f6ba00ff2b9577a [file] [log] [blame]
Kevin O'Connorda4a6482008-06-08 13:48:06 -04001// Support for enabling/disabling BIOS ram shadowing.
2//
Kevin O'Connore7739302009-07-26 19:16:09 -04003// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connorda4a6482008-06-08 13:48:06 -04004// Copyright (C) 2006 Fabrice Bellard
5//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05006// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connorda4a6482008-06-08 13:48:06 -04007
8#include "util.h" // memcpy
9#include "pci.h" // pci_config_writeb
Kevin O'Connor9521e262008-07-04 13:04:29 -040010#include "config.h" // CONFIG_*
Kevin O'Connor2ed2f582008-11-08 15:53:36 -050011#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
Kevin O'Connorda4a6482008-06-08 13:48:06 -040012
Kevin O'Connorda4a6482008-06-08 13:48:06 -040013// Test if 'addr' is in the range from 'start'..'start+size'
14#define IN_RANGE(addr, start, size) ({ \
15 u32 __addr = (addr); \
16 u32 __start = (start); \
17 u32 __size = (size); \
18 (__addr - __start < __size); \
19 })
20
Kevin O'Connor35284962009-07-24 21:49:26 -040021// On the emulators, the bios at 0xf0000 is also at 0xffff0000
22#define BIOS_SRC_ADDR 0xffff0000
23
Kevin O'Connorda4a6482008-06-08 13:48:06 -040024// Enable shadowing and copy bios.
25static void
Kevin O'Connore7739302009-07-26 19:16:09 -040026copy_bios(u16 bdf)
Kevin O'Connorda4a6482008-06-08 13:48:06 -040027{
Kevin O'Connore7739302009-07-26 19:16:09 -040028 pci_config_writeb(bdf, 0x59, 0x30);
Kevin O'Connor35284962009-07-24 21:49:26 -040029 memcpy((void*)BUILD_BIOS_ADDR, (void*)BIOS_SRC_ADDR, BUILD_BIOS_SIZE);
Kevin O'Connorda4a6482008-06-08 13:48:06 -040030}
31
Kevin O'Connore7739302009-07-26 19:16:09 -040032// Make the 0xc0000-0x100000 area read/writable.
Kevin O'Connorda4a6482008-06-08 13:48:06 -040033void
34make_bios_writable()
35{
36 if (CONFIG_COREBOOT)
37 return;
38
39 dprintf(3, "enabling shadow ram\n");
40
41 // Locate chip controlling ram shadowing.
Kevin O'Connor4132e022008-12-04 19:39:10 -050042 int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -050043 if (bdf < 0) {
Kevin O'Connorda4a6482008-06-08 13:48:06 -040044 dprintf(1, "Unable to unlock ram - bridge not found\n");
45 return;
46 }
47
Kevin O'Connore7739302009-07-26 19:16:09 -040048 // Make ram from 0xc0000-0xf0000 writable
49 int clear = 0;
50 int i;
51 for (i=0; i<6; i++) {
52 if (CONFIG_OPTIONROMS_DEPLOYED) {
53 int reg = pci_config_readb(bdf, 0x5a + i);
54 if ((reg & 0x11) != 0x11) {
55 // Need to copy optionroms to work around qemu implementation
56 void *mem = (void*)(BUILD_ROM_START + i * 32*1024);
57 memcpy((void*)BUILD_BIOS_TMP_ADDR, mem, 32*1024);
58 pci_config_writeb(bdf, 0x5a + i, 0x33);
59 memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024);
60 clear = 1;
61 } else {
62 pci_config_writeb(bdf, 0x5a + i, 0x33);
63 }
64 } else {
65 pci_config_writeb(bdf, 0x5a + i, 0x33);
66 }
67 }
68 if (clear)
69 memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024);
70
Kevin O'Connor35284962009-07-24 21:49:26 -040071 int reg = pci_config_readb(bdf, 0x59);
Kevin O'Connore7739302009-07-26 19:16:09 -040072 if (reg & 0x10) {
Kevin O'Connor35284962009-07-24 21:49:26 -040073 // Ram already present - just enable writes
Kevin O'Connore7739302009-07-26 19:16:09 -040074 pci_config_writeb(bdf, 0x59, 0x30);
Kevin O'Connor35284962009-07-24 21:49:26 -040075 return;
76 }
Kevin O'Connorda4a6482008-06-08 13:48:06 -040077
78 // Enable shadowing and copy bios.
Kevin O'Connore3677b12008-07-04 15:29:23 -040079 if (IN_RANGE((u32)copy_bios, BUILD_BIOS_ADDR, BUILD_BIOS_SIZE)) {
Kevin O'Connorda4a6482008-06-08 13:48:06 -040080 // Jump to shadow enable function - use the copy in the
81 // temporary storage area so that memory does not change under
82 // the executing code.
Kevin O'Connor35284962009-07-24 21:49:26 -040083 u32 pos = (u32)copy_bios - BUILD_BIOS_ADDR + BIOS_SRC_ADDR;
Kevin O'Connore7739302009-07-26 19:16:09 -040084 void (*func)(u16 bdf) = (void*)pos;
85 func(bdf);
Kevin O'Connorda4a6482008-06-08 13:48:06 -040086 } else {
Kevin O'Connore7739302009-07-26 19:16:09 -040087 copy_bios(bdf);
Kevin O'Connorda4a6482008-06-08 13:48:06 -040088 }
Kevin O'Connorda4a6482008-06-08 13:48:06 -040089}
90
91// Make the BIOS code segment area (0xf0000) read-only.
92void
93make_bios_readonly()
94{
95 if (CONFIG_COREBOOT)
96 return;
97
98 dprintf(3, "locking shadow ram\n");
99
Kevin O'Connor4132e022008-12-04 19:39:10 -0500100 int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -0500101 if (bdf < 0) {
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400102 dprintf(1, "Unable to lock ram - bridge not found\n");
103 return;
104 }
105
Kevin O'Connore7739302009-07-26 19:16:09 -0400106 // Flush any pending writes before locking memory.
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400107 wbinvd();
Kevin O'Connore7739302009-07-26 19:16:09 -0400108
109 // Write protect roms from 0xc0000-0xf0000
110 int i;
111 for (i=0; i<6; i++) {
112 u32 mem = BUILD_ROM_START + i * 32*1024;
113 if (RomEnd <= mem + 16*1024) {
114 if (RomEnd > mem)
115 pci_config_writeb(bdf, 0x5a + i, 0x31);
116 break;
117 }
118 pci_config_writeb(bdf, 0x5a + i, 0x11);
119 }
120
121 // Write protect 0xf0000-0x100000
122 pci_config_writeb(bdf, 0x59, 0x10);
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400123}