--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ DevicePath.c\r
+\r
+Abstract:\r
+\r
+ BDS internal function define the default device path string, it can be\r
+ replaced by platform device path.\r
+\r
+--*/\r
+\r
+\r
+#ifdef TIANO_EXTENSION_FLAG\r
+EFI_GUID UnknownDeviceGuid = UNKNOWN_DEVICE_GUID;\r
+#endif \r
+\r
+EFI_GUID mEfiUnixThunkProtocolGuid = EFI_UNIX_THUNK_PROTOCOL_GUID;\r
+EFI_GUID mEfiUnixUgaGuid = EFI_UNIX_UGA_GUID;\r
+EFI_GUID mEfiMsgPcAnsiGuid = DEVICE_PATH_MESSAGING_PC_ANSI;\r
+EFI_GUID mEfiMsgVt100Guid = DEVICE_PATH_MESSAGING_VT_100;\r
+EFI_GUID mEfiMsgVt100PlusGuid = DEVICE_PATH_MESSAGING_VT_100_PLUS;\r
+EFI_GUID mEfiMsgVt100Utf8Guid = DEVICE_PATH_MESSAGING_VT_UTF8;\r
+\r
+VOID *\r
+ReallocatePool (\r
+ IN VOID *OldPool,\r
+ IN UINTN OldSize,\r
+ IN UINTN NewSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Adjusts the size of a previously allocated buffer.\r
+\r
+Arguments:\r
+\r
+ OldPool - A pointer to the buffer whose size is being adjusted.\r
+\r
+ OldSize - The size of the current buffer.\r
+\r
+ NewSize - The size of the new buffer.\r
+\r
+Returns:\r
+\r
+ EFI_SUCEESS - The requested number of bytes were allocated.\r
+\r
+ EFI_OUT_OF_RESOURCES - The pool requested could not be allocated.\r
+\r
+ EFI_INVALID_PARAMETER - The buffer was invalid.\r
+\r
+--*/\r
+{\r
+ VOID *NewPool;\r
+\r
+ NewPool = NULL;\r
+ if (NewSize) {\r
+ NewPool = AllocateZeroPool (NewSize);\r
+ }\r
+\r
+ if (OldPool) {\r
+ if (NewPool) {\r
+ CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
+ }\r
+\r
+ gBS->FreePool (OldPool);\r
+ }\r
+\r
+ return NewPool;\r
+}\r
+\r
+CHAR16 *\r
+CatPrint (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN CHAR16 *fmt,\r
+ ...\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Concatenates a formatted unicode string to allocated pool. \r
+ The caller must free the resulting buffer.\r
+\r
+Arguments:\r
+\r
+ Str - Tracks the allocated pool, size in use, and \r
+ amount of pool allocated.\r
+\r
+ fmt - The format string\r
+\r
+Returns:\r
+\r
+ Allocated buffer with the formatted string printed in it. \r
+ The caller must free the allocated buffer. The buffer\r
+ allocation is not packed.\r
+\r
+--*/\r
+{\r
+ UINT16 *AppendStr;\r
+ VA_LIST args;\r
+ UINTN strsize;\r
+\r
+ AppendStr = AllocateZeroPool (0x1000);\r
+ if (AppendStr == NULL) {\r
+ return Str->str;\r
+ }\r
+\r
+ VA_START (args, fmt);\r
+ UnicodeVSPrint (AppendStr, 0x1000, fmt, args);\r
+ VA_END (args);\r
+ if (NULL == Str->str) {\r
+ strsize = StrSize (AppendStr);\r
+ Str->str = AllocateZeroPool (strsize);\r
+ ASSERT (Str->str != NULL);\r
+ } else {\r
+ strsize = StrSize (AppendStr) + StrSize (Str->str) - sizeof (UINT16);\r
+ Str->str = ReallocatePool (\r
+ Str->str,\r
+ StrSize (Str->str),\r
+ strsize\r
+ );\r
+ ASSERT (Str->str != NULL);\r
+ }\r
+\r
+ Str->maxlen = MAX_CHAR * sizeof (UINT16);\r
+ if (strsize < Str->maxlen) {\r
+ StrCat (Str->str, AppendStr);\r
+ Str->len = strsize - sizeof (UINT16);\r
+ }\r
+\r
+ gBS->FreePool (AppendStr);\r
+ return Str->str;\r
+}\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BdsLibUnpackDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Function unpacks a device path data structure so that all the nodes\r
+ of a device path are naturally aligned.\r
+\r
+Arguments:\r
+\r
+ DevPath - A pointer to a device path data structure\r
+\r
+Returns:\r
+\r
+ If the memory for the device path is successfully allocated, then a \r
+ pointer to the new device path is returned. Otherwise, NULL is returned.\r
+\r
+--*/\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Src;\r
+ EFI_DEVICE_PATH_PROTOCOL *Dest;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewPath;\r
+ UINTN Size;\r
+\r
+ //\r
+ // Walk device path and round sizes to valid boundries\r
+ //\r
+ Src = DevPath;\r
+ Size = 0;\r
+ for (;;) {\r
+ Size += DevicePathNodeLength (Src);\r
+ Size += ALIGN_SIZE (Size);\r
+\r
+ if (IsDevicePathEnd (Src)) {\r
+ break;\r
+ }\r
+\r
+ Src = NextDevicePathNode (Src);\r
+ }\r
+ //\r
+ // Allocate space for the unpacked path\r
+ //\r
+ NewPath = AllocateZeroPool (Size);\r
+ if (NewPath) {\r
+\r
+ ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);\r
+\r
+ //\r
+ // Copy each node\r
+ //\r
+ Src = DevPath;\r
+ Dest = NewPath;\r
+ for (;;) {\r
+ Size = DevicePathNodeLength (Src);\r
+ CopyMem (Dest, Src, Size);\r
+ Size += ALIGN_SIZE (Size);\r
+ SetDevicePathNodeLength (Dest, Size);\r
+ Dest->Type |= EFI_DP_TYPE_UNPACKED;\r
+ Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);\r
+\r
+ if (IsDevicePathEnd (Src)) {\r
+ break;\r
+ }\r
+\r
+ Src = NextDevicePathNode (Src);\r
+ }\r
+ }\r
+\r
+ return NewPath;\r
+}\r
+\r
+VOID\r
+DevPathPci (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ PCI_DEVICE_PATH *Pci;\r
+\r
+ Pci = DevPath;\r
+ CatPrint (Str, L"Pci(%x|%x)", Pci->Device, Pci->Function);\r
+}\r
+\r
+VOID\r
+DevPathPccard (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ PCCARD_DEVICE_PATH *Pccard;\r
+\r
+ Pccard = DevPath;\r
+ CatPrint (Str, L"Pcmcia(Function%x)", Pccard->FunctionNumber);\r
+}\r
+\r
+VOID\r
+DevPathMemMap (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MEMMAP_DEVICE_PATH *MemMap;\r
+\r
+ MemMap = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"MemMap(%d:%.lx-%.lx)",\r
+ MemMap->MemoryType,\r
+ MemMap->StartingAddress,\r
+ MemMap->EndingAddress\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathController (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CONTROLLER_DEVICE_PATH *Controller;\r
+\r
+ Controller = DevPath;\r
+ CatPrint (Str, L"Ctrl(%d)", Controller->ControllerNumber);\r
+}\r
+\r
+VOID\r
+DevPathVendor (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Convert Vendor device path to device name\r
+\r
+Arguments:\r
+\r
+ Str - The buffer store device name\r
+ DevPath - Pointer to vendor device path\r
+\r
+Returns:\r
+\r
+ When it return, the device name have been stored in *Str.\r
+\r
+--*/\r
+{\r
+ VENDOR_DEVICE_PATH *Vendor;\r
+ CHAR16 *Type;\r
+ INT32 *Temp;\r
+\r
+ Vendor = DevPath;\r
+ Temp = (INT32 *) (&Vendor->Guid);\r
+\r
+ switch (DevicePathType (&Vendor->Header)) {\r
+ case HARDWARE_DEVICE_PATH:\r
+ //\r
+ // If the device is an Unix device, we will give it a readable device name.\r
+ //\r
+ if (CompareGuid (&Vendor->Guid, &mEfiUnixThunkProtocolGuid)) {\r
+ CatPrint (Str, L"%s", L"UnixBus");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &mEfiUnixUgaGuid)) {\r
+ CatPrint (Str, L"%s", L"UGA");\r
+ return ;\r
+ } else {\r
+ Type = L"Hw";\r
+ break;\r
+ }\r
+\r
+ case MESSAGING_DEVICE_PATH:\r
+ //\r
+ // If the device is an Unix device, we will give it a readable device name.\r
+ //\r
+ if (CompareGuid (&Vendor->Guid, &mEfiMsgPcAnsiGuid)) {\r
+ CatPrint (Str, L"%s", L"PC-ANSI");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100Guid)) {\r
+ CatPrint (Str, L"%s", L"VT100");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100PlusGuid)) {\r
+ CatPrint (Str, L"%s", L"VT100+");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100Utf8Guid)) {\r
+ CatPrint (Str, L"%s", L"VT100-UTF8");\r
+ return ;\r
+ } else {\r
+ Type = L"Msg";\r
+ break;\r
+ }\r
+\r
+ case MEDIA_DEVICE_PATH:\r
+ Type = L"Media";\r
+ break;\r
+\r
+ default:\r
+ Type = L"?";\r
+ break;\r
+ }\r
+\r
+ CatPrint (Str, L"Ven%s(%g)", Type, &Vendor->Guid);\r
+}\r
+\r
+VOID\r
+DevPathAcpi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+\r
+ Acpi = DevPath;\r
+ if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+ CatPrint (Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);\r
+ } else {\r
+ CatPrint (Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID);\r
+ }\r
+}\r
+\r
+VOID\r
+DevPathAtapi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ATAPI_DEVICE_PATH *Atapi;\r
+\r
+ Atapi = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"Ata(%s,%s)",\r
+ Atapi->PrimarySecondary ? L"Secondary" : L"Primary",\r
+ Atapi->SlaveMaster ? L"Slave" : L"Master"\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathScsi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ SCSI_DEVICE_PATH *Scsi;\r
+\r
+ Scsi = DevPath;\r
+ CatPrint (Str, L"Scsi(Pun%x,Lun%x)", Scsi->Pun, Scsi->Lun);\r
+}\r
+\r
+VOID\r
+DevPathFibre (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ FIBRECHANNEL_DEVICE_PATH *Fibre;\r
+\r
+ Fibre = DevPath;\r
+ CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun);\r
+}\r
+\r
+VOID\r
+DevPath1394 (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ F1394_DEVICE_PATH *F1394;\r
+\r
+ F1394 = DevPath;\r
+ CatPrint (Str, L"1394(%g)", &F1394->Guid);\r
+}\r
+\r
+VOID\r
+DevPathUsb (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ USB_DEVICE_PATH *Usb;\r
+\r
+ Usb = DevPath;\r
+ CatPrint (Str, L"Usb(%x, %x)", Usb->ParentPortNumber, Usb->InterfaceNumber);\r
+}\r
+\r
+VOID\r
+DevPathUsbClass (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ USB_CLASS_DEVICE_PATH *UsbClass;\r
+\r
+ UsbClass = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"Usb Class(%x, %x, %x, %x, %x)",\r
+ UsbClass->VendorId,\r
+ UsbClass->ProductId,\r
+ UsbClass->DeviceClass,\r
+ UsbClass->DeviceSubClass,\r
+ UsbClass->DeviceProtocol\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathI2O (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ I2O_DEVICE_PATH *I2O;\r
+\r
+ I2O = DevPath;\r
+ CatPrint (Str, L"I2O(%x)", I2O->Tid);\r
+}\r
+\r
+VOID\r
+DevPathMacAddr (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MAC_ADDR_DEVICE_PATH *MAC;\r
+ UINTN HwAddressSize;\r
+ UINTN Index;\r
+\r
+ MAC = DevPath;\r
+\r
+ HwAddressSize = sizeof (EFI_MAC_ADDRESS);\r
+ if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {\r
+ HwAddressSize = 6;\r
+ }\r
+\r
+ CatPrint (Str, L"Mac(");\r
+\r
+ for (Index = 0; Index < HwAddressSize; Index++) {\r
+ CatPrint (Str, L"%02x", MAC->MacAddress.Addr[Index]);\r
+ }\r
+\r
+ CatPrint (Str, L")");\r
+}\r
+\r
+VOID\r
+DevPathIPv4 (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ IPv4_DEVICE_PATH *IP;\r
+\r
+ IP = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"IPv4(%d.%d.%d.%d:%d)",\r
+ IP->RemoteIpAddress.Addr[0],\r
+ IP->RemoteIpAddress.Addr[1],\r
+ IP->RemoteIpAddress.Addr[2],\r
+ IP->RemoteIpAddress.Addr[3],\r
+ IP->RemotePort\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathIPv6 (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ IPv6_DEVICE_PATH *IP;\r
+\r
+ IP = DevPath;\r
+ CatPrint (Str, L"IP-v6(not-done)");\r
+}\r
+\r
+VOID\r
+DevPathInfiniBand (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ INFINIBAND_DEVICE_PATH *InfiniBand;\r
+\r
+ InfiniBand = DevPath;\r
+ CatPrint (Str, L"InfiniBand(not-done)");\r
+}\r
+\r
+VOID\r
+DevPathUart (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ UART_DEVICE_PATH *Uart;\r
+ CHAR8 Parity;\r
+\r
+ Uart = DevPath;\r
+ switch (Uart->Parity) {\r
+ case 0:\r
+ Parity = 'D';\r
+ break;\r
+\r
+ case 1:\r
+ Parity = 'N';\r
+ break;\r
+\r
+ case 2:\r
+ Parity = 'E';\r
+ break;\r
+\r
+ case 3:\r
+ Parity = 'O';\r
+ break;\r
+\r
+ case 4:\r
+ Parity = 'M';\r
+ break;\r
+\r
+ case 5:\r
+ Parity = 'S';\r
+ break;\r
+\r
+ default:\r
+ Parity = 'x';\r
+ break;\r
+ }\r
+\r
+ if (Uart->BaudRate == 0) {\r
+ CatPrint (Str, L"Uart(DEFAULT %c", Parity);\r
+ } else {\r
+ CatPrint (Str, L"Uart(%d %c", Uart->BaudRate, Parity);\r
+ }\r
+\r
+ if (Uart->DataBits == 0) {\r
+ CatPrint (Str, L"D");\r
+ } else {\r
+ CatPrint (Str, L"%d", Uart->DataBits);\r
+ }\r
+\r
+ switch (Uart->StopBits) {\r
+ case 0:\r
+ CatPrint (Str, L"D)");\r
+ break;\r
+\r
+ case 1:\r
+ CatPrint (Str, L"1)");\r
+ break;\r
+\r
+ case 2:\r
+ CatPrint (Str, L"1.5)");\r
+ break;\r
+\r
+ case 3:\r
+ CatPrint (Str, L"2)");\r
+ break;\r
+\r
+ default:\r
+ CatPrint (Str, L"x)");\r
+ break;\r
+ }\r
+}\r
+\r
+VOID\r
+DevPathHardDrive (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ HARDDRIVE_DEVICE_PATH *Hd;\r
+\r
+ Hd = DevPath;\r
+ switch (Hd->SignatureType) {\r
+ case SIGNATURE_TYPE_MBR:\r
+ CatPrint (\r
+ Str,\r
+ L"HD(Part%d,Sig%08x)",\r
+ Hd->PartitionNumber,\r
+ *((UINT32 *) (&(Hd->Signature[0])))\r
+ );\r
+ break;\r
+\r
+ case SIGNATURE_TYPE_GUID:\r
+ CatPrint (\r
+ Str,\r
+ L"HD(Part%d,Sig%g)",\r
+ Hd->PartitionNumber,\r
+ (EFI_GUID *) &(Hd->Signature[0])\r
+ );\r
+ break;\r
+\r
+ default:\r
+ CatPrint (\r
+ Str,\r
+ L"HD(Part%d,MBRType=%02x,SigType=%02x)",\r
+ Hd->PartitionNumber,\r
+ Hd->MBRType,\r
+ Hd->SignatureType\r
+ );\r
+ break;\r
+ }\r
+}\r
+\r
+VOID\r
+DevPathCDROM (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CDROM_DEVICE_PATH *Cd;\r
+\r
+ Cd = DevPath;\r
+ CatPrint (Str, L"CDROM(Entry%x)", Cd->BootEntry);\r
+}\r
+\r
+VOID\r
+DevPathFilePath (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ FILEPATH_DEVICE_PATH *Fp;\r
+\r
+ Fp = DevPath;\r
+ CatPrint (Str, L"%s", Fp->PathName);\r
+}\r
+\r
+VOID\r
+DevPathMediaProtocol (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;\r
+\r
+ MediaProt = DevPath;\r
+ CatPrint (Str, L"%g", &MediaProt->Protocol);\r
+}\r
+\r
+VOID\r
+DevPathFvFilePath (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
+\r
+ FvFilePath = DevPath;\r
+ CatPrint (Str, L"%g", &FvFilePath->NameGuid);\r
+}\r
+\r
+VOID\r
+DevPathBssBss (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ BBS_BBS_DEVICE_PATH *Bbs;\r
+ CHAR16 *Type;\r
+\r
+ Bbs = DevPath;\r
+ switch (Bbs->DeviceType) {\r
+ case BBS_TYPE_FLOPPY:\r
+ Type = L"Floppy";\r
+ break;\r
+\r
+ case BBS_TYPE_HARDDRIVE:\r
+ Type = L"Harddrive";\r
+ break;\r
+\r
+ case BBS_TYPE_CDROM:\r
+ Type = L"CDROM";\r
+ break;\r
+\r
+ case BBS_TYPE_PCMCIA:\r
+ Type = L"PCMCIA";\r
+ break;\r
+\r
+ case BBS_TYPE_USB:\r
+ Type = L"Usb";\r
+ break;\r
+\r
+ case BBS_TYPE_EMBEDDED_NETWORK:\r
+ Type = L"Net";\r
+ break;\r
+\r
+ default:\r
+ Type = L"?";\r
+ break;\r
+ }\r
+ //\r
+ // Since current Print function hasn't implemented %a (for ansi string)\r
+ // we will only print Unicode strings.\r
+ //\r
+ CatPrint (Str, L"Legacy-%s", Type);\r
+}\r
+\r
+VOID\r
+DevPathEndInstance (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CatPrint (Str, L",");\r
+}\r
+\r
+VOID\r
+DevPathNodeUnknown (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CatPrint (Str, L"?");\r
+}\r
+\r
+DEVICE_PATH_STRING_TABLE DevPathTable[] = {\r
+ {
+ HARDWARE_DEVICE_PATH,\r
+ HW_PCI_DP,\r
+ DevPathPci\r
+ },
+ {
+ HARDWARE_DEVICE_PATH,\r
+ HW_PCCARD_DP,\r
+ DevPathPccard\r
+ },
+ {
+ HARDWARE_DEVICE_PATH,\r
+ HW_MEMMAP_DP,\r
+ DevPathMemMap\r
+ },
+ {
+ HARDWARE_DEVICE_PATH,\r
+ HW_VENDOR_DP,\r
+ DevPathVendor\r
+ },
+ {
+ HARDWARE_DEVICE_PATH,\r
+ HW_CONTROLLER_DP,\r
+ DevPathController\r
+ },
+ {
+ ACPI_DEVICE_PATH,\r
+ ACPI_DP,\r
+ DevPathAcpi\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_ATAPI_DP,\r
+ DevPathAtapi\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_SCSI_DP,\r
+ DevPathScsi\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_FIBRECHANNEL_DP,\r
+ DevPathFibre\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_1394_DP,\r
+ DevPath1394\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_USB_DP,\r
+ DevPathUsb\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_USB_CLASS_DP,\r
+ DevPathUsbClass\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_I2O_DP,\r
+ DevPathI2O\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_MAC_ADDR_DP,\r
+ DevPathMacAddr\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_IPv4_DP,\r
+ DevPathIPv4\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_IPv6_DP,\r
+ DevPathIPv6\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_INFINIBAND_DP,\r
+ DevPathInfiniBand\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_UART_DP,\r
+ DevPathUart\r
+ },
+ {
+ MESSAGING_DEVICE_PATH,\r
+ MSG_VENDOR_DP,\r
+ DevPathVendor\r
+ },
+ {
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_HARDDRIVE_DP,\r
+ DevPathHardDrive\r
+ },
+ {
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_CDROM_DP,\r
+ DevPathCDROM\r
+ },
+ {
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_VENDOR_DP,\r
+ DevPathVendor\r
+ },
+ {
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_FILEPATH_DP,\r
+ DevPathFilePath\r
+ },
+ {
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_PROTOCOL_DP,\r
+ DevPathMediaProtocol\r
+ },
+\r
+#if (EFI_SPECIFICATION_VERSION < 0x00020000)\r
+ {
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_FV_FILEPATH_DP,\r
+ DevPathFvFilePath\r
+ },
+#endif\r
+\r
+ {
+ BBS_DEVICE_PATH,\r
+ BBS_BBS_DP,\r
+ DevPathBssBss\r
+ },
+ {
+ END_DEVICE_PATH_TYPE,\r
+ END_INSTANCE_DEVICE_PATH_SUBTYPE,\r
+ DevPathEndInstance\r
+ },
+ {
+ 0,\r
+ 0,\r
+ NULL\r
+ }
+};\r
+\r
+CHAR16 *\r
+DevicePathToStr (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+/*++\r
+\r
+ Turns the Device Path into a printable string. Allcoates\r
+ the string from pool. The caller must SafeFreePool the returned\r
+ string.\r
+\r
+--*/\r
+{\r
+ POOL_PRINT Str;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
+ VOID (*DumpNode) (POOL_PRINT *, VOID *);\r
+\r
+ UINTN Index;\r
+ UINTN NewSize;\r
+\r
+ ZeroMem (&Str, sizeof (Str));\r
+\r
+ if (DevPath == NULL) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Unpacked the device path\r
+ //\r
+ DevPath = BdsLibUnpackDevicePath (DevPath);\r
+ ASSERT (DevPath);\r
+\r
+ //\r
+ // Process each device path node\r
+ //\r
+ DevPathNode = DevPath;\r
+ while (!IsDevicePathEnd (DevPathNode)) {\r
+ //\r
+ // Find the handler to dump this device path node\r
+ //\r
+ DumpNode = NULL;\r
+ for (Index = 0; DevPathTable[Index].Function; Index += 1) {\r
+\r
+ if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&\r
+ DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType\r
+ ) {\r
+ DumpNode = DevPathTable[Index].Function;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // If not found, use a generic function\r
+ //\r
+ if (!DumpNode) {\r
+ DumpNode = DevPathNodeUnknown;\r
+ }\r
+ //\r
+ // Put a path seperator in if needed\r
+ //\r
+ if (Str.len && DumpNode != DevPathEndInstance) {\r
+ CatPrint (&Str, L"/");\r
+ }\r
+ //\r
+ // Print this node of the device path\r
+ //\r
+ DumpNode (&Str, DevPathNode);\r
+\r
+ //\r
+ // Next device path node\r
+ //\r
+ DevPathNode = NextDevicePathNode (DevPathNode);\r
+ }\r
+ //\r
+ // Shrink pool used for string allocation\r
+ //\r
+ gBS->FreePool (DevPath);\r
+\r
+Done:\r
+ NewSize = (Str.len + 1) * sizeof (CHAR16);\r
+ Str.str = ReallocatePool (Str.str, NewSize, NewSize);\r
+ ASSERT (Str.str != NULL);\r
+ Str.str[Str.len] = 0;\r
+ return Str.str;\r
+}\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+LibDuplicateDevicePathInstance (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Function creates a device path data structure that identically matches the \r
+ device path passed in.\r
+\r
+Arguments:\r
+\r
+ DevPath - A pointer to a device path data structure.\r
+\r
+Returns:\r
+\r
+ The new copy of DevPath is created to identically match the input. \r
+ Otherwise, NULL is returned.\r
+\r
+--*/\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevPath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
+ EFI_DEVICE_PATH_PROTOCOL *Temp;\r
+ UINTN Size;\r
+\r
+ //\r
+ // get the size of an instance from the input\r
+ //\r
+ Temp = DevPath;\r
+ DevicePathInst = GetNextDevicePathInstance (&Temp, &Size);\r
+\r
+ //\r
+ // Make a copy\r
+ //\r
+ NewDevPath = NULL;\r
+ if (Size) {\r
+ NewDevPath = AllocateZeroPool (Size);\r
+ ASSERT (NewDevPath != NULL);\r
+ }\r
+\r
+ if (NewDevPath) {\r
+ CopyMem (NewDevPath, DevicePathInst, Size);\r
+ }\r
+\r
+ return NewDevPath;\r
+}\r