Use efi_devpath_str for debug path info.

Kill our own hand-rolled (and somewhat flawed) devpath_str in favor of
the recently added efi_devpath_str in libefi. This gives us much
better names at the expense of not being able to debug on EFI 1.2
machines (since the UEFI protocol efi_devpath_str depends on was added
in UEFI 2.0). However, this isn't the first thing that requires newer
than EFI 1.2, so it's quite possible that this doesn't change the
universe of machines we can EFI boot from. This will now give us the
full UEFI path, even for devices we don't yet know about. More
importantly, it gives us the full HD(...) part of the path, which is
sufficient by itself to locate disks that follow the rules (dd one
disk (but not partition) to another still needs the rest of the path
to disambiguate, but that isn't following the rules that require every
GPT table to have globally unique GUIDs for every partion).

This also has the side effect of shrinking boot1.efi by ~3k.

Sponsored by: Netflix
This commit is contained in:
Warner Losh 2017-08-26 23:04:19 +00:00
parent 57d7e4f502
commit 4532588625
4 changed files with 29 additions and 184 deletions

View File

@ -135,178 +135,6 @@ devpath_last(EFI_DEVICE_PATH *devpath)
return (devpath);
}
/*
* devpath_node_str is a basic output method for a devpath node which
* only understands a subset of the available sub types.
*
* If we switch to UEFI 2.x then we should update it to use:
* EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
*/
static int
devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
{
switch (devpath->Type) {
case MESSAGING_DEVICE_PATH:
switch (devpath->SubType) {
case MSG_ATAPI_DP: {
ATAPI_DEVICE_PATH *atapi;
atapi = (ATAPI_DEVICE_PATH *)(void *)devpath;
return snprintf(buf, size, "ata(%s,%s,0x%x)",
(atapi->PrimarySecondary == 1) ? "Sec" : "Pri",
(atapi->SlaveMaster == 1) ? "Slave" : "Master",
atapi->Lun);
}
case MSG_USB_DP: {
USB_DEVICE_PATH *usb;
usb = (USB_DEVICE_PATH *)devpath;
return snprintf(buf, size, "usb(0x%02x,0x%02x)",
usb->ParentPortNumber, usb->InterfaceNumber);
}
case MSG_SCSI_DP: {
SCSI_DEVICE_PATH *scsi;
scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
return snprintf(buf, size, "scsi(0x%02x,0x%02x)",
scsi->Pun, scsi->Lun);
}
case MSG_SATA_DP: {
SATA_DEVICE_PATH *sata;
sata = (SATA_DEVICE_PATH *)(void *)devpath;
return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)",
sata->HBAPortNumber, sata->PortMultiplierPortNumber,
sata->Lun);
}
default:
return snprintf(buf, size, "msg(0x%02x)",
devpath->SubType);
}
break;
case HARDWARE_DEVICE_PATH:
switch (devpath->SubType) {
case HW_PCI_DP: {
PCI_DEVICE_PATH *pci;
pci = (PCI_DEVICE_PATH *)devpath;
return snprintf(buf, size, "pci(0x%02x,0x%02x)",
pci->Device, pci->Function);
}
default:
return snprintf(buf, size, "hw(0x%02x)",
devpath->SubType);
}
break;
case ACPI_DEVICE_PATH: {
ACPI_HID_DEVICE_PATH *acpi;
acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath;
if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
switch (EISA_ID_TO_NUM(acpi->HID)) {
case 0x0a03:
return snprintf(buf, size, "pciroot(0x%x)",
acpi->UID);
case 0x0a08:
return snprintf(buf, size, "pcieroot(0x%x)",
acpi->UID);
case 0x0604:
return snprintf(buf, size, "floppy(0x%x)",
acpi->UID);
case 0x0301:
return snprintf(buf, size, "keyboard(0x%x)",
acpi->UID);
case 0x0501:
return snprintf(buf, size, "serial(0x%x)",
acpi->UID);
case 0x0401:
return snprintf(buf, size, "parallelport(0x%x)",
acpi->UID);
default:
return snprintf(buf, size, "acpi(pnp%04x,0x%x)",
EISA_ID_TO_NUM(acpi->HID), acpi->UID);
}
}
return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID,
acpi->UID);
}
case MEDIA_DEVICE_PATH:
switch (devpath->SubType) {
case MEDIA_CDROM_DP: {
CDROM_DEVICE_PATH *cdrom;
cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
return snprintf(buf, size, "cdrom(%x)",
cdrom->BootEntry);
}
case MEDIA_HARDDRIVE_DP: {
HARDDRIVE_DEVICE_PATH *hd;
hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
return snprintf(buf, size, "hd(%x)",
hd->PartitionNumber);
}
default:
return snprintf(buf, size, "media(0x%02x)",
devpath->SubType);
}
case BBS_DEVICE_PATH:
return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType);
case END_DEVICE_PATH_TYPE:
return (0);
}
return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
devpath->SubType);
}
/*
* devpath_strlcat appends a text description of devpath to buf but not more
* than size - 1 characters followed by NUL-terminator.
*/
int
devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
{
size_t len, used;
const char *sep;
sep = "";
used = 0;
while (!IsDevicePathEnd(devpath)) {
len = snprintf(buf, size - used, "%s", sep);
used += len;
if (used > size)
return (used);
buf += len;
len = devpath_node_str(buf, size - used, devpath);
used += len;
if (used > size)
return (used);
buf += len;
devpath = NextDevicePathNode(devpath);
sep = ":";
}
return (used);
}
/*
* devpath_str is convenience method which returns the text description of
* devpath using a static buffer, so it isn't thread safe!
*/
char *
devpath_str(EFI_DEVICE_PATH *devpath)
{
static char buf[256];
devpath_strlcat(buf, sizeof(buf), devpath);
return buf;
}
/*
* load_loader attempts to load the loader image data.
*
@ -470,9 +298,13 @@ probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
EFI_ERROR_CODE(status));
return (status);
}
DPRINTF("probing: %s\n", devpath_str(devpath));
#ifdef EFI_DEBUG
{
CHAR16 *text = efi_devpath_name(devpath);
DPRINTF("probing: %S\n", text);
efi_free_devpath_name(text);
}
#endif
status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
if (status == EFI_UNSUPPORTED)
return (status);
@ -646,7 +478,13 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
if (status != EFI_SUCCESS)
DPRINTF("Failed to get image DevicePath (%lu)\n",
EFI_ERROR_CODE(status));
DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath));
#ifdef EFI_DEBUG
{
CHAR16 *text = efi_devpath_name(imgpath);
DPRINTF("boot1 imagepath: %S\n", text);
efi_free_devpath_name(text);
}
#endif
}
for (i = 0; i < nhandles; i++)

View File

@ -106,7 +106,4 @@ extern const boot_module_t zfs_module;
/* Functions available to modules. */
extern void add_device(dev_info_t **devinfop, dev_info_t *devinfo);
extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
extern int devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath);
extern char *devpath_str(EFI_DEVICE_PATH *devpath);
#endif

View File

@ -101,8 +101,13 @@ load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize)
ssize_t read;
void *buf;
DPRINTF("Loading '%s' from %s\n", filepath, devpath_str(dev->devpath));
#ifdef EFI_DEBUG
{
CHAR16 *text = efi_devpath_name(dev->devpath);
DPRINTF("Loading '%s' from %S\n", filepath, text);
efi_free_devpath_name(text);
}
#endif
if (init_dev(dev) < 0) {
DPRINTF("Failed to init device\n");
return (EFI_UNSUPPORTED);

View File

@ -150,9 +150,14 @@ load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize)
spa = devinfo->devdata;
DPRINTF("load: '%s' spa: '%s', devpath: %s\n", filepath, spa->spa_name,
devpath_str(devinfo->devpath));
#ifdef EFI_DEBUG
{
CHAR16 *text = efi_devpath_name(devinfo->devpath);
DPRINTF("load: '%s' spa: '%s', devpath: %S\n", filepath,
spa->spa_name, text);
efi_free_devpath_name(text);
}
#endif
if ((err = zfs_spa_init(spa)) != 0) {
DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err);
return (EFI_NOT_FOUND);