Date: Thu, 7 Nov 2019 17:39:21 +0200 From: Toomas Soome <tsoome@me.com> To: Warner Losh <imp@bsdimp.com> Cc: Toomas Soome <tsoome@freebsd.org>, src-committers <src-committers@freebsd.org>, svn-src-all <svn-src-all@freebsd.org>, svn-src-head <svn-src-head@freebsd.org> Subject: Re: svn commit: r354435 - head/stand/efi/libefi Message-ID: <1AFEA810-CC13-444E-BF28-1C3D07CA0FC2@me.com> In-Reply-To: <CANCZdfrpHvM3dMt=Ctpnrb0Nc3RjQ8-hp7=uSE7bOWBq2scTzQ@mail.gmail.com> References: <201911071117.xA7BH390010873@repo.freebsd.org> <CANCZdfrpHvM3dMt=Ctpnrb0Nc3RjQ8-hp7=uSE7bOWBq2scTzQ@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
> On 7. Nov 2019, at 17:29, Warner Losh <imp@bsdimp.com> wrote: >=20 >=20 >=20 > On Thu, Nov 7, 2019 at 4:17 AM Toomas Soome <tsoome@freebsd.org = <mailto:tsoome@freebsd.org>> wrote: > Author: tsoome > Date: Thu Nov 7 11:17:03 2019 > New Revision: 354435 > URL: https://svnweb.freebsd.org/changeset/base/354435 = <https://svnweb.freebsd.org/changeset/base/354435> >=20 > Log: > loader: implement fallback efi_devpath_to_name() >=20 > UEFI 1.10 on macs does not seem to provide devpath to name = translation, > provide our own (limited) version, so we can get information about = commmon > devices. >=20 > We specifically deleted our own version of this function (it was wrong = in many ways too) because we thought we could require a minimum UEFI 2.0 = for full functionality... This sort of function is a total pain to = maintain. >=20 > I'd prefer the fallback was "you don't get this" rather than bloating = the code, especially for devices that we don't care about and will never = care about for booting... >=20 > Warner I can see why, but then again, try to debug such system=E2=80=A6 btw, = that particular one I debug is MacBookPro11,4 with quad core i7=E2=80=A6. = not even that old hw anyhow. I=E2=80=99d rather keep some bloat than spend 2-3 days to write code = just to get any idea what is going on in the machine=E2=80=A6 rgds, toomas > =20 > MFC after: 1 week >=20 > Modified: > head/stand/efi/libefi/devpath.c >=20 > Modified: head/stand/efi/libefi/devpath.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- head/stand/efi/libefi/devpath.c Thu Nov 7 07:21:45 2019 = (r354434) > +++ head/stand/efi/libefi/devpath.c Thu Nov 7 11:17:03 2019 = (r354435) > @@ -29,13 +29,16 @@ __FBSDID("$FreeBSD$"); > #include <efi.h> > #include <efilib.h> > #include <efichar.h> > +#include <uuid.h> > +#include <machine/_inttypes.h> >=20 > static EFI_GUID ImageDevicePathGUID =3D > EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID; > static EFI_GUID DevicePathGUID =3D DEVICE_PATH_PROTOCOL; > static EFI_GUID DevicePathToTextGUID =3D = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; > static EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *toTextProtocol; > -static EFI_GUID DevicePathFromTextGUID =3D = EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID; > +static EFI_GUID DevicePathFromTextGUID =3D > + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID; > static EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *fromTextProtocol; >=20 > EFI_DEVICE_PATH * > @@ -64,6 +67,427 @@ efi_lookup_devpath(EFI_HANDLE handle) > return (devpath); > } >=20 > +static char * > +efi_make_tail(char *suffix) > +{ > + char *tail; > + > + tail =3D NULL; > + if (suffix !=3D NULL) > + (void)asprintf(&tail, "/%s", suffix); > + else > + tail =3D strdup(""); > + return (tail); > +} > + > +typedef struct { > + EFI_DEVICE_PATH Header; > + EFI_GUID Guid; > + UINT8 VendorDefinedData[1]; > +} __packed VENDOR_DEVICE_PATH_WITH_DATA; > + > +static char * > +efi_vendor_path(const char *type, VENDOR_DEVICE_PATH *node, char = *suffix) > +{ > + uint32_t size =3D DevicePathNodeLength(&node->Header) - = sizeof(*node); > + VENDOR_DEVICE_PATH_WITH_DATA *dp =3D = (VENDOR_DEVICE_PATH_WITH_DATA *)node; > + char *name, *tail, *head; > + char *uuid; > + int rv; > + > + uuid_to_string((const uuid_t *)(void *)&node->Guid, &uuid, = &rv); > + if (rv !=3D uuid_s_ok) > + return (NULL); > + > + tail =3D efi_make_tail(suffix); > + rv =3D asprintf(&head, "%sVendor(%s)[%x:", type, uuid, size); > + free(uuid); > + if (rv < 0) > + return (NULL); > + > + if (DevicePathNodeLength(&node->Header) > sizeof(*node)) { > + for (uint32_t i =3D 0; i < size; i++) { > + rv =3D asprintf(&name, "%s%02x", head, > + dp->VendorDefinedData[i]); > + if (rv < 0) { > + free(tail); > + free(head); > + return (NULL); > + } > + free(head); > + head =3D name; > + } > + } > + > + if (asprintf(&name, "%s]%s", head, tail) < 0) > + name =3D NULL; > + free(head); > + free(tail); > + return (name); > +} > + > +static char * > +efi_hw_dev_path(EFI_DEVICE_PATH *node, char *suffix) > +{ > + uint8_t subtype =3D DevicePathSubType(node); > + char *name, *tail; > + > + tail =3D efi_make_tail(suffix); > + switch (subtype) { > + case HW_PCI_DP: > + if (asprintf(&name, "Pci(%x,%x)%s", > + ((PCI_DEVICE_PATH *)node)->Function, > + ((PCI_DEVICE_PATH *)node)->Device, tail) < 0) > + name =3D NULL; > + break; > + case HW_PCCARD_DP: > + if (asprintf(&name, "PCCARD(%x)%s", > + ((PCCARD_DEVICE_PATH *)node)->FunctionNumber, = tail) < 0) > + name =3D NULL; > + break; > + case HW_MEMMAP_DP: > + if (asprintf(&name, "MMap(%x,%" PRIx64 ",%" PRIx64 = ")%s", > + ((MEMMAP_DEVICE_PATH *)node)->MemoryType, > + ((MEMMAP_DEVICE_PATH *)node)->StartingAddress, > + ((MEMMAP_DEVICE_PATH *)node)->EndingAddress, tail) = < 0) > + name =3D NULL; > + break; > + case HW_VENDOR_DP: > + name =3D efi_vendor_path("Hardware", > + (VENDOR_DEVICE_PATH *)node, tail); > + break; > + case HW_CONTROLLER_DP: > + if (asprintf(&name, "Ctrl(%x)%s", > + ((CONTROLLER_DEVICE_PATH *)node)->Controller, = tail) < 0) > + name =3D NULL; > + break; > + default: > + if (asprintf(&name, "UnknownHW(%x)%s", subtype, tail) = < 0) > + name =3D NULL; > + break; > + } > + free(tail); > + return (name); > +} > + > +static char * > +efi_acpi_dev_path(EFI_DEVICE_PATH *node, char *suffix) > +{ > + uint8_t subtype =3D DevicePathSubType(node); > + ACPI_HID_DEVICE_PATH *acpi =3D (ACPI_HID_DEVICE_PATH *)node; > + char *name, *tail; > + > + tail =3D efi_make_tail(suffix); > + switch (subtype) { > + case ACPI_DP: > + if ((acpi->HID & PNP_EISA_ID_MASK) =3D=3D = PNP_EISA_ID_CONST) { > + switch (EISA_ID_TO_NUM (acpi->HID)) { > + case 0x0a03: > + if (asprintf(&name, "PciRoot(%x)%s", > + acpi->UID, tail) < 0) > + name =3D NULL; > + break; > + case 0x0a08: > + if (asprintf(&name, "PcieRoot(%x)%s", > + acpi->UID, tail) < 0) > + name =3D NULL; > + break; > + case 0x0604: > + if (asprintf(&name, "Floppy(%x)%s", > + acpi->UID, tail) < 0) > + name =3D NULL; > + break; > + case 0x0301: > + if (asprintf(&name, "Keyboard(%x)%s", > + acpi->UID, tail) < 0) > + name =3D NULL; > + break; > + case 0x0501: > + if (asprintf(&name, "Serial(%x)%s", > + acpi->UID, tail) < 0) > + name =3D NULL; > + break; > + case 0x0401: > + if (asprintf(&name, = "ParallelPort(%x)%s", > + acpi->UID, tail) < 0) > + name =3D NULL; > + break; > + default: > + if (asprintf(&name, = "Acpi(PNP%04x,%x)%s", > + EISA_ID_TO_NUM(acpi->HID), > + acpi->UID, tail) < 0) > + name =3D NULL; > + break; > + } > + } else { > + if (asprintf(&name, "Acpi(%08x,%x)%s", > + acpi->HID, acpi->UID, tail) < 0) > + name =3D NULL; > + } > + break; > + case ACPI_EXTENDED_DP: > + default: > + if (asprintf(&name, "UnknownACPI(%x)%s", subtype, = tail) < 0) > + name =3D NULL; > + break; > + } > + free(tail); > + return (name); > +} > + > +static char * > +efi_messaging_dev_path(EFI_DEVICE_PATH *node, char *suffix) > +{ > + uint8_t subtype =3D DevicePathSubType(node); > + char *name; > + char *tail; > + > + tail =3D efi_make_tail(suffix); > + switch (subtype) { > + case MSG_ATAPI_DP: > + if (asprintf(&name, "ATA(%s,%s,%x)%s", > + ((ATAPI_DEVICE_PATH *)node)->PrimarySecondary =3D=3D= 1 ? > + "Secondary" : "Primary", > + ((ATAPI_DEVICE_PATH *)node)->SlaveMaster =3D=3D 1 = ? > + "Slave" : "Master", > + ((ATAPI_DEVICE_PATH *)node)->Lun, tail) < 0) > + name =3D NULL; > + break; > + case MSG_SCSI_DP: > + if (asprintf(&name, "SCSI(%x,%x)%s", > + ((SCSI_DEVICE_PATH *)node)->Pun, > + ((SCSI_DEVICE_PATH *)node)->Lun, tail) < 0) > + name =3D NULL; > + break; > + case MSG_FIBRECHANNEL_DP: > + if (asprintf(&name, "Fibre(%" PRIx64 ",%" PRIx64 = ")%s", > + ((FIBRECHANNEL_DEVICE_PATH *)node)->WWN, > + ((FIBRECHANNEL_DEVICE_PATH *)node)->Lun, tail) < = 0) > + name =3D NULL; > + break; > + case MSG_1394_DP: > + if (asprintf(&name, "I1394(%016" PRIx64 ")%s", > + ((F1394_DEVICE_PATH *)node)->Guid, tail) < 0) > + name =3D NULL; > + break; > + case MSG_USB_DP: > + if (asprintf(&name, "USB(%x,%x)%s", > + ((USB_DEVICE_PATH *)node)->ParentPortNumber, > + ((USB_DEVICE_PATH *)node)->InterfaceNumber, tail) = < 0) > + name =3D NULL; > + break; > + case MSG_USB_CLASS_DP: > + if (asprintf(&name, "UsbClass(%x,%x,%x,%x,%x)%s", > + ((USB_CLASS_DEVICE_PATH *)node)->VendorId, > + ((USB_CLASS_DEVICE_PATH *)node)->ProductId, > + ((USB_CLASS_DEVICE_PATH *)node)->DeviceClass, > + ((USB_CLASS_DEVICE_PATH *)node)->DeviceSubClass, > + ((USB_CLASS_DEVICE_PATH *)node)->DeviceProtocol, = tail) < 0) > + name =3D NULL; > + break; > + case MSG_MAC_ADDR_DP: > + if (asprintf(&name, = "MAC(%02x:%02x:%02x:%02x:%02x:%02x,%x)%s", > + ((MAC_ADDR_DEVICE_PATH = *)node)->MacAddress.Addr[0], > + ((MAC_ADDR_DEVICE_PATH = *)node)->MacAddress.Addr[1], > + ((MAC_ADDR_DEVICE_PATH = *)node)->MacAddress.Addr[2], > + ((MAC_ADDR_DEVICE_PATH = *)node)->MacAddress.Addr[3], > + ((MAC_ADDR_DEVICE_PATH = *)node)->MacAddress.Addr[4], > + ((MAC_ADDR_DEVICE_PATH = *)node)->MacAddress.Addr[5], > + ((MAC_ADDR_DEVICE_PATH *)node)->IfType, tail) < 0) > + name =3D NULL; > + break; > + case MSG_VENDOR_DP: > + name =3D efi_vendor_path("Messaging", > + (VENDOR_DEVICE_PATH *)node, tail); > + break; > + case MSG_UART_DP: > + if (asprintf(&name, "UART(%" PRIu64 ",%u,%x,%x)%s", > + ((UART_DEVICE_PATH *)node)->BaudRate, > + ((UART_DEVICE_PATH *)node)->DataBits, > + ((UART_DEVICE_PATH *)node)->Parity, > + ((UART_DEVICE_PATH *)node)->StopBits, tail) < 0) > + name =3D NULL; > + break; > + case MSG_SATA_DP: > + if (asprintf(&name, "Sata(%x,%x,%x)%s", > + ((SATA_DEVICE_PATH *)node)->HBAPortNumber, > + ((SATA_DEVICE_PATH = *)node)->PortMultiplierPortNumber, > + ((SATA_DEVICE_PATH *)node)->Lun, tail) < 0) > + name =3D NULL; > + break; > + default: > + if (asprintf(&name, "UnknownMessaging(%x)%s", > + subtype, tail) < 0) > + name =3D NULL; > + break; > + } > + free(tail); > + return (name); > +} > + > +static char * > +efi_media_dev_path(EFI_DEVICE_PATH *node, char *suffix) > +{ > + uint8_t subtype =3D DevicePathSubType(node); > + HARDDRIVE_DEVICE_PATH *hd; > + char *name; > + char *str; > + char *tail; > + int rv; > + > + tail =3D efi_make_tail(suffix); > + name =3D NULL; > + switch (subtype) { > + case MEDIA_HARDDRIVE_DP: > + hd =3D (HARDDRIVE_DEVICE_PATH *)node; > + switch (hd->SignatureType) { > + case SIGNATURE_TYPE_MBR: > + if (asprintf(&name, "HD(%d,MBR,%08x,%" PRIx64 > + ",%" PRIx64 ")%s", > + hd->PartitionNumber, > + *((uint32_t = *)(uintptr_t)&hd->Signature[0]), > + hd->PartitionStart, > + hd->PartitionSize, tail) < 0) > + name =3D NULL; > + break; > + case SIGNATURE_TYPE_GUID: > + name =3D NULL; > + uuid_to_string((const uuid_t *)(void *) > + &hd->Signature[0], &str, &rv); > + if (rv !=3D uuid_s_ok) > + break; > + rv =3D asprintf(&name, "HD(%d,GPT,%s,%" PRIx64 = ",%" > + PRIx64 ")%s", > + hd->PartitionNumber, str, > + hd->PartitionStart, hd->PartitionSize, = tail); > + free(str); > + break; > + default: > + if (asprintf(&name, "HD(%d,%d,0)%s", > + hd->PartitionNumber, > + hd->SignatureType, tail) < 0) { > + name =3D NULL; > + } > + break; > + } > + break; > + case MEDIA_CDROM_DP: > + if (asprintf(&name, "CD(%x,%" PRIx64 ",%" PRIx64 = ")%s", > + ((CDROM_DEVICE_PATH *)node)->BootEntry, > + ((CDROM_DEVICE_PATH *)node)->PartitionStart, > + ((CDROM_DEVICE_PATH *)node)->PartitionSize, tail) = < 0) { > + name =3D NULL; > + } > + break; > + case MEDIA_VENDOR_DP: > + name =3D efi_vendor_path("Media", > + (VENDOR_DEVICE_PATH *)node, tail); > + break; > + case MEDIA_FILEPATH_DP: > + name =3D NULL; > + str =3D NULL; > + if (ucs2_to_utf8(((FILEPATH_DEVICE_PATH = *)node)->PathName, > + &str) =3D=3D 0) { > + (void)asprintf(&name, "%s%s", str, tail); > + free(str); > + } > + break; > + case MEDIA_PROTOCOL_DP: > + name =3D NULL; > + uuid_to_string((const uuid_t *)(void *) > + &((MEDIA_PROTOCOL_DEVICE_PATH *)node)->Protocol, > + &str, &rv); > + if (rv !=3D uuid_s_ok) > + break; > + rv =3D asprintf(&name, "Protocol(%s)%s", str, tail); > + free(str); > + break; > + default: > + if (asprintf(&name, "UnknownMedia(%x)%s", > + subtype, tail) < 0) > + name =3D NULL; > + } > + free(tail); > + return (name); > +} > + > +static char * > +efi_translate_devpath(EFI_DEVICE_PATH *devpath) > +{ > + EFI_DEVICE_PATH *dp =3D NextDevicePathNode(devpath); > + char *name, *ptr; > + uint8_t type; > + > + if (!IsDevicePathEnd(devpath)) > + name =3D efi_translate_devpath(dp); > + else > + return (NULL); > + > + ptr =3D NULL; > + type =3D DevicePathType(devpath); > + switch (type) { > + case HARDWARE_DEVICE_PATH: > + ptr =3D efi_hw_dev_path(devpath, name); > + break; > + case ACPI_DEVICE_PATH: > + ptr =3D efi_acpi_dev_path(devpath, name); > + break; > + case MESSAGING_DEVICE_PATH: > + ptr =3D efi_messaging_dev_path(devpath, name); > + break; > + case MEDIA_DEVICE_PATH: > + ptr =3D efi_media_dev_path(devpath, name); > + break; > + case BBS_DEVICE_PATH: > + default: > + if (asprintf(&ptr, "UnknownPath(%x)%s", type, > + name? name : "") < 0) > + ptr =3D NULL; > + break; > + } > + > + if (ptr !=3D NULL) { > + free(name); > + name =3D ptr; > + } > + return (name); > +} > + > +static CHAR16 * > +efi_devpath_to_name(EFI_DEVICE_PATH *devpath) > +{ > + char *name =3D NULL; > + CHAR16 *ptr =3D NULL; > + size_t len; > + int rv; > + > + name =3D efi_translate_devpath(devpath); > + if (name =3D=3D NULL) > + return (NULL); > + > + /* > + * We need to return memory from AllocatePool, so it can be = freed > + * with FreePool() in efi_free_devpath_name(). > + */ > + rv =3D utf8_to_ucs2(name, &ptr, &len); > + free(name); > + if (rv =3D=3D 0) { > + CHAR16 *out =3D NULL; > + EFI_STATUS status; > + > + status =3D BS->AllocatePool(EfiLoaderData, len, (void = **)&out); > + if (EFI_ERROR(status)) { > + free(ptr); > + return (out); > + } > + memcpy(out, ptr, len); > + free(ptr); > + ptr =3D out; > + } > + =20 > + return (ptr); > +} > + > CHAR16 * > efi_devpath_name(EFI_DEVICE_PATH *devpath) > { > @@ -78,7 +502,7 @@ efi_devpath_name(EFI_DEVICE_PATH *devpath) > toTextProtocol =3D NULL; > } > if (toTextProtocol =3D=3D NULL) > - return (NULL); > + return (efi_devpath_to_name(devpath)); >=20 > return (toTextProtocol->ConvertDevicePathToText(devpath, TRUE, = TRUE)); > } > @@ -86,8 +510,8 @@ efi_devpath_name(EFI_DEVICE_PATH *devpath) > void > efi_free_devpath_name(CHAR16 *text) > { > - > - BS->FreePool(text); > + if (text !=3D NULL) > + BS->FreePool(text); > } >=20 > EFI_DEVICE_PATH *
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1AFEA810-CC13-444E-BF28-1C3D07CA0FC2>