Once again my intuition was right.
I looked into
stand/i386/gptzfsboot/zfsboot.c from releng/15.1, function i386_zfs_probe:
Code:
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);
/* If this is not boot disk, use generic probe. */
if (dev.dd.d_unit != boot_unit)
zfs_probe_dev(devname, NULL, true);
else
zfs_probe_dev(devname, &pool_guid, true);
if (pool_guid != 0 && bdev == NULL) {
bdev = malloc(sizeof (struct i386_devdesc));
bzero(bdev, sizeof (struct i386_devdesc));
bdev->zfs.dd.d_dev = &zfs_dev;
bdev->zfs.pool_guid = pool_guid;
}
}
What does that means "If this is not boot disk, use generic probe."?
So, if the disk is not the boot disk, it passes NULL in lieu of
pool_guid.
Generic probe ok, but how can it works without this
pool_guid?
It's obvious that without this var,
bdev isn't filled, even if a pool is found. And that's exactly the case.
So, I just got rid of this test and always call
zfs_probe_dev(devname, &pool_guid, true);. Now, gptzfsboot can boot another disk than the booting one.
I think this is more a workaround than a solution to the bug, because I suspect the guy that added these lines did that for a good reason. Another point is that doesn't explain why loader.efi is also impacted. It uses, as gptzfsboot, libsa, so it's maybe a bug in libsa in fact. That said, I found nothing weird on this way.
I will fill a PR, but I want to read more loader.efi and libsa code before, maybe the light will come. In the meaning time, I post a gptzfsboot that should work for
_max_.