efi: Move grub_reboot() into kernel
[grub.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_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   dp = dp0;
331
332   while (1)
333     {
334       grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
335       grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
336
337       if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
338         break;
339       if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
340                && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
341         {
342           grub_efi_uint16_t len;
343           len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
344                  / sizeof (grub_efi_char16_t));
345           filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2;
346         }
347
348       dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
349     }
350
351   if (!filesize)
352     return NULL;
353
354   dp = dp0;
355
356   p = name = grub_malloc (filesize);
357   if (!name)
358     return NULL;
359
360   while (1)
361     {
362       grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
363       grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
364
365       if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
366         break;
367       else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
368                && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
369         {
370           grub_efi_file_path_device_path_t *fp;
371           grub_efi_uint16_t len;
372
373           *p++ = '/';
374
375           len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
376                  / sizeof (grub_efi_char16_t));
377           fp = (grub_efi_file_path_device_path_t *) dp;
378           /* According to EFI spec Path Name is NULL terminated */
379           while (len > 0 && fp->path_name[len - 1] == 0)
380             len--;
381
382           p = (char *) grub_utf16_to_utf8 ((unsigned char *) p, fp->path_name, len);
383         }
384
385       dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
386     }
387
388   *p = '\0';
389
390   for (pi = name, p = name; *pi;)
391     {
392       /* EFI breaks paths with backslashes.  */
393       if (*pi == '\\' || *pi == '/')
394         {
395           *p++ = '/';
396           while (*pi == '\\' || *pi == '/')
397             pi++;
398           continue;
399         }
400       *p++ = *pi++;
401     }
402   *p = '\0';
403
404   return name;
405 }
406
407 grub_efi_device_path_t *
408 grub_efi_get_device_path (grub_efi_handle_t handle)
409 {
410   return grub_efi_open_protocol (handle, &device_path_guid,
411                                  GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
412 }
413
414 /* Return the device path node right before the end node.  */
415 grub_efi_device_path_t *
416 grub_efi_find_last_device_path (const grub_efi_device_path_t *dp)
417 {
418   grub_efi_device_path_t *next, *p;
419
420   if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
421     return 0;
422
423   for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
424        ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
425        p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
426     ;
427
428   return p;
429 }
430
431 /* Duplicate a device path.  */
432 grub_efi_device_path_t *
433 grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp)
434 {
435   grub_efi_device_path_t *p;
436   grub_size_t total_size = 0;
437
438   for (p = (grub_efi_device_path_t *) dp;
439        ;
440        p = GRUB_EFI_NEXT_DEVICE_PATH (p))
441     {
442       total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
443       if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
444         break;
445     }
446
447   p = grub_malloc (total_size);
448   if (! p)
449     return 0;
450
451   grub_memcpy (p, dp, total_size);
452   return p;
453 }
454
455 static void
456 dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor)
457 {
458   grub_uint32_t vendor_data_len = vendor->header.length - sizeof (*vendor);
459   grub_printf ("/%sVendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)[%x: ",
460                type,
461                (unsigned) vendor->vendor_guid.data1,
462                (unsigned) vendor->vendor_guid.data2,
463                (unsigned) vendor->vendor_guid.data3,
464                (unsigned) vendor->vendor_guid.data4[0],
465                (unsigned) vendor->vendor_guid.data4[1],
466                (unsigned) vendor->vendor_guid.data4[2],
467                (unsigned) vendor->vendor_guid.data4[3],
468                (unsigned) vendor->vendor_guid.data4[4],
469                (unsigned) vendor->vendor_guid.data4[5],
470                (unsigned) vendor->vendor_guid.data4[6],
471                (unsigned) vendor->vendor_guid.data4[7],
472                vendor_data_len);
473   if (vendor->header.length > sizeof (*vendor))
474     {
475       grub_uint32_t i;
476       for (i = 0; i < vendor_data_len; i++)
477         grub_printf ("%02x ", vendor->vendor_defined_data[i]);
478     }
479   grub_printf ("]");
480 }
481
482
483 /* Print the chain of Device Path nodes. This is mainly for debugging. */
484 void
485 grub_efi_print_device_path (grub_efi_device_path_t *dp)
486 {
487   while (1)
488     {
489       grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
490       grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
491       grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
492
493       switch (type)
494         {
495         case GRUB_EFI_END_DEVICE_PATH_TYPE:
496           switch (subtype)
497             {
498             case GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE:
499               grub_printf ("/EndEntire\n");
500               //grub_putchar ('\n');
501               break;
502             case GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE:
503               grub_printf ("/EndThis\n");
504               //grub_putchar ('\n');
505               break;
506             default:
507               grub_printf ("/EndUnknown(%x)\n", (unsigned) subtype);
508               break;
509             }
510           break;
511
512         case GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE:
513           switch (subtype)
514             {
515             case GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE:
516               {
517                 grub_efi_pci_device_path_t *pci
518                   = (grub_efi_pci_device_path_t *) dp;
519                 grub_printf ("/PCI(%x,%x)",
520                              (unsigned) pci->function, (unsigned) pci->device);
521               }
522               break;
523             case GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE:
524               {
525                 grub_efi_pccard_device_path_t *pccard
526                   = (grub_efi_pccard_device_path_t *) dp;
527                 grub_printf ("/PCCARD(%x)",
528                              (unsigned) pccard->function);
529               }
530               break;
531             case GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE:
532               {
533                 grub_efi_memory_mapped_device_path_t *mmapped
534                   = (grub_efi_memory_mapped_device_path_t *) dp;
535                 grub_printf ("/MMap(%x,%llx,%llx)",
536                              (unsigned) mmapped->memory_type,
537                              (unsigned long long) mmapped->start_address,
538                              (unsigned long long) mmapped->end_address);
539               }
540               break;
541             case GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE:
542               dump_vendor_path ("Hardware",
543                                 (grub_efi_vendor_device_path_t *) dp);
544               break;
545             case GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE:
546               {
547                 grub_efi_controller_device_path_t *controller
548                   = (grub_efi_controller_device_path_t *) dp;
549                 grub_printf ("/Ctrl(%x)",
550                              (unsigned) controller->controller_number);
551               }
552               break;
553             default:
554               grub_printf ("/UnknownHW(%x)", (unsigned) subtype);
555               break;
556             }
557           break;
558
559         case GRUB_EFI_ACPI_DEVICE_PATH_TYPE:
560           switch (subtype)
561             {
562             case GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE:
563               {
564                 grub_efi_acpi_device_path_t *acpi
565                   = (grub_efi_acpi_device_path_t *) dp;
566                 grub_printf ("/ACPI(%x,%x)",
567                              (unsigned) acpi->hid,
568                              (unsigned) acpi->uid);
569               }
570               break;
571             case GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE:
572               {
573                 grub_efi_expanded_acpi_device_path_t *eacpi
574                   = (grub_efi_expanded_acpi_device_path_t *) dp;
575                 grub_printf ("/ACPI(");
576
577                 if (GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)[0] == '\0')
578                   grub_printf ("%x,", (unsigned) eacpi->hid);
579                 else
580                   grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp));
581
582                 if (GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)[0] == '\0')
583                   grub_printf ("%x,", (unsigned) eacpi->uid);
584                 else
585                   grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp));
586
587                 if (GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)[0] == '\0')
588                   grub_printf ("%x)", (unsigned) eacpi->cid);
589                 else
590                   grub_printf ("%s)", GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp));
591               }
592               break;
593             default:
594               grub_printf ("/UnknownACPI(%x)", (unsigned) subtype);
595               break;
596             }
597           break;
598
599         case GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE:
600           switch (subtype)
601             {
602             case GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE:
603               {
604                 grub_efi_atapi_device_path_t *atapi
605                   = (grub_efi_atapi_device_path_t *) dp;
606                 grub_printf ("/ATAPI(%x,%x,%x)",
607                              (unsigned) atapi->primary_secondary,
608                              (unsigned) atapi->slave_master,
609                              (unsigned) atapi->lun);
610               }
611               break;
612             case GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE:
613               {
614                 grub_efi_scsi_device_path_t *scsi
615                   = (grub_efi_scsi_device_path_t *) dp;
616                 grub_printf ("/SCSI(%x,%x)",
617                              (unsigned) scsi->pun,
618                              (unsigned) scsi->lun);
619               }
620               break;
621             case GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE:
622               {
623                 grub_efi_fibre_channel_device_path_t *fc
624                   = (grub_efi_fibre_channel_device_path_t *) dp;
625                 grub_printf ("/FibreChannel(%llx,%llx)",
626                              (unsigned long long) fc->wwn,
627                              (unsigned long long) fc->lun);
628               }
629               break;
630             case GRUB_EFI_1394_DEVICE_PATH_SUBTYPE:
631               {
632                 grub_efi_1394_device_path_t *firewire
633                   = (grub_efi_1394_device_path_t *) dp;
634                 grub_printf ("/1394(%llx)",
635                              (unsigned long long) firewire->guid);
636               }
637               break;
638             case GRUB_EFI_USB_DEVICE_PATH_SUBTYPE:
639               {
640                 grub_efi_usb_device_path_t *usb
641                   = (grub_efi_usb_device_path_t *) dp;
642                 grub_printf ("/USB(%x,%x)",
643                              (unsigned) usb->parent_port_number,
644                              (unsigned) usb->usb_interface);
645               }
646               break;
647             case GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE:
648               {
649                 grub_efi_usb_class_device_path_t *usb_class
650                   = (grub_efi_usb_class_device_path_t *) dp;
651                 grub_printf ("/USBClass(%x,%x,%x,%x,%x)",
652                              (unsigned) usb_class->vendor_id,
653                              (unsigned) usb_class->product_id,
654                              (unsigned) usb_class->device_class,
655                              (unsigned) usb_class->device_subclass,
656                              (unsigned) usb_class->device_protocol);
657               }
658               break;
659             case GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE:
660               {
661                 grub_efi_i2o_device_path_t *i2o
662                   = (grub_efi_i2o_device_path_t *) dp;
663                 grub_printf ("/I2O(%x)", (unsigned) i2o->tid);
664               }
665               break;
666             case GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE:
667               {
668                 grub_efi_mac_address_device_path_t *mac
669                   = (grub_efi_mac_address_device_path_t *) dp;
670                 grub_printf ("/MacAddr(%02x:%02x:%02x:%02x:%02x:%02x,%x)",
671                              (unsigned) mac->mac_address[0],
672                              (unsigned) mac->mac_address[1],
673                              (unsigned) mac->mac_address[2],
674                              (unsigned) mac->mac_address[3],
675                              (unsigned) mac->mac_address[4],
676                              (unsigned) mac->mac_address[5],
677                              (unsigned) mac->if_type);
678               }
679               break;
680             case GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE:
681               {
682                 grub_efi_ipv4_device_path_t *ipv4
683                   = (grub_efi_ipv4_device_path_t *) dp;
684                 grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)",
685                              (unsigned) ipv4->local_ip_address[0],
686                              (unsigned) ipv4->local_ip_address[1],
687                              (unsigned) ipv4->local_ip_address[2],
688                              (unsigned) ipv4->local_ip_address[3],
689                              (unsigned) ipv4->remote_ip_address[0],
690                              (unsigned) ipv4->remote_ip_address[1],
691                              (unsigned) ipv4->remote_ip_address[2],
692                              (unsigned) ipv4->remote_ip_address[3],
693                              (unsigned) ipv4->local_port,
694                              (unsigned) ipv4->remote_port,
695                              (unsigned) ipv4->protocol,
696                              (unsigned) ipv4->static_ip_address);
697               }
698               break;
699             case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE:
700               {
701                 grub_efi_ipv6_device_path_t *ipv6
702                   = (grub_efi_ipv6_device_path_t *) dp;
703                 grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)",
704                              (unsigned) ipv6->local_ip_address[0],
705                              (unsigned) ipv6->local_ip_address[1],
706                              (unsigned) ipv6->local_ip_address[2],
707                              (unsigned) ipv6->local_ip_address[3],
708                              (unsigned) ipv6->local_ip_address[4],
709                              (unsigned) ipv6->local_ip_address[5],
710                              (unsigned) ipv6->local_ip_address[6],
711                              (unsigned) ipv6->local_ip_address[7],
712                              (unsigned) ipv6->remote_ip_address[0],
713                              (unsigned) ipv6->remote_ip_address[1],
714                              (unsigned) ipv6->remote_ip_address[2],
715                              (unsigned) ipv6->remote_ip_address[3],
716                              (unsigned) ipv6->remote_ip_address[4],
717                              (unsigned) ipv6->remote_ip_address[5],
718                              (unsigned) ipv6->remote_ip_address[6],
719                              (unsigned) ipv6->remote_ip_address[7],
720                              (unsigned) ipv6->local_port,
721                              (unsigned) ipv6->remote_port,
722                              (unsigned) ipv6->protocol,
723                              (unsigned) ipv6->static_ip_address);
724               }
725               break;
726             case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE:
727               {
728                 grub_efi_infiniband_device_path_t *ib
729                   = (grub_efi_infiniband_device_path_t *) dp;
730                 grub_printf ("/InfiniBand(%x,%llx,%llx,%llx)",
731                              (unsigned) ib->port_gid[0], /* XXX */
732                              (unsigned long long) ib->remote_id,
733                              (unsigned long long) ib->target_port_id,
734                              (unsigned long long) ib->device_id);
735               }
736               break;
737             case GRUB_EFI_UART_DEVICE_PATH_SUBTYPE:
738               {
739                 grub_efi_uart_device_path_t *uart
740                   = (grub_efi_uart_device_path_t *) dp;
741                 grub_printf ("/UART(%llu,%u,%x,%x)",
742                              (unsigned long long) uart->baud_rate,
743                              uart->data_bits,
744                              uart->parity,
745                              uart->stop_bits);
746               }
747               break;
748             case GRUB_EFI_SATA_DEVICE_PATH_SUBTYPE:
749               {
750                 grub_efi_sata_device_path_t *sata;
751                 sata = (grub_efi_sata_device_path_t *) dp;
752                 grub_printf ("/Sata(%x,%x,%x)",
753                              sata->hba_port,
754                              sata->multiplier_port,
755                              sata->lun);
756               }
757               break;
758
759             case GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE:
760               dump_vendor_path ("Messaging",
761                                 (grub_efi_vendor_device_path_t *) dp);
762               break;
763             default:
764               grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype);
765               break;
766             }
767           break;
768
769         case GRUB_EFI_MEDIA_DEVICE_PATH_TYPE:
770           switch (subtype)
771             {
772             case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE:
773               {
774                 grub_efi_hard_drive_device_path_t *hd = (grub_efi_hard_drive_device_path_t *) dp;
775                 grub_printf ("/HD(%u,%llx,%llx,%02x%02x%02x%02x%02x%02x%02x%02x,%x,%x)",
776                              hd->partition_number,
777                              (unsigned long long) hd->partition_start,
778                              (unsigned long long) hd->partition_size,
779                              (unsigned) hd->partition_signature[0],
780                              (unsigned) hd->partition_signature[1],
781                              (unsigned) hd->partition_signature[2],
782                              (unsigned) hd->partition_signature[3],
783                              (unsigned) hd->partition_signature[4],
784                              (unsigned) hd->partition_signature[5],
785                              (unsigned) hd->partition_signature[6],
786                              (unsigned) hd->partition_signature[7],
787                              (unsigned) hd->partmap_type,
788                              (unsigned) hd->signature_type);
789               }
790               break;
791             case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE:
792               {
793                 grub_efi_cdrom_device_path_t *cd
794                   = (grub_efi_cdrom_device_path_t *) dp;
795                 grub_printf ("/CD(%u,%llx,%llx)",
796                              cd->boot_entry,
797                              (unsigned long long) cd->partition_start,
798                              (unsigned long long) cd->partition_size);
799               }
800               break;
801             case GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE:
802               dump_vendor_path ("Media",
803                                 (grub_efi_vendor_device_path_t *) dp);
804               break;
805             case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE:
806               {
807                 grub_efi_file_path_device_path_t *fp;
808                 grub_uint8_t *buf;
809                 fp = (grub_efi_file_path_device_path_t *) dp;
810                 buf = grub_malloc ((len - 4) * 2 + 1);
811                 if (buf)
812                   *grub_utf16_to_utf8 (buf, fp->path_name,
813                                        (len - 4) / sizeof (grub_efi_char16_t))
814                     = '\0';
815                 else
816                   grub_errno = GRUB_ERR_NONE;
817                 grub_printf ("/File(%s)", buf);
818                 grub_free (buf);
819               }
820               break;
821             case GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE:
822               {
823                 grub_efi_protocol_device_path_t *proto
824                   = (grub_efi_protocol_device_path_t *) dp;
825                 grub_printf ("/Protocol(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
826                              (unsigned) proto->guid.data1,
827                              (unsigned) proto->guid.data2,
828                              (unsigned) proto->guid.data3,
829                              (unsigned) proto->guid.data4[0],
830                              (unsigned) proto->guid.data4[1],
831                              (unsigned) proto->guid.data4[2],
832                              (unsigned) proto->guid.data4[3],
833                              (unsigned) proto->guid.data4[4],
834                              (unsigned) proto->guid.data4[5],
835                              (unsigned) proto->guid.data4[6],
836                              (unsigned) proto->guid.data4[7]);
837               }
838               break;
839             default:
840               grub_printf ("/UnknownMedia(%x)", (unsigned) subtype);
841               break;
842             }
843           break;
844
845         case GRUB_EFI_BIOS_DEVICE_PATH_TYPE:
846           switch (subtype)
847             {
848             case GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE:
849               {
850                 grub_efi_bios_device_path_t *bios
851                   = (grub_efi_bios_device_path_t *) dp;
852                 grub_printf ("/BIOS(%x,%x,%s)",
853                              (unsigned) bios->device_type,
854                              (unsigned) bios->status_flags,
855                              (char *) (dp + 1));
856               }
857               break;
858             default:
859               grub_printf ("/UnknownBIOS(%x)", (unsigned) subtype);
860               break;
861             }
862           break;
863
864         default:
865           grub_printf ("/UnknownType(%x,%x)\n",
866                        (unsigned) type,
867                        (unsigned) subtype);
868           return;
869           break;
870         }
871
872       if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
873         break;
874
875       dp = (grub_efi_device_path_t *) ((char *) dp + len);
876     }
877 }
878
879 /* Compare device paths.  */
880 int
881 grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
882                                const grub_efi_device_path_t *dp2)
883 {
884   if (! dp1 || ! dp2)
885     /* Return non-zero.  */
886     return 1;
887
888   while (1)
889     {
890       grub_efi_uint8_t type1, type2;
891       grub_efi_uint8_t subtype1, subtype2;
892       grub_efi_uint16_t len1, len2;
893       int ret;
894
895       type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
896       type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
897
898       if (type1 != type2)
899         return (int) type2 - (int) type1;
900
901       subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
902       subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
903
904       if (subtype1 != subtype2)
905         return (int) subtype1 - (int) subtype2;
906
907       len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
908       len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
909
910       if (len1 != len2)
911         return (int) len1 - (int) len2;
912
913       ret = grub_memcmp (dp1, dp2, len1);
914       if (ret != 0)
915         return ret;
916
917       if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
918         break;
919
920       dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
921       dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
922     }
923
924   return 0;
925 }