]> git.proxmox.com Git - grub2.git/blob - grub-core/loader/efi/appleloader.c
d8ca4a7f3e4ef9218f2fe98d90db676d56163f4a
[grub2.git] / grub-core / loader / efi / appleloader.c
1 /* appleloader.c - apple legacy boot loader. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008,2009 Free Software Foundation, Inc.
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
20 #include <grub/loader.h>
21 #include <grub/err.h>
22 #include <grub/mm.h>
23 #include <grub/dl.h>
24 #include <grub/misc.h>
25 #include <grub/efi/api.h>
26 #include <grub/efi/efi.h>
27 #include <grub/command.h>
28 #include <grub/i18n.h>
29
30 GRUB_MOD_LICENSE ("GPLv3+");
31
32 static grub_dl_t my_mod;
33
34 static grub_efi_handle_t image_handle;
35 static grub_efi_char16_t *cmdline;
36
37 static grub_err_t
38 grub_appleloader_unload (void)
39 {
40 grub_efi_boot_services_t *b;
41
42 b = grub_efi_system_table->boot_services;
43 efi_call_1 (b->unload_image, image_handle);
44
45 grub_free (cmdline);
46 cmdline = 0;
47
48 grub_dl_unref (my_mod);
49 return GRUB_ERR_NONE;
50 }
51
52 static grub_err_t
53 grub_appleloader_boot (void)
54 {
55 grub_efi_boot_services_t *b;
56
57 b = grub_efi_system_table->boot_services;
58 efi_call_3 (b->start_image, image_handle, 0, 0);
59
60 grub_appleloader_unload ();
61
62 return grub_errno;
63 }
64
65 struct piwg_full_device_path
66 {
67 struct grub_efi_memory_mapped_device_path comp1;
68 struct grub_efi_piwg_device_path comp2;
69 struct grub_efi_device_path end;
70 };
71
72 /* early 2006 Core Duo / Core Solo models */
73 static struct piwg_full_device_path devpath_1 =
74 {
75 .comp1 =
76 {
77 .header = {
78 .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE,
79 .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE,
80 .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0}
81 },
82 .memory_type = GRUB_EFI_MEMORY_MAPPED_IO,
83 .start_address = 0xffe00000,
84 .end_address = 0xfff9ffff
85 },
86 .comp2 =
87 {
88 .header = {
89 .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
90 .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE,
91 .length = {sizeof (struct grub_efi_piwg_device_path), 0}
92 },
93 .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B,
94 0x01, 0xAE, 0xF2, 0xB7}}
95 },
96 .end =
97 {
98 .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
99 .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
100 .length = {sizeof (struct grub_efi_device_path), 0}
101 }
102 };
103
104 /* mid-2006 Mac Pro (and probably other Core 2 models) */
105 static struct piwg_full_device_path devpath_2 =
106 {
107 .comp1 =
108 {
109 .header = {
110 .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE,
111 .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE,
112 .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0}
113 },
114 .memory_type = GRUB_EFI_MEMORY_MAPPED_IO,
115 .start_address = 0xffe00000,
116 .end_address = 0xfff7ffff
117 },
118 .comp2 =
119 {
120 .header = {
121 .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
122 .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE,
123 .length = {sizeof (struct grub_efi_piwg_device_path), 0}
124 },
125 .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B,
126 0x01, 0xAE, 0xF2, 0xB7}}
127 },
128 .end =
129 {
130 .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
131 .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
132 .length = {sizeof (struct grub_efi_device_path), 0}
133 }
134 };
135
136 /* mid-2007 MBP ("Santa Rosa" based models) */
137 static struct piwg_full_device_path devpath_3 =
138 {
139 .comp1 =
140 {
141 .header = {
142 .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE,
143 .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE,
144 .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0}
145 },
146 .memory_type = GRUB_EFI_MEMORY_MAPPED_IO,
147 .start_address = 0xffe00000,
148 .end_address = 0xfff8ffff
149 },
150 .comp2 =
151 {
152 .header = {
153 .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
154 .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE,
155 .length = {sizeof (struct grub_efi_piwg_device_path), 0}
156 },
157 .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B,
158 0x01, 0xAE, 0xF2, 0xB7}}
159 },
160 .end =
161 {
162 .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
163 .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
164 .length = {sizeof (struct grub_efi_device_path), 0}
165 }
166 };
167
168 /* early-2008 MBA */
169 static struct piwg_full_device_path devpath_4 =
170 {
171 .comp1 =
172 {
173 .header = {
174 .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE,
175 .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE,
176 .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0}
177 },
178 .memory_type = GRUB_EFI_MEMORY_MAPPED_IO,
179 .start_address = 0xffc00000,
180 .end_address = 0xfff8ffff
181 },
182 .comp2 =
183 {
184 .header = {
185 .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
186 .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE,
187 .length = {sizeof (struct grub_efi_piwg_device_path), 0}
188 },
189 .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B,
190 0x01, 0xAE, 0xF2, 0xB7}}
191 },
192 .end =
193 {
194 .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
195 .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
196 .length = {sizeof (struct grub_efi_device_path), 0}
197 }
198 };
199
200 /* late-2008 MB/MBP (NVidia chipset) */
201 static struct piwg_full_device_path devpath_5 =
202 {
203 .comp1 =
204 {
205 .header = {
206 .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE,
207 .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE,
208 .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0}
209 },
210 .memory_type = GRUB_EFI_MEMORY_MAPPED_IO,
211 .start_address = 0xffcb4000,
212 .end_address = 0xffffbfff
213 },
214 .comp2 =
215 {
216 .header = {
217 .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
218 .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE,
219 .length = {sizeof (struct grub_efi_piwg_device_path), 0}
220 },
221 .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B,
222 0x01, 0xAE, 0xF2, 0xB7}}
223 },
224 .end =
225 {
226 .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
227 .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
228 .length = {sizeof (struct grub_efi_device_path), 0}
229 }
230 };
231
232 /* mid-2010 MB/MBP (NVidia chipset) */
233 static struct piwg_full_device_path devpath_6 =
234 {
235 .comp1 =
236 {
237 .header = {
238 .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE,
239 .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE,
240 .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0}
241 },
242 .memory_type = GRUB_EFI_MEMORY_MAPPED_IO,
243 .start_address = 0xffcc4000,
244 .end_address = 0xffffbfff
245 },
246 .comp2 =
247 {
248 .header = {
249 .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
250 .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE,
251 .length = {sizeof (struct grub_efi_piwg_device_path), 0}
252 },
253 .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B,
254 0x01, 0xAE, 0xF2, 0xB7}}
255 },
256 .end =
257 {
258 .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
259 .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
260 .length = {sizeof (struct grub_efi_device_path), 0}
261 }
262 };
263
264 struct devdata
265 {
266 char *model;
267 grub_efi_device_path_t *devpath;
268 };
269
270 struct devdata devs[] =
271 {
272 {"Core Duo/Solo", (grub_efi_device_path_t *) &devpath_1},
273 {"Mac Pro", (grub_efi_device_path_t *) &devpath_2},
274 {"MBP", (grub_efi_device_path_t *) &devpath_3},
275 {"MBA", (grub_efi_device_path_t *) &devpath_4},
276 {"MB NV", (grub_efi_device_path_t *) &devpath_5},
277 {"MB NV2", (grub_efi_device_path_t *) &devpath_6},
278 {NULL, NULL},
279 };
280
281 static grub_err_t
282 grub_cmd_appleloader (grub_command_t cmd __attribute__ ((unused)),
283 int argc, char *argv[])
284 {
285 grub_efi_boot_services_t *b;
286 grub_efi_loaded_image_t *loaded_image;
287 struct devdata *pdev;
288
289 grub_dl_ref (my_mod);
290
291 /* Initialize some global variables. */
292 image_handle = 0;
293
294 b = grub_efi_system_table->boot_services;
295
296 for (pdev = devs ; pdev->devpath ; pdev++)
297 if (efi_call_6 (b->load_image, 0, grub_efi_image_handle, pdev->devpath,
298 NULL, 0, &image_handle) == GRUB_EFI_SUCCESS)
299 break;
300
301 if (! pdev->devpath)
302 {
303 grub_error (GRUB_ERR_BAD_OS, "can't find model");
304 goto fail;
305 }
306
307 grub_printf ("Model : %s\n", pdev->model);
308
309 loaded_image = grub_efi_get_loaded_image (image_handle);
310 if (! loaded_image)
311 {
312 grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
313 goto fail;
314 }
315
316 if (argc > 0)
317 {
318 int i, len;
319 grub_efi_char16_t *p16;
320
321 for (i = 0, len = 0; i < argc; i++)
322 len += grub_strlen (argv[i]) + 1;
323
324 len *= sizeof (grub_efi_char16_t);
325 cmdline = p16 = grub_malloc (len);
326 if (! cmdline)
327 goto fail;
328
329 for (i = 0; i < argc; i++)
330 {
331 char *p8;
332
333 p8 = argv[i];
334 while (*p8)
335 *(p16++) = *(p8++);
336
337 *(p16++) = ' ';
338 }
339 *(--p16) = 0;
340
341 loaded_image->load_options = cmdline;
342 loaded_image->load_options_size = len;
343 }
344
345 grub_loader_set (grub_appleloader_boot, grub_appleloader_unload, 0);
346
347 return 0;
348
349 fail:
350
351 grub_dl_unref (my_mod);
352 return grub_errno;
353 }
354
355 static grub_command_t cmd;
356
357 GRUB_MOD_INIT(appleloader)
358 {
359 cmd = grub_register_command ("appleloader", grub_cmd_appleloader,
360 "[OPTS]", N_("Boot legacy system."));
361 my_mod = mod;
362 }
363
364 GRUB_MOD_FINI(appleloader)
365 {
366 grub_unregister_command (cmd);
367 }