[grub] * Wed Aug 04 2010 Peter Jones <pjones at redhat.com> - 0.97-66 - Draw the inverted line correctly in th

Peter Jones pjones at fedoraproject.org
Wed Aug 4 19:34:10 UTC 2010


commit ca82c7c53d6acb2118c0229d8738a53c85397251
Author: Peter Jones <pjones at redhat.com>
Date:   Wed Aug 4 15:36:49 2010 -0400

    * Wed Aug 04 2010 Peter Jones <pjones at redhat.com> - 0.97-66
    - Draw the inverted line correctly in the menu
      Resolves: rhbz#613153
    - Don't fail to boot on UEFI when the memory map changes (shayes)
      Resolves: rhbz#607213
    - Allow drive remaping in UEFI mode so ordering changes don't cause failure
      Resolves: rhbz#598572

 grub-0.97-add-strnchr.patch |  234 +++++
 grub-0.97-efimap.patch      | 2005 +++++++++++++++++++++++++++++++++++++++++++
 grub.spec                   |   18 +-
 3 files changed, 2256 insertions(+), 1 deletions(-)
---
diff --git a/grub-0.97-add-strnchr.patch b/grub-0.97-add-strnchr.patch
new file mode 100644
index 0000000..ebb3c3f
--- /dev/null
+++ b/grub-0.97-add-strnchr.patch
@@ -0,0 +1,234 @@
+From 20b9bd8c6047a703aadbb3fac7ad25acbe1e6b8a Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones at redhat.com>
+Date: Thu, 29 Jul 2010 17:02:53 -0400
+Subject: [PATCH 1/2] Add grub_strnchr(const char *s, int c) and some other string funcs.
+
+Add grub_strnchr(), which returns the first character of "s" that is not
+"c".
+---
+ efi/efimisc.c    |   43 +++++++++------------------
+ efi/grub/misc.h  |    5 ++-
+ stage2/char_io.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ stage2/shared.h  |   11 +++++++
+ 4 files changed, 114 insertions(+), 31 deletions(-)
+
+diff --git a/efi/efimisc.c b/efi/efimisc.c
+index 995be97..a319fdd 100644
+--- a/efi/efimisc.c
++++ b/efi/efimisc.c
+@@ -256,6 +256,19 @@ stop_floppy (void)
+   /* NOTUSED */
+ }
+ 
++char *
++grub_strndup (const char *s, int n)
++{
++  int l = grub_strnlen(s, n);
++  char *new = grub_malloc(l + 1);
++
++  if (new == NULL)
++    return NULL;
++
++  new[l] = '\0';
++  return grub_strncpy(new, s, l);
++}
++
+ int
+ safe_parse_maxulong (char **str_ptr, unsigned long *myulong_ptr)
+ {
+@@ -310,34 +323,6 @@ safe_parse_maxulong (char **str_ptr, unsigned long *myulong_ptr)
+   return 1;
+ }
+ 
+-char *
+-grub_strchr (const char *s, int c)
+-{
+-  while (*s)
+-    {
+-      if (*s == c)
+-	return (char *) s;
+-      s++;
+-    }
+-
+-  return 0;
+-}
+-
+-char *
+-grub_strrchr (const char *s, int c)
+-{
+-  char *p = 0;
+-
+-  while (*s)
+-    {
+-      if (*s == c)
+-	p = (char *) s;
+-      s++;
+-    }
+-
+-  return p;
+-}
+-
+ int
+ currticks (void)
+ {
+@@ -506,7 +491,7 @@ grub_set_config_file (char *path_name)
+ 	       DEFAULT_SAVED_DEFAULT_FILE_NAME);
+ }
+ 
+-static grub_efi_guid_t simple_file_system_guid = GRUB_EFI_SIMPLE_FILE_SYSTEM_GUID;
++grub_efi_guid_t simple_file_system_guid = GRUB_EFI_SIMPLE_FILE_SYSTEM_GUID;
+ 
+ static grub_efi_file_t *
+ simple_open_file(grub_efi_handle_t dev_handle,
+diff --git a/efi/grub/misc.h b/efi/grub/misc.h
+index 0d9b09b..5ec54d5 100644
+--- a/efi/grub/misc.h
++++ b/efi/grub/misc.h
+@@ -28,8 +28,6 @@
+ 	grub_real_dprintf(__FILE__, __LINE__, condition, fmt, ## args)
+ 
+ char *grub_stpcpy (char *dest, const char *src);
+-char *grub_strchr (const char *s, int c);
+-char *grub_strrchr (const char *s, int c);
+ void grub_real_dprintf (const char *file,
+ 			const int line,
+ 			const char *condition,
+@@ -44,6 +42,9 @@ grub_uint8_t *grub_utf16_to_utf8 (grub_uint8_t * dest,
+ void *grub_malloc (grub_size_t size);
+ void grub_free (void *ptr);
+ 
++char *grub_strndup (const char *s, int n);
++#define strndup grub_strndup
++
+ int safe_parse_maxulong (char **str_ptr, unsigned long *myulong_ptr);
+ 
+ #define E820_RAM        1
+diff --git a/stage2/char_io.c b/stage2/char_io.c
+index 9104eed..002b7c9 100644
+--- a/stage2/char_io.c
++++ b/stage2/char_io.c
+@@ -1462,6 +1462,92 @@ grub_strtok_r(char *s, const char *delim, char **ptrptr) {
+   return tmp;
+ }
+ 
++char *
++grub_strchr (const char *s, int c)
++{
++  while (*s)
++    {
++      if (*s == c)
++	return (char *) s;
++      s++;
++    }
++
++  return 0;
++}
++
++char *
++grub_strnchr (const char *s, int c)
++{
++  while (*s)
++    {
++      if (*s != c)
++	return (char *) s;
++      s++;
++    }
++
++  return 0;
++}
++
++char *
++grub_strrchr (const char *s, int c)
++{
++  char *p = 0;
++
++  while (*s)
++    {
++      if (*s == c)
++	p = (char *) s;
++      s++;
++    }
++
++  return p;
++}
++
++int
++grub_strnlen (const char *s, int n)
++{
++  int i;
++
++  if (n == 0)
++    return 0;
++
++  for (i = 0; s[i] != '\0' && i < n; i++)
++    ;
++  return i;
++}
++
++char *
++grub_strncpy(char *new, const char *s, int n)
++{
++  int i;
++
++  for (i = 0; s[i] != '\0' && i < n; i++)
++    new[i] = s[i];
++  return new;
++}
++
++int
++grub_strncasecmp(const char *s0, const char *s1, int n)
++{
++  int c0, c1;
++
++  if (s0 == s1 || n == 0)
++    return 0;
++
++  do {
++    c0 = *s0 & ~0x20;
++    c1 = *s1 & ~0x20;
++
++    if (--n == 0 || c0 == '\0')
++      break;
++
++    *s0++;
++    *s1++;
++  } while (c0 == c1);
++
++  return (c0 > c1 ? 1 : c0 < c1 ? -1 : 0);
++}
++
+ #endif /* ! STAGE1_5 */
+ 
+ #ifdef GRUB_UTIL
+diff --git a/stage2/shared.h b/stage2/shared.h
+index 1c93314..6882027 100644
+--- a/stage2/shared.h
++++ b/stage2/shared.h
+@@ -377,6 +377,11 @@ extern void *grub_scratch_mem;
+ #define strspn grub_strspn
+ #define strcspn grub_strcspn
+ #define strtok_r grub_strtok_r
++#define strchr grub_strchr
++#define strrchr grub_strrchr
++#define strnchr grub_strnchr
++#define strncpy grub_strncpy
++#define strncasecmp grub_strncasecmp
+ #endif /* WITHOUT_LIBC_STUBS */
+ 
+ #ifndef ASM_FILE
+@@ -914,6 +919,12 @@ char *grub_strcpy (char *dest, const char *src);
+ int grub_strspn(const char *s, const char *accept);
+ int grub_strcspn(const char *s, const char *reject);
+ char *grub_strtok_r(char *s, const char *delim, char **ptrptr);
++char *grub_strchr (const char *s, int c);
++char *grub_strrchr (const char *s, int c);
++char *grub_strnchr (const char *s, int c);
++int grub_strnlen (const char *s, int n);
++char *grub_strncpy (char *new, const char *s, int n);
++int grub_strncasecmp(const char *s0, const char *s1, int n);
+ 
+ #ifndef GRUB_UTIL
+ typedef unsigned long grub_jmp_buf[8];
+-- 
+1.7.2
+
diff --git a/grub-0.97-efimap.patch b/grub-0.97-efimap.patch
new file mode 100644
index 0000000..2907717
--- /dev/null
+++ b/grub-0.97-efimap.patch
@@ -0,0 +1,2005 @@
+From f344803d5e03b81e06a882df5745014a0d5b1629 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones at redhat.com>
+Date: Mon, 19 Jul 2010 17:28:53 -0400
+Subject: [PATCH 2/2] Make "device" on EFI allow you to specify device by efi device path (#598572)
+
+Make it so we can rename devices at runtime (from the config) on UEFI
+so we can map everything consistently accross reboots.
+---
+ efi/Makefile.am     |    2 +-
+ efi/eficore.c       |  420 ----------------------
+ efi/efidisk.c       |  268 ++++++++++-----
+ efi/efidp.c         |  985 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ efi/efimisc.c       |   73 ++++
+ efi/grub/efi/api.h  |   14 +-
+ efi/grub/efi/misc.h |   12 +
+ efi/grub/misc.h     |    4 +
+ stage2/builtins.c   |   37 ++-
+ stage2/shared.h     |    2 +
+ 10 files changed, 1295 insertions(+), 522 deletions(-)
+ create mode 100644 efi/efidp.c
+
+diff --git a/efi/Makefile.am b/efi/Makefile.am
+index d856040..4cffe7d 100644
+--- a/efi/Makefile.am
++++ b/efi/Makefile.am
+@@ -68,7 +68,7 @@ RELOC_FLAGS = $(STAGE2_CFLAGS) -I$(top_srcdir)/stage1 \
+ 
+ noinst_LIBRARIES = libgrubefi.a
+ libgrubefi_a_SOURCES = $(EFI_ARCH)/callwrap.c eficore.c efimm.c efimisc.c \
+-	eficon.c efidisk.c graphics.c efigraph.c efiuga.c \
++	eficon.c efidisk.c graphics.c efigraph.c efiuga.c efidp.c \
+ 	font_8x16.c efiserial.c $(EFI_ARCH)/loader/linux.c efichainloader.c \
+ 	xpm.c pxe.c efitftp.c
+ libgrubefi_a_CFLAGS = $(RELOC_FLAGS) -nostdinc
+diff --git a/efi/eficore.c b/efi/eficore.c
+index f763be6..5141c53 100644
+--- a/efi/eficore.c
++++ b/efi/eficore.c
+@@ -229,423 +229,3 @@ grub_efi_get_device_path (grub_efi_handle_t handle)
+ 				 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ }
+ 
+-/* Print the chain of Device Path nodes. This is mainly for debugging. */
+-void
+-grub_efi_print_device_path (grub_efi_device_path_t *dp)
+-{
+-  while (1)
+-    {
+-      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
+-      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
+-      grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
+-
+-      switch (type)
+-	{
+-	case GRUB_EFI_END_DEVICE_PATH_TYPE:
+-	  switch (subtype)
+-	    {
+-	    case GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE:
+-	      grub_printf ("/EndEntire\n");
+-	      //grub_putchar ('\n');
+-	      break;
+-	    case GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE:
+-	      grub_printf ("/EndThis\n");
+-	      //grub_putchar ('\n');
+-	      break;
+-	    default:
+-	      grub_printf ("/EndUnknown(%x)\n", (unsigned) subtype);
+-	      break;
+-	    }
+-	  break;
+-
+-	case GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE:
+-	  switch (subtype)
+-	    {
+-	    case GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_pci_device_path_t pci;
+-		grub_memcpy (&pci, dp, len);
+-		grub_printf ("/PCI(%x,%x)",
+-			     (unsigned) pci.function, (unsigned) pci.device);
+-	      }
+-	      break;
+-	    case GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_pccard_device_path_t pccard;
+-		grub_memcpy (&pccard, dp, len);
+-		grub_printf ("/PCCARD(%x)",
+-			     (unsigned) pccard.function);
+-	      }
+-	      break;
+-	    case GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_memory_mapped_device_path_t mmapped;
+-		grub_memcpy (&mmapped, dp, len);
+-		grub_printf ("/MMap(%x,%llx,%llx)",
+-			     (unsigned) mmapped.memory_type,
+-			     mmapped.start_address,
+-			     mmapped.end_address);
+-	      }
+-	      break;
+-	    case GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_vendor_device_path_t vendor;
+-		grub_memcpy (&vendor, dp, sizeof (vendor));
+-		grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
+-			     (unsigned) vendor.vendor_guid.data1,
+-			     (unsigned) vendor.vendor_guid.data2,
+-			     (unsigned) vendor.vendor_guid.data3,
+-			     (unsigned) vendor.vendor_guid.data4[0],
+-			     (unsigned) vendor.vendor_guid.data4[1],
+-			     (unsigned) vendor.vendor_guid.data4[2],
+-			     (unsigned) vendor.vendor_guid.data4[3],
+-			     (unsigned) vendor.vendor_guid.data4[4],
+-			     (unsigned) vendor.vendor_guid.data4[5],
+-			     (unsigned) vendor.vendor_guid.data4[6],
+-			     (unsigned) vendor.vendor_guid.data4[7]);
+-	      }
+-	      break;
+-	    case GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_controller_device_path_t controller;
+-		grub_memcpy (&controller, dp, len);
+-		grub_printf ("/Ctrl(%x)",
+-			     (unsigned) controller.controller_number);
+-	      }
+-	      break;
+-	    default:
+-	      grub_printf ("/UnknownHW(%x)", (unsigned) subtype);
+-	      break;
+-	    }
+-	  break;
+-
+-	case GRUB_EFI_ACPI_DEVICE_PATH_TYPE:
+-	  switch (subtype)
+-	    {
+-	    case GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_acpi_device_path_t acpi;
+-		grub_memcpy (&acpi, dp, len);
+-		grub_printf ("/ACPI(%x,%x)",
+-			     (unsigned) acpi.hid,
+-			     (unsigned) acpi.uid);
+-	      }
+-	      break;
+-	    case GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_expanded_acpi_device_path_t eacpi;
+-		grub_memcpy (&eacpi, dp, sizeof (eacpi));
+-		grub_printf ("/ACPI(");
+-
+-		if (GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)[0] == '\0')
+-		  grub_printf ("%x,", (unsigned) eacpi.hid);
+-		else
+-		  grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp));
+-
+-		if (GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)[0] == '\0')
+-		  grub_printf ("%x,", (unsigned) eacpi.uid);
+-		else
+-		  grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp));
+-
+-		if (GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)[0] == '\0')
+-		  grub_printf ("%x)", (unsigned) eacpi.cid);
+-		else
+-		  grub_printf ("%s)", GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp));
+-	      }
+-	      break;
+-	    default:
+-	      grub_printf ("/UnknownACPI(%x)", (unsigned) subtype);
+-	      break;
+-	    }
+-	  break;
+-
+-	case GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE:
+-	  switch (subtype)
+-	    {
+-	    case GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_atapi_device_path_t atapi;
+-		grub_memcpy (&atapi, dp, len);
+-		grub_printf ("/ATAPI(%x,%x,%x)",
+-			     (unsigned) atapi.primary_secondary,
+-			     (unsigned) atapi.slave_master,
+-			     (unsigned) atapi.lun);
+-	      }
+-	      break;
+-	    case GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_scsi_device_path_t scsi;
+-		grub_memcpy (&scsi, dp, len);
+-		grub_printf ("/SCSI(%x,%x)",
+-			     (unsigned) scsi.pun,
+-			     (unsigned) scsi.lun);
+-	      }
+-	      break;
+-	    case GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_fibre_channel_device_path_t fc;
+-		grub_memcpy (&fc, dp, len);
+-		grub_printf ("/FibreChannel(%llx,%llx)",
+-			     fc.wwn, fc.lun);
+-	      }
+-	      break;
+-	    case GRUB_EFI_1394_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_1394_device_path_t firewire;
+-		grub_memcpy (&firewire, dp, len);
+-		grub_printf ("/1394(%llx)", firewire.guid);
+-	      }
+-	      break;
+-	    case GRUB_EFI_USB_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_usb_device_path_t usb;
+-		grub_memcpy (&usb, dp, len);
+-		grub_printf ("/USB(%x,%x)",
+-			     (unsigned) usb.parent_port_number,
+-			     (unsigned) usb.interface);
+-	      }
+-	      break;
+-	    case GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_usb_class_device_path_t usb_class;
+-		grub_memcpy (&usb_class, dp, len);
+-		grub_printf ("/USBClass(%x,%x,%x,%x,%x)",
+-			     (unsigned) usb_class.vendor_id,
+-			     (unsigned) usb_class.product_id,
+-			     (unsigned) usb_class.device_class,
+-			     (unsigned) usb_class.device_subclass,
+-			     (unsigned) usb_class.device_protocol);
+-	      }
+-	      break;
+-	    case GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_i2o_device_path_t i2o;
+-		grub_memcpy (&i2o, dp, len);
+-		grub_printf ("/I2O(%x)", (unsigned) i2o.tid);
+-	      }
+-	      break;
+-	    case GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_mac_address_device_path_t mac;
+-		grub_memcpy (&mac, dp, len);
+-		grub_printf ("/MacAddr(%x:%x:%x:%x:%x:%x,%x)",
+-			     (unsigned) mac.mac_address[0],
+-			     (unsigned) mac.mac_address[1],
+-			     (unsigned) mac.mac_address[2],
+-			     (unsigned) mac.mac_address[3],
+-			     (unsigned) mac.mac_address[4],
+-			     (unsigned) mac.mac_address[5],
+-			     (unsigned) mac.if_type);
+-	      }
+-	      break;
+-	    case GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_ipv4_device_path_t ipv4;
+-		grub_memcpy (&ipv4, dp, len);
+-		grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)",
+-			     (unsigned) ipv4.local_ip_address[0],
+-			     (unsigned) ipv4.local_ip_address[1],
+-			     (unsigned) ipv4.local_ip_address[2],
+-			     (unsigned) ipv4.local_ip_address[3],
+-			     (unsigned) ipv4.remote_ip_address[0],
+-			     (unsigned) ipv4.remote_ip_address[1],
+-			     (unsigned) ipv4.remote_ip_address[2],
+-			     (unsigned) ipv4.remote_ip_address[3],
+-			     (unsigned) ipv4.local_port,
+-			     (unsigned) ipv4.remote_port,
+-			     (unsigned) ipv4.protocol,
+-			     (unsigned) ipv4.static_ip_address);
+-	      }
+-	      break;
+-	    case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_ipv6_device_path_t ipv6;
+-		grub_memcpy (&ipv6, dp, len);
+-		grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)",
+-			     (unsigned) ipv6.local_ip_address[0],
+-			     (unsigned) ipv6.local_ip_address[1],
+-			     (unsigned) ipv6.local_ip_address[2],
+-			     (unsigned) ipv6.local_ip_address[3],
+-			     (unsigned) ipv6.local_ip_address[4],
+-			     (unsigned) ipv6.local_ip_address[5],
+-			     (unsigned) ipv6.local_ip_address[6],
+-			     (unsigned) ipv6.local_ip_address[7],
+-			     (unsigned) ipv6.remote_ip_address[0],
+-			     (unsigned) ipv6.remote_ip_address[1],
+-			     (unsigned) ipv6.remote_ip_address[2],
+-			     (unsigned) ipv6.remote_ip_address[3],
+-			     (unsigned) ipv6.remote_ip_address[4],
+-			     (unsigned) ipv6.remote_ip_address[5],
+-			     (unsigned) ipv6.remote_ip_address[6],
+-			     (unsigned) ipv6.remote_ip_address[7],
+-			     (unsigned) ipv6.local_port,
+-			     (unsigned) ipv6.remote_port,
+-			     (unsigned) ipv6.protocol,
+-			     (unsigned) ipv6.static_ip_address);
+-	      }
+-	      break;
+-	    case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_infiniband_device_path_t ib;
+-		grub_memcpy (&ib, dp, len);
+-		grub_printf ("/InfiniBand(%x,%llx,%llx,%llx)",
+-			     (unsigned) ib.port_gid[0], /* XXX */
+-			     ib.remote_id,
+-			     ib.target_port_id,
+-			     ib.device_id);
+-	      }
+-	      break;
+-	    case GRUB_EFI_UART_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_uart_device_path_t uart;
+-		grub_memcpy (&uart, dp, len);
+-		grub_printf ("/UART(%llu,%u,%x,%x)",
+-			     uart.baud_rate,
+-			     uart.data_bits,
+-			     uart.parity,
+-			     uart.stop_bits);
+-	      }
+-	      break;
+-	    case GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_vendor_messaging_device_path_t vendor;
+-		grub_memcpy (&vendor, dp, sizeof (vendor));
+-		grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
+-			     (unsigned) vendor.vendor_guid.data1,
+-			     (unsigned) vendor.vendor_guid.data2,
+-			     (unsigned) vendor.vendor_guid.data3,
+-			     (unsigned) vendor.vendor_guid.data4[0],
+-			     (unsigned) vendor.vendor_guid.data4[1],
+-			     (unsigned) vendor.vendor_guid.data4[2],
+-			     (unsigned) vendor.vendor_guid.data4[3],
+-			     (unsigned) vendor.vendor_guid.data4[4],
+-			     (unsigned) vendor.vendor_guid.data4[5],
+-			     (unsigned) vendor.vendor_guid.data4[6],
+-			     (unsigned) vendor.vendor_guid.data4[7]);
+-	      }
+-	      break;
+-	    default:
+-	      grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype);
+-	      break;
+-	    }
+-	  break;
+-
+-	case GRUB_EFI_MEDIA_DEVICE_PATH_TYPE:
+-	  switch (subtype)
+-	    {
+-	    case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_hard_drive_device_path_t hd;
+-		grub_memcpy (&hd, dp, len);
+-		grub_printf ("/HD(%u,%llx,%llx,%02x%02x%02x%02x%02x%02x%02x%02x,%x,%x)",
+-			     hd.partition_number,
+-			     hd.partition_start,
+-			     hd.partition_size,
+-			     (unsigned) hd.partition_signature[0],
+-			     (unsigned) hd.partition_signature[1],
+-			     (unsigned) hd.partition_signature[2],
+-			     (unsigned) hd.partition_signature[3],
+-			     (unsigned) hd.partition_signature[4],
+-			     (unsigned) hd.partition_signature[5],
+-			     (unsigned) hd.partition_signature[6],
+-			     (unsigned) hd.partition_signature[7],
+-			     (unsigned) hd.mbr_type,
+-			     (unsigned) hd.signature_type);
+-	      }
+-	      break;
+-	    case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_cdrom_device_path_t cd;
+-		grub_memcpy (&cd, dp, len);
+-		grub_printf ("/CD(%u,%llx,%llx)",
+-			     cd.boot_entry,
+-			     cd.partition_start,
+-			     cd.partition_size);
+-	      }
+-	      break;
+-	    case GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_vendor_media_device_path_t vendor;
+-		grub_memcpy (&vendor, dp, sizeof (vendor));
+-		grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
+-			     (unsigned) vendor.vendor_guid.data1,
+-			     (unsigned) vendor.vendor_guid.data2,
+-			     (unsigned) vendor.vendor_guid.data3,
+-			     (unsigned) vendor.vendor_guid.data4[0],
+-			     (unsigned) vendor.vendor_guid.data4[1],
+-			     (unsigned) vendor.vendor_guid.data4[2],
+-			     (unsigned) vendor.vendor_guid.data4[3],
+-			     (unsigned) vendor.vendor_guid.data4[4],
+-			     (unsigned) vendor.vendor_guid.data4[5],
+-			     (unsigned) vendor.vendor_guid.data4[6],
+-			     (unsigned) vendor.vendor_guid.data4[7]);
+-	      }
+-	      break;
+-	    case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_file_path_device_path_t *fp;
+-		grub_uint8_t buf[(len - 4) * 2 + 1];
+-		fp = (grub_efi_file_path_device_path_t *) dp;
+-		*grub_utf16_to_utf8 (buf, fp->path_name,
+-				     (len - 4) / sizeof (grub_efi_char16_t))
+-		  = '\0';
+-		grub_printf ("/File(%s)", buf);
+-	      }
+-	      break;
+-	    case GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_protocol_device_path_t proto;
+-		grub_memcpy (&proto, dp, sizeof (proto));
+-		grub_printf ("/Protocol(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
+-			     (unsigned) proto.guid.data1,
+-			     (unsigned) proto.guid.data2,
+-			     (unsigned) proto.guid.data3,
+-			     (unsigned) proto.guid.data4[0],
+-			     (unsigned) proto.guid.data4[1],
+-			     (unsigned) proto.guid.data4[2],
+-			     (unsigned) proto.guid.data4[3],
+-			     (unsigned) proto.guid.data4[4],
+-			     (unsigned) proto.guid.data4[5],
+-			     (unsigned) proto.guid.data4[6],
+-			     (unsigned) proto.guid.data4[7]);
+-	      }
+-	      break;
+-	    default:
+-	      grub_printf ("/UnknownMedia(%x)", (unsigned) subtype);
+-	      break;
+-	    }
+-	  break;
+-
+-	case GRUB_EFI_BIOS_DEVICE_PATH_TYPE:
+-	  switch (subtype)
+-	    {
+-	    case GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE:
+-	      {
+-		grub_efi_bios_device_path_t bios;
+-		grub_memcpy (&bios, dp, sizeof (bios));
+-		grub_printf ("/BIOS(%x,%x,%s)",
+-			     (unsigned) bios.device_type,
+-			     (unsigned) bios.status_flags,
+-			     (char *) (dp + 1));
+-	      }
+-	      break;
+-	    default:
+-	      grub_printf ("/UnknownBIOS(%x)", (unsigned) subtype);
+-	      break;
+-	    }
+-	  break;
+-
+-	default:
+-	  grub_printf ("/UnknownType(%x,%x)\n",
+-		       (unsigned) type,
+-		       (unsigned) subtype);
+-	  return;
+-	  break;
+-	}
+-
+-      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
+-	break;
+-
+-      dp = (grub_efi_device_path_t *) ((char *) dp + len);
+-    }
+-}
+diff --git a/efi/efidisk.c b/efi/efidisk.c
+index 885ae1b..145ed16 100644
+--- a/efi/efidisk.c
++++ b/efi/efidisk.c
+@@ -38,100 +38,12 @@ struct grub_efidisk_data
+ /* GUIDs.  */
+ static grub_efi_guid_t disk_io_guid = GRUB_EFI_DISK_IO_GUID;
+ static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID;
++static grub_efi_guid_t device_path_from_text_guid = GRUB_EFI_DEVICE_PATH_FROM_TEXT_GUID;
+ 
+ static struct grub_efidisk_data *fd_devices;
+ static struct grub_efidisk_data *hd_devices;
+ static struct grub_efidisk_data *cd_devices;
+ 
+-/* Duplicate a device path.  */
+-static grub_efi_device_path_t *
+-duplicate_device_path (const grub_efi_device_path_t *dp)
+-{
+-  grub_efi_device_path_t *p;
+-  grub_size_t total_size = 0;
+-
+-  for (p = (grub_efi_device_path_t *) dp;
+-       ;
+-       p = GRUB_EFI_NEXT_DEVICE_PATH (p))
+-    {
+-      total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
+-      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
+-	break;
+-    }
+-
+-  p = grub_malloc (total_size);
+-  if (! p)
+-    return 0;
+-
+-  grub_memcpy (p, dp, total_size);
+-  return p;
+-}
+-
+-/* Return the device path node right before the end node.  */
+-static grub_efi_device_path_t *
+-find_last_device_path (const grub_efi_device_path_t *dp)
+-{
+-  grub_efi_device_path_t *next, *p;
+-
+-  if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
+-    return 0;
+-
+-  for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
+-       ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
+-       p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
+-    ;
+-
+-  return p;
+-}
+-
+-/* Compare device paths.  */
+-static int
+-compare_device_paths (const grub_efi_device_path_t *dp1,
+-		      const grub_efi_device_path_t *dp2)
+-{
+-  if (! dp1 || ! dp2)
+-    /* Return non-zero.  */
+-    return 1;
+-
+-  while (1)
+-    {
+-      grub_efi_uint8_t type1, type2;
+-      grub_efi_uint8_t subtype1, subtype2;
+-      grub_efi_uint16_t len1, len2;
+-      int ret;
+-
+-      type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
+-      type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
+-
+-      if (type1 != type2)
+-	return (int) type2 - (int) type1;
+-
+-      subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
+-      subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
+-
+-      if (subtype1 != subtype2)
+-	return (int) subtype1 - (int) subtype2;
+-
+-      len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
+-      len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
+-
+-      if (len1 != len2)
+-	return (int) len1 - (int) len2;
+-
+-      ret = grub_memcmp ((char *)dp1, (char *)dp2, len1);
+-      if (ret != 0)
+-	return ret;
+-
+-      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
+-	break;
+-
+-      dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
+-      dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
+-    }
+-
+-  return 0;
+-}
+-
+ static struct grub_efidisk_data *
+ make_devices (void)
+ {
+@@ -648,3 +560,181 @@ grub_get_drive_partition_from_bdev_handle (grub_efi_handle_t handle,
+ 
+   return 0;
+ }
++
++int
++check_device (const char *device)
++{
++  grub_efi_device_path_t *dp;
++
++  dp = device_path_from_utf8(device);
++  if (dp == NULL)
++    return 0;
++
++  grub_free(dp);
++  return 1;
++}
++
++static void
++swap_devices (struct grub_efidisk_data *d0,
++	      struct grub_efidisk_data *d1)
++{
++  struct grub_efidisk_data tmp;
++
++  if (!d0 || !d1)
++    return;
++
++  memcpy(&tmp, d1, sizeof(*d1));
++
++  memcpy(&d0->handle, &d1->handle, sizeof(d1->handle));
++  d0->device_path = d1->device_path;
++  d0->last_device_path = d1->last_device_path;
++  d0->block_io = d1->block_io;
++  d0->disk_io = d1->disk_io;
++
++  memcpy(d1->handle, tmp.handle, sizeof(tmp.handle));
++  d1->device_path = tmp.device_path;
++  d1->last_device_path = tmp.last_device_path;
++  d1->block_io = tmp.block_io;
++  d1->disk_io = tmp.disk_io;
++}
++
++static int
++compare_hd_device_paths(grub_efi_hard_drive_device_path_t *hd0,
++			grub_efi_hard_drive_device_path_t *hd1)
++{
++  grub_efi_uint64_t x;
++  int sigsize;
++
++  if ((x = hd1->partition_number - hd0->partition_number))
++    return x;
++
++  if ((x = hd1->partition_start - hd0->partition_start))
++    return x;
++
++
++  if ((x = hd1->partition_size - hd0->partition_size))
++    return x;
++
++  if ((x = hd1->signature_type - hd0->signature_type))
++    return x;
++
++  switch (hd0->signature_type)
++    {
++    case 1:
++      sigsize = 4;
++      break;
++    case 2:
++      sigsize = 16;
++      break;
++    default:
++      sigsize = 0;
++      break;
++    }
++  x = grub_memcmp((char *)hd0->partition_signature,
++                  (char *)hd1->partition_signature, sigsize);
++  return x;
++}
++
++static grub_efi_device_path_t *
++get_parent_of_disk(grub_efi_device_path_t *hd)
++{
++  grub_efi_uintn_t num_handles;
++  grub_efi_handle_t *handles;
++  grub_efi_handle_t *handle;
++  grub_efi_device_path_t *ret;
++
++  handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL,
++				     &simple_file_system_guid,
++                                    0, &num_handles);
++  for (handle = handles; num_handles--; handle++)
++    {
++      grub_efi_device_path_t *fsdp, *hddp;
++
++      fsdp = grub_efi_get_device_path (*handle);
++      if (!fsdp)
++	continue;
++      hddp = find_last_device_path(fsdp);
++
++      if (compare_hd_device_paths((grub_efi_hard_drive_device_path_t *)hddp,
++				   (grub_efi_hard_drive_device_path_t *)hd) == 0)
++        {
++	  grub_efi_device_path_t *p;
++	  ret = duplicate_device_path((grub_efi_device_path_t *)fsdp);
++	  if (!ret)
++	    return NULL;
++	  for (p = ret; ; p = GRUB_EFI_NEXT_DEVICE_PATH(p))
++	    {
++	      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH(p))
++		break;
++	      if ((GRUB_EFI_DEVICE_PATH_TYPE(p) ==
++			GRUB_EFI_MEDIA_DEVICE_PATH_TYPE)
++		      && (GRUB_EFI_DEVICE_PATH_SUBTYPE(p) ==
++				GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
++	        {
++		  p->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++		  p->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++		  p->length[0] = 4;
++		  p->length[1] = 0;
++		  break;
++		}
++	    }
++	  return ret;
++	}
++    }
++  return NULL;
++}
++
++void
++assign_device_name (int drive, const char *device)
++{
++  grub_efi_device_path_t *dp0, *dp1;
++  struct grub_efidisk_data *devices;
++  struct grub_efidisk_data *d, *d0 = NULL, *d1 = NULL;
++  int n = -1;
++
++  dp0 = device_path_from_utf8(device);
++  if (!dp0)
++    return;
++
++  dp1 = get_parent_of_disk(dp0);
++  grub_free(dp0);
++  if (!dp1)
++    return;
++
++  if (drive & 0x80)
++    {
++      drive -= 0x80;
++      devices = hd_devices;
++    }
++  else
++    {
++      devices = cd_devices;
++      drive -= 0x100;
++    }
++
++  for (d = devices; d; d = d->next)
++    {
++      if (!d->device_path)
++	continue;
++
++      if (++n == drive)
++	d0 = d;
++
++      int x;
++      if (!(x = compare_device_paths(dp1, d->device_path)))
++	d1 = d;
++
++      if (d0 && d1)
++        {
++	  /* if they're the same node, that just means it's already at
++	   * the right position. */
++	  if (d0 != d1)
++	    {
++	      swap_devices(d0, d1);
++	      grub_free(dp1);
++	      return;
++	    }
++	}
++    }
++  grub_free(dp1);
++}
+diff --git a/efi/efidp.c b/efi/efidp.c
+new file mode 100644
+index 0000000..af6cdd5
+--- /dev/null
++++ b/efi/efidp.c
+@@ -0,0 +1,984 @@
++/*
++ * GRUB  --  GRand Unified Bootloader
++ * Copyright (C) 2010 Free Software Foundation, Inc.
++ *
++ *  GRUB is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with GRUB; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <grub/types.h>
++#include <grub/misc.h>
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/efi/misc.h>
++
++#include <shared.h>
++
++/* Duplicate a device path.  */
++grub_efi_device_path_t *
++duplicate_device_path (const grub_efi_device_path_t *dp)
++{
++  grub_efi_device_path_t *p;
++  grub_size_t total_size = 0;
++
++  for (p = (grub_efi_device_path_t *) dp;
++       ;
++       p = GRUB_EFI_NEXT_DEVICE_PATH (p))
++    {
++      total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
++      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
++	break;
++    }
++
++  p = grub_malloc (total_size);
++  if (! p)
++    return 0;
++
++  grub_memcpy (p, dp, total_size);
++  return p;
++}
++
++/* Return the device path node right before the end node.  */
++grub_efi_device_path_t *
++find_last_device_path (const grub_efi_device_path_t *dp)
++{
++  grub_efi_device_path_t *next, *p;
++
++  if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
++    return 0;
++
++  for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
++       ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
++       p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
++    ;
++
++  return p;
++}
++
++/* Compare device paths.  */
++int
++compare_device_paths (const grub_efi_device_path_t *dp1,
++		      const grub_efi_device_path_t *dp2)
++{
++  if (! dp1 || ! dp2)
++    /* Return non-zero.  */
++    return 1;
++
++  while (1)
++    {
++      grub_efi_uint8_t type1, type2;
++      grub_efi_uint8_t subtype1, subtype2;
++      grub_efi_uint16_t len1, len2;
++      int ret;
++
++      type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
++      type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
++
++      if (type1 != type2)
++	return (int) type2 - (int) type1;
++
++      subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
++      subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
++
++      if (subtype1 != subtype2)
++	return (int) subtype1 - (int) subtype2;
++
++      len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
++      len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
++
++      if (len1 != len2)
++	return (int) len1 - (int) len2;
++
++      ret = grub_memcmp ((char *)dp1, (char *)dp2, len1);
++      if (ret != 0)
++	return ret;
++
++      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
++	break;
++
++      dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
++      dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
++    }
++
++  return 0;
++}
++
++/* Print the chain of Device Path nodes. This is mainly for debugging. */
++void
++grub_efi_print_device_path (grub_efi_device_path_t *dp)
++{
++  while (1)
++    {
++      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
++      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
++      grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
++
++      switch (type)
++	{
++	case GRUB_EFI_END_DEVICE_PATH_TYPE:
++	  switch (subtype)
++	    {
++	    case GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE:
++	      grub_printf ("/EndEntire\n");
++	      //grub_putchar ('\n');
++	      break;
++	    case GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE:
++	      grub_printf ("/EndThis\n");
++	      //grub_putchar ('\n');
++	      break;
++	    default:
++	      grub_printf ("/EndUnknown(%x)\n", (unsigned) subtype);
++	      break;
++	    }
++	  break;
++
++	case GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE:
++	  switch (subtype)
++	    {
++	    case GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_pci_device_path_t pci;
++		grub_memcpy (&pci, dp, len);
++		grub_printf ("/PCI(%x,%x)",
++			     (unsigned) pci.function, (unsigned) pci.device);
++	      }
++	      break;
++	    case GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_pccard_device_path_t pccard;
++		grub_memcpy (&pccard, dp, len);
++		grub_printf ("/PCCARD(%x)",
++			     (unsigned) pccard.function);
++	      }
++	      break;
++	    case GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_memory_mapped_device_path_t mmapped;
++		grub_memcpy (&mmapped, dp, len);
++		grub_printf ("/MMap(%x,%llx,%llx)",
++			     (unsigned) mmapped.memory_type,
++			     mmapped.start_address,
++			     mmapped.end_address);
++	      }
++	      break;
++	    case GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_vendor_device_path_t vendor;
++		grub_memcpy (&vendor, dp, sizeof (vendor));
++		grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
++			     (unsigned) vendor.vendor_guid.data1,
++			     (unsigned) vendor.vendor_guid.data2,
++			     (unsigned) vendor.vendor_guid.data3,
++			     (unsigned) vendor.vendor_guid.data4[0],
++			     (unsigned) vendor.vendor_guid.data4[1],
++			     (unsigned) vendor.vendor_guid.data4[2],
++			     (unsigned) vendor.vendor_guid.data4[3],
++			     (unsigned) vendor.vendor_guid.data4[4],
++			     (unsigned) vendor.vendor_guid.data4[5],
++			     (unsigned) vendor.vendor_guid.data4[6],
++			     (unsigned) vendor.vendor_guid.data4[7]);
++	      }
++	      break;
++	    case GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_controller_device_path_t controller;
++		grub_memcpy (&controller, dp, len);
++		grub_printf ("/Ctrl(%x)",
++			     (unsigned) controller.controller_number);
++	      }
++	      break;
++	    default:
++	      grub_printf ("/UnknownHW(%x)", (unsigned) subtype);
++	      break;
++	    }
++	  break;
++
++	case GRUB_EFI_ACPI_DEVICE_PATH_TYPE:
++	  switch (subtype)
++	    {
++	    case GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_acpi_device_path_t acpi;
++		grub_memcpy (&acpi, dp, len);
++		grub_printf ("/ACPI(%x,%x)",
++			     (unsigned) acpi.hid,
++			     (unsigned) acpi.uid);
++	      }
++	      break;
++	    case GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_expanded_acpi_device_path_t eacpi;
++		grub_memcpy (&eacpi, dp, sizeof (eacpi));
++		grub_printf ("/ACPI(");
++
++		if (GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)[0] == '\0')
++		  grub_printf ("%x,", (unsigned) eacpi.hid);
++		else
++		  grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp));
++
++		if (GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)[0] == '\0')
++		  grub_printf ("%x,", (unsigned) eacpi.uid);
++		else
++		  grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp));
++
++		if (GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)[0] == '\0')
++		  grub_printf ("%x)", (unsigned) eacpi.cid);
++		else
++		  grub_printf ("%s)", GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp));
++	      }
++	      break;
++	    default:
++	      grub_printf ("/UnknownACPI(%x)", (unsigned) subtype);
++	      break;
++	    }
++	  break;
++
++	case GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE:
++	  switch (subtype)
++	    {
++	    case GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_atapi_device_path_t atapi;
++		grub_memcpy (&atapi, dp, len);
++		grub_printf ("/ATAPI(%x,%x,%x)",
++			     (unsigned) atapi.primary_secondary,
++			     (unsigned) atapi.slave_master,
++			     (unsigned) atapi.lun);
++	      }
++	      break;
++	    case GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_scsi_device_path_t scsi;
++		grub_memcpy (&scsi, dp, len);
++		grub_printf ("/SCSI(%x,%x)",
++			     (unsigned) scsi.pun,
++			     (unsigned) scsi.lun);
++	      }
++	      break;
++	    case GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_fibre_channel_device_path_t fc;
++		grub_memcpy (&fc, dp, len);
++		grub_printf ("/FibreChannel(%llx,%llx)",
++			     fc.wwn, fc.lun);
++	      }
++	      break;
++	    case GRUB_EFI_1394_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_1394_device_path_t firewire;
++		grub_memcpy (&firewire, dp, len);
++		grub_printf ("/1394(%llx)", firewire.guid);
++	      }
++	      break;
++	    case GRUB_EFI_USB_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_usb_device_path_t usb;
++		grub_memcpy (&usb, dp, len);
++		grub_printf ("/USB(%x,%x)",
++			     (unsigned) usb.parent_port_number,
++			     (unsigned) usb.interface);
++	      }
++	      break;
++	    case GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_usb_class_device_path_t usb_class;
++		grub_memcpy (&usb_class, dp, len);
++		grub_printf ("/USBClass(%x,%x,%x,%x,%x)",
++			     (unsigned) usb_class.vendor_id,
++			     (unsigned) usb_class.product_id,
++			     (unsigned) usb_class.device_class,
++			     (unsigned) usb_class.device_subclass,
++			     (unsigned) usb_class.device_protocol);
++	      }
++	      break;
++	    case GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_i2o_device_path_t i2o;
++		grub_memcpy (&i2o, dp, len);
++		grub_printf ("/I2O(%x)", (unsigned) i2o.tid);
++	      }
++	      break;
++	    case GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_mac_address_device_path_t mac;
++		grub_memcpy (&mac, dp, len);
++		grub_printf ("/MacAddr(%x:%x:%x:%x:%x:%x,%x)",
++			     (unsigned) mac.mac_address[0],
++			     (unsigned) mac.mac_address[1],
++			     (unsigned) mac.mac_address[2],
++			     (unsigned) mac.mac_address[3],
++			     (unsigned) mac.mac_address[4],
++			     (unsigned) mac.mac_address[5],
++			     (unsigned) mac.if_type);
++	      }
++	      break;
++	    case GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_ipv4_device_path_t ipv4;
++		grub_memcpy (&ipv4, dp, len);
++		grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)",
++			     (unsigned) ipv4.local_ip_address[0],
++			     (unsigned) ipv4.local_ip_address[1],
++			     (unsigned) ipv4.local_ip_address[2],
++			     (unsigned) ipv4.local_ip_address[3],
++			     (unsigned) ipv4.remote_ip_address[0],
++			     (unsigned) ipv4.remote_ip_address[1],
++			     (unsigned) ipv4.remote_ip_address[2],
++			     (unsigned) ipv4.remote_ip_address[3],
++			     (unsigned) ipv4.local_port,
++			     (unsigned) ipv4.remote_port,
++			     (unsigned) ipv4.protocol,
++			     (unsigned) ipv4.static_ip_address);
++	      }
++	      break;
++	    case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_ipv6_device_path_t ipv6;
++		grub_memcpy (&ipv6, dp, len);
++		grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)",
++			     (unsigned) ipv6.local_ip_address[0],
++			     (unsigned) ipv6.local_ip_address[1],
++			     (unsigned) ipv6.local_ip_address[2],
++			     (unsigned) ipv6.local_ip_address[3],
++			     (unsigned) ipv6.local_ip_address[4],
++			     (unsigned) ipv6.local_ip_address[5],
++			     (unsigned) ipv6.local_ip_address[6],
++			     (unsigned) ipv6.local_ip_address[7],
++			     (unsigned) ipv6.remote_ip_address[0],
++			     (unsigned) ipv6.remote_ip_address[1],
++			     (unsigned) ipv6.remote_ip_address[2],
++			     (unsigned) ipv6.remote_ip_address[3],
++			     (unsigned) ipv6.remote_ip_address[4],
++			     (unsigned) ipv6.remote_ip_address[5],
++			     (unsigned) ipv6.remote_ip_address[6],
++			     (unsigned) ipv6.remote_ip_address[7],
++			     (unsigned) ipv6.local_port,
++			     (unsigned) ipv6.remote_port,
++			     (unsigned) ipv6.protocol,
++			     (unsigned) ipv6.static_ip_address);
++	      }
++	      break;
++	    case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_infiniband_device_path_t ib;
++		grub_memcpy (&ib, dp, len);
++		grub_printf ("/InfiniBand(%x,%llx,%llx,%llx)",
++			     (unsigned) ib.port_gid[0], /* XXX */
++			     ib.remote_id,
++			     ib.target_port_id,
++			     ib.device_id);
++	      }
++	      break;
++	    case GRUB_EFI_UART_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_uart_device_path_t uart;
++		grub_memcpy (&uart, dp, len);
++		grub_printf ("/UART(%llu,%u,%x,%x)",
++			     uart.baud_rate,
++			     uart.data_bits,
++			     uart.parity,
++			     uart.stop_bits);
++	      }
++	      break;
++	    case GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_vendor_messaging_device_path_t vendor;
++		grub_memcpy (&vendor, dp, sizeof (vendor));
++		grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
++			     (unsigned) vendor.vendor_guid.data1,
++			     (unsigned) vendor.vendor_guid.data2,
++			     (unsigned) vendor.vendor_guid.data3,
++			     (unsigned) vendor.vendor_guid.data4[0],
++			     (unsigned) vendor.vendor_guid.data4[1],
++			     (unsigned) vendor.vendor_guid.data4[2],
++			     (unsigned) vendor.vendor_guid.data4[3],
++			     (unsigned) vendor.vendor_guid.data4[4],
++			     (unsigned) vendor.vendor_guid.data4[5],
++			     (unsigned) vendor.vendor_guid.data4[6],
++			     (unsigned) vendor.vendor_guid.data4[7]);
++	      }
++	      break;
++	    default:
++	      grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype);
++	      break;
++	    }
++	  break;
++
++	case GRUB_EFI_MEDIA_DEVICE_PATH_TYPE:
++	  switch (subtype)
++	    {
++	    case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_hard_drive_device_path_t hd;
++		grub_memcpy (&hd, dp, len);
++		grub_printf ("/HD(%u,%llx,%llx,%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
++			     hd.partition_number,
++			     hd.partition_start,
++			     hd.partition_size,
++			     (unsigned) hd.partition_signature[3],
++			     (unsigned) hd.partition_signature[2],
++			     (unsigned) hd.partition_signature[1],
++			     (unsigned) hd.partition_signature[0],
++			     (unsigned) hd.partition_signature[5],
++			     (unsigned) hd.partition_signature[4],
++			     (unsigned) hd.partition_signature[7],
++			     (unsigned) hd.partition_signature[6],
++			     (unsigned) hd.partition_signature[9],
++			     (unsigned) hd.partition_signature[8],
++			     (unsigned) hd.partition_signature[10],
++			     (unsigned) hd.partition_signature[11],
++			     (unsigned) hd.partition_signature[12],
++			     (unsigned) hd.partition_signature[13],
++			     (unsigned) hd.partition_signature[14],
++			     (unsigned) hd.partition_signature[15]);
++	      }
++	      break;
++	    case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_cdrom_device_path_t cd;
++		grub_memcpy (&cd, dp, len);
++		grub_printf ("/CD(%u,%llx,%llx)",
++			     cd.boot_entry,
++			     cd.partition_start,
++			     cd.partition_size);
++	      }
++	      break;
++	    case GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_vendor_media_device_path_t vendor;
++		grub_memcpy (&vendor, dp, sizeof (vendor));
++		grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
++			     (unsigned) vendor.vendor_guid.data1,
++			     (unsigned) vendor.vendor_guid.data2,
++			     (unsigned) vendor.vendor_guid.data3,
++			     (unsigned) vendor.vendor_guid.data4[0],
++			     (unsigned) vendor.vendor_guid.data4[1],
++			     (unsigned) vendor.vendor_guid.data4[2],
++			     (unsigned) vendor.vendor_guid.data4[3],
++			     (unsigned) vendor.vendor_guid.data4[4],
++			     (unsigned) vendor.vendor_guid.data4[5],
++			     (unsigned) vendor.vendor_guid.data4[6],
++			     (unsigned) vendor.vendor_guid.data4[7]);
++	      }
++	      break;
++	    case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_file_path_device_path_t *fp;
++		grub_uint8_t buf[(len - 4) * 2 + 1];
++		fp = (grub_efi_file_path_device_path_t *) dp;
++		*grub_utf16_to_utf8 (buf, fp->path_name,
++				     (len - 4) / sizeof (grub_efi_char16_t))
++		  = '\0';
++		grub_printf ("/File(%s)", buf);
++	      }
++	      break;
++	    case GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_protocol_device_path_t proto;
++		grub_memcpy (&proto, dp, sizeof (proto));
++		grub_printf ("/Protocol(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
++			     (unsigned) proto.guid.data1,
++			     (unsigned) proto.guid.data2,
++			     (unsigned) proto.guid.data3,
++			     (unsigned) proto.guid.data4[0],
++			     (unsigned) proto.guid.data4[1],
++			     (unsigned) proto.guid.data4[2],
++			     (unsigned) proto.guid.data4[3],
++			     (unsigned) proto.guid.data4[4],
++			     (unsigned) proto.guid.data4[5],
++			     (unsigned) proto.guid.data4[6],
++			     (unsigned) proto.guid.data4[7]);
++	      }
++	      break;
++	    default:
++	      grub_printf ("/UnknownMedia(%x)", (unsigned) subtype);
++	      break;
++	    }
++	  break;
++
++	case GRUB_EFI_BIOS_DEVICE_PATH_TYPE:
++	  switch (subtype)
++	    {
++	    case GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_bios_device_path_t bios;
++		grub_memcpy (&bios, dp, sizeof (bios));
++		grub_printf ("/BIOS(%x,%x,%s)",
++			     (unsigned) bios.device_type,
++			     (unsigned) bios.status_flags,
++			     (char *) (dp + 1));
++	      }
++	      break;
++	    default:
++	      grub_printf ("/UnknownBIOS(%x)", (unsigned) subtype);
++	      break;
++	    }
++	  break;
++
++	default:
++	  grub_printf ("/UnknownType(%x,%x)\n",
++		       (unsigned) type,
++		       (unsigned) subtype);
++	  return;
++	  break;
++	}
++
++      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
++	break;
++
++      dp = (grub_efi_device_path_t *) ((char *) dp + len);
++    }
++}
++
++static inline int
++dpname_matches(char *str, char *candidate)
++{
++  grub_size_t clen = grub_strlen(candidate);
++  char scratch[clen + 2];
++  int rc;
++
++  grub_strncpy(scratch, candidate, clen);
++  scratch[clen+1] = '\0';
++  if (scratch[clen-1] == '$')
++    {
++      scratch[--clen] = '\0';
++      rc = !grub_strncasecmp(str, scratch, clen);
++      return rc;
++    }
++
++    grub_strncpy(scratch+clen, "(", 2);
++    clen = grub_strlen(scratch);
++    rc = !grub_strncasecmp(str, scratch, clen);
++    return rc;
++}
++
++static void
++finish_param_parse(char *pos, char **end, char *tmp)
++{
++  if (!pos || !end || !tmp)
++    return;
++
++  if (*end)
++    **end = *tmp;
++}
++
++static char *
++get_next_param(char *pos, char **end, char *tmp)
++{
++  char *comma = NULL;
++  char *openparen = NULL;
++  char *closeparen = NULL;
++
++  if (!pos || !end || !tmp)
++    return NULL;
++
++  if (*end)
++    **end = *tmp;
++
++  openparen = grub_strchr(pos, '(');
++  if (*openparen)
++    {
++      pos = grub_strnchr(openparen + 1, ' ');
++      comma = grub_strchr(pos, ',');
++      closeparen = grub_strchr(pos, ')');
++
++      if (*comma)
++	{
++	  *tmp = *comma;
++	  *comma = '\0';
++	  *end = comma;
++	}
++      else if (*closeparen)
++	{
++	  *tmp = *closeparen;
++	  *closeparen = '\0';
++	  *end = closeparen;
++	}
++      return pos;
++    }
++
++  comma = grub_strchr(pos, ',');
++  if (*comma)
++    {
++      pos = grub_strnchr(comma + 1, ' ');
++      comma = grub_strchr(pos, ',');
++      closeparen = grub_strchr(pos, ')');
++
++      if (*comma)
++	{
++	  *tmp = *comma;
++	  *comma = '\0';
++	  *end = comma;
++	}
++      else if (*closeparen)
++	{
++	  *tmp = *closeparen;
++	  *closeparen = '\0';
++	  *end = closeparen;
++	}
++      return pos;
++    }
++
++  closeparen = grub_strchr(pos, ')');
++  if (*closeparen)
++    pos = grub_strnchr(closeparen + 1, ' ');
++
++  return pos;
++}
++
++struct generic_device_path
++  {
++    grub_efi_uint8_t type;
++    grub_efi_uint8_t subtype;
++    grub_efi_uint16_t length;
++  } __attribute__((packed));
++
++struct hd_media_device_path
++  {
++    grub_efi_uint8_t type;
++    grub_efi_uint8_t subtype;
++    grub_efi_uint16_t length;
++    grub_efi_uint32_t partition;
++    grub_efi_uint64_t startlba;
++    grub_efi_uint64_t size;
++    grub_efi_uint8_t signature[16];
++    grub_efi_uint8_t mbr_type;
++    grub_efi_uint8_t signature_type;
++  } __attribute__((packed));
++
++static inline int
++parse_device_path_component(const char *orig_str, void *data)
++{
++  int orig_str_len = strlen(orig_str) + 1;
++  char str[orig_str_len];
++  char tmp;
++  char *pos = str;
++  int ret = 0;
++
++  grub_strcpy(str, orig_str);
++  if (dpname_matches(str, "pci"))
++    {
++    }
++  else if (dpname_matches(str, "pccard"))
++    {
++    }
++  else if (dpname_matches(str, "mmap"))
++    {
++    }
++  else if (dpname_matches(str, "ctrl"))
++    {
++    }
++  else if (dpname_matches(str, "acpi"))
++    {
++    }
++    /* XXX what about _ADR? */
++  /* messaging device paths */
++  else if (dpname_matches(str, "atapi"))
++    {
++    }
++  else if (dpname_matches(str, "scsi"))
++    {
++    }
++  else if (dpname_matches(str, "fibrechannel"))
++    {
++    }
++  else if (dpname_matches(str, "1394"))
++    {
++    }
++  else if (dpname_matches(str, "usb"))
++    {
++    }
++  else if (dpname_matches(str, "sata"))
++    {
++    }
++    /* XXX what about usb-wwid */
++    /* XXX what about lun */
++  else if (dpname_matches(str, "usbclass"))
++    {
++    }
++  else if (dpname_matches(str, "i2o"))
++    {
++    }
++  else if (dpname_matches(str, "macaddr"))
++    {
++    }
++  else if (dpname_matches(str, "ipv4"))
++    {
++    }
++  else if (dpname_matches(str, "ipv6"))
++    {
++    }
++    /* XXX what about vlan */
++  else if (dpname_matches(str, "infiniband"))
++    {
++    }
++  else if (dpname_matches(str, "uart"))
++    {
++    }
++  else if (dpname_matches(str, "uartflowctrl"))
++    {
++    }
++  else if (dpname_matches(str, "sas"))
++    {
++    }
++  else if (dpname_matches(str, "iscsi"))
++    {
++    }
++  /* media device paths */
++  else if (dpname_matches(str, "hd"))
++    {
++      /* these look roughly like:
++       *  HD(Partition,Type,Signature,Start, Size)
++       * but:
++       * - type may be optional.  1 or "MBR" means MBR. 2 or "GPT" means GPT.
++       * - start and size are optional
++       * - there can be random spaces
++       */
++      struct hd_media_device_path hddp;
++      unsigned long tmpul;
++      char *end = NULL, c;
++      char tmps[19] = "0x";
++      char *tmpsp;
++
++      ret = 42;
++
++      hddp.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
++      hddp.subtype = GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE;
++      hddp.length = ret;
++
++      //pos += grub_strcspn(pos, '(');
++      pos = get_next_param(pos, &end, &c);
++      if (!*pos)
++	{
++broken_hd:
++	  finish_param_parse(pos, &end, &c);
++	  return 0;
++	}
++      grub_strncpy(tmps+2, pos, 16);
++      tmps[18] = '\0';
++      tmpsp = tmps;
++      safe_parse_maxulong(&tmpsp, &tmpul);
++      hddp.partition = tmpul;
++
++      pos = get_next_param(pos, &end, &c);
++      if (!*pos)
++	goto broken_hd;
++      grub_strcpy(tmps+2, pos);
++      tmpsp = tmps;
++      safe_parse_maxulong(&tmpsp, &tmpul);
++      hddp.startlba = tmpul;
++
++      pos = get_next_param(pos, &end, &c);
++      if (!*pos)
++	goto broken_hd;
++      grub_strcpy(tmps+2, pos);
++      tmpsp = tmps;
++      safe_parse_maxulong(&tmpsp, &tmpul);
++      hddp.size = tmpul;
++
++      pos = get_next_param(pos, &end, &c);
++      if (!*pos)
++	goto broken_hd;
++      if (!grub_strcmp(pos, "None"))
++	{
++	  hddp.signature_type = 0;
++	  grub_memset(hddp.signature, '\0', sizeof(hddp.signature));
++	}
++      else if (grub_strnlen(pos, 36) == 8)
++        {
++	  grub_efi_uint32_t tmpu32;
++	  grub_strncpy(tmps+2, pos, 8);
++	  tmps[10] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu32 = tmpul;
++	  hddp.signature_type = 1;
++	  grub_memcpy(hddp.signature, &tmpu32, sizeof(tmpu32));
++	}
++      else if (grub_strnlen(pos, 36) == 36)
++	{
++	  grub_efi_uint32_t tmpu32;
++	  grub_efi_uint16_t tmpu16;
++	  grub_efi_uint8_t tmpu8;
++
++	  grub_strncpy(tmps+2, pos, 8);
++	  tmps[10] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu32 = tmpul;
++	  grub_memcpy(hddp.signature, &tmpu32, sizeof(tmpu32));
++
++	  grub_strncpy(tmps+2, pos+9, 4);
++	  tmps[6] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu16 = tmpul;
++	  grub_memcpy(hddp.signature + 4, &tmpu16, sizeof(tmpu16));
++
++	  grub_strncpy(tmps+2, pos+14, 4);
++	  tmps[6] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu16 = tmpul;
++	  grub_memcpy(hddp.signature + 6, &tmpu16, sizeof(tmpu16));
++
++	  /* these are displayed like a u16, but they're a u8.  thanks. */
++	  grub_strncpy(tmps+2, pos+19, 2);
++	  tmps[4] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu8 = tmpul;
++	  grub_memcpy(hddp.signature + 8, &tmpu8, sizeof(tmpu8));
++	  grub_strncpy(tmps+2, pos+21, 2);
++	  tmps[4] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu8 = tmpul;
++	  grub_memcpy(hddp.signature + 9, &tmpu8, sizeof(tmpu8));
++
++	  grub_strncpy(tmps+2, pos+24, 2);
++	  tmps[4] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu8 = tmpul;
++	  grub_memcpy(hddp.signature + 10, &tmpu8, sizeof(tmpu8));
++
++	  grub_strncpy(tmps+2, pos+26, 2);
++	  tmps[4] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu8 = tmpul;
++	  grub_memcpy(hddp.signature + 11, &tmpu8, sizeof(tmpu8));
++
++	  grub_strncpy(tmps+2, pos+28, 2);
++	  tmps[4] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu8 = tmpul;
++	  grub_memcpy(hddp.signature + 12, &tmpu8, sizeof(tmpu8));
++
++	  grub_strncpy(tmps+2, pos+30, 2);
++	  tmps[4] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu8 = tmpul;
++	  grub_memcpy(hddp.signature + 13, &tmpu8, sizeof(tmpu8));
++
++	  grub_strncpy(tmps+2, pos+32, 2);
++	  tmps[4] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu8 = tmpul;
++	  grub_memcpy(hddp.signature + 14, &tmpu8, sizeof(tmpu8));
++
++	  grub_strncpy(tmps+2, pos+34, 2);
++	  tmps[4] = '\0';
++	  tmpsp = tmps;
++	  safe_parse_maxulong(&tmpsp, &tmpul);
++	  tmpu8 = tmpul;
++	  grub_memcpy(hddp.signature + 15, &tmpu8, sizeof(tmpu8));
++
++	  hddp.signature_type = 2;
++	}
++      else
++	goto broken_hd;
++
++      hddp.mbr_type = hddp.signature_type;
++
++      if (data)
++	grub_memcpy(data, &hddp, sizeof(hddp));
++    }
++  else if (dpname_matches(str, "cd"))
++    {
++    }
++  else if (dpname_matches(str, "file"))
++    {
++    }
++  else if (dpname_matches(str, "protocol"))
++    {
++    }
++    /* what about piwg firmware file? */
++    /* what about piwg firmware volume? */
++    /* what about relative offset media */
++  else if (dpname_matches(str, "bios"))
++    {
++    }
++  /* This is the end beautiful friend */
++  else if (dpname_matches(str, "EndEntire$"))
++    {
++      struct generic_device_path gdp = {
++	      .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
++	      .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
++	      .length = 4
++      };
++      ret = 4;
++      if (data)
++	grub_memmove(data, &gdp, sizeof(gdp));
++    }
++  else if (dpname_matches(str, "EndThis$"))
++    {
++      struct generic_device_path gdp = {
++	      .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
++	      .subtype = GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE,
++	      .length = 4
++      };
++      ret = 4;
++      if (data)
++	grub_memmove(data, &gdp, sizeof(gdp));
++    }
++  else if (dpname_matches(str, "EndUnknown$"))
++    {
++      struct generic_device_path gdp = {
++	      .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
++	      .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
++	      .length = 4
++      };
++      ret = 4;
++      if (data)
++	grub_memmove(data, &gdp, sizeof(gdp));
++    }
++  /* handle anything we didn't recognize */
++  else if (dpname_matches(str, "vendor"))
++    {
++      /* needs to handle:
++       * 1) hw vendor
++       * 2) messaging vendor
++       * 3) media vendor
++       */
++    }
++  else
++    {
++    }
++
++  return ret;
++}
++
++grub_efi_device_path_t *
++device_path_from_utf8 (const char *device)
++{
++  grub_size_t device_len;
++  grub_efi_device_path_t *dp = NULL;
++
++  device_len = parse_device_path_component(device, dp);
++  device_len += parse_device_path_component("EndEntire", dp);
++  dp = grub_malloc(device_len);
++  if (!dp)
++    return NULL;
++  device_len = parse_device_path_component(device, dp);
++  device_len += parse_device_path_component("EndEntire",
++				     (void *)((unsigned long)dp + device_len));
++
++
++  return dp;
++}
+diff --git a/efi/efimisc.c b/efi/efimisc.c
+index a319fdd..480ba25 100644
+--- a/efi/efimisc.c
++++ b/efi/efimisc.c
+@@ -108,6 +108,79 @@ grub_real_dprintf (const char *file, const int line, const char *condition,
+   va_end (args);
+ }
+ 
++grub_size_t
++grub_utf8_char_len(grub_uint8_t ch)
++{
++  return ((0xe5000000 >> ((ch >> 3) & 0x1e)) & 3) + 1;
++}
++
++#define UTF8_SHIFT_AND_MASK(unicode, byte)  (unicode)<<=6; (unicode) |= (0x3f & (byte))
++
++/* convert utf8 to utf32 */
++grub_uint32_t
++grub_utf8_to_utf32(const grub_uint8_t *src, grub_size_t length)
++{
++  grub_uint32_t unicode;
++
++  switch (length)
++    {
++    case 1:
++      return src[0];
++    case 2:
++      unicode = src[0] & 0x1f;
++      UTF8_SHIFT_AND_MASK(unicode, src[1]);
++      return unicode;
++    case 3:
++      unicode = src[0] & 0x0f;
++      UTF8_SHIFT_AND_MASK(unicode, src[1]);
++      UTF8_SHIFT_AND_MASK(unicode, src[2]);
++      return unicode;
++    case 4:
++      unicode = src[0] & 0x07;
++      UTF8_SHIFT_AND_MASK(unicode, src[1]);
++      UTF8_SHIFT_AND_MASK(unicode, src[2]);
++      UTF8_SHIFT_AND_MASK(unicode, src[3]);
++      return unicode;
++    default:
++      return 0xffff;
++    }
++}
++
++/* convert utf8 to utf16 */
++void
++grub_utf8_to_utf16(const grub_uint8_t *src, grub_size_t srclen,
++		   grub_uint16_t *dst, grub_size_t dstlen)
++{
++  const grub_uint8_t *end = src + srclen;
++  grub_efi_char16_t *dstend = dst + dstlen;
++
++  while (src < end && dst < dstend)
++    {
++      grub_size_t len = grub_utf8_char_len(*src);
++      /* get the utf32 codepoint */
++      grub_uint32_t codepoint = grub_utf8_to_utf32(src, len);
++
++      /* convert that codepoint to utf16 codepoints */
++      if (codepoint <= 0xffff)
++	{
++	  /* it's a single utf16 character */
++	  *dst++ = (grub_efi_char16_t) codepoint;
++	}
++      else
++	{
++	  /* it's multiple utf16 characters, with surrogate pairs */
++	  codepoint = codepoint - 0x10000;
++	  *dst++ = (grub_efi_char16_t) ((codepoint >> 10) + 0xd800);
++	  *dst++ = (grub_efi_char16_t) ((codepoint & 0x3ff) + 0xdc00);
++	}
++
++	src += len;
++    }
++
++  if (dst < dstend)
++    *dst = 0;
++}
++
+ /* Convert UTF-16 to UTF-8.  */
+ grub_uint8_t *
+ grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
+diff --git a/efi/grub/efi/api.h b/efi/grub/efi/api.h
+index 6743a0b..8f75a68 100644
+--- a/efi/grub/efi/api.h
++++ b/efi/grub/efi/api.h
+@@ -90,6 +90,11 @@
+     { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+   }
+ 
++#define GRUB_EFI_DEVICE_PATH_FROM_TEXT_GUID	\
++  { 0x05c99a21, 0xc70f, 0x4ad2, \
++    { 0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e } \
++  }
++
+ #define GRUB_EFI_GRAPHICS_OUTPUT_GUID	\
+   { 0x9042a9de, 0x23dc, 0x4a38, \
+     { 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \
+@@ -553,7 +558,7 @@ struct grub_efi_hard_drive_device_path
+   grub_efi_uint32_t partition_number;
+   grub_efi_lba_t partition_start;
+   grub_efi_lba_t partition_size;
+-  grub_efi_uint8_t partition_signature[8];
++  grub_efi_uint8_t partition_signature[16];
+   grub_efi_uint8_t mbr_type;
+   grub_efi_uint8_t signature_type;
+ };
+@@ -615,6 +620,13 @@ struct grub_efi_bios_device_path
+ };
+ typedef struct grub_efi_bios_device_path grub_efi_bios_device_path_t;
+ 
++struct grub_efi_device_path_from_text
++{
++  grub_efi_device_path_t * (*convert_text_to_device_node) (const grub_efi_char16_t *text_device_node);
++  grub_efi_device_path_t * (*convert_text_to_device_path) (const grub_efi_char16_t *text_device_path);
++};
++typedef struct grub_efi_device_path_from_text grub_efi_device_path_from_text_t;
++
+ struct grub_efi_open_protocol_information_entry
+ {
+   grub_efi_handle_t agent_handle;
+diff --git a/efi/grub/efi/misc.h b/efi/grub/efi/misc.h
+index b089904..7dc34e7 100644
+--- a/efi/grub/efi/misc.h
++++ b/efi/grub/efi/misc.h
+@@ -43,4 +43,16 @@ int grub_get_drive_partition_from_bdev_handle (grub_efi_handle_t handle,
+ char *grub_efi_file_path_to_path_name (grub_efi_device_path_t *file_path);
+ void grub_load_saved_default (grub_efi_handle_t dev_handle);
+ 
++grub_efi_device_path_t *
++find_last_device_path (const grub_efi_device_path_t *dp);
++grub_efi_device_path_t *
++duplicate_device_path (const grub_efi_device_path_t *dp);
++int
++compare_device_paths (const grub_efi_device_path_t *dp1,
++		      const grub_efi_device_path_t *dp2);
++grub_efi_device_path_t *
++device_path_from_utf8 (const char *device);
++
++extern grub_efi_guid_t simple_file_system_guid;
++
+ #endif /* ! GRUB_EFI_MISC_HEADER */
+diff --git a/efi/grub/misc.h b/efi/grub/misc.h
+index 5ec54d5..5ef2226 100644
+--- a/efi/grub/misc.h
++++ b/efi/grub/misc.h
+@@ -36,6 +36,10 @@ void grub_real_dprintf (const char *file,
+ void grub_exit (void) __attribute__ ((noreturn));
+ void grub_abort (void) __attribute__ ((noreturn));
+ void grub_fatal (const char *fmt, ...) __attribute__ ((noreturn));
++grub_size_t grub_utf8_char_len(grub_uint8_t ch);
++grub_uint32_t grub_utf8_to_utf32(const grub_uint8_t *src, grub_size_t length);
++void grub_utf8_to_utf16(const grub_uint8_t *src, grub_size_t srclen,
++			grub_uint16_t *dst, grub_size_t dstlen);
+ grub_uint8_t *grub_utf16_to_utf8 (grub_uint8_t * dest,
+ 				  grub_uint16_t * src, grub_size_t size);
+ 
+diff --git a/stage2/builtins.c b/stage2/builtins.c
+index de356d4..ad856f8 100644
+--- a/stage2/builtins.c
++++ b/stage2/builtins.c
+@@ -905,7 +905,7 @@ static struct builtin builtin_default =
+ };
+ 
+ 
+-#ifdef GRUB_UTIL
++#if defined(GRUB_UTIL) || defined(PLATFORM_EFI)
+ /* device */
+ static int
+ device_func (char *arg, int flags)
+@@ -913,16 +913,17 @@ device_func (char *arg, int flags)
+   char *drive = arg;
+   char *device;
+ 
+-  /* Get the drive number from DRIVE.  */
+-  if (! set_device (drive))
+-    return 1;
+-
+   /* Get the device argument.  */
+   device = skip_to (0, drive);
+-  
++
++  nul_terminate (drive);
+   /* Terminate DEVICE.  */
+   nul_terminate (device);
+ 
++  /* Get the drive number from DRIVE.  */
++  if (! set_device (drive))
++    return 1;
++
+   if (! *device || ! check_device (device))
+     {
+       errnum = ERR_FILE_NOT_FOUND;
+@@ -930,7 +931,7 @@ device_func (char *arg, int flags)
+     }
+ 
+   assign_device_name (current_drive, device);
+-  
++
+   return 0;
+ }
+ 
+@@ -941,9 +942,20 @@ static struct builtin builtin_device =
+   BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+   "device DRIVE DEVICE",
+   "Specify DEVICE as the actual drive for a BIOS drive DRIVE. This command"
+-  " can be used only in the grub shell."
++  " can be used only in the grub shell and in EFI."
+ };
+-#endif /* GRUB_UTIL */
++#endif /* defined(GRUB_UTIL) || defined(PLATFORM_EFI) */
++#ifdef PLATFORM_EFI
++static struct builtin builtin_efimap =
++{
++  "efimap",
++  device_func,
++  BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
++  "efimap DRIVE DEVICE",
++  "Specify DEVICE as the actual drive for a BIOS drive DRIVE. This command"
++  " can be used only in EFI."
++};
++#endif /* PLATFORM_EFI */
+ 
+ 
+ #ifdef SUPPORT_NETBOOT
+@@ -5169,9 +5181,9 @@ struct builtin *builtin_table[] =
+   &builtin_configfile,
+   &builtin_debug,
+   &builtin_default,
+-#ifdef GRUB_UTIL
++#if defined(GRUB_UTIL) || defined(PLATFORM_EFI)
+   &builtin_device,
+-#endif /* GRUB_UTIL */
++#endif /* defined(GRUB_UTIL) || defined(PLATFORM_EFI) */
+ #ifdef SUPPORT_NETBOOT
+   &builtin_dhcp,
+ #endif /* SUPPORT_NETBOOT */
+@@ -5182,6 +5194,9 @@ struct builtin *builtin_table[] =
+ #ifdef GRUB_UTIL
+   &builtin_dump,
+ #endif /* GRUB_UTIL */
++#ifdef PLATFORM_EFI
++  &builtin_efimap,
++#endif
+ #ifndef PLATFORM_EFI
+   &builtin_embed,
+ #endif
+diff --git a/stage2/shared.h b/stage2/shared.h
+index 6882027..08964a3 100644
+--- a/stage2/shared.h
++++ b/stage2/shared.h
+@@ -1043,6 +1043,8 @@ void init_bios_info (void);
+ #ifdef PLATFORM_EFI
+ void grub_set_config_file (char *path_name);
+ int grub_save_saved_default (int new_default);
++extern int check_device (const char *device);
++extern void assign_device_name (int drive, const char *device);
+ #endif
+ int grub_load_linux (char *kernel, char *arg);
+ int grub_load_initrd (char *initrd);
+-- 
+1.7.2
+
diff --git a/grub.spec b/grub.spec
index 4c065cf..18bdc70 100644
--- a/grub.spec
+++ b/grub.spec
@@ -1,6 +1,6 @@
 Name: grub
 Version: 0.97
