summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorToomas Soome <tsoome@me.com>2017-12-12 18:01:57 +0200
committerDan McDonald <danmcd@joyent.com>2018-02-15 17:46:29 -0500
commiteea30b2609e6094732d948fa0c740852cb14c13d (patch)
treefaa7fcaa88acebbc932b756c41273e3769081575 /usr/src
parent9a5a2388e3d1f52bed03f56813569786dc86e353 (diff)
downloadillumos-joyent-eea30b2609e6094732d948fa0c740852cb14c13d.tar.gz
9073 loader.efi: chain loader should provide proper device handle
Reviewed by: Yuri Pankov <yuripv@yuripv.net> Reviewed by: Alexander Eremin <alexander.eremin@nexenta.com> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/boot/sys/boot/efi/include/efilib.h1
-rw-r--r--usr/src/boot/sys/boot/efi/libefi/efipart.c73
-rw-r--r--usr/src/boot/sys/boot/efi/loader/main.c38
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);