Index: sys/boot/efi/boot1/boot1.c =================================================================== --- sys/boot/efi/boot1/boot1.c +++ sys/boot/efi/boot1/boot1.c @@ -51,7 +51,10 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab); static void try_load(const boot_module_t* mod); -static EFI_STATUS probe_handle(EFI_HANDLE h); +static void probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, + BOOLEAN match); +static EFI_STATUS probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, + BOOLEAN match); EFI_SYSTEM_TABLE *systab; EFI_BOOT_SERVICES *bs; @@ -168,10 +171,29 @@ } } +static BOOLEAN +paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath) +{ + int len; + + if (imgpath == NULL || imgpath->Type != devpath->Type || + imgpath->SubType != devpath->SubType) + return (FALSE); + + len = DevicePathNodeLength(imgpath); + + if (len != DevicePathNodeLength(devpath)) + return (FALSE); + + return (memcmp(imgpath, devpath, (size_t)len) == 0); +} + EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) { EFI_HANDLE *handles; + EFI_LOADED_IMAGE *img; + EFI_DEVICE_PATH *imgpath; EFI_STATUS status; EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; @@ -254,20 +276,32 @@ /* Scan all partitions, probing with all modules. */ nhandles = hsize / sizeof(*handles); printf(" Probing %zu block devices...", nhandles); - for (i = 0; i < nhandles; i++) { - status = probe_handle(handles[i]); - switch (status) { - case EFI_UNSUPPORTED: - printf("."); - break; - case EFI_SUCCESS: - printf("+"); - break; - default: - printf("x"); - break; + + /* + * We start by probing handles which match our images media path, so if + * possible we boot from a partition on our device. + */ + status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img); + if (status == EFI_SUCCESS) { + status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID, + (void **)&imgpath); + } + + if (status == EFI_SUCCESS) { + while (!IsDevicePathMessaging(imgpath) && + !IsDevicePathEnd(NextDevicePathNode(imgpath))) + imgpath = NextDevicePathNode(imgpath); + if (IsDevicePathMessaging(imgpath)) { + for (i = 0; i < nhandles; i++) + probe_handle_status(handles[i], imgpath, TRUE); + } else { + imgpath = NULL; } } + + /* Now check for other bootable partitions. */ + for (i = 0; i < nhandles; i++) + probe_handle_status(handles[i], imgpath, FALSE); printf(" done\n"); /* Status summary. */ @@ -287,13 +321,34 @@ panic("No bootable partitions found!"); } +static void +probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN match) +{ + + switch (probe_handle(h, imgpath, match)) { + case EFI_UNSUPPORTED: + printf("."); + break; + case EFI_SUCCESS: + printf("%c", match ? '*' : '+'); + break; + case EFI_NOT_FOUND: + /* Didn't match or already tested. */ + break; + default: + printf("x"); + break; + } +} + static EFI_STATUS -probe_handle(EFI_HANDLE h) +probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN match) { dev_info_t *devinfo; EFI_BLOCK_IO *blkio; EFI_DEVICE_PATH *devpath; EFI_STATUS status; + BOOLEAN matched; UINTN i; /* Figure out if we're dealing with an actual partition. */ @@ -307,8 +362,34 @@ return (status); } - while (!IsDevicePathEnd(NextDevicePathNode(devpath))) + matched = FALSE; + while (!IsDevicePathEnd(NextDevicePathNode(devpath))) { + if (IsDevicePathMessaging(devpath) && !matched) { + if (match) { + if (!paths_match(imgpath, devpath)) + return (EFI_NOT_FOUND); + matched = TRUE; + } else if (paths_match(imgpath, devpath)) { + /* Already tested. */ + return (EFI_NOT_FOUND); + } + } devpath = NextDevicePathNode(devpath); + } + + if (IsDevicePathMessaging(devpath)) { + if (match) { + if (!paths_match(imgpath, devpath)) + return (EFI_NOT_FOUND); + matched = TRUE; + } else if (paths_match(imgpath, devpath)) { + /* Already tested. */ + return (EFI_NOT_FOUND); + } + } + + if (match && !matched) + return (EFI_NOT_FOUND); status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); if (status == EFI_UNSUPPORTED) Index: sys/boot/efi/boot1/ufs_module.c =================================================================== --- sys/boot/efi/boot1/ufs_module.c +++ sys/boot/efi/boot1/ufs_module.c @@ -101,11 +101,15 @@ ssize_t read; void *buf; - if (init_dev(dev) < 0) + if (init_dev(dev) < 0) { + DPRINTF("Failed to device %p\n", dev); return (EFI_UNSUPPORTED); + } - if ((ino = lookup(loader_path)) == 0) + if ((ino = lookup(loader_path)) == 0) { + DPRINTF("Failed to lookup %d on %p\n", loader_path, dev); return (EFI_NOT_FOUND); + } if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) { printf("Failed to read size of '%s' ino: %d\n", loader_path, @@ -139,15 +143,12 @@ size_t *bufsize) { dev_info_t *dev; - EFI_STATUS status; for (dev = devices; dev != NULL; dev = dev->next) { - status = try_load(dev, loader_path, buf, bufsize); - if (status == EFI_SUCCESS) { + if (try_load(dev, loader_path, buf, bufsize) == + EFI_SUCCESS) { *devinfop = dev; return (EFI_SUCCESS); - } else if (status != EFI_NOT_FOUND) { - return (status); } } Index: sys/boot/efi/boot1/zfs_module.c =================================================================== --- sys/boot/efi/boot1/zfs_module.c +++ sys/boot/efi/boot1/zfs_module.c @@ -102,24 +102,30 @@ EFI_STATUS status; spa = devinfo->devdata; - if (zfs_spa_init(spa) != 0) { - /* Init failed, don't report this loudly. */ + + if ((err = zfs_spa_init(spa)) != 0) { + DPRINTF("Failed to load pool %s (%d)\n", spa->spa_name, err); return (EFI_NOT_FOUND); } - if (zfs_mount(spa, 0, &zfsmount) != 0) { - /* Mount failed, don't report this loudly. */ + if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) { + DPRINTF("Failed to mount pool %s (%d)\n", spa->spa_name, err); return (EFI_NOT_FOUND); } if ((err = zfs_lookup(&zfsmount, loader_path, &dn)) != 0) { + if (err == ENOENT) { + DPRINTF("Failed to find %s on pool %s (%d)\n", + loader_path, spa->spa_name, err); + return (EFI_NOT_FOUND); + } printf("Failed to lookup %s on pool %s (%d)\n", loader_path, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) { - printf("Failed to lookup %s on pool %s (%d)\n", loader_path, + printf("Failed to stat %s on pool %s (%d)\n", loader_path, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } @@ -149,15 +155,12 @@ size_t *bufsize) { dev_info_t *devinfo; - EFI_STATUS status; for (devinfo = devices; devinfo != NULL; devinfo = devinfo->next) { - status = try_load(devinfo, loader_path, bufp, bufsize); - if (status == EFI_SUCCESS) { + if (try_load(devinfo, loader_path, bufp, bufsize) == + EFI_SUCCESS) { *devinfop = devinfo; return (EFI_SUCCESS); - } else if (status != EFI_NOT_FOUND) { - return (status); } } Index: sys/boot/efi/include/efidevp.h =================================================================== --- sys/boot/efi/include/efidevp.h +++ sys/boot/efi/include/efidevp.h @@ -40,9 +40,7 @@ #define EFI_DP_TYPE_MASK 0x7F #define EFI_DP_TYPE_UNPACKED 0x80 -//#define END_DEVICE_PATH_TYPE 0xff #define END_DEVICE_PATH_TYPE 0x7f -//#define END_DEVICE_PATH_TYPE_UNPACKED 0x7f #define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff #define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 @@ -56,8 +54,9 @@ #define DevicePathSubType(a) ( (a)->SubType ) #define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) ) #define NextDevicePathNode(a) ( (EFI_DEVICE_PATH *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a))) -//#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE_UNPACKED ) -#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE ) +#define IsDevicePathType(a, t) ( DevicePathType(a) == t ) +#define IsDevicePathEndType(a) IsDevicePathType(a, END_DEVICE_PATH_TYPE) +#define IsDevicePathMessaging(a) IsDevicePathType(a, MESSAGING_DEVICE_PATH) #define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE ) #define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) ) #define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED )