Syncboot/gnu-efi/lib/dpath.c
Curle d588e232c4 Major overhaul of this branch.
This branch has been dedicated to purely the UEFI bootloader.
As such, all other code has been removed.

This code can be compiled with Visual Studio, gcc or llvm.
2019-07-17 21:10:29 +01:00

1261 lines
31 KiB
C

/*++
Copyright (c) 1998 Intel Corporation
Module Name:
dpath.c
Abstract:
MBR & Device Path functions
Revision History
2014/04 B.Burette - updated device path text representation, conforming to
UEFI specification 2.4 (dec. 2013). More specifically:
- § 9.3.5: added some media types ie. Sata()
- § 9.6.1.2: Acpi(PNP0A03,0) makes more sense when displayed as PciRoot(0)
- § 9.6.1.5: use commas (instead of '|') between option specific parameters
- § 9.6.1.6: hex values in device paths must be preceded by "0x" or "0X"
--*/
#include "lib.h"
#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
EFI_DEVICE_PATH *
DevicePathFromHandle (
IN EFI_HANDLE Handle
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH *DevicePath;
Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &DevicePathProtocol, (VOID*)&DevicePath);
if (EFI_ERROR(Status)) {
DevicePath = NULL;
}
return DevicePath;
}
EFI_DEVICE_PATH *
DevicePathInstance (
IN OUT EFI_DEVICE_PATH **DevicePath,
OUT UINTN *Size
)
{
EFI_DEVICE_PATH *Start, *Next, *DevPath;
UINTN Count;
DevPath = *DevicePath;
Start = DevPath;
if (!DevPath) {
return NULL;
}
//
// Check for end of device path type
//
for (Count = 0; ; Count++) {
Next = NextDevicePathNode(DevPath);
if (IsDevicePathEndType(DevPath)) {
break;
}
if (Count > 01000) {
//
// BugBug: Debug code to catch bogus device paths
//
DEBUG((D_ERROR, "DevicePathInstance: DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) - ((UINT8 *) Start) ));
DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start);
break;
}
DevPath = Next;
}
ASSERT (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE ||
DevicePathSubType(DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
//
// Set next position
//
if (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
Next = NULL;
}
*DevicePath = Next;
//
// Return size and start of device path instance
//
*Size = ((UINT8 *) DevPath) - ((UINT8 *) Start);
return Start;
}
UINTN
DevicePathInstanceCount (
IN EFI_DEVICE_PATH *DevicePath
)
{
UINTN Count, Size;
Count = 0;
while (DevicePathInstance(&DevicePath, &Size)) {
Count += 1;
}
return Count;
}
EFI_DEVICE_PATH *
AppendDevicePath (
IN EFI_DEVICE_PATH *Src1,
IN EFI_DEVICE_PATH *Src2
)
// Src1 may have multiple "instances" and each instance is appended
// Src2 is appended to each instance is Src1. (E.g., it's possible
// to append a new instance to the complete device path by passing
// it in Src2)
{
UINTN Src1Size, Src1Inst, Src2Size, Size;
EFI_DEVICE_PATH *Dst, *Inst;
UINT8 *DstPos;
//
// If there's only 1 path, just duplicate it
//
if (!Src1) {
ASSERT (!IsDevicePathUnpacked (Src2));
return DuplicateDevicePath (Src2);
}
if (!Src2) {
ASSERT (!IsDevicePathUnpacked (Src1));
return DuplicateDevicePath (Src1);
}
//
// Verify we're not working with unpacked paths
//
// ASSERT (!IsDevicePathUnpacked (Src1));
// ASSERT (!IsDevicePathUnpacked (Src2));
//
// Append Src2 to every instance in Src1
//
Src1Size = DevicePathSize(Src1);
Src1Inst = DevicePathInstanceCount(Src1);
Src2Size = DevicePathSize(Src2);
Size = Src1Size * Src1Inst + Src2Size;
Dst = AllocatePool (Size);
if (Dst) {
DstPos = (UINT8 *) Dst;
//
// Copy all device path instances
//
while ((Inst = DevicePathInstance (&Src1, &Size))) {
CopyMem(DstPos, Inst, Size);
DstPos += Size;
CopyMem(DstPos, Src2, Src2Size);
DstPos += Src2Size;
CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH));
DstPos += sizeof(EFI_DEVICE_PATH);
}
// Change last end marker
DstPos -= sizeof(EFI_DEVICE_PATH);
CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH));
}
return Dst;
}
EFI_DEVICE_PATH *
AppendDevicePathNode (
IN EFI_DEVICE_PATH *Src1,
IN EFI_DEVICE_PATH *Src2
)
// Src1 may have multiple "instances" and each instance is appended
// Src2 is a signal device path node (without a terminator) that is
// appended to each instance is Src1.
{
EFI_DEVICE_PATH *Temp, *Eop;
UINTN Length;
//
// Build a Src2 that has a terminator on it
//
Length = DevicePathNodeLength(Src2);
Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH));
if (!Temp) {
return NULL;
}
CopyMem (Temp, Src2, Length);
Eop = NextDevicePathNode(Temp);
SetDevicePathEndNode(Eop);
//
// Append device paths
//
Src1 = AppendDevicePath (Src1, Temp);
FreePool (Temp);
return Src1;
}
EFI_DEVICE_PATH *
FileDevicePath (
IN EFI_HANDLE Device OPTIONAL,
IN CHAR16 *FileName
)
/*++
N.B. Results are allocated from pool. The caller must FreePool
the resulting device path structure
--*/
{
UINTN Size;
FILEPATH_DEVICE_PATH *FilePath;
EFI_DEVICE_PATH *Eop, *DevicePath;
Size = StrSize(FileName);
FilePath = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH));
DevicePath = NULL;
if (FilePath) {
//
// Build a file path
//
FilePath->Header.Type = MEDIA_DEVICE_PATH;
FilePath->Header.SubType = MEDIA_FILEPATH_DP;
SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
CopyMem (FilePath->PathName, FileName, Size);
Eop = NextDevicePathNode(&FilePath->Header);
SetDevicePathEndNode(Eop);
//
// Append file path to device's device path
//
DevicePath = (EFI_DEVICE_PATH *) FilePath;
if (Device) {
DevicePath = AppendDevicePath (
DevicePathFromHandle(Device),
DevicePath
);
FreePool(FilePath);
}
}
return DevicePath;
}
UINTN
DevicePathSize (
IN EFI_DEVICE_PATH *DevPath
)
{
EFI_DEVICE_PATH *Start;
//
// Search for the end of the device path structure
//
Start = DevPath;
while (!IsDevicePathEnd(DevPath)) {
DevPath = NextDevicePathNode(DevPath);
}
//
// Compute the size
//
return ((UINTN) DevPath - (UINTN) Start) + sizeof(EFI_DEVICE_PATH);
}
EFI_DEVICE_PATH *
DuplicateDevicePath (
IN EFI_DEVICE_PATH *DevPath
)
{
EFI_DEVICE_PATH *NewDevPath;
UINTN Size;
//
// Compute the size
//
Size = DevicePathSize (DevPath);
//
// Make a copy
//
NewDevPath = AllocatePool (Size);
if (NewDevPath) {
CopyMem (NewDevPath, DevPath, Size);
}
return NewDevPath;
}
EFI_DEVICE_PATH *
UnpackDevicePath (
IN EFI_DEVICE_PATH *DevPath
)
{
EFI_DEVICE_PATH *Src, *Dest, *NewPath;
UINTN Size;
//
// Walk device path and round sizes to valid boundries
//
Src = DevPath;
Size = 0;
for (; ;) {
Size += DevicePathNodeLength(Src);
Size += ALIGN_SIZE(Size);
if (IsDevicePathEnd(Src)) {
break;
}
Src = NextDevicePathNode(Src);
}
//
// Allocate space for the unpacked path
//
NewPath = AllocateZeroPool (Size);
if (NewPath) {
ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0);
//
// Copy each node
//
Src = DevPath;
Dest = NewPath;
for (; ;) {
Size = DevicePathNodeLength(Src);
CopyMem (Dest, Src, Size);
Size += ALIGN_SIZE(Size);
SetDevicePathNodeLength (Dest, Size);
Dest->Type |= EFI_DP_TYPE_UNPACKED;
Dest = (EFI_DEVICE_PATH *) (((UINT8 *) Dest) + Size);
if (IsDevicePathEnd(Src)) {
break;
}
Src = NextDevicePathNode(Src);
}
}
return NewPath;
}
EFI_DEVICE_PATH*
AppendDevicePathInstance (
IN EFI_DEVICE_PATH *Src,
IN EFI_DEVICE_PATH *Instance
)
{
UINT8 *Ptr;
EFI_DEVICE_PATH *DevPath;
UINTN SrcSize;
UINTN InstanceSize;
if (Src == NULL) {
return DuplicateDevicePath (Instance);
}
SrcSize = DevicePathSize(Src);
InstanceSize = DevicePathSize(Instance);
Ptr = AllocatePool (SrcSize + InstanceSize);
DevPath = (EFI_DEVICE_PATH *)Ptr;
ASSERT(DevPath);
CopyMem (Ptr, Src, SrcSize);
// FreePool (Src);
while (!IsDevicePathEnd(DevPath)) {
DevPath = NextDevicePathNode(DevPath);
}
//
// Convert the End to an End Instance, since we are
// appending another instacne after this one its a good
// idea.
//
DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
DevPath = NextDevicePathNode(DevPath);
CopyMem (DevPath, Instance, InstanceSize);
return (EFI_DEVICE_PATH *)Ptr;
}
EFI_STATUS
LibDevicePathToInterface (
IN EFI_GUID *Protocol,
IN EFI_DEVICE_PATH *FilePath,
OUT VOID **Interface
)
{
EFI_STATUS Status;
EFI_HANDLE Device;
Status = uefi_call_wrapper(BS->LocateDevicePath, 3, Protocol, &FilePath, &Device);
if (!EFI_ERROR(Status)) {
// If we didn't get a direct match return not found
Status = EFI_NOT_FOUND;
if (IsDevicePathEnd(FilePath)) {
//
// It was a direct match, lookup the protocol interface
//
Status =uefi_call_wrapper(BS->HandleProtocol, 3, Device, Protocol, Interface);
}
}
//
// If there was an error, do not return an interface
//
if (EFI_ERROR(Status)) {
*Interface = NULL;
}
return Status;
}
static VOID
_DevPathPci (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
PCI_DEVICE_PATH *Pci;
Pci = DevPath;
CatPrint(Str, L"Pci(0x%x,0x%x)", Pci->Device, Pci->Function);
}
static VOID
_DevPathPccard (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
PCCARD_DEVICE_PATH *Pccard;
Pccard = DevPath;
CatPrint(Str, L"Pccard(0x%x)", Pccard-> FunctionNumber );
}
static VOID
_DevPathMemMap (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
MEMMAP_DEVICE_PATH *MemMap;
MemMap = DevPath;
CatPrint(Str, L"MemMap(%d,0x%x,0x%x)",
MemMap->MemoryType,
MemMap->StartingAddress,
MemMap->EndingAddress
);
}
static VOID
_DevPathController (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
CONTROLLER_DEVICE_PATH *Controller;
Controller = DevPath;
CatPrint(Str, L"Ctrl(%d)",
Controller->Controller
);
}
static VOID
_DevPathVendor (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
VENDOR_DEVICE_PATH *Vendor;
CHAR16 *Type;
UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownDevPath;
Vendor = DevPath;
switch (DevicePathType(&Vendor->Header)) {
case HARDWARE_DEVICE_PATH: Type = L"Hw"; break;
case MESSAGING_DEVICE_PATH: Type = L"Msg"; break;
case MEDIA_DEVICE_PATH: Type = L"Media"; break;
default: Type = L"?"; break;
}
CatPrint(Str, L"Ven%s(%g", Type, &Vendor->Guid);
if (CompareGuid (&Vendor->Guid, &UnknownDevice) == 0) {
//
// GUID used by EFI to enumerate an EDD 1.1 device
//
UnknownDevPath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *)Vendor;
CatPrint(Str, L":%02x)", UnknownDevPath->LegacyDriveLetter);
} else {
CatPrint(Str, L")");
}
}
/*
Type: 2 (ACPI Device Path) SubType: 1 (ACPI Device Path)
*/
static VOID
_DevPathAcpi (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
ACPI_HID_DEVICE_PATH *Acpi;
Acpi = DevPath;
if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
switch ( EISA_ID_TO_NUM( Acpi-> HID ) ) {
case 0x301 : {
CatPrint( Str , L"Keyboard(%d)" , Acpi-> UID ) ;
break ;
}
case 0x401 : {
CatPrint( Str , L"ParallelPort(%d)" , Acpi-> UID ) ;
break ;
}
case 0x501 : {
CatPrint( Str , L"Serial(%d)" , Acpi-> UID ) ;
break ;
}
case 0x604 : {
CatPrint( Str , L"Floppy(%d)" , Acpi-> UID ) ;
break ;
}
case 0xa03 : {
CatPrint( Str , L"PciRoot(%d)" , Acpi-> UID ) ;
break ;
}
case 0xa08 : {
CatPrint( Str , L"PcieRoot(%d)" , Acpi-> UID ) ;
break ;
}
default : {
CatPrint( Str , L"Acpi(PNP%04x" , EISA_ID_TO_NUM( Acpi-> HID ) ) ;
if ( Acpi-> UID ) CatPrint( Str , L",%d" , Acpi-> UID ) ;
CatPrint( Str , L")" ) ;
break ;
}
}
} else {
CatPrint( Str , L"Acpi(0x%X" , Acpi-> HID ) ;
if ( Acpi-> UID ) CatPrint( Str , L",%d" , Acpi-> UID ) ;
CatPrint( Str , L")" , Acpi-> HID , Acpi-> UID ) ;
}
}
static VOID
_DevPathAtapi (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
ATAPI_DEVICE_PATH *Atapi;
Atapi = DevPath;
CatPrint(Str, L"Ata(%s,%s)",
Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
Atapi->SlaveMaster ? L"Slave" : L"Master"
);
}
static VOID
_DevPathScsi (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
SCSI_DEVICE_PATH *Scsi;
Scsi = DevPath;
CatPrint(Str, L"Scsi(%d,%d)", Scsi->Pun, Scsi->Lun);
}
static VOID
_DevPathFibre (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
FIBRECHANNEL_DEVICE_PATH *Fibre;
Fibre = DevPath;
CatPrint( Str , L"Fibre%s(0x%016lx,0x%016lx)" ,
DevicePathType( & Fibre-> Header ) == MSG_FIBRECHANNEL_DP ? L"" : L"Ex" ,
Fibre-> WWN , Fibre-> Lun ) ;
}
static VOID
_DevPath1394 (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
F1394_DEVICE_PATH *F1394;
F1394 = DevPath;
CatPrint(Str, L"1394(%g)", &F1394->Guid);
}
static VOID
_DevPathUsb (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
USB_DEVICE_PATH *Usb;
Usb = DevPath;
CatPrint( Str , L"Usb(0x%x,0x%x)" , Usb-> Port , Usb-> Endpoint ) ;
}
static VOID
_DevPathI2O (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
I2O_DEVICE_PATH *I2O;
I2O = DevPath;
CatPrint(Str, L"I2O(0x%X)", I2O->Tid);
}
static VOID
_DevPathMacAddr (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
MAC_ADDR_DEVICE_PATH *MAC;
UINTN HwAddressSize;
UINTN Index;
MAC = DevPath;
/* HwAddressSize = sizeof(EFI_MAC_ADDRESS); */
HwAddressSize = DevicePathNodeLength( & MAC-> Header ) ;
HwAddressSize -= sizeof( MAC-> Header ) ;
HwAddressSize -= sizeof( MAC-> IfType ) ;
if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
HwAddressSize = 6;
}
CatPrint(Str, L"Mac(");
for(Index = 0; Index < HwAddressSize; Index++) {
CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]);
}
if ( MAC-> IfType != 0 ) {
CatPrint(Str, L",%d" , MAC-> IfType ) ;
}
CatPrint(Str, L")");
}
static VOID
CatPrintIPv4(
IN OUT POOL_PRINT * Str ,
IN EFI_IPv4_ADDRESS * Address
)
{
CatPrint( Str , L"%d.%d.%d.%d" , Address-> Addr[ 0 ] , Address-> Addr[ 1 ] ,
Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) ;
}
static BOOLEAN
IsNotNullIPv4(
IN EFI_IPv4_ADDRESS * Address
)
{
UINT8 val ;
val = Address-> Addr[ 0 ] | Address-> Addr[ 1 ] ;
val |= Address-> Addr[ 2 ] | Address-> Addr[ 3 ] ;
return val != 0 ;
}
static VOID
CatPrintNetworkProtocol(
IN OUT POOL_PRINT * Str ,
IN UINT16 Proto
)
{
if ( Proto == 6 ) {
CatPrint( Str , L"TCP" ) ;
} else if ( Proto == 17 ) {
CatPrint( Str , L"UDP" ) ;
} else {
CatPrint( Str , L"%d" , Proto ) ;
}
}
static VOID
_DevPathIPv4 (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
IPv4_DEVICE_PATH *IP;
BOOLEAN show ;
IP = DevPath;
CatPrint( Str , L"IPv4(") ;
CatPrintIPv4( Str , & IP-> RemoteIpAddress ) ;
CatPrint( Str , L",") ;
CatPrintNetworkProtocol( Str , IP-> Protocol ) ;
CatPrint( Str , L",%s" , IP-> StaticIpAddress ? L"Static" : L"DHCP" ) ;
show = IsNotNullIPv4( & IP-> LocalIpAddress ) ;
if ( ! show && DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) {
/* only version 2 includes gateway and netmask */
show |= IsNotNullIPv4( & IP-> GatewayIpAddress ) ;
show |= IsNotNullIPv4( & IP-> SubnetMask ) ;
}
if ( show ) {
CatPrint( Str , L"," ) ;
CatPrintIPv4( Str , & IP-> LocalIpAddress ) ;
if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) {
/* only version 2 includes gateway and netmask */
show = IsNotNullIPv4( & IP-> GatewayIpAddress ) ;
show |= IsNotNullIPv4( & IP-> SubnetMask ) ;
if ( show ) {
CatPrint( Str , L",") ;
CatPrintIPv4( Str , & IP-> GatewayIpAddress ) ;
if ( IsNotNullIPv4( & IP-> SubnetMask ) ) {
CatPrint( Str , L",") ;
CatPrintIPv4( Str , & IP-> SubnetMask ) ;
}
}
}
}
CatPrint( Str , L")") ;
}
#define CatPrintIPv6_ADD( x , y ) ( ( (UINT16) ( x ) ) << 8 | ( y ) )
static VOID
CatPrintIPv6(
IN OUT POOL_PRINT * Str ,
IN EFI_IPv6_ADDRESS * Address
)
{
CatPrint( Str , L"%x:%x:%x:%x:%x:%x:%x:%x" ,
CatPrintIPv6_ADD( Address-> Addr[ 0 ] , Address-> Addr[ 1 ] ) ,
CatPrintIPv6_ADD( Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) ,
CatPrintIPv6_ADD( Address-> Addr[ 4 ] , Address-> Addr[ 5 ] ) ,
CatPrintIPv6_ADD( Address-> Addr[ 6 ] , Address-> Addr[ 7 ] ) ,
CatPrintIPv6_ADD( Address-> Addr[ 8 ] , Address-> Addr[ 9 ] ) ,
CatPrintIPv6_ADD( Address-> Addr[ 10 ] , Address-> Addr[ 11 ] ) ,
CatPrintIPv6_ADD( Address-> Addr[ 12 ] , Address-> Addr[ 13 ] ) ,
CatPrintIPv6_ADD( Address-> Addr[ 14 ] , Address-> Addr[ 15 ] ) ) ;
}
static VOID
_DevPathIPv6 (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
IPv6_DEVICE_PATH *IP;
IP = DevPath;
CatPrint( Str , L"IPv6(") ;
CatPrintIPv6( Str , & IP-> RemoteIpAddress ) ;
CatPrint( Str , L",") ;
CatPrintNetworkProtocol( Str, IP-> Protocol ) ;
CatPrint( Str , L",%s," , IP-> IPAddressOrigin ?
( IP-> IPAddressOrigin == 1 ? L"StatelessAutoConfigure" :
L"StatefulAutoConfigure" ) : L"Static" ) ;
CatPrintIPv6( Str , & IP-> LocalIpAddress ) ;
if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv6_DEVICE_PATH ) ) {
CatPrint( Str , L",") ;
CatPrintIPv6( Str , & IP-> GatewayIpAddress ) ;
CatPrint( Str , L",") ;
CatPrint( Str , L"%d" , & IP-> PrefixLength ) ;
}
CatPrint( Str , L")") ;
}
static VOID
_DevPathUri (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
URI_DEVICE_PATH *Uri;
Uri = DevPath;
CatPrint( Str, L"Uri(%a)", Uri->Uri );
}
static VOID
_DevPathInfiniBand (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
INFINIBAND_DEVICE_PATH *InfiniBand;
InfiniBand = DevPath;
CatPrint( Str , L"Infiniband(0x%x,%g,0x%lx,0x%lx,0x%lx)" ,
InfiniBand-> ResourceFlags , InfiniBand-> PortGid , InfiniBand-> ServiceId ,
InfiniBand-> TargetPortId , InfiniBand-> DeviceId ) ;
}
static VOID
_DevPathUart (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
UART_DEVICE_PATH *Uart;
CHAR8 Parity;
Uart = DevPath;
switch (Uart->Parity) {
case 0 : Parity = 'D'; break;
case 1 : Parity = 'N'; break;
case 2 : Parity = 'E'; break;
case 3 : Parity = 'O'; break;
case 4 : Parity = 'M'; break;
case 5 : Parity = 'S'; break;
default : Parity = 'x'; break;
}
if (Uart->BaudRate == 0) {
CatPrint(Str, L"Uart(DEFAULT %c",Uart->BaudRate,Parity);
} else {
CatPrint(Str, L"Uart(%d %c",Uart->BaudRate,Parity);
}
if (Uart->DataBits == 0) {
CatPrint(Str, L"D");
} else {
CatPrint(Str, L"%d",Uart->DataBits);
}
switch (Uart->StopBits) {
case 0 : CatPrint(Str, L"D)"); break;
case 1 : CatPrint(Str, L"1)"); break;
case 2 : CatPrint(Str, L"1.5)"); break;
case 3 : CatPrint(Str, L"2)"); break;
default : CatPrint(Str, L"x)"); break;
}
}
static VOID
_DevPathSata (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
SATA_DEVICE_PATH * Sata ;
Sata = DevPath;
CatPrint( Str , L"Sata(0x%x,0x%x,0x%x)" , Sata-> HBAPortNumber ,
Sata-> PortMultiplierPortNumber , Sata-> Lun ) ;
}
static VOID
_DevPathHardDrive (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
HARDDRIVE_DEVICE_PATH *Hd;
Hd = DevPath;
switch (Hd->SignatureType) {
case SIGNATURE_TYPE_MBR:
CatPrint(Str, L"HD(Part%d,Sig%08X)",
Hd->PartitionNumber,
*((UINT32 *)(&(Hd->Signature[0])))
);
break;
case SIGNATURE_TYPE_GUID:
CatPrint(Str, L"HD(Part%d,Sig%g)",
Hd->PartitionNumber,
(EFI_GUID *) &(Hd->Signature[0])
);
break;
default:
CatPrint(Str, L"HD(Part%d,MBRType=%02x,SigType=%02x)",
Hd->PartitionNumber,
Hd->MBRType,
Hd->SignatureType
);
break;
}
}
static VOID
_DevPathCDROM (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
CDROM_DEVICE_PATH *Cd;
Cd = DevPath;
CatPrint( Str , L"CDROM(0x%x)" , Cd-> BootEntry ) ;
}
static VOID
_DevPathFilePath (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
FILEPATH_DEVICE_PATH *Fp;
Fp = DevPath;
CatPrint(Str, L"%s", Fp->PathName);
}
static VOID
_DevPathMediaProtocol (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;
MediaProt = DevPath;
CatPrint(Str, L"%g", &MediaProt->Protocol);
}
static VOID
_DevPathBssBss (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
BBS_BBS_DEVICE_PATH *Bss;
CHAR16 *Type;
Bss = DevPath;
switch (Bss->DeviceType) {
case BBS_TYPE_FLOPPY: Type = L"Floppy"; break;
case BBS_TYPE_HARDDRIVE: Type = L"Harddrive"; break;
case BBS_TYPE_CDROM: Type = L"CDROM"; break;
case BBS_TYPE_PCMCIA: Type = L"PCMCIA"; break;
case BBS_TYPE_USB: Type = L"Usb"; break;
case BBS_TYPE_EMBEDDED_NETWORK: Type = L"Net"; break;
default: Type = L"?"; break;
}
CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String);
}
static VOID
_DevPathEndInstance (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath EFI_UNUSED
)
{
CatPrint(Str, L",");
}
/**
* Print unknown device node.
* UEFI 2.4 § 9.6.1.6 table 89.
*/
static VOID
_DevPathNodeUnknown (
IN OUT POOL_PRINT *Str,
IN VOID *DevPath
)
{
EFI_DEVICE_PATH * Path ;
UINT8 * value ;
int length , index ;
Path = DevPath ;
value = DevPath ;
value += 4 ;
switch ( Path-> Type ) {
case HARDWARE_DEVICE_PATH : { /* Unknown Hardware Device Path */
CatPrint( Str , L"HardwarePath(%d" , Path-> SubType ) ;
break ;
}
case ACPI_DEVICE_PATH : { /* Unknown ACPI Device Path */
CatPrint( Str , L"AcpiPath(%d" , Path-> SubType ) ;
break ;
}
case MESSAGING_DEVICE_PATH : { /* Unknown Messaging Device Path */
CatPrint( Str , L"Msg(%d" , Path-> SubType ) ;
break ;
}
case MEDIA_DEVICE_PATH : { /* Unknown Media Device Path */
CatPrint( Str , L"MediaPath(%d" , Path-> SubType ) ;
break ;
}
case BBS_DEVICE_PATH : { /* Unknown BIOS Boot Specification Device Path */
CatPrint( Str , L"BbsPath(%d" , Path-> SubType ) ;
break ;
}
default : { /* Unknown Device Path */
CatPrint( Str , L"Path(%d,%d" , Path-> Type , Path-> SubType ) ;
break ;
}
}
length = DevicePathNodeLength( Path ) ;
for ( index = 0 ; index < length ; index ++ ) {
if ( index == 0 ) CatPrint( Str , L",0x" ) ;
CatPrint( Str , L"%02x" , * value ) ;
value ++ ;
}
CatPrint( Str , L")" ) ;
}
/*
* Table to convert "Type" and "SubType" to a "convert to text" function/
* Entries hold "Type" and "SubType" for know values.
* Special "SubType" 0 is used as default for known type with unknown subtype.
*/
struct {
UINT8 Type;
UINT8 SubType;
VOID (*Function)(POOL_PRINT *, VOID *);
} DevPathTable[] = {
{ HARDWARE_DEVICE_PATH, HW_PCI_DP, _DevPathPci},
{ HARDWARE_DEVICE_PATH, HW_PCCARD_DP, _DevPathPccard},
{ HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, _DevPathMemMap},
{ HARDWARE_DEVICE_PATH, HW_VENDOR_DP, _DevPathVendor},
{ HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, _DevPathController},
{ ACPI_DEVICE_PATH, ACPI_DP, _DevPathAcpi},
{ MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, _DevPathAtapi},
{ MESSAGING_DEVICE_PATH, MSG_SCSI_DP, _DevPathScsi},
{ MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, _DevPathFibre},
{ MESSAGING_DEVICE_PATH, MSG_1394_DP, _DevPath1394},
{ MESSAGING_DEVICE_PATH, MSG_USB_DP, _DevPathUsb},
{ MESSAGING_DEVICE_PATH, MSG_I2O_DP, _DevPathI2O},
{ MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, _DevPathMacAddr},
{ MESSAGING_DEVICE_PATH, MSG_IPv4_DP, _DevPathIPv4},
{ MESSAGING_DEVICE_PATH, MSG_IPv6_DP, _DevPathIPv6},
{ MESSAGING_DEVICE_PATH, MSG_URI_DP, _DevPathUri},
{ MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, _DevPathInfiniBand},
{ MESSAGING_DEVICE_PATH, MSG_UART_DP, _DevPathUart},
{ MESSAGING_DEVICE_PATH , MSG_SATA_DP , _DevPathSata } ,
{ MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, _DevPathVendor},
{ MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, _DevPathHardDrive},
{ MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, _DevPathCDROM},
{ MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, _DevPathVendor},
{ MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, _DevPathFilePath},
{ MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, _DevPathMediaProtocol},
{ BBS_DEVICE_PATH, BBS_BBS_DP, _DevPathBssBss},
{ END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance},
{ 0, 0, NULL}
};
CHAR16 *
DevicePathToStr (
EFI_DEVICE_PATH *DevPath
)
/*++
Turns the Device Path into a printable string. Allcoates
the string from pool. The caller must FreePool the returned
string.
--*/
{
POOL_PRINT Str;
EFI_DEVICE_PATH *DevPathNode;
VOID (*DumpNode)(POOL_PRINT *, VOID *);
UINTN Index, NewSize;
ZeroMem(&Str, sizeof(Str));
//
// Unpacked the device path
//
DevPath = UnpackDevicePath(DevPath);
ASSERT (DevPath);
//
// Process each device path node
//
DevPathNode = DevPath;
while (!IsDevicePathEnd(DevPathNode)) {
//
// Find the handler to dump this device path node
//
DumpNode = NULL;
for (Index = 0; DevPathTable[Index].Function; Index += 1) {
if (DevicePathType(DevPathNode) == DevPathTable[Index].Type &&
DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) {
DumpNode = DevPathTable[Index].Function;
break;
}
}
//
// If not found, use a generic function
//
if (!DumpNode) {
DumpNode = _DevPathNodeUnknown;
}
//
// Put a path seperator in if needed
//
if (Str.len && DumpNode != _DevPathEndInstance) {
CatPrint (&Str, L"/");
}
//
// Print this node of the device path
//
DumpNode (&Str, DevPathNode);
//
// Next device path node
//
DevPathNode = NextDevicePathNode(DevPathNode);
}
//
// Shrink pool used for string allocation
//
FreePool (DevPath);
NewSize = (Str.len + 1) * sizeof(CHAR16);
Str.str = ReallocatePool (Str.str, NewSize, NewSize);
Str.str[Str.len] = 0;
return Str.str;
}
BOOLEAN
LibMatchDevicePaths (
IN EFI_DEVICE_PATH *Multi,
IN EFI_DEVICE_PATH *Single
)
{
EFI_DEVICE_PATH *DevicePath, *DevicePathInst;
UINTN Size;
if (!Multi || !Single) {
return FALSE;
}
DevicePath = Multi;
while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) {
if (CompareMem (Single, DevicePathInst, Size) == 0) {
return TRUE;
}
}
return FALSE;
}
EFI_DEVICE_PATH *
LibDuplicateDevicePathInstance (
IN EFI_DEVICE_PATH *DevPath
)
{
EFI_DEVICE_PATH *NewDevPath,*DevicePathInst,*Temp;
UINTN Size = 0;
//
// get the size of an instance from the input
//
Temp = DevPath;
DevicePathInst = DevicePathInstance (&Temp, &Size);
//
// Make a copy and set proper end type
//
NewDevPath = NULL;
if (Size) {
NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH));
}
if (NewDevPath) {
CopyMem (NewDevPath, DevicePathInst, Size);
Temp = NextDevicePathNode(NewDevPath);
SetDevicePathEndNode(Temp);
}
return NewDevPath;
}