2009-09-08 Felix Zielcke <fzielcke@z-51.de>
[grub2/phcoder/solaris.git] / efiemu / loadcore_common.c
bloba4db0ee9b947e613f95f47a4485fb118c3a6c021
1 /* Load runtime image of EFIemu. Functions common to 32/64-bit mode */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2009 Free Software Foundation, Inc.
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.
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.
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/>.
20 #include <grub/file.h>
21 #include <grub/err.h>
22 #include <grub/mm.h>
23 #include <grub/misc.h>
24 #include <grub/efiemu/efiemu.h>
25 #include <grub/cpu/efiemu.h>
27 /* Are we in 32 or 64-bit mode?*/
28 static grub_efiemu_mode_t grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED;
29 /* Runtime ELF file */
30 static grub_ssize_t efiemu_core_size;
31 static void *efiemu_core = 0;
32 /* Linked list of segments */
33 static grub_efiemu_segment_t efiemu_segments = 0;
35 /* equivalent to sizeof (grub_efi_uintn_t) but taking the mode into account*/
36 int
37 grub_efiemu_sizeof_uintn_t (void)
39 if (grub_efiemu_mode == GRUB_EFIEMU32)
40 return 4;
41 if (grub_efiemu_mode == GRUB_EFIEMU64)
42 return 8;
43 return 0;
46 /* Check the header and set mode */
47 static grub_err_t
48 grub_efiemu_check_header (void *ehdr, grub_size_t size,
49 grub_efiemu_mode_t *mode)
51 /* Check the magic numbers. */
52 if ((*mode == GRUB_EFIEMU_NOTLOADED || *mode == GRUB_EFIEMU32)
53 && grub_efiemu_check_header32 (ehdr,size))
55 *mode = GRUB_EFIEMU32;
56 return GRUB_ERR_NONE;
58 if ((*mode == GRUB_EFIEMU_NOTLOADED || *mode == GRUB_EFIEMU64)
59 && grub_efiemu_check_header64 (ehdr,size))
61 *mode = GRUB_EFIEMU64;
62 return GRUB_ERR_NONE;
64 return grub_error (GRUB_ERR_BAD_OS, "invalid ELF magic");
67 /* Unload segments */
68 static int
69 grub_efiemu_unload_segs (grub_efiemu_segment_t seg)
71 grub_efiemu_segment_t segn;
72 for (; seg; seg = segn)
74 segn = seg->next;
75 grub_efiemu_mm_return_request (seg->handle);
76 grub_free (seg);
78 return 1;
82 grub_err_t
83 grub_efiemu_loadcore_unload(void)
85 switch (grub_efiemu_mode)
87 case GRUB_EFIEMU32:
88 grub_efiemu_loadcore_unload32 ();
89 break;
91 case GRUB_EFIEMU64:
92 grub_efiemu_loadcore_unload64 ();
93 break;
95 default:
96 break;
99 grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED;
101 grub_free (efiemu_core);
102 efiemu_core = 0;
104 grub_efiemu_unload_segs (efiemu_segments);
105 efiemu_segments = 0;
107 grub_efiemu_free_syms ();
109 return GRUB_ERR_NONE;
112 /* Load runtime file and do some initial preparations */
113 grub_err_t
114 grub_efiemu_loadcore_init (grub_file_t file)
116 grub_err_t err;
118 efiemu_core_size = grub_file_size (file);
119 efiemu_core = 0;
120 efiemu_core = grub_malloc (efiemu_core_size);
121 if (! efiemu_core)
122 return grub_errno;
124 if (grub_file_read (file, efiemu_core, efiemu_core_size)
125 != (int) efiemu_core_size)
127 grub_free (efiemu_core);
128 efiemu_core = 0;
129 return grub_errno;
132 if (grub_efiemu_check_header (efiemu_core, efiemu_core_size,
133 &grub_efiemu_mode))
135 grub_free (efiemu_core);
136 efiemu_core = 0;
137 return GRUB_ERR_BAD_MODULE;
140 switch (grub_efiemu_mode)
142 case GRUB_EFIEMU32:
143 if ((err = grub_efiemu_loadcore_init32 (efiemu_core, efiemu_core_size,
144 &efiemu_segments)))
146 grub_free (efiemu_core);
147 efiemu_core = 0;
148 grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED;
149 return err;
151 break;
153 case GRUB_EFIEMU64:
154 if ((err = grub_efiemu_loadcore_init64 (efiemu_core, efiemu_core_size,
155 &efiemu_segments)))
157 grub_free (efiemu_core);
158 efiemu_core = 0;
159 grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED;
160 return err;
162 break;
164 default:
165 return grub_error (GRUB_ERR_BAD_OS, "unknown EFI runtime");
167 return GRUB_ERR_NONE;
170 grub_err_t
171 grub_efiemu_loadcore_load (void)
173 grub_err_t err;
174 switch (grub_efiemu_mode)
176 case GRUB_EFIEMU32:
177 if ((err = grub_efiemu_loadcore_load32 (efiemu_core, efiemu_core_size,
178 efiemu_segments)))
179 grub_efiemu_loadcore_unload ();
180 return err;
181 case GRUB_EFIEMU64:
182 if ((err = grub_efiemu_loadcore_load64 (efiemu_core, efiemu_core_size,
183 efiemu_segments)))
184 grub_efiemu_loadcore_unload ();
185 return err;
186 default:
187 return grub_error (GRUB_ERR_BAD_OS, "unknown EFI runtime");