blob: 264656d1ceb720998eb1fc2c0fda50a5d5cd6f15 [file] [log] [blame]
Kevin O'Connorda4a6482008-06-08 13:48:06 -04001// Support for enabling/disabling BIOS ram shadowing.
2//
3// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4// 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
21// Enable shadowing and copy bios.
22static void
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -050023copy_bios(u16 bdf)
Kevin O'Connorda4a6482008-06-08 13:48:06 -040024{
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -050025 int v = pci_config_readb(bdf, 0x59);
Kevin O'Connorda4a6482008-06-08 13:48:06 -040026 v |= 0x30;
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -050027 pci_config_writeb(bdf, 0x59, v);
Kevin O'Connore3677b12008-07-04 15:29:23 -040028 memcpy((void *)BUILD_BIOS_ADDR, (void *)BUILD_BIOS_TMP_ADDR
29 , BUILD_BIOS_SIZE);
Kevin O'Connorda4a6482008-06-08 13:48:06 -040030}
31
32// Make the BIOS code segment area (0xf0000) writable.
33void
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
48 // Copy the bios to a temporary area.
Kevin O'Connore3677b12008-07-04 15:29:23 -040049 memcpy((void *)BUILD_BIOS_TMP_ADDR, (void *)BUILD_BIOS_ADDR
50 , BUILD_BIOS_SIZE);
Kevin O'Connorda4a6482008-06-08 13:48:06 -040051
52 // Enable shadowing and copy bios.
Kevin O'Connore3677b12008-07-04 15:29:23 -040053 if (IN_RANGE((u32)copy_bios, BUILD_BIOS_ADDR, BUILD_BIOS_SIZE)) {
Kevin O'Connorda4a6482008-06-08 13:48:06 -040054 // Jump to shadow enable function - use the copy in the
55 // temporary storage area so that memory does not change under
56 // the executing code.
Kevin O'Connore3677b12008-07-04 15:29:23 -040057 u32 pos = (u32)copy_bios - BUILD_BIOS_ADDR + BUILD_BIOS_TMP_ADDR;
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -050058 void (*func)(u16 bdf) = (void*)pos;
59 func(bdf);
Kevin O'Connorda4a6482008-06-08 13:48:06 -040060 } else {
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -050061 copy_bios(bdf);
Kevin O'Connorda4a6482008-06-08 13:48:06 -040062 }
63
64 // Clear the temporary area.
Kevin O'Connore3677b12008-07-04 15:29:23 -040065 memset((void *)BUILD_BIOS_TMP_ADDR, 0, BUILD_BIOS_SIZE);
Kevin O'Connorda4a6482008-06-08 13:48:06 -040066}
67
68// Make the BIOS code segment area (0xf0000) read-only.
69void
70make_bios_readonly()
71{
72 if (CONFIG_COREBOOT)
73 return;
74
75 dprintf(3, "locking shadow ram\n");
76
Kevin O'Connor4132e022008-12-04 19:39:10 -050077 int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -050078 if (bdf < 0) {
Kevin O'Connorda4a6482008-06-08 13:48:06 -040079 dprintf(1, "Unable to lock ram - bridge not found\n");
80 return;
81 }
82
83 wbinvd();
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -050084 int v = pci_config_readb(bdf, 0x59);
Kevin O'Connorda4a6482008-06-08 13:48:06 -040085 v = (v & 0x0f) | (0x10);
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -050086 pci_config_writeb(bdf, 0x59, v);
Kevin O'Connorda4a6482008-06-08 13:48:06 -040087}