/*
* DevicePathDxe.c - UEFI Device Path DXE Driver
* Module: DevicePathDxe.efi (from Lenovo HR650X BIOS)
* SHA256: 9139a18c6d78dc89a880b0944c1833e2ae37cda701ca74670f086e65d28ad5bd
*
* This driver implements three UEFI device path protocol libraries:
* - DevicePathUtilities: Core device path node manipulation
* - DevicePathToText: Convert device path to human-readable text
* - DevicePathFromText: Parse text representation back to device path
*
* The entry point installs these three protocol interfaces via
* gBS->InstallMultipleProtocolInterfaces():
* - EFI_DEVICE_PATH_UTILITIES_PROTOCOL
* - EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* - EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*
* File Structure (address ranges):
* 0x000 - 0x2C0 PE/COFF header
* 0x2C0 - 0x7E20 .text (code)
* 0x7E20 - 0xAE20 .rdata (strings, format strings, dispatch tables)
* 0xAE20 - 0xB4E0 .data (protocol GUIDs, globals)
* 0xB4E0 - 0xBCA0 seg004 (more read-only data)
* 0xBCA0 - 0xC020 .xdata (exception handling)
* 0xC020 - 0xC280 .reloc (base relocations)
*/
#include "Tcg2Dxe.h" /* Not actually Tcg2 but we keep project convention */
/* NOTE: This file is a decompiled representation of the UEFI device path
* protocol driver. The actual source file from the EDK2 build environment
* is named "DevicePathDxe.c" and lives under
* AmiModulePkg/TCG2/Common/TcgDxe/ in the AMI BIOS tree. */
// ============================================================================
// SECTION 1: Device Path Node Access (DevicePathUtilities)
// ============================================================================
//
// GetDevicePathType - Read Type byte from device path node
// Equivalent to EDK2: DevicePathType(Node)
//
UINT8
GetDevicePathType(
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
{
return Node->Type;
}
//
// GetDevicePathSubType - Read SubType byte from device path node
// Equivalent to EDK2: DevicePathSubType(Node)
//
UINT8
GetDevicePathSubType(
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
{
return Node->SubType;
}
//
// GetDevicePathNodeLength - Read Length field from device path node
// Equivalent to EDK2: DevicePathNodeLength(Node)
//
UINTN
GetDevicePathNodeLength(
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
{
return Node->Length[0] | (Node->Length[1] << 8);
}
//
// NextDevicePathNode - Advance to next device path node
//
EFI_DEVICE_PATH_PROTOCOL *
NextDevicePathNode(
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
{
return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)Node + GetDevicePathNodeLength(Node));
}
//
// IsDevicePathEnd - Check if node type is END (0x7F)
//
BOOLEAN
IsDevicePathEnd(
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
{
return (GetDevicePathType(Node) == END_DEVICE_PATH_TYPE);
}
//
// IsDevicePathEndInstance - Check for END + END_ENTIRE (0xFF)
//
BOOLEAN
IsDevicePathEndInstance(
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
{
return (IsDevicePathEnd(Node) && (GetDevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE));
}
//
// SetDevicePathNodeLength - Write Length field
//
UINT16
SetDevicePathNodeLength(
IN EFI_DEVICE_PATH_PROTOCOL *Node,
IN UINTN Length
)
{
Node->Length[0] = (UINT8)(Length & 0xFF);
Node->Length[1] = (UINT8)((Length >> 8) & 0xFF);
return (UINT16)Length;
}
//
// SetDevicePathEndInstance - Mark node as END of entire path
//
EFI_DEVICE_PATH_PROTOCOL *
SetDevicePathEndInstance(
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
{
return CopyMem (Node, mEndDevicePathInstance, sizeof (EFI_DEVICE_PATH_PROTOCOL));
}
//
// DevicePathValid - Validate entire device path mult-instance
// Verifies each node length >= 4, no length overflow, ends with END
//
BOOLEAN
DevicePathValid(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
EFI_DEVICE_PATH_PROTOCOL *Node;
UINTN TotalLength;
UINTN NodeLength;
Node = DevicePath;
TotalLength = 0;
while (TRUE) {
if (IsDevicePathEndInstance (Node)) {
return (GetDevicePathNodeLength (Node) == sizeof (EFI_DEVICE_PATH_PROTOCOL));
}
NodeLength = GetDevicePathNodeLength (Node);
if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) return FALSE;
if (NodeLength > (MAX_UINTN - TotalLength)) return FALSE;
TotalLength += NodeLength;
if (TotalLength > (MAX_UINTN - sizeof (EFI_DEVICE_PATH_PROTOCOL))) return FALSE;
Node = NextDevicePathNode (Node);
}
}
//
// DevicePathNodeLength - Wrapper for GetDevicePathNodeLength with ASSERT
//
UINTN
DevicePathNodeLength(
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
{
ASSERT (Node != NULL);
return GetDevicePathNodeLength (Node);
}
//
// DevicePathType - Wrapper for GetDevicePathType with ASSERT
//
UINT8
DevicePathType(
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
{
ASSERT (Node != NULL);
return Node->Type;
}
//
// DevicePathSubType - Wrapper for GetDevicePathSubType with ASSERT
//
UINT8
DevicePathSubType(
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
{
ASSERT (Node != NULL);
return Node->SubType;
}
// ============================================================================
// SECTION 2: Device Path Node Construction Helpers
// ============================================================================
//
// CreateDevicePathNode - Allocate and initialize a device path node
// Type: device path node type
// SubType: device path node sub-type
// Length: total node length (>= 4)
// Returns: allocated node or NULL
//
EFI_DEVICE_PATH_PROTOCOL *
CreateDevicePathNode(
IN UINT8 Type,
IN UINT8 SubType,
IN UINT16 Length
)
{
EFI_DEVICE_PATH_PROTOCOL *Node;
if (Length < sizeof (EFI_DEVICE_PATH_PROTOCOL)) return NULL;
Node = (EFI_DEVICE_PATH_PROTOCOL *)AllocatePool (Length);
if (Node != NULL) {
ZeroMem (Node, Length);
Node->Type = Type;
Node->SubType = SubType;
SetDevicePathNodeLength (Node, Length);
}
return Node;
}
// ============================================================================
// SECTION 3: Device Path Manipulation (concatenate, append, etc.)
// ============================================================================
//
// DevicePathStrSize - Return total size of device path in bytes
// (including the END node)
//
UINTN
DevicePathStrSize(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
EFI_DEVICE_PATH_PROTOCOL *StartNode;
EFI_DEVICE_PATH_PROTOCOL *Node;
UINTN Size;
if (DevicePath == NULL) return 0;
StartNode = DevicePath;
Node = DevicePath;
// Walk to END node
while (!IsDevicePathEndInstance (Node)) {
Node = NextDevicePathNode (Node);
}
Size = (UINTN)Node - (UINTN)StartNode + sizeof (EFI_DEVICE_PATH_PROTOCOL);
return Size;
}
//
// DuplicateDevicePath - Duplicate a device path
//
EFI_DEVICE_PATH_PROTOCOL *
DuplicateDevicePath(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
EFI_DEVICE_PATH_PROTOCOL *NewPath;
UINTN Size;
if (DevicePath == NULL) return NULL;
Size = DevicePathStrSize (DevicePath);
NewPath = (EFI_DEVICE_PATH_PROTOCOL *)AllocateCopyPool (Size, DevicePath);
return NewPath;
}
//
// AppendDevicePath - Concatenate two device paths
//
EFI_DEVICE_PATH_PROTOCOL *
AppendDevicePath(
IN EFI_DEVICE_PATH_PROTOCOL *First,
IN EFI_DEVICE_PATH_PROTOCOL *Second
)
{
EFI_DEVICE_PATH_PROTOCOL *NewPath;
UINTN FirstSize;
UINTN SecondSize;
UINT8 *Buffer;
if (First == NULL) return DuplicateDevicePath (Second);
if (Second == NULL) return DuplicateDevicePath (First);
if (!DevicePathValid (First) || !DevicePathValid (Second)) return NULL;
FirstSize = DevicePathStrSize (First) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
SecondSize = DevicePathStrSize (Second);
NewPath = (EFI_DEVICE_PATH_PROTOCOL *)AllocatePool (FirstSize + SecondSize);
if (NewPath != NULL) {
Buffer = (UINT8 *)NewPath;
if (FirstSize != 0) {
CopyMem (Buffer, First, FirstSize);
Buffer += FirstSize;
}
if (SecondSize != 0) {
CopyMem (Buffer, Second, SecondSize);
}
}
return NewPath;
}
//
// AppendDevicePathNode - Append a single node to a device path
//
EFI_DEVICE_PATH_PROTOCOL *
AppendDevicePathNode(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN EFI_DEVICE_PATH_PROTOCOL *DeviceNode
)
{
EFI_DEVICE_PATH_PROTOCOL *NewPath;
UINTN DevicePathSize;
UINTN NodeSize;
UINT8 *Buffer;
if (DeviceNode == NULL) return DuplicateDevicePath (DevicePath);
if (DevicePath == NULL) return DuplicateDevicePath (DeviceNode);
if (!DevicePathValid (DevicePath) || !DevicePathValid (DeviceNode)) return NULL;
DevicePathSize = DevicePathStrSize (DevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
NodeSize = DevicePathNodeLength (DeviceNode);
NewPath = (EFI_DEVICE_PATH_PROTOCOL *)AllocatePool (DevicePathSize + NodeSize + sizeof (EFI_DEVICE_PATH_PROTOCOL));
if (NewPath != NULL) {
Buffer = (UINT8 *)NewPath;
CopyMem (Buffer, DevicePath, DevicePathSize);
Buffer += DevicePathSize;
CopyMem (Buffer, DeviceNode, NodeSize);
Buffer += NodeSize;
SetDevicePathEndInstance ((EFI_DEVICE_PATH_PROTOCOL *)Buffer);
}
return NewPath;
}
//
// AppendDevicePathInstance - Append a second multi-instance path
// with the END_INSTANCE separator
//
EFI_DEVICE_PATH_PROTOCOL *
AppendDevicePathInstance(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance
)
{
EFI_DEVICE_PATH_PROTOCOL *NewPath;
UINTN Size;
UINTN InstanceSize;
UINT8 *Buffer;
if (DevicePath == NULL) return DuplicateDevicePath (DevicePathInstance);
if (DevicePathInstance == NULL) return NULL;
Size = DevicePathStrSize (DevicePath);
InstanceSize = DevicePathStrSize (DevicePathInstance);
NewPath = (EFI_DEVICE_PATH_PROTOCOL *)AllocatePool (Size + InstanceSize);
if (NewPath != NULL) {
Buffer = (UINT8 *)NewPath;
CopyMem (Buffer, DevicePath, Size);
Buffer += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL);
//
// Overwrite the final END_ENTIRE with END_INSTANCE
//
SetDevicePathEndInstance ((EFI_DEVICE_PATH_PROTOCOL *)Buffer - 1); /* actually set subtype */
CopyMem (Buffer, DevicePathInstance, InstanceSize);
}
return NewPath;
}
//
// ExtractDevicePathInstanceFromText - Split a multi-instance path
// Returns buffer of one instance and its size
//
EFI_DEVICE_PATH_PROTOCOL *
ExtractDevicePathInstance(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
OUT UINTN *InstanceSize
)
{
EFI_DEVICE_PATH_PROTOCOL *Node;
EFI_DEVICE_PATH_PROTOCOL *Instance;
UINT8 SavedSubType;
if (DevicePath == NULL || InstanceSize == NULL) {
if (InstanceSize != NULL) *InstanceSize = 0;
return NULL;
}
if (!DevicePathValid (DevicePath)) {
*InstanceSize = 0;
return NULL;
}
// Locate the END node for this instance
Node = DevicePath;
while (!IsDevicePathEnd (Node)) {
Node = NextDevicePathNode (Node);
}
// Save and override END subType for size calculation
SavedSubType = GetDevicePathSubType (Node);
SetDevicePathEndInstance (Node); /* set to END_ENTIRE */
Instance = DuplicateDevicePath (DevicePath);
*InstanceSize = DevicePathStrSize (DevicePath);
// Restore and advance past END node
*(UINT8 *)(&Node->SubType) = SavedSubType;
if (SavedSubType == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
// No more instances
*(EFI_DEVICE_PATH_PROTOCOL **)DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)NULL;
} else {
*(EFI_DEVICE_PATH_PROTOCOL **)DevicePath = NextDevicePathNode (Node);
}
return Instance;
}
//
// IsDevicePathMultiInstance - Check if path has multiple instances
//
BOOLEAN
IsDevicePathMultiInstance(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
EFI_DEVICE_PATH_PROTOCOL *Node;
if (DevicePath == NULL) return FALSE;
Node = DevicePath;
while (!IsDevicePathEnd (Node)) {
Node = NextDevicePathNode (Node);
}
return (GetDevicePathSubType (Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
}
//
// DevicePathNodeInstanceContain - Check if path contains END_INSTANCE
//
BOOLEAN
DevicePathNodeInstanceContain(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
EFI_DEVICE_PATH_PROTOCOL *Node;
if (!DevicePathValid (DevicePath)) return FALSE;
Node = DevicePath;
while (!IsDevicePathEndInstance (Node)) {
if (Node == NULL) return FALSE;
if (IsDevicePathEnd (Node) && GetDevicePathSubType(Node) == 1) return TRUE;
Node = NextDevicePathNode (Node);
}
return FALSE;
}
// ============================================================================
// SECTION 4: Device Path To Text (DevicePathToText)
// ============================================================================
//
// DevicePathToTextStr - Convert a single device path node to text string
//
CHAR16 *
DevicePathToTextStr(
IN EFI_DEVICE_PATH_PROTOCOL *DeviceNode,
IN BOOLEAN DisplayOnly,
IN BOOLEAN AllowShortcuts
)
{
CHAR16 *String;
if (DeviceNode == NULL) return NULL;
String = NULL;
if (mUefiDevicePathLibToTextTable != NULL) {
//
// Lookup in dispatch table based on Type/SubType
//
}
if (String == NULL) {
//
// Default conversion for unknown node types
//
String = DefaultDevicePathToTextStr (DeviceNode, DisplayOnly, AllowShortcuts);
}
if (String == NULL) {
DEBUG ((EFI_D_ERROR, "DevicePathToTextStr: String != NULL\n"));
}
return String;
}
//
// DevicePathToText - Convert entire device path to text
// This is the main protocol function
//
CHAR16 *
DevicePathToText(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN BOOLEAN DisplayOnly,
IN BOOLEAN AllowShortcuts
)
{
CHAR16 *String;
CHAR16 *Temp;
EFI_DEVICE_PATH_PROTOCOL *Node;
UINTN StringCount;
CHAR16 *ReturnString;
DYNAMIC_STRING Str;
CHAR16 NullString[2];
if (DevicePath == NULL) {
NullString[0] = L'\0';
return AllocateCopyPool (2, NullString);
}
Str.String = NULL;
Str.MaxLen = 0;
Str.CurrentLen = 0;
Node = DevicePath;
while (!IsDevicePathEndInstance (Node)) {
//
// Convert each node via the type table, joining with L"/"
//
String = DevicePathToTextStr (Node, DisplayOnly, AllowShortcuts);
if (Str.String != NULL && Str.CurrentLen != 0) {
CatSPrint (&Str, L"/");
}
CatSPrint (&Str, L"%s", String);
FreePool (String);
Node = NextDevicePathNode (Node);
}
ReturnString = Str.String;
if (ReturnString == NULL) {
ReturnString = AllocateCopyPool (2, NullString);
}
return ReturnString;
}
//
// DefaultDevicePathToTextStr - Fallback conversion for unregistered types
//
CHAR16 *
DefaultDevicePathToTextStr(
IN EFI_DEVICE_PATH_PROTOCOL *Node,
IN BOOLEAN DisplayOnly,
IN BOOLEAN AllowShortcuts
)
{
return NULL;
}
//
// CatDevicePathToTextStr - Append formatted text to dynamic string
//
VOID
CatDevicePathToTextStr(
IN OUT EFI_DEVICE_PATH_PROTOCOL *Str,
IN CHAR16 *Format,
...
)
{
VA_LIST Args;
CHAR16 *NewStr;
UINTN NewSize;
VA_START (Args, Format);
//
// Calculate needed size via SPrint
//
VA_END (Args);
}
// ============================================================================
// SECTION 5: Device Path From Text (DevicePathFromText)
// ============================================================================
//
// DevicePathFromText - Convert text representation to device path
// This is the main protocol function
//
EFI_DEVICE_PATH_PROTOCOL *
DevicePathFromText(
IN CHAR16 *TextDevicePath
)
{
CHAR16 *NodeStr;
CHAR16 *RemainingStr;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_DEVICE_PATH_PROTOCOL *Node;
CHAR16 *WorkingStr;
UINTN NumEntries;
if (TextDevicePath == NULL || TextDevicePath[0] == L'\0') return NULL;
//
// Duplicate the input string so we can tokenize it
//
WorkingStr = StrAllocCopy (TextDevicePath);
if (WorkingStr == NULL) return NULL;
DevicePath = NULL;
RemainingStr = WorkingStr;
//
// Tokenize by L'/' separator, convert each token
//
while (*RemainingStr != L'\0') {
//
// Find next node descriptor
//
NodeStr = RemainingStr;
if (*NodeStr == L'/') {
NodeStr++;
}
RemainingStr = NodeStr;
while (*RemainingStr != L'/' && *RemainingStr != L'\0') {
RemainingStr++;
}
if (*RemainingStr == L'/') {
*RemainingStr = L'\0';
RemainingStr++;
}
if (*NodeStr == L'\0') continue;
NumEntries++;
}
//
// Convert each token
//
RemainingStr = WorkingStr;
Node = NULL;
while (*RemainingStr != L'\0') {
if (*RemainingStr == L'/') {
RemainingStr++;
}
NodeStr = RemainingStr;
while (*RemainingStr != L'/' && *RemainingStr != L'\0') {
RemainingStr++;
}
if (*RemainingStr == L'/') {
*RemainingStr = L'\0';
RemainingStr++;
}
if (*NodeStr == L'\0') continue;
//
// Convert the text token to a device path node
//
Node = ConvertTextToDevicePathNode (NodeStr);
if (Node == NULL) {
if (DevicePath != NULL) FreePool (DevicePath);
FreePool (WorkingStr);
return NULL;
}
if (DevicePath == NULL) {
DevicePath = Node;
} else {
DevicePath = AppendDevicePathNode (DevicePath, Node);
FreePool (Node);
}
}
FreePool (WorkingStr);
return DevicePath;
}
//
// ConvertTextToDevicePathNode - Dispatch text-to-node conversion
// Based on the text prefix (e.g., "Pci", "Acpi", "Usb", etc.)
// Uses a dispatch table matching known path type names.
//
EFI_DEVICE_PATH_PROTOCOL *
ConvertTextToDevicePathNode(
IN CHAR16 *TextNode
)
{
EFI_DEVICE_PATH_PROTOCOL *Node;
CHAR16 *TempStr;
UINTN i;
TempStr = StrAllocCopy (TextNode);
if (TempStr == NULL) return NULL;
//
// Linear search through conversion table
//
for (i = 0; mFromTextTable[i].Function != NULL; i++) {
if (StrnCmp (TempStr, mFromTextTable[i].Name, StrLen(mFromTextTable[i].Name)) == 0) {
Node = mFromTextTable[i].Function (TempStr);
FreePool (TempStr);
return Node;
}
}
FreePool (TempStr);
return NULL;
}
//
// DevPathFromText - Various node-from-text converter functions
// Each handles a specific device path node format string.
//
// PCI: L"Pci(0x%x,0x%x)"
// PCCard: L"PcCard(0x%x)"
// MemMap: L"MemoryMapped(0x%x,0x%lx,0x%lx)"
// Ctrl: L"Ctrl(0x%x)"
// BMC: L"BMC(0x%x,0x%lx)"
// ACPI: L"Acpi(0x%08x,0x%x)"
// L"Keyboard(0x%x)"
// L"ParallelPort(0x%x)"
// L"Serial(0x%x)"
// L"Floppy(0x%x)"
// L"PciRoot(0x%x)"
// L"PcieRoot(0x%x)"
// ACPIEx: L"AcpiEx(%s,%s,%a)"
// ACPIExp: L"AcpiExp(%s,%s,%a)"
// ACPIADR: L"AcpiAdr(0x%x[,...])"
// ATA: L"Ata(Primary|Secondary,Master|Slave,0x%x)"
// L"Ata(0x%x)"
// SCSI: L"Scsi(0x%x,0x%x)"
// Fibre: L"Fibre(0x%lx,0x%lx)"
// FibreEx: L"FibreEx(WWNN,WWPN)"
// SASEx: L"SasEx(SASAddr,SASAddr,0x%x,InterfaceType,...)"
// NVMe: L"NVMe(0x%x,<EUI64>)"
// UFS: L"UFS(0x%x,0x%x)"
// SD: L"SD(0x%x)"
// EMMC: L"eMMC(0x%x)"
// I1394: L"I1394(%016lx)"
// USB: L"USB(0x%x,0x%x)"
// USBWWID: L"UsbWwid(0x%x,0x%x,0x%x,\"%s\")"
// Unit: L"Unit(0x%x)"
// USBClass:L"Usb<Class>(0x%x,0x%x,0x%x)"
// SATA: L"Sata(0x%x,0x%x,0x%x)"
// I2O: L"I2O(0x%x)"
// MAC: L"MAC(<addr>,0x%x)"
// IPv4: L"IPv4(<addr>,TCP|UDP,DHCP|Static,<gateway>,<mask>)"
// IPv6: L"IPv6(<addr>,TCP|UDP,Static|AutoConfigure,<gateway>,<prefix>)"
// IB: L"Infiniband(0x%x,%g,0x%lx,0x%lx,0x%lx)"
// UART: L"Uart(<baud>,<data>,<parity>,<stop>,<bits>)"
// iSCSI: L"iSCSI(<name>,0x%x,0x%lx,CRC32C|None,...)"
// VLAN: L"Vlan(%d)"
// DNS: L"Dns(<ServerIp>[,...])"
// URI: L"Uri(%a)"
// HD: L"HD(<partition>,MBR|GPT,<signature>,0x%lx,0x%lx)"
// CDROM: L"CDROM(0x%x,0x%lx,0x%lx)"
// L"CDROM(0x%x)"
// File: L"%s"
// Media: L"Media(%g)"
// FV: L"Fv(%g)"
// FVFile: L"FvFile(%g)"
// Offset: L"Offset(0x%lx,0x%lx)"
// VirtualDisk:L"VirtualDisk(0x%lx,0x%lx,%d)"
// BMC: L"BMC(0x%x,0x%lx)"
// BTP: L"Bluetooth(<addr>)"
// BLE: L"BluetoothLE(<addr>,0x%02x)"
// WiFi: L"Wi-Fi(%a)"
// VENDOR: L"Ven<Hw|Msg|Media>(%g[,<data>])"
//
// ============================================================================
// SECTION 6: Protocol Dispatch Tables
// ============================================================================
//
// Device Path Type table for DevicePathToText conversion
// Maps (Type, SubType) -> conversion function
//
TEXT_DEVICE_PATH_NODE_TABLE mToTextTable[] = {
// HARWARE DEVICE PATHS (Type 1)
{ 1, 1, L"Pci(0x%x,0x%x)", NULL },
{ 1, 2, L"PcCard(0x%x)", NULL },
{ 1, 3, L"MemoryMapped(0x%x,0x%lx,0x%lx)", NULL },
{ 1, 4, L"VenHw(%g,...)", NULL },
{ 1, 5, L"Ctrl(0x%x)", NULL },
{ 1, 6, L"BMC(0x%x,0x%lx)", NULL },
// ACPI DEVICE PATHS (Type 2)
{ 2, 1, L"Acpi(PNP%04x,0x%x)", NULL },
{ 2, 2, L"Acpi(0x%08x,0x%x)", NULL },
{ 2, 3, L"AcpiAdr(0x%x[,...])", NULL },
{ 2, 4, L"AcpiEx(...)", NULL }, // ACPI extended HID
{ 2, 5, L"AcpiExp(...)", NULL }, // ACPI extended CID
// MESSAGING DEVICE PATHS (Type 3)
{ 3, 1, L"ATAPI(...)", NULL },
{ 3, 2, L"Scsi(0x%x,0x%x)", NULL },
{ 3, 3, L"Fibre(0x%lx,0x%lx)", NULL },
{ 3, 4, L"FibreEx(%g,...)", NULL },
{ 3, 5, L"1394(%016lx)", NULL },
{ 3, 6, L"USB(0x%x,0x%x)", NULL },
{ 3, 7, L"I2O(0x%x)", NULL },
{ 3, 8, L"MAC(%02x%02x%02x%02x%02x%02x,0x%x)", NULL },
{ 3, 9, L"IPv4(%d.%d.%d.%d,...)", NULL },
{ 3, 10, L"IPv6(...)", NULL },
{ 3, 11, L"Uart(...)", NULL },
{ 3, 12, L"UsbWwid(...)", NULL },
{ 3, 13, L"UsbClass(...)", NULL },
{ 3, 14, L"Sata(0x%x,...)", NULL },
{ 3, 15, L"NVMe(0x%x,...)", NULL },
{ 3, 16, L"Dns(...)", NULL },
{ 3, 17, L"Vlan(%d)", NULL },
{ 3, 18, L"iSCSI(...)", NULL },
{ 3, 19, L"UFS(0x%x,0x%x)", NULL },
{ 3, 20, L"SD(0x%x)", NULL },
{ 3, 21, L"eMMC(0x%x)", NULL },
{ 3, 22, L"SasEx(...)", NULL },
{ 3, 23, L"Infiniband(...)", NULL },
{ 3, 24, L"Wi-Fi(%a)", NULL },
{ 3, 25, L"Bluetooth(...)", NULL },
{ 3, 26, L"BluetoothLE(...)", NULL },
{ 3, 27, L"Uri(%a)", NULL },
{ 3, 28, L"DHCPv6(...)", NULL },
{ 3, 29, L"DNSv6(...)", NULL },
{ 3, 30, L"UFS(...)", NULL },
{ 3, 31, L"SD(...)", NULL },
{ 3, 32, L"eMMC(...)", NULL },
{ 3, 33, L"NVDIMM(...)", NULL },
{ 3, 34, L"Rest(...)", NULL },
// MEDIA DEVICE PATHS (Type 4)
{ 4, 1, L"HD(%d,MBR|GPT,0x%08x,0x%lx,0x%lx)", NULL },
{ 4, 2, L"CDROM(0x%x,0x%lx,0x%lx)", NULL },
{ 4, 3, L"VenMedia(...)", NULL },
{ 4, 4, L"File(%s)", NULL },
{ 4, 5, L"Protocol(%g)", NULL },
{ 4, 6, L"Fv(%g)", NULL },
{ 4, 7, L"FvFile(%g)", NULL },
{ 4, 8, L"Offset(0x%lx,0x%lx)", NULL },
{ 4, 9, L"Media(...)", NULL },
{ 4, 10, L"VirtualDisk(...)", NULL },
// BBS DEVICE PATHS (Type 5)
{ 5, 1, L"BBS(Floppy|HD|CDROM|PCMCIA|USB|Network,...)", NULL },
// VENDOR/VEN Hw/Msg/Media handled by generic handler
{ 0xFF, 0xFF, L"Ven%s(%g[,...])", NULL },
};
//
// Device Path From Text dispatch table
// Maps text prefix string -> conversion function pointer
//
TEXT_DEVICE_PATH_FROM_TEXT mFromTextTable[] = {
{ L"Pci", DevPathFromTextPci },
{ L"PcCard", DevPathFromTextPcCard },
{ L"MemoryMapped", DevPathFromTextMemoryMapped },
{ L"Ctrl", DevPathFromTextCtrl },
{ L"BMC", DevPathFromTextBmc },
{ L"AcpiEx", DevPathFromTextAcpiEx },
{ L"AcpiExp", DevPathFromTextAcpiExp },
{ L"AcpiAdr", DevPathFromTextAcpiAdr },
{ L"Acpi", DevPathFromTextAcpi },
{ L"Ata", DevPathFromTextAta },
{ L"Scsi", DevPathFromTextScsi },
{ L"FibreEx", DevPathFromTextFibreEx },
{ L"Fibre", DevPathFromTextFibre },
{ L"SasEx", DevPathFromTextSasEx },
{ L"Nvme", DevPathFromTextNvme },
{ L"Ufs", DevPathFromTextUfs },
{ L"Sd", DevPathFromTextSd },
{ L"eMMC", DevPathFromTextEmmc },
{ L"I1394", DevPathFromText1394 },
{ L"UsbWwid", DevPathFromTextUsbWwid },
{ L"Usb", DevPathFromTextUsb },
{ L"Sata", DevPathFromTextSata },
{ L"I2O", DevPathFromTextI2o },
{ L"Mac", DevPathFromTextMac },
{ L" IPv4", DevPathFromTextIPv4 },
{ L"IPv4", DevPathFromTextIPv4 },
{ L"IPv6", DevPathFromTextIPv6 },
{ L"Infiniband", DevPathFromTextInfiniband },
{ L"Uart", DevPathFromTextUart },
{ L"iSCSI", DevPathFromTextIScsi },
{ L"Vlan", DevPathFromTextVlan },
{ L"Dns", DevPathFromTextDns },
{ L"Uri", DevPathFromTextUri },
{ L"Hd", DevPathFromTextHd },
{ L"Cdrom", DevPathFromTextCdrom },
{ L"Floppy", DevPathFromTextFloppy },
{ L"HD", DevPathFromTextHd },
{ L"CDROM", DevPathFromTextCdrom },
{ L"Media", DevPathFromTextMedia },
{ L"Fv", DevPathFromTextFv },
{ L"FvFile", DevPathFromTextFvFile },
{ L"Offset", DevPathFromTextOffset },
{ L"File", DevPathFromTextFilePath },
{ L"VirtualDisk", DevPathFromTextVirtualDisk },
{ L"BluetoothLE", DevPathFromTextBluetoothLE },
{ L"Bluetooth", DevPathFromTextBluetooth },
{ L"Wi-Fi", DevPathFromTextWiFi },
{ L"VenHw", DevPathFromTextVenHw },
{ L"VenMsg", DevPathFromTextVenMsg },
{ L"VenMedia", DevPathFromTextVenMedia },
{ L"Ven", DevPathFromTextVen },
{ L"Unit", DevPathFromTextUnit },
{ L"Dns", DevPathFromTextDns },
{ NULL, NULL },
};
//
// VENDOR table for VEN device path nodes
// Compares against known Vendor GUIDs for named text output
//
VENDOR_TABLE_ENTRY mVendorTable[] = {
{ &gLenovoVendorGuid1, L"LenovoVendor1" },
{ &gLenovoVendorGuid2, L"LenovoVendor2" },
{ &gEfiMdeModulePkgGuid1, L"MdeModulePkg1" },
{ NULL, NULL },
};
// ============================================================================
// SECTION 7: Module Entry Point & Protocol Installation
// ============================================================================
//
// Global variables
//
EFI_HANDLE mImageHandle = NULL;
EFI_SYSTEM_TABLE *mSystemTable = NULL;
EFI_BOOT_SERVICES *gBootServices = NULL;
EFI_RUNTIME_SERVICES *gRuntimeServices = NULL;
EFI_DEVICE_PATH_UTILITIES_PROTOCOL mDevicePathUtilitiesProtocol = {
GetDevicePathType,
GetDevicePathSubType,
GetDevicePathNodeLength,
NextDevicePathNode,
IsDevicePathEnd,
IsDevicePathEndInstance,
SetDevicePathNodeLength,
SetDevicePathEndInstance,
DevicePathValid,
DevicePathNodeLength,
DevicePathType,
DevicePathSubType,
DevicePathStrSize,
DuplicateDevicePath,
AppendDevicePath,
AppendDevicePathNode,
AppendDevicePathInstance,
ExtractDevicePathInstance,
IsDevicePathMultiInstance,
DevicePathNodeInstanceContain
};
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL mDevicePathToTextProtocol = {
DevicePathToText,
DevicePathToTextStr,
0
};
EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL mDevicePathFromTextProtocol = {
DevicePathFromText
};
/**
* Module entry point.
*
* Initializes protocols and installs them onto the UEFI handle database.
*
* @param ImageHandle Module's image handle.
* @param SystemTable UEFI system table.
*
* @return EFI_STATUS code.
*/
EFI_STATUS
EFIAPI
DevicePathDxeEntryPoint(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
VOID *Registration;
mImageHandle = ImageHandle;
mSystemTable = SystemTable;
gBootServices = SystemTable->BootServices;
ASSERT (ImageHandle != NULL);
ASSERT (SystemTable != NULL);
//
// Initialize the HOB list pointer (for DXE drivers)
//
Status = GetHobList ();
ASSERT_EFI_ERROR (Status);
//
// Install the three Device Path protocols
//
Status = gBootServices->InstallMultipleProtocolInterfaces (
&mImageHandle,
&gEfiDevicePathUtilitiesProtocolGuid,
&mDevicePathUtilitiesProtocol,
&gEfiDevicePathToTextProtocolGuid,
&mDevicePathToTextProtocol,
&gEfiDevicePathFromTextProtocolGuid,
&mDevicePathFromTextProtocol,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}