2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2009 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 /* This is an emulation of EFI runtime services.
20 This allows a more uniform boot on i386 machines.
21 As it emulates only runtime service it isn't able
22 to chainload EFI bootloader on non-EFI system. */
25 #include <grub/file.h>
27 #include <grub/normal.h>
30 #include <grub/misc.h>
31 #include <grub/efiemu/efiemu.h>
32 #include <grub/command.h>
33 #include <grub/i18n.h>
35 GRUB_MOD_LICENSE ("GPLv3+");
37 /* System table. Two version depending on mode */
38 grub_efi_system_table32_t
*grub_efiemu_system_table32
= 0;
39 grub_efi_system_table64_t
*grub_efiemu_system_table64
= 0;
40 /* Modules may need to execute some actions after memory allocation happens */
41 static struct grub_efiemu_prepare_hook
*efiemu_prepare_hooks
= 0;
42 /* Linked list of configuration tables */
43 static struct grub_efiemu_configuration_table
*efiemu_config_tables
= 0;
44 static int prepared
= 0;
46 /* Free all allocated space */
48 grub_efiemu_unload (void)
50 struct grub_efiemu_configuration_table
*cur
, *d
;
51 struct grub_efiemu_prepare_hook
*curhook
, *d2
;
52 grub_efiemu_loadcore_unload ();
54 grub_efiemu_mm_unload ();
56 for (cur
= efiemu_config_tables
; cur
;)
60 cur
->unload (cur
->data
);
64 efiemu_config_tables
= 0;
66 for (curhook
= efiemu_prepare_hooks
; curhook
;)
70 curhook
->unload (curhook
->data
);
74 efiemu_prepare_hooks
= 0;
81 /* Remove previously registered table from the list */
83 grub_efiemu_unregister_configuration_table (grub_efi_guid_t guid
)
85 struct grub_efiemu_configuration_table
*cur
, *prev
;
87 /* Special treating if head is to remove */
88 while (efiemu_config_tables
89 && !grub_memcmp (&(efiemu_config_tables
->guid
), &guid
, sizeof (guid
)))
91 if (efiemu_config_tables
->unload
)
92 efiemu_config_tables
->unload (efiemu_config_tables
->data
);
93 cur
= efiemu_config_tables
->next
;
94 grub_free (efiemu_config_tables
);
95 efiemu_config_tables
= cur
;
97 if (!efiemu_config_tables
)
100 /* Remove from chain */
101 for (prev
= efiemu_config_tables
, cur
= prev
->next
; cur
;)
102 if (grub_memcmp (&(cur
->guid
), &guid
, sizeof (guid
)) == 0)
105 cur
->unload (cur
->data
);
106 prev
->next
= cur
->next
;
115 return GRUB_ERR_NONE
;
119 grub_efiemu_register_prepare_hook (grub_err_t (*hook
) (void *data
),
120 void (*unload
) (void *data
),
123 struct grub_efiemu_prepare_hook
*nhook
;
125 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "you must supply the hook");
126 nhook
= (struct grub_efiemu_prepare_hook
*) grub_malloc (sizeof (*nhook
));
128 return grub_error (GRUB_ERR_OUT_OF_MEMORY
, "couldn't prepare hook");
130 nhook
->unload
= unload
;
132 nhook
->next
= efiemu_prepare_hooks
;
133 efiemu_prepare_hooks
= nhook
;
134 return GRUB_ERR_NONE
;
137 /* Register a configuration table either supplying the address directly
141 grub_efiemu_register_configuration_table (grub_efi_guid_t guid
,
142 void * (*get_table
) (void *data
),
143 void (*unload
) (void *data
),
146 struct grub_efiemu_configuration_table
*tbl
;
149 if (! get_table
&& ! data
)
150 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
151 "you must set at least get_table or data");
152 err
= grub_efiemu_unregister_configuration_table (guid
);
156 tbl
= (struct grub_efiemu_configuration_table
*) grub_malloc (sizeof (*tbl
));
158 return grub_error (GRUB_ERR_OUT_OF_MEMORY
, "couldn't register table");
161 tbl
->get_table
= get_table
;
162 tbl
->unload
= unload
;
164 tbl
->next
= efiemu_config_tables
;
165 efiemu_config_tables
= tbl
;
167 return GRUB_ERR_NONE
;
171 grub_cmd_efiemu_unload (grub_command_t cmd
__attribute__ ((unused
)),
172 int argc
__attribute__ ((unused
)),
173 char *args
[] __attribute__ ((unused
)))
175 return grub_efiemu_unload ();
179 grub_cmd_efiemu_prepare (grub_command_t cmd
__attribute__ ((unused
)),
180 int argc
__attribute__ ((unused
)),
181 char *args
[] __attribute__ ((unused
)))
183 return grub_efiemu_prepare ();
188 /* Load the runtime from the file FILENAME. */
190 grub_efiemu_load_file (const char *filename
)
195 file
= grub_file_open (filename
);
199 err
= grub_efiemu_mm_init ();
202 grub_file_close (file
);
203 grub_efiemu_unload ();
204 return grub_error (grub_errno
, "couldn't init memory management");
207 grub_dprintf ("efiemu", "mm initialized\n");
209 err
= grub_efiemu_loadcore_init (file
);
212 grub_file_close (file
);
213 grub_efiemu_unload ();
217 grub_file_close (file
);
219 /* For configuration tables entry in system table. */
220 grub_efiemu_request_symbols (1);
222 return GRUB_ERR_NONE
;
226 grub_efiemu_autocore (void)
233 if (grub_efiemu_sizeof_uintn_t () != 0)
234 return GRUB_ERR_NONE
;
236 prefix
= grub_env_get ("prefix");
239 return grub_error (GRUB_ERR_FILE_NOT_FOUND
,
240 "couldn't find efiemu core because prefix "
243 suffix
= grub_efiemu_get_default_core_name ();
245 filename
= grub_xasprintf ("%s/" GRUB_TARGET_CPU
"-" GRUB_PLATFORM
"/%s",
248 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
249 "couldn't allocate temporary space");
251 err
= grub_efiemu_load_file (filename
);
252 grub_free (filename
);
255 #ifndef GRUB_MACHINE_EMU
256 err
= grub_machine_efiemu_init_tables ();
261 return GRUB_ERR_NONE
;
265 grub_efiemu_prepare (void)
270 return GRUB_ERR_NONE
;
272 err
= grub_efiemu_autocore ();
276 grub_dprintf ("efiemu", "Preparing %d-bit efiemu\n",
277 8 * grub_efiemu_sizeof_uintn_t ());
280 grub_efiemu_pnvram ();
284 if (grub_efiemu_sizeof_uintn_t () == 4)
285 return grub_efiemu_prepare32 (efiemu_prepare_hooks
, efiemu_config_tables
);
287 return grub_efiemu_prepare64 (efiemu_prepare_hooks
, efiemu_config_tables
);
292 grub_cmd_efiemu_load (grub_command_t cmd
__attribute__ ((unused
)),
293 int argc
, char *args
[])
297 grub_efiemu_unload ();
300 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "filename required");
302 err
= grub_efiemu_load_file (args
[0]);
305 #ifndef GRUB_MACHINE_EMU
306 err
= grub_machine_efiemu_init_tables ();
310 return GRUB_ERR_NONE
;
313 static grub_command_t cmd_loadcore
, cmd_prepare
, cmd_unload
;
315 GRUB_MOD_INIT(efiemu
)
317 cmd_loadcore
= grub_register_command ("efiemu_loadcore",
318 grub_cmd_efiemu_load
,
320 N_("Load and initialize EFI emulator."));
321 cmd_prepare
= grub_register_command ("efiemu_prepare",
322 grub_cmd_efiemu_prepare
,
324 N_("Finalize loading of EFI emulator."));
325 cmd_unload
= grub_register_command ("efiemu_unload", grub_cmd_efiemu_unload
,
327 N_("Unload EFI emulator."));
330 GRUB_MOD_FINI(efiemu
)
332 grub_unregister_command (cmd_loadcore
);
333 grub_unregister_command (cmd_prepare
);
334 grub_unregister_command (cmd_unload
);