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