-Release: 65%{?dist}
+Release: 66%{?dist}
 Epoch: 1
 Summary: Grand Unified Boot Loader.
 Group: System Environment/Base
@@ -53,6 +53,10 @@ Patch23: grub-0.97-gate-a20.patch
 Patch24: grub-0.97-efi-graphics-mode-selection.patch
 Patch25: grub-silent.patch
 Patch26: grub-0.97-bz553741-sha2.patch
+Patch27: grub-0.97-invert-highlighted-menu-line-rhbz613153.patch
+Patch28: grub-0.97-better-get-memory-map-rhbz607213.patch
+Patch29: grub-0.97-add-strnchr.patch
+Patch30: grub-0.97-efimap.patch
 
 %description
 GRUB (Grand Unified Boot Loader) is an experimental boot loader
@@ -89,6 +93,10 @@ systems.
 %patch24 -p1
 %patch25 -p1
 %patch26 -p1
+%patch27 -p1
+%patch28 -p1
+%patch29 -p1
+%patch30 -p1
 
 %build
 autoreconf
@@ -151,6 +159,14 @@ fi
 %{_datadir}/grub
 
 %changelog
+* Wed Aug 04 2010 Peter Jones <pjones at redhat.com> - 0.97-66
+- Draw the inverted line correctly in the menu
+  Resolves: rhbz#613153
+- Don't fail to boot on UEFI when the memory map changes (shayes)
+  Resolves: rhbz#607213
+- Allow drive remaping in UEFI mode so ordering changes don't cause failure
+  Resolves: rhbz#598572
+
 * Tue Mar 09 2010 Peter Jones <pjones at redhat.com> - 0.97-65
 - Add sha256 support to grub's password options (mitr)
   Resolves: rhbz#553741


More information about the scm-commits mailing list