Index: stand/efi/include/efizfs.h =================================================================== --- stand/efi/include/efizfs.h +++ stand/efi/include/efizfs.h @@ -40,13 +40,15 @@ STAILQ_ENTRY(zfsinfo) zi_link; EFI_HANDLE zi_handle; uint64_t zi_pool_guid; + uint64_t zi_vdev_guid; } zfsinfo_t; extern uint64_t pool_guid; +extern uint64_t primary_vdev_guid; void efi_zfs_probe(void); EFI_HANDLE efizfs_get_handle_by_guid(uint64_t); -bool efizfs_get_guid_by_handle(EFI_HANDLE, uint64_t *); +bool efizfs_get_guid_by_handle(EFI_HANDLE, uint64_t *, uint64_t *); zfsinfo_list_t *efizfs_get_zfsinfo_list(void); void efizfs_set_preferred(EFI_HANDLE); Index: stand/efi/libefi/efizfs.c =================================================================== --- stand/efi/libefi/efizfs.c +++ stand/efi/libefi/efizfs.c @@ -44,6 +44,7 @@ static zfsinfo_list_t zfsinfo; uint64_t pool_guid; +uint64_t primary_vdev_guid; static EFI_HANDLE preferred; @@ -73,7 +74,8 @@ } bool -efizfs_get_guid_by_handle(EFI_HANDLE handle, uint64_t *guid) +efizfs_get_guid_by_handle(EFI_HANDLE handle, uint64_t *guid, + uint64_t *vdev_guid) { zfsinfo_t *zi; @@ -82,6 +84,8 @@ STAILQ_FOREACH(zi, &zfsinfo, zi_link) { if (zi->zi_handle == handle) { *guid = zi->zi_pool_guid; + if (vdev_guid != NULL) + *vdev_guid = zi->zi_vdev_guid; return (true); } } @@ -89,13 +93,14 @@ } static void -insert_zfs(EFI_HANDLE handle, uint64_t guid) +insert_zfs(EFI_HANDLE handle, uint64_t guid, uint64_t vdev_guid) { zfsinfo_t *zi; zi = malloc(sizeof(zfsinfo_t)); zi->zi_handle = handle; zi->zi_pool_guid = guid; + zi->zi_vdev_guid = vdev_guid; STAILQ_INSERT_TAIL(&zfsinfo, zi, zi_link); } @@ -105,7 +110,7 @@ pdinfo_list_t *hdi; pdinfo_t *hd, *pd = NULL; char devname[SPECNAMELEN + 1]; - uint64_t guid; + uint64_t guid, vdev_guid; hdi = efiblk_get_pdinfo_list(&efipart_hddev); STAILQ_INIT(&zfsinfo); @@ -120,10 +125,12 @@ STAILQ_FOREACH(pd, &hd->pd_part, pd_link) { snprintf(devname, sizeof(devname), "%s%dp%d:", efipart_hddev.dv_name, hd->pd_unit, pd->pd_unit); - if (zfs_probe_dev(devname, &guid) == 0) { - insert_zfs(pd->pd_handle, guid); - if (pd->pd_handle == preferred) + if (zfs_probe_dev(devname, &guid, &vdev_guid) == 0) { + insert_zfs(pd->pd_handle, guid, vdev_guid); + if (pd->pd_handle == preferred) { pool_guid = guid; + primary_vdev_guid = vdev_guid; + } } } Index: stand/efi/loader/main.c =================================================================== --- stand/efi/loader/main.c +++ stand/efi/loader/main.c @@ -260,9 +260,10 @@ static bool try_as_currdev(pdinfo_t *hd, pdinfo_t *pp) { - uint64_t guid; #ifdef EFI_ZFS_BOOT + uint64_t guid, vdev_guid; + /* * If there's a zpool on this device, try it as a ZFS * filesystem, which has somewhat different setup than all @@ -270,8 +271,12 @@ * This all stems from ZFS being both a device (zpool) and * a filesystem, plus the boot env feature. */ - if (efizfs_get_guid_by_handle(pp->pd_handle, &guid)) - return (probe_zfs_currdev(guid)); + if (efizfs_get_guid_by_handle(pp->pd_handle, &guid, &vdev_guid)) + if (probe_zfs_currdev(guid)) { + pool_guid = guid; + primary_vdev_guid = vdev_guid; + return (true); + } #endif /* * All other filesystems just need the pdinfo @@ -505,6 +510,12 @@ printf("Trying ZFS pool\n"); if (probe_zfs_currdev(pool_guid)) return (0); + /* + * Invalidate the pool information because it failed a currdev + * probe, likely due to the sanity check. + */ + pool_guid = 0; + primary_vdev_guid = 0; } #endif /* EFI_ZFS_BOOT */ @@ -973,6 +984,8 @@ if (!interactive_interrupt("Failed to find bootable partition")) return (EFI_NOT_FOUND); + if (pool_guid != 0) + zfs_set_bootcfg_env(pool_guid, primary_vdev_guid); efi_init_environment(); #if !defined(__arm__) Index: stand/i386/loader/main.c =================================================================== --- stand/i386/loader/main.c +++ stand/i386/loader/main.c @@ -258,9 +258,6 @@ extract_currdev(void) { struct i386_devdesc new_currdev; -#ifdef LOADER_ZFS_SUPPORT - char buf[20]; -#endif int biosdev = -1; /* Assume we are booting from a BIOS disk by default */ @@ -291,10 +288,7 @@ new_currdev.d_kind.zfs.pool_guid = zargs->pool; new_currdev.d_kind.zfs.root_guid = zargs->root; if (zargs->size >= sizeof(*zargs) && zargs->primary_vdev != 0) { - sprintf(buf, "%llu", zargs->primary_pool); - setenv("vfs.zfs.boot.primary_pool", buf, 1); - sprintf(buf, "%llu", zargs->primary_vdev); - setenv("vfs.zfs.boot.primary_vdev", buf, 1); + zfs_set_bootcfg_env(zargs->primary_pool, zargs->primary_vdev); } } else { /* old style zfsboot block */ @@ -409,7 +403,7 @@ for (dev.dd.d_unit = 0; bd_unit2bios(&dev) >= 0; dev.dd.d_unit++) { snprintf(devname, sizeof(devname), "%s%d:", bioshd.dv_name, dev.dd.d_unit); - zfs_probe_dev(devname, NULL); + zfs_probe_dev(devname, NULL, NULL); } } #endif Index: stand/libsa/zfs/libzfs.h =================================================================== --- stand/libsa/zfs/libzfs.h +++ stand/libsa/zfs/libzfs.h @@ -47,13 +47,15 @@ int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec, const char **path); char *zfs_fmtdev(void *vdev); -int zfs_probe_dev(const char *devname, uint64_t *pool_guid); +int zfs_probe_dev(const char *devname, uint64_t *pool_guid, + uint64_t *vdev_guid); int zfs_list(const char *name); uint64_t ldi_get_size(void *); void init_zfs_bootenv(const char *currdev); int zfs_bootenv(const char *name); int zfs_belist_add(const char *name, uint64_t __unused); int zfs_set_env(void); +void zfs_set_bootcfg_env(uint64_t pool_guid, uint64_t vdev_guid); extern struct devsw zfs_dev; extern struct fs_ops zfs_fsops; Index: stand/libsa/zfs/zfs.c =================================================================== --- stand/libsa/zfs/zfs.c +++ stand/libsa/zfs/zfs.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -449,6 +450,7 @@ int fd; const char *devname; uint64_t *pool_guid; + uint64_t *vdev_guid; u_int secsz; }; @@ -463,15 +465,23 @@ } static int -zfs_probe(int fd, uint64_t *pool_guid) +zfs_probe(int fd, uint64_t *pool_guid, uint64_t *vdev_guid) { spa_t *spa; + vdev_t *vdev; int ret; spa = NULL; ret = vdev_probe(vdev_read, (void *)(uintptr_t)fd, &spa); - if (ret == 0 && pool_guid != NULL) - *pool_guid = spa->spa_guid; + if (ret == 0) { + if (pool_guid != NULL) + *pool_guid = spa->spa_guid; + if (vdev_guid != NULL) { + vdev = spa_get_primary_vdev(spa); + if (vdev != NULL) + *vdev_guid = vdev->v_guid; + } + } return (ret); } @@ -496,13 +506,14 @@ pa.fd = open(devname, O_RDONLY); if (pa.fd == -1) return (0); - ret = zfs_probe(pa.fd, ppa->pool_guid); + ret = zfs_probe(pa.fd, ppa->pool_guid, ppa->vdev_guid); if (ret == 0) return (0); /* Do we have BSD label here? */ if (part->type == PART_FREEBSD) { pa.devname = devname; pa.pool_guid = ppa->pool_guid; + pa.vdev_guid = ppa->vdev_guid; pa.secsz = ppa->secsz; table = ptable_open(&pa, part->end - part->start + 1, ppa->secsz, zfs_diskread); @@ -516,7 +527,7 @@ } int -zfs_probe_dev(const char *devname, uint64_t *pool_guid) +zfs_probe_dev(const char *devname, uint64_t *pool_guid, uint64_t *vdev_guid) { struct disk_devdesc *dev; struct ptable *table; @@ -526,6 +537,8 @@ if (pool_guid) *pool_guid = 0; + if (vdev_guid) + *vdev_guid = 0; pa.fd = open(devname, O_RDONLY); if (pa.fd == -1) return (ENXIO); @@ -540,7 +553,7 @@ free(dev); if (partition != -1 && slice != -1) { - ret = zfs_probe(pa.fd, pool_guid); + ret = zfs_probe(pa.fd, pool_guid, vdev_guid); if (ret == 0) return (0); } @@ -553,6 +566,7 @@ if (ret == 0) { pa.devname = devname; pa.pool_guid = pool_guid; + pa.vdev_guid = vdev_guid; table = ptable_open(&pa, mediasz / pa.secsz, pa.secsz, zfs_diskread); if (table != NULL) { @@ -940,6 +954,7 @@ return (0); } + int zfs_set_env(void) { @@ -1015,3 +1030,14 @@ return (rv); } + +void +zfs_set_bootcfg_env(uint64_t pool_guid, uint64_t vdev_guid) +{ + char buf[20]; + + sprintf(buf, "%"PRIu64, pool_guid); + setenv("vfs.zfs.boot.primary_pool", buf, 1); + sprintf(buf, "%"PRIu64, vdev_guid); + setenv("vfs.zfs.boot.primary_vdev", buf, 1); +} Index: stand/libsa/zfs/zfsimpl.c =================================================================== --- stand/libsa/zfs/zfsimpl.c +++ stand/libsa/zfs/zfsimpl.c @@ -719,7 +719,6 @@ return (0); } -#ifdef BOOT2 static spa_t * spa_get_primary(void) { @@ -745,7 +744,6 @@ vdev = kid; return (vdev); } -#endif static spa_t * spa_create(uint64_t guid, const char *name) Index: stand/sparc64/loader/main.c =================================================================== --- stand/sparc64/loader/main.c +++ stand/sparc64/loader/main.c @@ -794,7 +794,7 @@ guidp = &guid; else guidp = NULL; - if (zfs_probe_dev(devname, guidp) == ENXIO) + if (zfs_probe_dev(devname, guidp, NULL) == ENXIO) break; } } Index: stand/userboot/userboot/main.c =================================================================== --- stand/userboot/userboot/main.c +++ stand/userboot/userboot/main.c @@ -278,7 +278,7 @@ for (unit = 0; unit < userboot_disk_maxunit; unit++) { sprintf(devname, "disk%d:", unit); pool_guid = 0; - zfs_probe_dev(devname, &pool_guid); + zfs_probe_dev(devname, &pool_guid, NULL); if (pool_guid != 0) userboot_zfs_found = 1; }