]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/grub-2.04/grub-core/kern/efi/efi.c
1.0.07 release
[Ventoy.git] / GRUB2 / grub-2.04 / grub-core / kern / efi / efi.c
1 /* efi.c - generic EFI support */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2006,2007,2008,2009,2010 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/misc.h>
21 #include <grub/charset.h>
22 #include <grub/efi/api.h>
23 #include <grub/efi/efi.h>
24 #include <grub/efi/console_control.h>
25 #include <grub/efi/pe32.h>
26 #include <grub/time.h>
27 #include <grub/term.h>
28 #include <grub/kernel.h>
29 #include <grub/mm.h>
30 #include <grub/loader.h>
31
32 /* The handle of GRUB itself. Filled in by the startup code. */
33 grub_efi_handle_t grub_efi_image_handle;
34
35 /* The pointer to a system table. Filled in by the startup code. */
36 grub_efi_system_table_t *grub_efi_system_table;
37
38 static grub_efi_guid_t console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID;
39 static grub_efi_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID;
40 static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
41
42 void *
43 grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration)
44 {
45 void *interface;
46 grub_efi_status_t status;
47
48 status = efi_call_3 (grub_efi_system_table->boot_services->locate_protocol,
49 protocol, registration, &interface);
50 if (status != GRUB_EFI_SUCCESS)
51 return 0;
52
53 return interface;
54 }
55
56 /* Return the array of handles which meet the requirement. If successful,
57 the number of handles is stored in NUM_HANDLES. The array is allocated
58 from the heap. */
59 grub_efi_handle_t *
60 grub_efi_locate_handle (grub_efi_locate_search_type_t search_type,
61 grub_efi_guid_t *protocol,
62 void *search_key,
63 grub_efi_uintn_t *num_handles)
64 {
65 grub_efi_boot_services_t *b;
66 grub_efi_status_t status;
67 grub_efi_handle_t *buffer;
68 grub_efi_uintn_t buffer_size = 8 * sizeof (grub_efi_handle_t);
69
70 buffer = grub_malloc (buffer_size);
71 if (! buffer)
72 return 0;
73
74 b = grub_efi_system_table->boot_services;
75 status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
76 &buffer_size, buffer);
77 if (status == GRUB_EFI_BUFFER_TOO_SMALL)
78 {
79 grub_free (buffer);
80 buffer = grub_malloc (buffer_size);
81 if (! buffer)
82 return 0;
83
84 status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
85 &buffer_size, buffer);
86 }
87
88 if (status != GRUB_EFI_SUCCESS)
89 {
90 grub_free (buffer);
91 return 0;
92 }
93
94 *num_handles = buffer_size / sizeof (grub_efi_handle_t);
95 return buffer;
96 }
97
98 void *
99 grub_efi_open_protocol (grub_efi_handle_t handle,
100 grub_efi_guid_t *protocol,
101 grub_efi_uint32_t attributes)
102 {
103 grub_efi_boot_services_t *b;
104 grub_efi_status_t status;
105 void *interface;
106
107 b = grub_efi_system_table->boot_services;
108 status = efi_call_6 (b->open_protocol, handle,
109 protocol,
110 &interface,
111 grub_efi_image_handle,
112 0,
113 attributes);
114 if (status != GRUB_EFI_SUCCESS)
115 return 0;
116
117 return interface;
118 }
119
120 int
121 grub_efi_set_text_mode (int on)
122 {
123 grub_efi_console_control_protocol_t *c;
124 grub_efi_screen_mode_t mode, new_mode;
125
126 c = grub_efi_locate_protocol (&console_control_guid, 0);
127 if (! c)
128 /* No console control protocol instance available, assume it is
129 already in text mode. */
130 return 1;
131
132 if (efi_call_4 (c->get_mode, c, &mode, 0, 0) != GRUB_EFI_SUCCESS)
133 return 0;
134
135 new_mode = on ? GRUB_EFI_SCREEN_TEXT : GRUB_EFI_SCREEN_GRAPHICS;
136 if (mode != new_mode)
137 if (efi_call_2 (c->set_mode, c, new_mode) != GRUB_EFI_SUCCESS)
138 return 0;
139
140 return 1;
141 }
142
143 void
144 grub_efi_stall (grub_efi_uintn_t microseconds)
145 {
146 efi_call_1 (grub_efi_system_table->boot_services->stall, microseconds);
147 }
148
149 grub_efi_loaded_image_t *
150 grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
151 {
152 return grub_efi_open_protocol (image_handle,
153 &loaded_image_guid,
154 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
155 }
156
157 void
158 grub_reboot (void)
159 {
160 grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
161 efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
162 GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
163 for (;;) ;
164 }
165
166 void
167 grub_exit (void)
168 {
169 grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
170 efi_call_4 (grub_efi_system_table->boot_services->exit,
171 grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
172 for (;;) ;
173 }
174
175 grub_err_t
176 grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
177 grub_efi_uintn_t descriptor_size,
178 grub_efi_uint32_t descriptor_version,
179 grub_efi_memory_descriptor_t *virtual_map)
180 {
181 grub_efi_runtime_services_t *r;
182 grub_efi_status_t status;
183
184 r = grub_efi_system_table->runtime_services;
185 status = efi_call_4 (r->set_virtual_address_map, memory_map_size,
186 descriptor_size, descriptor_version, virtual_map);
187
188 if (status == GRUB_EFI_SUCCESS)
189 return GRUB_ERR_NONE;
190
191 return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed");
192 }
193
194 grub_err_t
195 grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
196 void *data, grub_size_t datasize)
197 {
198 grub_efi_status_t status;
199 grub_efi_runtime_services_t *r;
200 grub_efi_char16_t *var16;
201 grub_size_t len, len16;
202
203 len = grub_strlen (var);
204 len16 = len * GRUB_MAX_UTF16_PER_UTF8;
205 var16 = grub_malloc ((len16 + 1) * sizeof (var16[0]));
206 if (!var16)
207 return grub_errno;
208 len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
209 var16[len16] = 0;
210
211 r = grub_efi_system_table->runtime_services;
212
213 status = efi_call_5 (r->set_variable, var16, guid,
214 (GRUB_EFI_VARIABLE_NON_VOLATILE
215 | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS
216 | GRUB_EFI_VARIABLE_RUNTIME_ACCESS),
217 datasize, data);
218 grub_free (var16);
219 if (status == GRUB_EFI_SUCCESS)
220 return GRUB_ERR_NONE;
221
222 return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var);
223 }
224
225 void *
226 grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
227 grub_size_t *datasize_out)
228 {
229 grub_efi_status_t status;
230 grub_efi_uintn_t datasize = 0;
231 grub_efi_runtime_services_t *r;
232 grub_efi_char16_t *var16;
233 void *data;
234 grub_size_t len, len16;
235
236 *datasize_out = 0;
237
238 len = grub_strlen (var);
239 len16 = len * GRUB_MAX_UTF16_PER_UTF8;
240 var16 = grub_malloc ((len16 + 1) * sizeof (var16[0]));
241 if (!var16)
242 return NULL;
243 len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
244 var16[len16] = 0;
245
246 r = grub_efi_system_table->runtime_services;
247
248 status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL);
249
250 if (status != GRUB_EFI_BUFFER_TOO_SMALL || !datasize)
251 {
252 grub_free (var16);
253 return NULL;
254 }
255
256 data = grub_malloc (datasize);
257 if (!data)
258 {
259 grub_free (var16);
260 return NULL;
261 }
262
263 status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, data);
264 grub_free (var16);
265
266 if (status == GRUB_EFI_SUCCESS)
267 {
268 *datasize_out = datasize;
269 return data;
270 }
271
272 grub_free (data);
273 return NULL;
274 }
275
276 #pragma GCC diagnostic ignored "-Wcast-align"
277
278 /* Search the mods section from the PE32/PE32+ image. This code uses
279 a PE32 header, but should work with PE32+ as well. */
280 grub_addr_t
281 grub_efi_modules_addr (void)
282 {
283 grub_efi_loaded_image_t *image;
284 struct grub_pe32_header *header;
285 struct grub_pe32_coff_header *coff_header;
286 struct grub_pe32_section_table *sections;
287 struct grub_pe32_section_table *section;
288 struct grub_module_info *info;
289 grub_uint16_t i;
290
291 image = grub_efi_get_loaded_image (grub_efi_image_handle);
292 if (! image)
293 return 0;
294
295 header = image->image_base;
296 coff_header = &(header->coff_header);
297 sections
298 = (struct grub_pe32_section_table *) ((char *) coff_header
299 + sizeof (*coff_header)
300 + coff_header->optional_header_size);
301
302 for (i = 0, section = sections;
303 i < coff_header->num_sections;
304 i++, section++)
305 {
306 if (grub_strcmp (section->name, "mods") == 0)
307 break;
308 }
309
310 if (i == coff_header->num_sections)
311 return 0;
312
313 info = (struct grub_module_info *) ((char *) image->image_base
314 + section->virtual_address);
315 if (info->magic != GRUB_MODULE_MAGIC)
316 return 0;
317
318 return (grub_addr_t) info;
319 }
320
321 #pragma GCC diagnostic error "-Wcast-align"
322
323 char *
324 grub_efi_get_filename (grub_efi_device_path_t *dp0)
325 {
326 char *name = 0, *p, *pi;
327 grub_size_t filesize = 0;
328 grub_efi_device_path_t *dp;
329
330 if (!dp0)
331 return NULL;
332
333 dp = dp0;
334
335 while (1)
336 {
337 grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
338 grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
339
340 if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
341 break;
342 if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
343 && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
344 {
345 grub_efi_uint16_t len;
346 len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
347 / sizeof (grub_efi_char16_t));
348 filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2;
349 }
350
351 dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
352 }
353
354 if (!filesize)
355 return NULL;
356
357 dp = dp0;
358
359 p = name = grub_malloc (filesize);
360 if (!name)
361 return NULL;
362
363 while (1)
364 {
365 grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
366 grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
367
368 if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
369 break;
370 else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
371 && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
372 {
373 grub_efi_file_path_device_path_t *fp;
374 grub_efi_uint16_t len;
375 grub_efi_char16_t *dup_name;
376
377 *p++ = '/';
378
379 len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
380 / sizeof (grub_efi_char16_t));
381 fp = (grub_efi_file_path_device_path_t *) dp;
382 /* According to EFI spec Path Name is NULL terminated */
383 while (len > 0 && fp->path_name[len - 1] == 0)
384 len--;
385
386 dup_name = grub_malloc (len * sizeof (*dup_name));
387 if (!dup_name)
388 {
389 grub_free (name);
390 return NULL;
391 }
392 p = (char *) grub_utf16_to_utf8 ((unsigned char *) p,
393 grub_memcpy (dup_name, fp->path_name, len * sizeof (*dup_name)),
394 len);
395 grub_free (dup_name);
396 }
397
398 dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
399 }
400
401 *p = '\0';
402
403 for (pi = name, p = name; *pi;)
404 {
405 /* EFI breaks paths with backslashes. */
406 if (*pi == '\\' || *pi == '/')
407 {
408 *p++ = '/';
409 while (*pi == '\\' || *pi == '/')
410 pi++;
411 continue;
412 }
413 *p++ = *pi++;
414 }
415 *p = '\0';
416
417 return name;
418 }
419
420 grub_efi_device_path_t *
421 grub_efi_get_device_path (grub_efi_handle_t handle)
422 {
423 return grub_efi_open_protocol (handle, &device_path_guid,
424 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
425 }
426
427 /* Return the device path node right before the end node. */
428 grub_efi_device_path_t *
429 grub_efi_find_last_device_path (const grub_efi_device_path_t *dp)
430 {
431 grub_efi_device_path_t *next, *p;
432
433 if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
434 return 0;
435
436 for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
437 ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
438 p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
439 ;
440
441 return p;
442 }
443
444 /* Duplicate a device path. */
445 grub_efi_device_path_t *
446 grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp)
447 {
448 grub_efi_device_path_t *p;
449 grub_size_t total_size = 0;
450
451 for (p = (grub_efi_device_path_t *) dp;
452 ;
453 p = GRUB_EFI_NEXT_DEVICE_PATH (p))
454 {
455 total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
456 if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
457 break;
458 }
459
460 p = grub_malloc (total_size);
461 if (! p)
462 return 0;
463
464 grub_memcpy (p, dp, total_size);
465 return p;
466 }
467
468 static void
469 dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor)
470 {
471 grub_uint32_t vendor_data_len = vendor->header.length - sizeof (*vendor);
472 grub_printf ("/%sVendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)[%x: ",
473 type,
474 (unsigned) vendor->vendor_guid.data1,
475 (unsigned) vendor->vendor_guid.data2,
476 (unsigned) vendor->vendor_guid.data3,
477 (unsigned) vendor->vendor_guid.data4[0],
478 (unsigned) vendor->vendor_guid.data4[1],
479 (unsigned) vendor->vendor_guid.data4[2],
480 (unsigned) vendor->vendor_guid.data4[3],
481 (unsigned) vendor->vendor_guid.data4[4],
482 (unsigned) vendor->vendor_guid.data4[5],
483 (unsigned) vendor->vendor_guid.data4[6],
484 (unsigned) vendor->vendor_guid.data4[7],
485 vendor_data_len);
486 if (vendor->header.length > sizeof (*vendor))
487 {
488 grub_uint32_t i;
489 for (i = 0; i < vendor_data_len; i++)
490 grub_printf ("%02x ", vendor->vendor_defined_data[i]);
491 }
492 grub_printf ("]");
493 }
494
495
496 /* Print the chain of Device Path nodes. This is mainly for debugging. */
497 void
498 grub_efi_print_device_path (grub_efi_device_path_t *dp)
499 {
500 while (1)
501 {
502 grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
503 grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
504 grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
505
506 switch (type)
507 {
508 case GRUB_EFI_END_DEVICE_PATH_TYPE:
509 switch (subtype)
510 {
511 case GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE:
512 grub_printf ("/EndEntire\n");
513 //grub_putchar ('\n');
514 break;
515 case GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE:
516 grub_printf ("/EndThis\n");
517 //grub_putchar ('\n');
518 break;
519 default:
520 grub_printf ("/EndUnknown(%x)\n", (unsigned) subtype);
521 break;
522 }
523 break;
524
525 case GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE:
526 switch (subtype)
527 {
528 case GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE:
529 {
530 grub_efi_pci_device_path_t *pci
531 = (grub_efi_pci_device_path_t *) dp;
532 grub_printf ("/PCI(%x,%x)",
533 (unsigned) pci->function, (unsigned) pci->device);
534 }
535 break;
536 case GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE:
537 {
538 grub_efi_pccard_device_path_t *pccard
539 = (grub_efi_pccard_device_path_t *) dp;
540 grub_printf ("/PCCARD(%x)",
541 (unsigned) pccard->function);
542 }
543 break;
544 case GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE:
545 {
546 grub_efi_memory_mapped_device_path_t *mmapped
547 = (grub_efi_memory_mapped_device_path_t *) dp;
548 grub_printf ("/MMap(%x,%llx,%llx)",
549 (unsigned) mmapped->memory_type,
550 (unsigned long long) mmapped->start_address,
551 (unsigned long long) mmapped->end_address);
552 }
553 break;
554 case GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE:
555 dump_vendor_path ("Hardware",
556 (grub_efi_vendor_device_path_t *) dp);
557 break;
558 case GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE:
559 {
560 grub_efi_controller_device_path_t *controller
561 = (grub_efi_controller_device_path_t *) dp;
562 grub_printf ("/Ctrl(%x)",
563 (unsigned) controller->controller_number);
564 }
565 break;
566 default:
567 grub_printf ("/UnknownHW(%x)", (unsigned) subtype);
568 break;
569 }
570 break;
571
572 case GRUB_EFI_ACPI_DEVICE_PATH_TYPE:
573 switch (subtype)
574 {
575 case GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE:
576 {
577 grub_efi_acpi_device_path_t *acpi
578 = (grub_efi_acpi_device_path_t *) dp;
579 grub_printf ("/ACPI(%x,%x)",
580 (unsigned) acpi->hid,
581 (unsigned) acpi->uid);
582 }
583 break;
584 case GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE:
585 {
586 grub_efi_expanded_acpi_device_path_t *eacpi
587 = (grub_efi_expanded_acpi_device_path_t *) dp;
588 grub_printf ("/ACPI(");
589
590 if (GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)[0] == '\0')
591 grub_printf ("%x,", (unsigned) eacpi->hid);
592 else
593 grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp));
594
595 if (GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)[0] == '\0')
596 grub_printf ("%x,", (unsigned) eacpi->uid);
597 else
598 grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp));
599
600 if (GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)[0] == '\0')
601 grub_printf ("%x)", (unsigned) eacpi->cid);
602 else
603 grub_printf ("%s)", GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp));
604 }
605 break;
606 default:
607 grub_printf ("/UnknownACPI(%x)", (unsigned) subtype);
608 break;
609 }
610 break;
611
612 case GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE:
613 switch (subtype)
614 {
615 case GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE:
616 {
617 grub_efi_atapi_device_path_t *atapi
618 = (grub_efi_atapi_device_path_t *) dp;
619 grub_printf ("/ATAPI(%x,%x,%x)",
620 (unsigned) atapi->primary_secondary,
621 (unsigned) atapi->slave_master,
622 (unsigned) atapi->lun);
623 }
624 break;
625 case GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE:
626 {
627 grub_efi_scsi_device_path_t *scsi
628 = (grub_efi_scsi_device_path_t *) dp;
629 grub_printf ("/SCSI(%x,%x)",
630 (unsigned) scsi->pun,
631 (unsigned) scsi->lun);
632 }
633 break;
634 case GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE:
635 {
636 grub_efi_fibre_channel_device_path_t *fc
637 = (grub_efi_fibre_channel_device_path_t *) dp;
638 grub_printf ("/FibreChannel(%llx,%llx)",
639 (unsigned long long) fc->wwn,
640 (unsigned long long) fc->lun);
641 }
642 break;
643 case GRUB_EFI_1394_DEVICE_PATH_SUBTYPE:
644 {
645 grub_efi_1394_device_path_t *firewire
646 = (grub_efi_1394_device_path_t *) dp;
647 grub_printf ("/1394(%llx)",
648 (unsigned long long) firewire->guid);
649 }
650 break;
651 case GRUB_EFI_USB_DEVICE_PATH_SUBTYPE:
652 {
653 grub_efi_usb_device_path_t *usb
654 = (grub_efi_usb_device_path_t *) dp;
655 grub_printf ("/USB(%x,%x)",
656 (unsigned) usb->parent_port_number,
657 (unsigned) usb->usb_interface);
658 }
659 break;
660 case GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE:
661 {
662 grub_efi_usb_class_device_path_t *usb_class
663 = (grub_efi_usb_class_device_path_t *) dp;
664 grub_printf ("/USBClass(%x,%x,%x,%x,%x)",
665 (unsigned) usb_class->vendor_id,
666 (unsigned) usb_class->product_id,
667 (unsigned) usb_class->device_class,
668 (unsigned) usb_class->device_subclass,
669 (unsigned) usb_class->device_protocol);
670 }
671 break;
672 case GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE:
673 {
674 grub_efi_i2o_device_path_t *i2o
675 = (grub_efi_i2o_device_path_t *) dp;
676 grub_printf ("/I2O(%x)", (unsigned) i2o->tid);
677 }
678 break;
679 case GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE:
680 {
681 grub_efi_mac_address_device_path_t *mac
682 = (grub_efi_mac_address_device_path_t *) dp;
683 grub_printf ("/MacAddr(%02x:%02x:%02x:%02x:%02x:%02x,%x)",
684 (unsigned) mac->mac_address[0],
685 (unsigned) mac->mac_address[1],
686 (unsigned) mac->mac_address[2],
687 (unsigned) mac->mac_address[3],
688 (unsigned) mac->mac_address[4],
689 (unsigned) mac->mac_address[5],
690 (unsigned) mac->if_type);
691 }
692 break;
693 case GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE:
694 {
695 grub_efi_ipv4_device_path_t *ipv4
696 = (grub_efi_ipv4_device_path_t *) dp;
697 grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)",
698 (unsigned) ipv4->local_ip_address[0],
699 (unsigned) ipv4->local_ip_address[1],
700 (unsigned) ipv4->local_ip_address[2],
701 (unsigned) ipv4->local_ip_address[3],
702 (unsigned) ipv4->remote_ip_address[0],
703 (unsigned) ipv4->remote_ip_address[1],
704 (unsigned) ipv4->remote_ip_address[2],
705 (unsigned) ipv4->remote_ip_address[3],
706 (unsigned) ipv4->local_port,
707 (unsigned) ipv4->remote_port,
708 (unsigned) ipv4->protocol,
709 (unsigned) ipv4->static_ip_address);
710 }
711 break;
712 case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE:
713 {
714 grub_efi_ipv6_device_path_t *ipv6
715 = (grub_efi_ipv6_device_path_t *) dp;
716 grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)",
717 (unsigned) ipv6->local_ip_address[0],
718 (unsigned) ipv6->local_ip_address[1],
719 (unsigned) ipv6->local_ip_address[2],
720 (unsigned) ipv6->local_ip_address[3],
721 (unsigned) ipv6->local_ip_address[4],
722 (unsigned) ipv6->local_ip_address[5],
723 (unsigned) ipv6->local_ip_address[6],
724 (unsigned) ipv6->local_ip_address[7],
725 (unsigned) ipv6->remote_ip_address[0],
726 (unsigned) ipv6->remote_ip_address[1],
727 (unsigned) ipv6->remote_ip_address[2],
728 (unsigned) ipv6->remote_ip_address[3],
729 (unsigned) ipv6->remote_ip_address[4],
730 (unsigned) ipv6->remote_ip_address[5],
731 (unsigned) ipv6->remote_ip_address[6],
732 (unsigned) ipv6->remote_ip_address[7],
733 (unsigned) ipv6->local_port,
734 (unsigned) ipv6->remote_port,
735 (unsigned) ipv6->protocol,
736 (unsigned) ipv6->static_ip_address);
737 }
738 break;
739 case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE:
740 {
741 grub_efi_infiniband_device_path_t *ib
742 = (grub_efi_infiniband_device_path_t *) dp;
743 grub_printf ("/InfiniBand(%x,%llx,%llx,%llx)",
744 (unsigned) ib->port_gid[0], /* XXX */
745 (unsigned long long) ib->remote_id,
746 (unsigned long long) ib->target_port_id,
747 (unsigned long long) ib->device_id);
748 }
749 break;
750 case GRUB_EFI_UART_DEVICE_PATH_SUBTYPE:
751 {
752 grub_efi_uart_device_path_t *uart
753 = (grub_efi_uart_device_path_t *) dp;
754 grub_printf ("/UART(%llu,%u,%x,%x)",
755 (unsigned long long) uart->baud_rate,
756 uart->data_bits,
757 uart->parity,
758 uart->stop_bits);
759 }
760 break;
761 case GRUB_EFI_SATA_DEVICE_PATH_SUBTYPE:
762 {
763 grub_efi_sata_device_path_t *sata;
764 sata = (grub_efi_sata_device_path_t *) dp;
765 grub_printf ("/Sata(%x,%x,%x)",
766 sata->hba_port,
767 sata->multiplier_port,
768 sata->lun);
769 }
770 break;
771
772 case GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE:
773 dump_vendor_path ("Messaging",
774 (grub_efi_vendor_device_path_t *) dp);
775 break;
776 default:
777 grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype);
778 break;
779 }
780 break;
781
782 case GRUB_EFI_MEDIA_DEVICE_PATH_TYPE:
783 switch (subtype)
784 {
785 case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE:
786 {
787 grub_efi_hard_drive_device_path_t *hd = (grub_efi_hard_drive_device_path_t *) dp;
788 grub_printf ("/HD(%u,%llx,%llx,%02x%02x%02x%02x%02x%02x%02x%02x,%x,%x)",
789 hd->partition_number,
790 (unsigned long long) hd->partition_start,
791 (unsigned long long) hd->partition_size,
792 (unsigned) hd->partition_signature[0],
793 (unsigned) hd->partition_signature[1],
794 (unsigned) hd->partition_signature[2],
795 (unsigned) hd->partition_signature[3],
796 (unsigned) hd->partition_signature[4],
797 (unsigned) hd->partition_signature[5],
798 (unsigned) hd->partition_signature[6],
799 (unsigned) hd->partition_signature[7],
800 (unsigned) hd->partmap_type,
801 (unsigned) hd->signature_type);
802 }
803 break;
804 case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE:
805 {
806 grub_efi_cdrom_device_path_t *cd
807 = (grub_efi_cdrom_device_path_t *) dp;
808 grub_printf ("/CD(%u,%llx,%llx)",
809 cd->boot_entry,
810 (unsigned long long) cd->partition_start,
811 (unsigned long long) cd->partition_size);
812 }
813 break;
814 case GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE:
815 dump_vendor_path ("Media",
816 (grub_efi_vendor_device_path_t *) dp);
817 break;
818 case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE:
819 {
820 grub_efi_file_path_device_path_t *fp;
821 grub_uint8_t *buf;
822 fp = (grub_efi_file_path_device_path_t *) dp;
823 buf = grub_malloc ((len - 4) * 2 + 1);
824 if (buf)
825 {
826 grub_efi_char16_t *dup_name = grub_malloc (len - 4);
827 if (!dup_name)
828 {
829 grub_errno = GRUB_ERR_NONE;
830 grub_printf ("/File((null))");
831 grub_free (buf);
832 break;
833 }
834 *grub_utf16_to_utf8 (buf, grub_memcpy (dup_name, fp->path_name, len - 4),
835 (len - 4) / sizeof (grub_efi_char16_t))
836 = '\0';
837 grub_free (dup_name);
838 }
839 else
840 grub_errno = GRUB_ERR_NONE;
841 grub_printf ("/File(%s)", buf);
842 grub_free (buf);
843 }
844 break;
845 case GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE:
846 {
847 grub_efi_protocol_device_path_t *proto
848 = (grub_efi_protocol_device_path_t *) dp;
849 grub_printf ("/Protocol(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
850 (unsigned) proto->guid.data1,
851 (unsigned) proto->guid.data2,
852 (unsigned) proto->guid.data3,
853 (unsigned) proto->guid.data4[0],
854 (unsigned) proto->guid.data4[1],
855 (unsigned) proto->guid.data4[2],
856 (unsigned) proto->guid.data4[3],
857 (unsigned) proto->guid.data4[4],
858 (unsigned) proto->guid.data4[5],
859 (unsigned) proto->guid.data4[6],
860 (unsigned) proto->guid.data4[7]);
861 }
862 break;
863 default:
864 grub_printf ("/UnknownMedia(%x)", (unsigned) subtype);
865 break;
866 }
867 break;
868
869 case GRUB_EFI_BIOS_DEVICE_PATH_TYPE:
870 switch (subtype)
871 {
872 case GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE:
873 {
874 grub_efi_bios_device_path_t *bios
875 = (grub_efi_bios_device_path_t *) dp;
876 grub_printf ("/BIOS(%x,%x,%s)",
877 (unsigned) bios->device_type,
878 (unsigned) bios->status_flags,
879 (char *) (dp + 1));
880 }
881 break;
882 default:
883 grub_printf ("/UnknownBIOS(%x)", (unsigned) subtype);
884 break;
885 }
886 break;
887
888 default:
889 grub_printf ("/UnknownType(%x,%x)\n",
890 (unsigned) type,
891 (unsigned) subtype);
892 return;
893 break;
894 }
895
896 if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
897 break;
898
899 dp = (grub_efi_device_path_t *) ((char *) dp + len);
900 }
901 }
902
903 /* Compare device paths. */
904 int
905 grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
906 const grub_efi_device_path_t *dp2)
907 {
908 if (! dp1 || ! dp2)
909 /* Return non-zero. */
910 return 1;
911
912 while (1)
913 {
914 grub_efi_uint8_t type1, type2;
915 grub_efi_uint8_t subtype1, subtype2;
916 grub_efi_uint16_t len1, len2;
917 int ret;
918
919 type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
920 type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
921
922 if (type1 != type2)
923 return (int) type2 - (int) type1;
924
925 subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
926 subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
927
928 if (subtype1 != subtype2)
929 return (int) subtype1 - (int) subtype2;
930
931 len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
932 len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
933
934 if (len1 != len2)
935 return (int) len1 - (int) len2;
936
937 ret = grub_memcmp (dp1, dp2, len1);
938 if (ret != 0)
939 return ret;
940
941 if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
942 break;
943
944 dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
945 dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
946 }
947
948 return 0;
949 }
950
951 void * grub_efi_allocate_iso_buf(grub_uint64_t size)
952 {
953 grub_efi_boot_services_t *b;
954 grub_efi_status_t status;
955 grub_efi_physical_address_t address = 0;
956 grub_efi_uintn_t pages = GRUB_EFI_BYTES_TO_PAGES(size);
957
958 b = grub_efi_system_table->boot_services;
959 status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, GRUB_EFI_RUNTIME_SERVICES_DATA, pages, &address);
960 if (status != GRUB_EFI_SUCCESS)
961 {
962 return NULL;
963 }
964
965 return (void *)(unsigned long)address;
966 }