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/machine/efiemu.h>
33 #include <grub/command.h>
35 /* System table. Two version depending on mode */
36 grub_efi_system_table32_t
*grub_efiemu_system_table32
= 0;
37 grub_efi_system_table64_t
*grub_efiemu_system_table64
= 0;
38 /* Modules may need to execute some actions after memory allocation happens */
39 static struct grub_efiemu_prepare_hook
*efiemu_prepare_hooks
= 0;
40 /* Linked list of configuration tables */
41 static struct grub_efiemu_configuration_table
*efiemu_config_tables
= 0;
43 /* Free all allocated space */
45 grub_efiemu_unload (void)
47 struct grub_efiemu_configuration_table
*cur
, *d
;
48 struct grub_efiemu_prepare_hook
*curhook
, *d2
;
49 grub_efiemu_loadcore_unload ();
51 grub_efiemu_mm_unload ();
53 for (cur
= efiemu_config_tables
; cur
;)
57 cur
->unload (cur
->data
);
61 efiemu_config_tables
= 0;
63 for (curhook
= efiemu_prepare_hooks
; curhook
;)
67 curhook
->unload (curhook
->data
);
71 efiemu_prepare_hooks
= 0;
76 /* Remove previously registered table from the list */
78 grub_efiemu_unregister_configuration_table (grub_efi_guid_t guid
)
80 struct grub_efiemu_configuration_table
*cur
, *prev
;
82 /* Special treating if head is to remove */
83 while (efiemu_config_tables
84 && !grub_memcmp (&(efiemu_config_tables
->guid
), &guid
, sizeof (guid
)))
86 if (efiemu_config_tables
->unload
)
87 efiemu_config_tables
->unload (efiemu_config_tables
->data
);
88 cur
= efiemu_config_tables
->next
;
89 grub_free (efiemu_config_tables
);
90 efiemu_config_tables
= cur
;
92 if (!efiemu_config_tables
)
95 /* Remove from chain */
96 for (prev
= efiemu_config_tables
, cur
= prev
->next
; cur
;)
97 if (grub_memcmp (&(cur
->guid
), &guid
, sizeof (guid
)) == 0)
100 cur
->unload (cur
->data
);
101 prev
->next
= cur
->next
;
110 return GRUB_ERR_NONE
;
114 grub_efiemu_register_prepare_hook (grub_err_t (*hook
) (void *data
),
115 void (*unload
) (void *data
),
118 struct grub_efiemu_prepare_hook
*nhook
;
120 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "you must supply the hook");
121 nhook
= (struct grub_efiemu_prepare_hook
*) grub_malloc (sizeof (*nhook
));
123 return grub_error (GRUB_ERR_OUT_OF_MEMORY
, "couldn't prepare hook");
125 nhook
->unload
= unload
;
127 nhook
->next
= efiemu_prepare_hooks
;
128 efiemu_prepare_hooks
= nhook
;
129 return GRUB_ERR_NONE
;
132 /* Register a configuration table either supplying the address directly
136 grub_efiemu_register_configuration_table (grub_efi_guid_t guid
,
137 void * (*get_table
) (void *data
),
138 void (*unload
) (void *data
),
141 struct grub_efiemu_configuration_table
*tbl
;
144 if (! get_table
&& ! data
)
145 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
146 "you must set at least get_table or data");
147 if ((err
= grub_efiemu_unregister_configuration_table (guid
)))
150 tbl
= (struct grub_efiemu_configuration_table
*) grub_malloc (sizeof (*tbl
));
152 return grub_error (GRUB_ERR_OUT_OF_MEMORY
, "couldn't register table");
155 tbl
->get_table
= get_table
;
156 tbl
->unload
= unload
;
158 tbl
->next
= efiemu_config_tables
;
159 efiemu_config_tables
= tbl
;
161 return GRUB_ERR_NONE
;
165 grub_cmd_efiemu_unload (grub_command_t cmd
__attribute__ ((unused
)),
166 int argc
__attribute__ ((unused
)),
167 char *args
[] __attribute__ ((unused
)))
169 return grub_efiemu_unload ();
173 grub_cmd_efiemu_prepare (grub_command_t cmd
__attribute__ ((unused
)),
174 int argc
__attribute__ ((unused
)),
175 char *args
[] __attribute__ ((unused
)))
177 return grub_efiemu_prepare ();
184 grub_efiemu_exit_boot_services (grub_efi_uintn_t map_key
185 __attribute__ ((unused
)))
187 /* Nothing to do here yet */
192 grub_efiemu_finish_boot_services (void)
194 /* Nothing to do here yet */
198 /* Load the runtime from the file FILENAME. */
200 grub_efiemu_load_file (const char *filename
)
205 file
= grub_file_open (filename
);
209 err
= grub_efiemu_mm_init ();
212 grub_file_close (file
);
213 grub_efiemu_unload ();
214 return grub_error (grub_errno
, "Couldn't init memory management");
217 grub_dprintf ("efiemu", "mm initialized\n");
219 err
= grub_efiemu_loadcore_init (file
);
222 grub_file_close (file
);
223 grub_efiemu_unload ();
227 grub_file_close (file
);
229 /* For configuration tables entry in system table. */
230 grub_efiemu_request_symbols (1);
232 return GRUB_ERR_NONE
;
236 grub_efiemu_autocore (void)
243 if (grub_efiemu_sizeof_uintn_t () != 0)
244 return GRUB_ERR_NONE
;
246 prefix
= grub_env_get ("prefix");
249 return grub_error (GRUB_ERR_FILE_NOT_FOUND
,
250 "couldn't find efiemu core because prefix "
253 suffix
= grub_efiemu_get_default_core_name ();
255 filename
= grub_malloc (grub_strlen (prefix
) + grub_strlen (suffix
) + 2);
257 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
258 "couldn't allocate temporary space");
260 grub_sprintf (filename
, "%s/%s", prefix
, suffix
);
262 err
= grub_efiemu_load_file (filename
);
263 grub_free (filename
);
267 err
= grub_machine_efiemu_init_tables ();
272 return GRUB_ERR_NONE
;
276 grub_efiemu_prepare (void)
280 grub_dprintf ("efiemu", "Preparing %d-bit efiemu\n",
281 8 * grub_efiemu_sizeof_uintn_t ());
283 err
= grub_efiemu_autocore ();
285 /* Create NVRAM if not yet done. */
286 grub_efiemu_pnvram ();
288 if (grub_efiemu_sizeof_uintn_t () == 4)
289 return grub_efiemu_prepare32 (efiemu_prepare_hooks
, efiemu_config_tables
);
291 return grub_efiemu_prepare64 (efiemu_prepare_hooks
, efiemu_config_tables
);
296 grub_cmd_efiemu_load (grub_command_t cmd
__attribute__ ((unused
)),
297 int argc
, char *args
[])
301 grub_efiemu_unload ();
304 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "filename required");
306 err
= grub_efiemu_load_file (args
[0]);
310 err
= grub_machine_efiemu_init_tables ();
314 return GRUB_ERR_NONE
;
317 static grub_command_t cmd_loadcore
, cmd_prepare
, cmd_unload
;
320 grub_efiemu_pnvram_cmd_register (void);
322 GRUB_MOD_INIT(efiemu
)
324 cmd_loadcore
= grub_register_command ("efiemu_loadcore",
325 grub_cmd_efiemu_load
,
326 "efiemu_loadcore FILE",
327 "Load and initialize EFI emulator");
328 cmd_prepare
= grub_register_command ("efiemu_prepare",
329 grub_cmd_efiemu_prepare
,
331 "Finalize loading of EFI emulator");
332 cmd_unload
= grub_register_command ("efiemu_unload", grub_cmd_efiemu_unload
,
334 "Unload EFI emulator");
335 grub_efiemu_pnvram_cmd_register ();
338 GRUB_MOD_FINI(efiemu
)
340 grub_unregister_command (cmd_loadcore
);
341 grub_unregister_command (cmd_prepare
);
342 grub_unregister_command (cmd_unload
);
343 grub_efiemu_pnvram_cmd_unregister ();