File grub-0.97-efimap.patch of Package grub
From f344803d5e03b81e06a882df5745014a0d5b1629 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@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