malloc->zalloc
[grub2/phcoder.git] / efiemu / main.c
blob48253239972aa3390ac920a5d4fc4657760053ab
1 /*
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>
26 #include <grub/err.h>
27 #include <grub/normal.h>
28 #include <grub/mm.h>
29 #include <grub/dl.h>
30 #include <grub/misc.h>
31 #include <grub/efiemu/efiemu.h>
32 #include <grub/machine/efiemu.h>
33 #include <grub/command.h>
34 #include <grub/cpu/cpuid.h>
36 /* System table. Two version depending on mode */
37 grub_efi_system_table32_t *grub_efiemu_system_table32 = 0;
38 grub_efi_system_table64_t *grub_efiemu_system_table64 = 0;
39 /* Modules may need to execute some actions after memory allocation happens */
40 static struct grub_efiemu_prepare_hook *efiemu_prepare_hooks = 0;
41 /* Linked list of configuration tables */
42 static struct grub_efiemu_configuration_table *efiemu_config_tables = 0;
44 /* Free all allocated space */
45 grub_err_t
46 grub_efiemu_unload (void)
48 struct grub_efiemu_configuration_table *cur, *d;
49 struct grub_efiemu_prepare_hook *curhook, *d2;
50 grub_efiemu_loadcore_unload ();
52 grub_efiemu_mm_unload ();
54 for (cur = efiemu_config_tables; cur;)
56 d = cur->next;
57 if (cur->unload)
58 cur->unload (cur->data);
59 grub_free (cur);
60 cur = d;
62 efiemu_config_tables = 0;
64 for (curhook = efiemu_prepare_hooks; curhook;)
66 d2 = curhook->next;
67 if (curhook->unload)
68 curhook->unload (curhook->data);
69 grub_free (curhook);
70 curhook = d2;
72 efiemu_prepare_hooks = 0;
74 return GRUB_ERR_NONE;
77 /* Remove previously registered table from the list */
78 grub_err_t
79 grub_efiemu_unregister_configuration_table (grub_efi_guid_t guid)
81 struct grub_efiemu_configuration_table *cur, *prev;
83 /* Special treating if head is to remove */
84 while (efiemu_config_tables
85 && !grub_memcmp (&(efiemu_config_tables->guid), &guid, sizeof (guid)))
87 if (efiemu_config_tables->unload)
88 efiemu_config_tables->unload (efiemu_config_tables->data);
89 cur = efiemu_config_tables->next;
90 grub_free (efiemu_config_tables);
91 efiemu_config_tables = cur;
93 if (!efiemu_config_tables)
94 return GRUB_ERR_NONE;
96 /* Remove from chain */
97 for (prev = efiemu_config_tables, cur = prev->next; cur;)
98 if (grub_memcmp (&(cur->guid), &guid, sizeof (guid)) == 0)
100 if (cur->unload)
101 cur->unload (cur->data);
102 prev->next = cur->next;
103 grub_free (cur);
104 cur = prev->next;
106 else
108 prev = cur;
109 cur = cur->next;
111 return GRUB_ERR_NONE;
114 grub_err_t
115 grub_efiemu_register_prepare_hook (grub_err_t (*hook) (void *data),
116 void (*unload) (void *data),
117 void *data)
119 struct grub_efiemu_prepare_hook *nhook;
120 if (! hook)
121 return grub_error (GRUB_ERR_BAD_ARGUMENT, "you must supply the hook");
122 nhook = (struct grub_efiemu_prepare_hook *) grub_malloc (sizeof (*nhook));
123 if (! nhook)
124 return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't prepare hook");
125 nhook->hook = hook;
126 nhook->unload = unload;
127 nhook->data = data;
128 nhook->next = efiemu_prepare_hooks;
129 efiemu_prepare_hooks = nhook;
130 return GRUB_ERR_NONE;
133 /* Register a configuration table either supplying the address directly
134 or with a hook
136 grub_err_t
137 grub_efiemu_register_configuration_table (grub_efi_guid_t guid,
138 void * (*get_table) (void *data),
139 void (*unload) (void *data),
140 void *data)
142 struct grub_efiemu_configuration_table *tbl;
143 grub_err_t err;
145 if (! get_table && ! data)
146 return grub_error (GRUB_ERR_BAD_ARGUMENT,
147 "you must set at least get_table or data");
148 if ((err = grub_efiemu_unregister_configuration_table (guid)))
149 return err;
151 tbl = (struct grub_efiemu_configuration_table *) grub_malloc (sizeof (*tbl));
152 if (! tbl)
153 return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't register table");
155 tbl->guid = guid;
156 tbl->get_table = get_table;
157 tbl->unload = unload;
158 tbl->data = data;
159 tbl->next = efiemu_config_tables;
160 efiemu_config_tables = tbl;
162 return GRUB_ERR_NONE;
165 static grub_err_t
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 ();
173 static grub_err_t
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 ();
185 grub_efiemu_exit_boot_services (grub_efi_uintn_t map_key
186 __attribute__ ((unused)))
188 /* Nothing to do here yet */
189 return 1;
193 grub_efiemu_finish_boot_services (void)
195 /* Nothing to do here yet */
196 return 1;
199 /* Load the runtime from the file FILENAME. */
200 static grub_err_t
201 grub_efiemu_load_file (const char *filename)
203 grub_file_t file;
204 grub_err_t err;
206 file = grub_file_open (filename);
207 if (! file)
208 return 0;
210 err = grub_efiemu_mm_init ();
211 if (err)
213 grub_file_close (file);
214 grub_efiemu_unload ();
215 return grub_error (grub_errno, "Couldn't init memory management");
218 grub_dprintf ("efiemu", "mm initialized\n");
220 err = grub_efiemu_loadcore_init (file);
221 if (err)
223 grub_file_close (file);
224 grub_efiemu_unload ();
225 return err;
228 grub_file_close (file);
230 /* For configuration tables entry in system table. */
231 grub_efiemu_request_symbols (1);
233 return GRUB_ERR_NONE;
236 grub_err_t
237 grub_efiemu_autocore (void)
239 const char *prefix;
240 char *filename;
241 grub_err_t err;
242 int longmode;
244 if (grub_efiemu_sizeof_uintn_t () != 0)
245 return GRUB_ERR_NONE;
247 prefix = grub_env_get ("prefix");
249 if (! prefix)
250 return grub_error (GRUB_ERR_FILE_NOT_FOUND,
251 "couldn't find efiemu core because prefix "
252 "isn't set");
254 longmode = grub_i386_cpuid_has_longmode ();
256 filename = grub_malloc (grub_strlen (prefix) + sizeof ("efiemuXX.o") + 1);
257 if (! filename)
258 return grub_error (GRUB_ERR_OUT_OF_MEMORY,
259 "couldn't allocate temporary space");
261 if (longmode)
263 grub_sprintf (filename, "%s/efiemu64.o", prefix);
264 err = grub_efiemu_load_file (filename);
267 if (! longmode || err)
269 grub_sprintf (filename, "%s/efiemu32.o", prefix);
270 err = grub_efiemu_load_file (filename);
273 grub_free (filename);
275 if (err)
276 return err;
277 #ifndef GRUB_UTIL
278 err = grub_machine_efiemu_init_tables ();
279 if (err)
280 return err;
281 #endif
283 return GRUB_ERR_NONE;
286 grub_err_t
287 grub_efiemu_prepare (void)
289 grub_err_t err;
291 grub_dprintf ("efiemu", "Preparing %d-bit efiemu\n",
292 8 * grub_efiemu_sizeof_uintn_t ());
294 err = grub_efiemu_autocore ();
296 /* Create NVRAM if not yet done. */
297 grub_efiemu_pnvram ();
299 if (grub_efiemu_sizeof_uintn_t () == 4)
300 return grub_efiemu_prepare32 (efiemu_prepare_hooks, efiemu_config_tables);
301 else
302 return grub_efiemu_prepare64 (efiemu_prepare_hooks, efiemu_config_tables);
306 static grub_err_t
307 grub_cmd_efiemu_load (grub_command_t cmd __attribute__ ((unused)),
308 int argc, char *args[])
310 grub_err_t err;
312 grub_efiemu_unload ();
314 if (argc != 1)
315 return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename required");
317 err = grub_efiemu_load_file (args[0]);
318 if (err)
319 return err;
320 #ifndef GRUB_UTIL
321 err = grub_machine_efiemu_init_tables ();
322 if (err)
323 return err;
324 #endif
325 return GRUB_ERR_NONE;
328 static grub_command_t cmd_loadcore, cmd_prepare, cmd_unload;
330 void
331 grub_efiemu_pnvram_cmd_register (void);
333 GRUB_MOD_INIT(efiemu)
335 cmd_loadcore = grub_register_command ("efiemu_loadcore",
336 grub_cmd_efiemu_load,
337 "efiemu_loadcore FILE",
338 "Load and initialize EFI emulator");
339 cmd_prepare = grub_register_command ("efiemu_prepare",
340 grub_cmd_efiemu_prepare,
341 "efiemu_prepare",
342 "Finalize loading of EFI emulator");
343 cmd_unload = grub_register_command ("efiemu_unload", grub_cmd_efiemu_unload,
344 "efiemu_unload",
345 "Unload EFI emulator");
346 grub_efiemu_pnvram_cmd_register ();
349 GRUB_MOD_FINI(efiemu)
351 grub_unregister_command (cmd_loadcore);
352 grub_unregister_command (cmd_prepare);
353 grub_unregister_command (cmd_unload);
354 grub_efiemu_pnvram_cmd_unregister ();