[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