Move acpi code out of rombios32.c; clean up use of fixed memory addresses.
[seabios.git] / src / shadow.c
1 // 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 //
6 // This file may be distributed under the terms of the GNU GPLv3 license.
7
8 #include "util.h" // memcpy
9 #include "pci.h" // pci_config_writeb
10
11 // Test if 'addr' is in the range from 'start'..'start+size'
12 #define IN_RANGE(addr, start, size) ({   \
13             u32 __addr = (addr);         \
14             u32 __start = (start);       \
15             u32 __size = (size);         \
16             (__addr - __start < __size); \
17         })
18
19 // Enable shadowing and copy bios.
20 static void
21 copy_bios(PCIDevice d)
22 {
23     int v = pci_config_readb(d, 0x59);
24     v |= 0x30;
25     pci_config_writeb(d, 0x59, v);
26     memcpy((void *)0x000f0000, (void *)BUILD_BIOS_TMP_ADDR, 0x10000);
27 }
28
29 // Make the BIOS code segment area (0xf0000) writable.
30 void
31 make_bios_writable()
32 {
33     if (CONFIG_COREBOOT)
34         return;
35
36     dprintf(3, "enabling shadow ram\n");
37
38     // Locate chip controlling ram shadowing.
39     PCIDevice d;
40     int ret = pci_find_device(0x8086, 0x1237, 0, &d);
41     if (ret) {
42         dprintf(1, "Unable to unlock ram - bridge not found\n");
43         return;
44     }
45
46     // Copy the bios to a temporary area.
47     memcpy((void *)BUILD_BIOS_TMP_ADDR, (void *)0x000f0000, 0x10000);
48
49     // Enable shadowing and copy bios.
50     if (IN_RANGE((u32)copy_bios, 0xf0000, 0x10000)) {
51         // Jump to shadow enable function - use the copy in the
52         // temporary storage area so that memory does not change under
53         // the executing code.
54         u32 pos = (u32)copy_bios - 0xf0000 + BUILD_BIOS_TMP_ADDR;
55         void (*func)(PCIDevice) = (void*)pos;
56         func(d);
57     } else {
58         copy_bios(d);
59     }
60
61     // Clear the temporary area.
62     memset((void *)BUILD_BIOS_TMP_ADDR, 0, 0x10000);
63 }
64
65 // Make the BIOS code segment area (0xf0000) read-only.
66 void
67 make_bios_readonly()
68 {
69     if (CONFIG_COREBOOT)
70         return;
71
72     dprintf(3, "locking shadow ram\n");
73
74     PCIDevice d;
75     int ret = pci_find_device(0x8086, 0x1237, 0, &d);
76     if (ret) {
77         dprintf(1, "Unable to lock ram - bridge not found\n");
78         return;
79     }
80
81     wbinvd();
82     int v = pci_config_readb(d, 0x59);
83     v = (v & 0x0f) | (0x10);
84     pci_config_writeb(d, 0x59, v);
85 }