loader.efi: chain loader should provide proper device handle
Since the efipart rewrite, the chain command was looking for device handle using interface applicable only for net devices. Disk partitions and zfs pools need their own approach to find the proper handle. Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D12287
This commit is contained in:
parent
263f801fef
commit
44832ad99d
@ -61,6 +61,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);
|
||||
|
||||
|
@ -45,6 +45,7 @@ extern uint64_t pool_guid;
|
||||
|
||||
extern void efi_zfs_probe(void);
|
||||
extern zfsinfo_list_t *efizfs_get_zfsinfo_list(void);
|
||||
extern EFI_HANDLE efizfs_get_handle_by_guid(uint64_t);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -101,16 +101,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
|
||||
@ -671,24 +688,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;
|
||||
@ -699,11 +703,7 @@ 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);
|
||||
|
||||
@ -734,17 +734,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);
|
||||
|
||||
@ -763,18 +759,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);
|
||||
|
||||
@ -847,17 +839,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);
|
||||
|
||||
@ -881,7 +869,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;
|
||||
@ -893,11 +880,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);
|
||||
|
||||
|
@ -52,6 +52,19 @@ efizfs_get_zfsinfo_list(void)
|
||||
return (&zfsinfo);
|
||||
}
|
||||
|
||||
EFI_HANDLE
|
||||
efizfs_get_handle_by_guid(uint64_t guid)
|
||||
{
|
||||
zfsinfo_t *zi;
|
||||
|
||||
STAILQ_FOREACH(zi, &zfsinfo, zi_link) {
|
||||
if (zi->zi_pool_guid == guid) {
|
||||
return (zi->zi_handle);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
insert_zfs(EFI_HANDLE handle, uint64_t guid)
|
||||
{
|
||||
|
@ -871,9 +871,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);
|
||||
|
Loading…
Reference in New Issue
Block a user