From 32e797b89f71c52a1ea868a5d474ddcb9b53d6e4 Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Tue, 12 Dec 2017 18:01:57 +0200 Subject: [PATCH] loader.efi: chain loader should provide proper device handle illumos issue #9073 --- usr/src/boot/sys/boot/efi/include/efilib.h | 1 + usr/src/boot/sys/boot/efi/libefi/efipart.c | 73 ++++++++++++------------------ usr/src/boot/sys/boot/efi/loader/main.c | 38 ++++++++++++++-- 3 files changed, 64 insertions(+), 48 deletions(-) diff --git a/usr/src/boot/sys/boot/efi/include/efilib.h b/usr/src/boot/sys/boot/efi/include/efilib.h index d6bb4974b3..5f007c6d59 100644 --- a/usr/src/boot/sys/boot/efi/include/efilib.h +++ b/usr/src/boot/sys/boot/efi/include/efilib.h @@ -60,6 +60,7 @@ typedef struct pdinfo } 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); diff --git a/usr/src/boot/sys/boot/efi/libefi/efipart.c b/usr/src/boot/sys/boot/efi/libefi/efipart.c index e2ea9bb95a..942deab383 100644 --- a/usr/src/boot/sys/boot/efi/libefi/efipart.c +++ b/usr/src/boot/sys/boot/efi/libefi/efipart.c @@ -106,16 +106,33 @@ static pdinfo_list_t hdinfo; 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 @@ efipart_printhd(int verbose) 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,13 +809,9 @@ efipart_open(struct open_file *f, ...) 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 (EIO); + return (EINVAL); if (pd->pd_blkio == NULL) { status = BS->HandleProtocol(pd->pd_handle, &blkio_guid, @@ -851,17 +851,13 @@ static int 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 @@ static int 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 @@ efipart_strategy(void *devdata, int rw, daddr_t blk, size_t size, { 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 @@ efipart_realstrategy(void *devdata, int rw, daddr_t blk, size_t size, 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 @@ efipart_realstrategy(void *devdata, int rw, daddr_t blk, size_t size, 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); diff --git a/usr/src/boot/sys/boot/efi/loader/main.c b/usr/src/boot/sys/boot/efi/loader/main.c index 3492736f94..3570c4fd07 100644 --- a/usr/src/boot/sys/boot/efi/loader/main.c +++ b/usr/src/boot/sys/boot/efi/loader/main.c @@ -884,9 +884,41 @@ command_chain(int argc, char *argv[]) *(--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); -- 2.11.4.GIT