Curle
d588e232c4
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.
1261 lines
31 KiB
C
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;
|
|
}
|
|
|