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