changeset 18812:033958218f3c

loader.efi: chain loader should provide proper device handle illumos issue #9073
author Toomas Soome <tsoome@me.com>
date Tue, 12 Dec 2017 18:01:57 +0200
parents 4c609abb3bf5
children 275f2ccf7d09
files usr/src/boot/sys/boot/efi/include/efilib.h usr/src/boot/sys/boot/efi/libefi/efipart.c usr/src/boot/sys/boot/efi/loader/main.c
diffstat 3 files changed, 64 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/boot/sys/boot/efi/include/efilib.h	Wed Feb 14 23:10:02 2018 +0200
+++ b/usr/src/boot/sys/boot/efi/include/efilib.h	Tue Dec 12 18:01:57 2017 +0200
@@ -60,6 +60,7 @@
 } pdinfo_t;
 
 pdinfo_list_t *efiblk_get_pdinfo_list(struct devsw *dev);
+pdinfo_t *efiblk_get_pdinfo(struct devdesc *dev);
 
 void *efi_get_table(EFI_GUID *tbl);
 
--- a/usr/src/boot/sys/boot/efi/libefi/efipart.c	Wed Feb 14 23:10:02 2018 +0200
+++ b/usr/src/boot/sys/boot/efi/libefi/efipart.c	Tue Dec 12 18:01:57 2017 +0200
@@ -106,16 +106,33 @@
 static EFI_HANDLE *efipart_handles = NULL;
 static UINTN efipart_nhandles = 0;
 
-static pdinfo_t *
-efiblk_get_pdinfo(pdinfo_list_t *pdi, int unit)
+pdinfo_list_t *
+efiblk_get_pdinfo_list(struct devsw *dev)
 {
-	pdinfo_t *pd;
+	if (dev->dv_type == DEVT_DISK)
+		return (&hdinfo);
+	if (dev->dv_type == DEVT_CD)
+		return (&cdinfo);
+	if (dev->dv_type == DEVT_FD)
+		return (&fdinfo);
+	return (NULL);
+}
+
+pdinfo_t *
+efiblk_get_pdinfo(struct devdesc *dev)
+{
+	pdinfo_list_t *pdi;
+	pdinfo_t *pd = NULL;
+
+	pdi = efiblk_get_pdinfo_list(dev->d_dev);
+	if (pdi == NULL)
+		return (pd);
 
 	STAILQ_FOREACH(pd, pdi, pd_link) {
-		if (pd->pd_unit == unit)
+		if (pd->pd_unit == dev->d_unit)
 			return (pd);
 	}
-	return (NULL);
+	return (pd);
 }
 
 static int
@@ -777,24 +794,11 @@
 	return (efipart_print_common(&efipart_hddev, &hdinfo, verbose));
 }
 
