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