Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / commands / efi / loadbios.c
blob214adc3d2e205d756a07235ffac56e0f3e6573a5
1 /* loadbios.c - command to load a bios dump */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2009 Free Software Foundation, Inc.
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.
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.
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/>.
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>
26 #include <grub/i18n.h>
28 GRUB_MOD_LICENSE ("GPLv3+");
30 static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID;
31 static grub_efi_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID;
32 static grub_efi_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID;
34 #define EBDA_SEG_ADDR 0x40e
35 #define LOW_MEM_ADDR 0x413
36 #define FAKE_EBDA_SEG 0x9fc0
38 #define BLANK_MEM 0xffffffff
39 #define VBIOS_ADDR 0xc0000
40 #define SBIOS_ADDR 0xf0000
42 static int
43 enable_rom_area (void)
45 grub_pci_address_t addr;
46 grub_uint32_t *rom_ptr;
47 grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
49 rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
50 if (*rom_ptr != BLANK_MEM)
52 grub_puts_ (N_("ROM image is present."));
53 return 0;
56 /* FIXME: should be macroified. */
57 addr = grub_pci_make_address (dev, 144);
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);
67 *rom_ptr = 0;
68 if (*rom_ptr != 0)
70 grub_puts_ (N_("Can\'t enable ROM area."));
71 return 0;
74 return 1;
77 static void
78 lock_rom_area (void)
80 grub_pci_address_t addr;
81 grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
83 /* FIXME: should be macroified. */
84 addr = grub_pci_make_address (dev, 144);
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);
92 static void
93 fake_bios_data (int use_rom)
95 unsigned i;
96 void *acpi, *smbios;
97 grub_uint16_t *ebda_seg_ptr, *low_mem_ptr;
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;
104 acpi = 0;
105 smbios = 0;
106 for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
108 grub_efi_guid_t *guid =
109 &grub_efi_system_table->configuration_table[i].vendor_guid;
111 if (! grub_memcmp (guid, &acpi2_guid, sizeof (grub_efi_guid_t)))
113 acpi = grub_efi_system_table->configuration_table[i].vendor_table;
114 grub_dprintf ("efi", "ACPI2: %p\n", acpi);
116 else if (! grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_guid_t)))
118 void *t;
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);
125 else if (! grub_memcmp (guid, &smbios_guid, sizeof (grub_efi_guid_t)))
127 smbios = grub_efi_system_table->configuration_table[i].vendor_table;
128 grub_dprintf ("efi", "SMBIOS: %p\n", smbios);
132 *ebda_seg_ptr = FAKE_EBDA_SEG;
133 *low_mem_ptr = (FAKE_EBDA_SEG >> 6);
135 *((grub_uint16_t *) (FAKE_EBDA_SEG << 4)) = 640 - *low_mem_ptr;
137 if (acpi)
138 grub_memcpy ((char *) ((FAKE_EBDA_SEG << 4) + 16), acpi, 1024 - 16);
140 if ((use_rom) && (smbios))
141 grub_memcpy ((char *) SBIOS_ADDR, (char *) smbios + 16, 16);
144 static grub_err_t
145 grub_cmd_fakebios (struct grub_command *cmd __attribute__ ((unused)),
146 int argc __attribute__ ((unused)),
147 char *argv[] __attribute__ ((unused)))
149 if (enable_rom_area ())
151 fake_bios_data (1);
152 lock_rom_area ();
154 else
155 fake_bios_data (0);
157 return 0;
160 static grub_err_t
161 grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)),
162 int argc, char *argv[])
164 grub_file_t file;
165 int size;
167 if (argc == 0)
168 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
170 if (argc > 1)
172 file = grub_file_open (argv[1]);
173 if (! file)
174 return grub_errno;
176 if (file->size != 4)
177 grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid int10 dump size");
178 else
179 grub_file_read (file, (void *) 0x40, 4);
181 grub_file_close (file);
182 if (grub_errno)
183 return grub_errno;
186 file = grub_file_open (argv[0]);
187 if (! file)
188 return grub_errno;
190 size = file->size;
191 if ((size < 0x10000) || (size > 0x40000))
192 grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid bios dump size");
193 else if (enable_rom_area ())
195 grub_file_read (file, (void *) VBIOS_ADDR, size);
196 fake_bios_data (size <= 0x40000);
197 lock_rom_area ();
200 grub_file_close (file);
201 return grub_errno;
204 static grub_command_t cmd_fakebios, cmd_loadbios;
206 GRUB_MOD_INIT(loadbios)
208 cmd_fakebios = grub_register_command ("fakebios", grub_cmd_fakebios,
209 0, N_("Create BIOS-like structures for"
210 " backward compatibility with"
211 " existing OS."));
213 cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
214 N_("BIOS_DUMP [INT10_DUMP]"),
215 N_("Load BIOS dump."));
218 GRUB_MOD_FINI(loadbios)
220 grub_unregister_command (cmd_fakebios);
221 grub_unregister_command (cmd_loadbios);