-pdinfo_list_t *
-efiblk_get_pdinfo_list(struct devsw *dev)
-{
-	if (dev->dv_type == DEVT_DISK)
-		return (&hdinfo);
-	if (dev->dv_type == DEVT_CD)
-		return (&cdinfo);
-	if (dev->dv_type == DEVT_FD)
-		return (&fdinfo);
-	return (NULL);
-}
-
 static int
 efipart_open(struct open_file *f, ...)
 {
 	va_list args;
 	struct disk_devdesc *dev;
-	pdinfo_list_t *pdi;
 	pdinfo_t *pd;
 	EFI_BLOCK_IO *blkio;
 	EFI_STATUS status;
@@ -805,14 +809,10 @@
 	if (dev == NULL)
 		return (EINVAL);
 
-	pdi = efiblk_get_pdinfo_list(dev->d_dev);
-	if (pdi == NULL)
+	pd = efiblk_get_pdinfo((struct devdesc *)dev);
+	if (pd == NULL)
 		return (EINVAL);
 
-	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
-	if (pd == NULL)
-		return (EIO);
-
 	if (pd->pd_blkio == NULL) {
 		status = BS->HandleProtocol(pd->pd_handle, &blkio_guid,
 		    (void **)&pd->pd_blkio);
@@ -851,17 +851,13 @@
 efipart_close(struct open_file *f)
 {
 	struct disk_devdesc *dev;
-	pdinfo_list_t *pdi;
 	pdinfo_t *pd;
 
 	dev = (struct disk_devdesc *)(f->f_devdata);
 	if (dev == NULL)
 		return (EINVAL);
-	pdi = efiblk_get_pdinfo_list(dev->d_dev);
-	if (pdi == NULL)
-		return (EINVAL);
 
-	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
+	pd = efiblk_get_pdinfo((struct devdesc *)dev);
 	if (pd == NULL)
 		return (EINVAL);
 
@@ -880,18 +876,14 @@
 efipart_ioctl(struct open_file *f, u_long cmd, void *data)
 {
 	struct disk_devdesc *dev;
-	pdinfo_list_t *pdi;
 	pdinfo_t *pd;
 	int rc;
 
 	dev = (struct disk_devdesc *)(f->f_devdata);
 	if (dev == NULL)
 		return (EINVAL);
-	pdi = efiblk_get_pdinfo_list(dev->d_dev);
-	if (pdi == NULL)
-		return (EINVAL);
 
-	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
+	pd = efiblk_get_pdinfo((struct devdesc *)dev);
 	if (pd == NULL)
 		return (EINVAL);
 
@@ -964,17 +956,13 @@
 {
 	struct bcache_devdata bcd;
 	struct disk_devdesc *dev;
-	pdinfo_list_t *pdi;
 	pdinfo_t *pd;
 
 	dev = (struct disk_devdesc *)devdata;
 	if (dev == NULL)
 		return (EINVAL);
-	pdi = efiblk_get_pdinfo_list(dev->d_dev);
-	if (pdi == NULL)
-		return (EINVAL);
 
-	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
+	pd = efiblk_get_pdinfo((struct devdesc *)dev);
 	if (pd == NULL)
 		return (EINVAL);
 
@@ -1002,7 +990,6 @@
     char *buf, size_t *rsize)
 {
 	struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
-	pdinfo_list_t *pdi;
 	pdinfo_t *pd;
 	EFI_BLOCK_IO *blkio;
 	uint64_t off, disk_blocks, d_offset = 0;
@@ -1014,11 +1001,7 @@
 	if (dev == NULL || blk < 0)
 		return (EINVAL);
 
-	pdi = efiblk_get_pdinfo_list(dev->d_dev);
-	if (pdi == NULL)
-		return (EINVAL);
-
-	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
+	pd = efiblk_get_pdinfo((struct devdesc *)dev);
 	if (pd == NULL)
 		return (EINVAL);
 
--- a/usr/src/boot/sys/boot/efi/loader/main.c	Wed Feb 14 23:10:02 2018 +0200
+++ b/usr/src/boot/sys/boot/efi/loader/main.c	Tue Dec 12 18:01:57 2017 +0200
@@ -884,9 +884,41 @@
 		*(--argv) = 0;
 	}
 
-	if (efi_getdev((void **)&dev, name, (const char **)&path) == 0)
-		loaded_image->DeviceHandle =
-		    efi_find_handle(dev->d_dev, dev->d_unit);
+	if (efi_getdev((void **)&dev, name, (const char **)&path) == 0) {
+		struct zfs_devdesc *z_dev;
+		struct disk_devdesc *d_dev;
+		pdinfo_t *hd, *pd;
+
+		switch (dev->d_type) {
+		case DEVT_ZFS:
+			z_dev = (struct zfs_devdesc *)dev;
+			loaded_image->DeviceHandle =
+			    efizfs_get_handle_by_guid(z_dev->pool_guid);
+			break;
+		case DEVT_NET:
+			loaded_image->DeviceHandle =
+			    efi_find_handle(dev->d_dev, dev->d_unit);
+			break;
+		default:
+			hd = efiblk_get_pdinfo(dev);
+			if (STAILQ_EMPTY(&hd->pd_part)) {
+				loaded_image->DeviceHandle = hd->pd_handle;
+				break;
+			}
+			d_dev = (struct disk_devdesc *)dev;
+			STAILQ_FOREACH(pd, &hd->pd_part, pd_link) {
+				/*
+				 * d_partition should be 255
+				 */
+				if (pd->pd_unit == d_dev->d_slice) {
+					loaded_image->DeviceHandle =
+					    pd->pd_handle;
+					break;
+				}
+			}
+			break;
+		}
+	}
 
 	dev_cleanup();
 	status = BS->StartImage(loaderhandle, NULL, NULL);