]> git.proxmox.com Git - grub2.git/blame - commands/efi/loadbios.c
2010-01-03 Carles Pina i Estany <carles@pina.cat>
[grub2.git] / commands / efi / loadbios.c
CommitLineData
e7e6862a 1/* loadbios.c - command to load a bios dump */
2/*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2009 Free Software Foundation, Inc.
5 *
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <grub/dl.h>
21#include <grub/misc.h>
22#include <grub/file.h>
23#include <grub/efi/efi.h>
24#include <grub/pci.h>
25#include <grub/command.h>
77a79592 26#include <grub/i18n.h>
e7e6862a 27
28static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID;
29static grub_efi_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID;
30static grub_efi_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID;
31
32#define EBDA_SEG_ADDR 0x40e
33#define LOW_MEM_ADDR 0x413
34#define FAKE_EBDA_SEG 0x9fc0
35
36#define BLANK_MEM 0xffffffff
37#define VBIOS_ADDR 0xc0000
38#define SBIOS_ADDR 0xf0000
39
40static int
41enable_rom_area (void)
42{
43 grub_pci_address_t addr;
44 grub_uint32_t *rom_ptr;
181aaf0e 45 grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
e7e6862a 46
47 rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
48 if (*rom_ptr != BLANK_MEM)
49 {
941903f2 50 grub_printf ("ROM image is present.\n");
e7e6862a 51 return 0;
52 }
53
181aaf0e 54 addr = grub_pci_make_address (dev, 36);
e7e6862a 55 grub_pci_write_byte (addr++, 0x30);
56 grub_pci_write_byte (addr++, 0x33);
57 grub_pci_write_byte (addr++, 0x33);
58 grub_pci_write_byte (addr++, 0x33);
59 grub_pci_write_byte (addr++, 0x33);
60 grub_pci_write_byte (addr++, 0x33);
61 grub_pci_write_byte (addr++, 0x33);
62 grub_pci_write_byte (addr, 0);
63
64 *rom_ptr = 0;
65 if (*rom_ptr != 0)
66 {
941903f2 67 grub_printf ("Can\'t enable ROM area.\n");
e7e6862a 68 return 0;
69 }
70
71 return 1;
72}
73
74static void
75lock_rom_area (void)
76{
77 grub_pci_address_t addr;
181aaf0e 78 grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
e7e6862a 79
181aaf0e 80 addr = grub_pci_make_address (dev, 36);
e7e6862a 81 grub_pci_write_byte (addr++, 0x10);
82 grub_pci_write_byte (addr++, 0x11);
83 grub_pci_write_byte (addr++, 0x11);
84 grub_pci_write_byte (addr++, 0x11);
85 grub_pci_write_byte (addr, 0x11);
86}
87
88static void
89fake_bios_data (int use_rom)
90{
91 unsigned i;
92 void *acpi, *smbios;
93 grub_uint16_t *ebda_seg_ptr, *low_mem_ptr;
94
95 ebda_seg_ptr = (grub_uint16_t *) EBDA_SEG_ADDR;
96 low_mem_ptr = (grub_uint16_t *) LOW_MEM_ADDR;
97 if ((*ebda_seg_ptr) || (*low_mem_ptr))
98 return;
99
100 acpi = 0;
101 smbios = 0;
102 for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
103 {
104 grub_efi_guid_t *guid =
105 &grub_efi_system_table->configuration_table[i].vendor_guid;
106
107 if (! grub_memcmp (guid, &acpi2_guid, sizeof (grub_efi_guid_t)))
108 {
109 acpi = grub_efi_system_table->configuration_table[i].vendor_table;
110 grub_dprintf ("efi", "ACPI2: %p\n", acpi);
111 }
112 else if (! grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_guid_t)))
113 {
114 void *t;
115
116 t = grub_efi_system_table->configuration_table[i].vendor_table;
117 if (! acpi)
118 acpi = t;
119 grub_dprintf ("efi", "ACPI: %p\n", t);
120 }
121 else if (! grub_memcmp (guid, &smbios_guid, sizeof (grub_efi_guid_t)))
122 {
123 smbios = grub_efi_system_table->configuration_table[i].vendor_table;
124 grub_dprintf ("efi", "SMBIOS: %p\n", smbios);
125 }
126 }
127
128 *ebda_seg_ptr = FAKE_EBDA_SEG;
129 *low_mem_ptr = (FAKE_EBDA_SEG >> 6);
130
131 *((grub_uint16_t *) (FAKE_EBDA_SEG << 4)) = 640 - *low_mem_ptr;
132
133 if (acpi)
134 grub_memcpy ((char *) ((FAKE_EBDA_SEG << 4) + 16), acpi, 1024 - 16);
135
136 if ((use_rom) && (smbios))
137 grub_memcpy ((char *) SBIOS_ADDR, (char *) smbios + 16, 16);
138}
139
140static grub_err_t
141grub_cmd_fakebios (struct grub_command *cmd __attribute__ ((unused)),
142 int argc __attribute__ ((unused)),
143 char *argv[] __attribute__ ((unused)))
144{
145 if (enable_rom_area ())
146 {
147 fake_bios_data (1);
148 lock_rom_area ();
149 }
150 else
151 fake_bios_data (0);
a96df3f2 152
153 return 0;
e7e6862a 154}
155
156static grub_err_t
157grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)),
158 int argc, char *argv[])
159{
160 grub_file_t file;
161 int size;
162
163 if (argc == 0)
61ba42be 164 return grub_error (GRUB_ERR_BAD_ARGUMENT, "no ROM image specified");
e7e6862a 165
166 if (argc > 1)
167 {
168 file = grub_file_open (argv[1]);
169 if (! file)
170 return grub_errno;
171
172 if (file->size != 4)
7fd0baee 173 grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid int10 dump size");
e7e6862a 174 else
5c5215d5 175 grub_file_read (file, (void *) 0x40, 4);
e7e6862a 176
177 grub_file_close (file);
178 if (grub_errno)
179 return grub_errno;
180 }
181
182 file = grub_file_open (argv[0]);
183 if (! file)
184 return grub_errno;
185
186 size = file->size;
187 if ((size < 0x10000) || (size > 0x40000))
7fd0baee 188 grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid bios dump size");
e7e6862a 189 else if (enable_rom_area ())
190 {
5c5215d5 191 grub_file_read (file, (void *) VBIOS_ADDR, size);
e7e6862a 192 fake_bios_data (size <= 0x40000);
193 lock_rom_area ();
194 }
195
196 grub_file_close (file);
197 return grub_errno;
198}
199
200static grub_command_t cmd_fakebios, cmd_loadbios;
201
202GRUB_MOD_INIT(loadbios)
203{
e7e6862a 204 cmd_fakebios = grub_register_command ("fakebios", grub_cmd_fakebios,
77a79592 205 0, N_("Fake bios."));
e7e6862a 206
207 cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
fdcdbb66 208 "BIOS_DUMP [INT10_DUMP]",
77a79592 209 N_("Load bios dump."));
e7e6862a 210}
211
212GRUB_MOD_FINI(loadbios)
213{
214 grub_unregister_command (cmd_fakebios);
215 grub_unregister_command (cmd_loadbios);
216}