source: grub-pc/trunk/fuentes/grub-core/commands/efi/loadbios.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 5.7 KB
Line 
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>
26#include <grub/i18n.h>
27
28GRUB_MOD_LICENSE ("GPLv3+");
29
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;
47  grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
48
49  rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
50  if (*rom_ptr != BLANK_MEM)
51    {
52      grub_puts_ (N_("ROM image is present."));
53      return 0;
54    }
55
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);
66
67  *rom_ptr = 0;
68  if (*rom_ptr != 0)
69    {
70      grub_puts_ (N_("Can\'t enable ROM area."));
71      return 0;
72    }
73
74  return 1;
75}
76
77static void
78lock_rom_area (void)
79{
80  grub_pci_address_t addr;
81  grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
82
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);
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    {
108      grub_efi_packed_guid_t *guid =
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);
156
157  return 0;
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)
168    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
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)
177        grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid int10 dump size");
178      else
179        grub_file_read (file, (void *) 0x40, 4);
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))
192    grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid bios dump size");
193  else if (enable_rom_area ())
194    {
195      grub_file_read (file, (void *) VBIOS_ADDR, size);
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{
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."));
212
213  cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
214                                        N_("BIOS_DUMP [INT10_DUMP]"),
215                                        N_("Load BIOS dump."));
216}
217
218GRUB_MOD_FINI(loadbios)
219{
220  grub_unregister_command (cmd_fakebios);
221  grub_unregister_command (cmd_loadbios);
222}
Note: See TracBrowser for help on using the repository browser.