]> git.proxmox.com Git - grub2.git/blame - grub-core/commands/efi/loadbios.c
lsefisystab: add missing comma after 7994077
[grub2.git] / grub-core / 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
e745cf0c
VS
28GRUB_MOD_LICENSE ("GPLv3+");
29
e7e6862a 30static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID;
31static grub_efi_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID;
32static grub_efi_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID;
33
34#define EBDA_SEG_ADDR 0x40e
35#define LOW_MEM_ADDR 0x413
36#define FAKE_EBDA_SEG 0x9fc0
37
38#define BLANK_MEM 0xffffffff
39#define VBIOS_ADDR 0xc0000
40#define SBIOS_ADDR 0xf0000
41
42static int
43enable_rom_area (void)
44{
45 grub_pci_address_t addr;
46 grub_uint32_t *rom_ptr;
181aaf0e 47 grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
e7e6862a 48
49 rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
50 if (*rom_ptr != BLANK_MEM)
51 {
6e0632e2 52 grub_puts_ (N_("ROM image is present."));
e7e6862a 53 return 0;
54 }
55
61c8e880 56 /* FIXME: should be macroified. */
fbb8a887 57 addr = grub_pci_make_address (dev, 144);
e7e6862a 58 grub_pci_write_byte (addr++, 0x30);
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++, 0x33);
63 grub_pci_write_byte (addr++, 0x33);
64 grub_pci_write_byte (addr++, 0x33);
65 grub_pci_write_byte (addr, 0);
66
67 *rom_ptr = 0;
68 if (*rom_ptr != 0)
69 {
6e0632e2 70 grub_puts_ (N_("Can\'t enable ROM area."));
e7e6862a 71 return 0;
72 }
73
74 return 1;
75}
76
77static void
78lock_rom_area (void)
79{
80 grub_pci_address_t addr;
181aaf0e 81 grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
e7e6862a 82
61c8e880 83 /* FIXME: should be macroified. */
fbb8a887 84 addr = grub_pci_make_address (dev, 144);
e7e6862a 85 grub_pci_write_byte (addr++, 0x10);
86 grub_pci_write_byte (addr++, 0x11);
87 grub_pci_write_byte (addr++, 0x11);
88 grub_pci_write_byte (addr++, 0x11);
89 grub_pci_write_byte (addr, 0x11);
90}
91
92static void
93fake_bios_data (int use_rom)
94{
95 unsigned i;
96 void *acpi, *smbios;
97 grub_uint16_t *ebda_seg_ptr, *low_mem_ptr;
98
99 ebda_seg_ptr = (grub_uint16_t *) EBDA_SEG_ADDR;
100 low_mem_ptr = (grub_uint16_t *) LOW_MEM_ADDR;
101 if ((*ebda_seg_ptr) || (*low_mem_ptr))
102 return;
103
104 acpi = 0;
105 smbios = 0;
106 for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
107 {
44bbfa33 108 grub_efi_packed_guid_t *guid =
e7e6862a 109 &grub_efi_system_table->configuration_table[i].vendor_guid;
110
111 if (! grub_memcmp (guid, &acpi2_guid, sizeof (grub_efi_guid_t)))
112 {
113 acpi = grub_efi_system_table->configuration_table[i].vendor_table;
114 grub_dprintf ("efi", "ACPI2: %p\n", acpi);
115 }
116 else if (! grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_guid_t)))
117 {
118 void *t;
119
120 t = grub_efi_system_table->configuration_table[i].vendor_table;
121 if (! acpi)
122 acpi = t;
123 grub_dprintf ("efi", "ACPI: %p\n", t);
124 }
125 else if (! grub_memcmp (guid, &smbios_guid, sizeof (grub_efi_guid_t)))
126 {
127 smbios = grub_efi_system_table->configuration_table[i].vendor_table;
128 grub_dprintf ("efi", "SMBIOS: %p\n", smbios);
129 }
130 }
131
132 *ebda_seg_ptr = FAKE_EBDA_SEG;
133 *low_mem_ptr = (FAKE_EBDA_SEG >> 6);
134
135 *((grub_uint16_t *) (FAKE_EBDA_SEG << 4)) = 640 - *low_mem_ptr;
136
137 if (acpi)
138 grub_memcpy ((char *) ((FAKE_EBDA_SEG << 4) + 16), acpi, 1024 - 16);
139
140 if ((use_rom) && (smbios))
141 grub_memcpy ((char *) SBIOS_ADDR, (char *) smbios + 16, 16);
142}
143
144static grub_err_t
145grub_cmd_fakebios (struct grub_command *cmd __attribute__ ((unused)),
146 int argc __attribute__ ((unused)),
147 char *argv[] __attribute__ ((unused)))
148{
149 if (enable_rom_area ())
150 {
151 fake_bios_data (1);
152 lock_rom_area ();
153 }
154 else
155 fake_bios_data (0);
a96df3f2 156
157 return 0;
e7e6862a 158}
159
160static grub_err_t
161grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)),
162 int argc, char *argv[])
163{
164 grub_file_t file;
165 int size;
166
167 if (argc == 0)
9c4b5c13 168 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
e7e6862a 169
170 if (argc > 1)
171 {
172 file = grub_file_open (argv[1]);
173 if (! file)
174 return grub_errno;
175
176 if (file->size != 4)
7fd0baee 177 grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid int10 dump size");
e7e6862a 178 else
5c5215d5 179 grub_file_read (file, (void *) 0x40, 4);
e7e6862a 180
181 grub_file_close (file);
182 if (grub_errno)
183 return grub_errno;
184 }
185
186 file = grub_file_open (argv[0]);
187 if (! file)
188 return grub_errno;
189
190 size = file->size;
191 if ((size < 0x10000) || (size > 0x40000))
7fd0baee 192 grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid bios dump size");
e7e6862a 193 else if (enable_rom_area ())
194 {
5c5215d5 195 grub_file_read (file, (void *) VBIOS_ADDR, size);
e7e6862a 196 fake_bios_data (size <= 0x40000);
197 lock_rom_area ();
198 }
199
200 grub_file_close (file);
201 return grub_errno;
202}
203
204static grub_command_t cmd_fakebios, cmd_loadbios;
205
206GRUB_MOD_INIT(loadbios)
207{
e7e6862a 208 cmd_fakebios = grub_register_command ("fakebios", grub_cmd_fakebios,
9c4b5c13
VS
209 0, N_("Create BIOS-like structures for"
210 " backward compatibility with"
211 " existing OS."));
e7e6862a 212
213 cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
6e0632e2 214 N_("BIOS_DUMP [INT10_DUMP]"),
29c44ad1 215 N_("Load BIOS dump."));
e7e6862a 216}
217
218GRUB_MOD_FINI(loadbios)
219{
220 grub_unregister_command (cmd_fakebios);
221 grub_unregister_command (cmd_loadbios);
222}