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
;
124 nhook
= (struct grub_efiemu_prepare_hook
*) grub_malloc (sizeof (*nhook
));
128 nhook
->unload
= unload
;
130 nhook
->next
= efiemu_prepare_hooks
;
131 efiemu_prepare_hooks
= nhook
;
132 return GRUB_ERR_NONE
;
135 /* Register a configuration table either supplying the address directly
139 grub_efiemu_register_configuration_table (grub_efi_guid_t guid
,
140 void * (*get_table
) (void *data
),
141 void (*unload
) (void *data
),
144 struct grub_efiemu_configuration_table
*tbl
;
147 err
= grub_efiemu_unregister_configuration_table (guid
);
151 tbl
= (struct grub_efiemu_configuration_table
*) grub_malloc (sizeof (*tbl
));
156 tbl
->get_table
= get_table
;
157 tbl
->unload
= unload
;
159 tbl
->next
= efiemu_config_tables
;
160 efiemu_config_tables
= tbl
;
162 return GRUB_ERR_NONE
;
166 grub_cmd_efiemu_unload (grub_command_t cmd
__attribute__ ((unused
)),
167 int argc
__attribute__ ((unused
)),
168 char *args
[] __attribute__ ((unused
)))
170 return grub_efiemu_unload ();
174 grub_cmd_efiemu_prepare (grub_command_t cmd
__attribute__ ((unused
)),
175 int argc
__attribute__ ((unused
)),
176 char *args
[] __attribute__ ((unused
)))
178 return grub_efiemu_prepare ();
183 /* Load the runtime from the file FILENAME. */
185 grub_efiemu_load_file (const char *filename
)
190 file
= grub_file_open (filename
);
194 err
= grub_efiemu_mm_init ();
197 grub_file_close (file
);
198 grub_efiemu_unload ();
202 grub_dprintf ("efiemu", "mm initialized\n");
204 err
= grub_efiemu_loadcore_init (file
, filename
);
207 grub_file_close (file
);
208 grub_efiemu_unload ();
212 grub_file_close (file
);
214 /* For configuration tables entry in system table. */
215 grub_efiemu_request_symbols (1);
217 return GRUB_ERR_NONE
;
221 grub_efiemu_autocore (void)
228 if (grub_efiemu_sizeof_uintn_t () != 0)
229 return GRUB_ERR_NONE
;
231 prefix
= grub_env_get ("prefix");
234 return grub_error (GRUB_ERR_FILE_NOT_FOUND
,
235 N_("variable `%s' isn't set"), "prefix");
237 suffix
= grub_efiemu_get_default_core_name ();
239 filename
= grub_xasprintf ("%s/" GRUB_TARGET_CPU
"-" GRUB_PLATFORM
"/%s",
244 err
= grub_efiemu_load_file (filename
);
245 grub_free (filename
);
248 #ifndef GRUB_MACHINE_EMU
249 err
= grub_machine_efiemu_init_tables ();
254 return GRUB_ERR_NONE
;
258 grub_efiemu_prepare (void)
263 return GRUB_ERR_NONE
;
265 err
= grub_efiemu_autocore ();
269 grub_dprintf ("efiemu", "Preparing %d-bit efiemu\n",
270 8 * grub_efiemu_sizeof_uintn_t ());
273 grub_efiemu_pnvram ();
277 if (grub_efiemu_sizeof_uintn_t () == 4)
278 return grub_efiemu_prepare32 (efiemu_prepare_hooks
, efiemu_config_tables
);
280 return grub_efiemu_prepare64 (efiemu_prepare_hooks
, efiemu_config_tables
);
285 grub_cmd_efiemu_load (grub_command_t cmd
__attribute__ ((unused
)),
286 int argc
, char *args
[])
290 grub_efiemu_unload ();
293 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
295 err
= grub_efiemu_load_file (args
[0]);
298 #ifndef GRUB_MACHINE_EMU
299 err
= grub_machine_efiemu_init_tables ();
303 return GRUB_ERR_NONE
;
306 static grub_command_t cmd_loadcore
, cmd_prepare
, cmd_unload
;
308 GRUB_MOD_INIT(efiemu
)
310 cmd_loadcore
= grub_register_command ("efiemu_loadcore",
311 grub_cmd_efiemu_load
,
313 N_("Load and initialize EFI emulator."));
314 cmd_prepare
= grub_register_command ("efiemu_prepare",
315 grub_cmd_efiemu_prepare
,
317 N_("Finalize loading of EFI emulator."));
318 cmd_unload
= grub_register_command ("efiemu_unload", grub_cmd_efiemu_unload
,
320 N_("Unload EFI emulator."));
323 GRUB_MOD_FINI(efiemu
)
325 grub_unregister_command (cmd_loadcore
);
326 grub_unregister_command (cmd_prepare
);
327 grub_unregister_command (cmd_unload
);