/** @file | |
Main file for support of shell consist mapping. | |
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "UefiShellCommandLib.h" | |
#include <Library/DevicePathLib.h> | |
#include <Library/SortLib.h> | |
#include <Library/UefiLib.h> | |
#include <Protocol/UsbIo.h> | |
#include <Protocol/BlockIo.h> | |
#include <Protocol/SimpleFileSystem.h> | |
typedef enum { | |
MTDTypeUnknown, | |
MTDTypeFloppy, | |
MTDTypeHardDisk, | |
MTDTypeCDRom, | |
MTDTypeEnd | |
} MTD_TYPE; | |
typedef struct { | |
CHAR16 *Str; | |
UINTN Len; | |
} POOL_PRINT; | |
typedef struct { | |
UINTN Hi; | |
MTD_TYPE Mtd; | |
POOL_PRINT Csd; | |
BOOLEAN Digital; | |
} DEVICE_CONSIST_MAPPING_INFO; | |
typedef struct { | |
MTD_TYPE MTDType; | |
CHAR16 *Name; | |
} MTD_NAME; | |
/** | |
Serial Decode function. | |
@param DevPath The Device path info. | |
@param MapInfo The map info. | |
@param OrigDevPath The original device path protocol. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
typedef | |
EFI_STATUS | |
(*SERIAL_DECODE_FUNCTION) ( | |
EFI_DEVICE_PATH_PROTOCOL *DevPath, | |
DEVICE_CONSIST_MAPPING_INFO *MapInfo, | |
EFI_DEVICE_PATH_PROTOCOL *OrigDevPath | |
); | |
typedef struct { | |
UINT8 Type; | |
UINT8 SubType; | |
SERIAL_DECODE_FUNCTION SerialFun; | |
INTN (EFIAPI *CompareFun) (EFI_DEVICE_PATH_PROTOCOL *DevPath, EFI_DEVICE_PATH_PROTOCOL *DevPath2); | |
} DEV_PATH_CONSIST_MAPPING_TABLE; | |
/** | |
Concatenates a formatted unicode string to allocated pool. | |
The caller must free the resulting buffer. | |
@param Str Tracks the allocated pool, size in use, and amount of pool allocated. | |
@param Fmt The format string | |
@param ... The data will be printed. | |
@retval EFI_SUCCESS The string is concatenated successfully. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
CatPrint ( | |
IN OUT POOL_PRINT *Str, | |
IN CHAR16 *Fmt, | |
... | |
) | |
{ | |
UINT16 *AppendStr; | |
VA_LIST Args; | |
UINTN StringSize; | |
CHAR16 *NewStr; | |
AppendStr = AllocateZeroPool (0x1000); | |
if (AppendStr == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
VA_START (Args, Fmt); | |
UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args); | |
VA_END (Args); | |
if (NULL == Str->Str) { | |
StringSize = StrSize (AppendStr); | |
NewStr = AllocateZeroPool (StringSize); | |
} else { | |
StringSize = StrSize (AppendStr); | |
StringSize += (StrSize (Str->Str) - sizeof (UINT16)); | |
NewStr = ReallocatePool ( | |
StrSize (Str->Str), | |
StringSize, | |
Str->Str | |
); | |
} | |
if (NewStr == NULL) { | |
FreePool (AppendStr); | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Str->Str = NewStr; | |
StrCatS (Str->Str, StringSize/sizeof(CHAR16), AppendStr); | |
Str->Len = StringSize; | |
FreePool (AppendStr); | |
return EFI_SUCCESS; | |
} | |
MTD_NAME mMTDName[] = { | |
{ | |
MTDTypeUnknown, | |
L"F" | |
}, | |
{ | |
MTDTypeFloppy, | |
L"FP" | |
}, | |
{ | |
MTDTypeHardDisk, | |
L"HD" | |
}, | |
{ | |
MTDTypeCDRom, | |
L"CD" | |
}, | |
{ | |
MTDTypeEnd, | |
NULL | |
} | |
}; | |
/** | |
Function to append a 64 bit number / 25 onto the string. | |
@param[in, out] Str The string so append onto. | |
@param[in] Num The number to divide and append. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
AppendCSDNum2 ( | |
IN OUT POOL_PRINT *Str, | |
IN UINT64 Num | |
) | |
{ | |
EFI_STATUS Status; | |
UINT64 Result; | |
UINT32 Rem; | |
ASSERT (Str != NULL); | |
Result = DivU64x32Remainder (Num, 25, &Rem); | |
if (Result > 0) { | |
Status = AppendCSDNum2 (Str, Result); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
} | |
return CatPrint (Str, L"%c", Rem + 'a'); | |
} | |
/** | |
Function to append a 64 bit number onto the mapping info. | |
@param[in, out] MappingItem The mapping info object to append onto. | |
@param[in] Num The info to append. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
AppendCSDNum ( | |
IN OUT DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN UINT64 Num | |
) | |
{ | |
EFI_STATUS Status; | |
ASSERT (MappingItem != NULL); | |
if (MappingItem->Digital) { | |
Status = CatPrint (&MappingItem->Csd, L"%ld", Num); | |
} else { | |
Status = AppendCSDNum2 (&MappingItem->Csd, Num); | |
} | |
if (!EFI_ERROR (Status)) { | |
MappingItem->Digital = (BOOLEAN) !(MappingItem->Digital); | |
} | |
return Status; | |
} | |
/** | |
Function to append string into the mapping info. | |
@param[in, out] MappingItem The mapping info object to append onto. | |
@param[in] Str The info to append. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
AppendCSDStr ( | |
IN OUT DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN CHAR16 *Str | |
) | |
{ | |
CHAR16 *Index; | |
EFI_STATUS Status; | |
ASSERT (Str != NULL && MappingItem != NULL); | |
Status = EFI_SUCCESS; | |
if (MappingItem->Digital) { | |
// | |
// To aVOID mult-meaning, the mapping is: | |
// 0 1 2 3 4 5 6 7 8 9 a b c d e f | |
// 0 16 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
// | |
for (Index = Str; *Index != 0; Index++) { | |
switch (*Index) { | |
case '0': | |
case '2': | |
case '3': | |
case '4': | |
case '5': | |
case '6': | |
case '7': | |
case '8': | |
case '9': | |
Status = CatPrint (&MappingItem->Csd, L"%c", *Index); | |
break; | |
case '1': | |
Status = CatPrint (&MappingItem->Csd, L"16"); | |
break; | |
case 'a': | |
case 'b': | |
case 'c': | |
case 'd': | |
case 'e': | |
case 'f': | |
Status = CatPrint (&MappingItem->Csd, L"1%c", *Index - 'a' + '0'); | |
break; | |
case 'A': | |
case 'B': | |
case 'C': | |
case 'D': | |
case 'E': | |
case 'F': | |
Status = CatPrint (&MappingItem->Csd, L"1%c", *Index - 'A' + '0'); | |
break; | |
} | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
} | |
} else { | |
for (Index = Str; *Index != 0; Index++) { | |
// | |
// The mapping is: | |
// 0 1 2 3 4 5 6 7 8 9 a b c d e f | |
// a b c d e f g h i j k l m n o p | |
// | |
if (*Index >= '0' && *Index <= '9') { | |
Status = CatPrint (&MappingItem->Csd, L"%c", *Index - '0' + 'a'); | |
} else if (*Index >= 'a' && *Index <= 'f') { | |
Status = CatPrint (&MappingItem->Csd, L"%c", *Index - 'a' + 'k'); | |
} else if (*Index >= 'A' && *Index <= 'F') { | |
Status = CatPrint (&MappingItem->Csd, L"%c", *Index - 'A' + 'k'); | |
} | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
} | |
} | |
MappingItem->Digital = (BOOLEAN)!(MappingItem->Digital); | |
return (EFI_SUCCESS); | |
} | |
/** | |
Function to append a Guid to the mapping item. | |
@param[in, out] MappingItem The item to append onto. | |
@param[in] Guid The guid to append. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
AppendCSDGuid ( | |
DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
EFI_GUID *Guid | |
) | |
{ | |
CHAR16 Buffer[64]; | |
ASSERT (Guid != NULL && MappingItem != NULL); | |
UnicodeSPrint ( | |
Buffer, | |
0, | |
L"%g", | |
Guid | |
); | |
return AppendCSDStr (MappingItem, Buffer); | |
} | |
/** | |
Function to compare 2 APCI device paths. | |
@param[in] DevicePath1 The first device path to compare. | |
@param[in] DevicePath2 The second device path to compare. | |
@retval 0 The device paths represent the same device. | |
@return Non zero if the devices are different, zero otherwise. | |
**/ | |
INTN | |
EFIAPI | |
DevPathCompareAcpi ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 | |
) | |
{ | |
ACPI_HID_DEVICE_PATH *Acpi1; | |
ACPI_HID_DEVICE_PATH *Acpi2; | |
if (DevicePath1 == NULL || DevicePath2 == NULL) { | |
return (-2); | |
} | |
Acpi1 = (ACPI_HID_DEVICE_PATH *) DevicePath1; | |
Acpi2 = (ACPI_HID_DEVICE_PATH *) DevicePath2; | |
if (Acpi1->HID > Acpi2->HID || (Acpi1->HID == Acpi2->HID && Acpi1->UID > Acpi2->UID)) { | |
return 1; | |
} | |
if (Acpi1->HID == Acpi2->HID && Acpi1->UID == Acpi2->UID) { | |
return 0; | |
} | |
return -1; | |
} | |
/** | |
Function to compare 2 PCI device paths. | |
@param[in] DevicePath1 The first device path to compare. | |
@param[in] DevicePath2 The second device path to compare. | |
@retval 0 The device paths represent the same device. | |
@return Non zero if the devices are different, zero otherwise. | |
**/ | |
INTN | |
EFIAPI | |
DevPathComparePci ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 | |
) | |
{ | |
PCI_DEVICE_PATH *Pci1; | |
PCI_DEVICE_PATH *Pci2; | |
ASSERT(DevicePath1 != NULL); | |
ASSERT(DevicePath2 != NULL); | |
Pci1 = (PCI_DEVICE_PATH *) DevicePath1; | |
Pci2 = (PCI_DEVICE_PATH *) DevicePath2; | |
if (Pci1->Device > Pci2->Device || (Pci1->Device == Pci2->Device && Pci1->Function > Pci2->Function)) { | |
return 1; | |
} | |
if (Pci1->Device == Pci2->Device && Pci1->Function == Pci2->Function) { | |
return 0; | |
} | |
return -1; | |
} | |
/** | |
Do a comparison on 2 device paths. | |
@param[in] DevicePath1 The first device path. | |
@param[in] DevicePath2 The second device path. | |
@retval 0 The 2 device paths are the same. | |
@retval <0 DevicePath2 is greater than DevicePath1. | |
@retval >0 DevicePath1 is greater than DevicePath2. | |
**/ | |
INTN | |
EFIAPI | |
DevPathCompareDefault ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 | |
) | |
{ | |
UINTN DevPathSize1; | |
UINTN DevPathSize2; | |
ASSERT(DevicePath1 != NULL); | |
ASSERT(DevicePath2 != NULL); | |
DevPathSize1 = DevicePathNodeLength (DevicePath1); | |
DevPathSize2 = DevicePathNodeLength (DevicePath2); | |
if (DevPathSize1 > DevPathSize2) { | |
return 1; | |
} else if (DevPathSize1 < DevPathSize2) { | |
return -1; | |
} else { | |
return CompareMem (DevicePath1, DevicePath2, DevPathSize1); | |
} | |
} | |
/** | |
DevicePathNode must be SerialHDD Channel type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialHardDrive ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
HARDDRIVE_DEVICE_PATH *Hd; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Hd = (HARDDRIVE_DEVICE_PATH *) DevicePathNode; | |
if (MappingItem->Mtd == MTDTypeUnknown) { | |
MappingItem->Mtd = MTDTypeHardDisk; | |
} | |
return AppendCSDNum (MappingItem, Hd->PartitionNumber); | |
} | |
/** | |
DevicePathNode must be SerialAtapi Channel type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialAtapi ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
ATAPI_DEVICE_PATH *Atapi; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Atapi = (ATAPI_DEVICE_PATH *) DevicePathNode; | |
return AppendCSDNum (MappingItem, (Atapi->PrimarySecondary * 2 + Atapi->SlaveMaster)); | |
} | |
/** | |
DevicePathNode must be SerialCDROM Channel type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialCdRom ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
CDROM_DEVICE_PATH *Cd; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Cd = (CDROM_DEVICE_PATH *) DevicePathNode; | |
MappingItem->Mtd = MTDTypeCDRom; | |
return AppendCSDNum (MappingItem, Cd->BootEntry); | |
} | |
/** | |
DevicePathNode must be SerialFibre Channel type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialFibre ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
EFI_STATUS Status; | |
FIBRECHANNEL_DEVICE_PATH *Fibre; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Fibre = (FIBRECHANNEL_DEVICE_PATH *) DevicePathNode; | |
Status = AppendCSDNum (MappingItem, Fibre->WWN); | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Fibre->Lun); | |
} | |
return Status; | |
} | |
/** | |
DevicePathNode must be SerialUart type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialUart ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
EFI_STATUS Status; | |
UART_DEVICE_PATH *Uart; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Uart = (UART_DEVICE_PATH *) DevicePathNode; | |
Status = AppendCSDNum (MappingItem, Uart->BaudRate); | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Uart->DataBits); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Uart->Parity); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Uart->StopBits); | |
} | |
return Status; | |
} | |
/** | |
DevicePathNode must be SerialUSB type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialUsb ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
USB_DEVICE_PATH *Usb; | |
EFI_USB_IO_PROTOCOL *UsbIo; | |
EFI_HANDLE TempHandle; | |
EFI_STATUS Status; | |
USB_INTERFACE_DESCRIPTOR InterfaceDesc; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Usb = (USB_DEVICE_PATH *) DevicePathNode; | |
Status = AppendCSDNum (MappingItem, Usb->ParentPortNumber); | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Usb->InterfaceNumber); | |
} | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
if (PcdGetBool(PcdUsbExtendedDecode)) { | |
Status = gBS->LocateDevicePath( &gEfiUsbIoProtocolGuid, &DevicePath, &TempHandle ); | |
UsbIo = NULL; | |
if (!EFI_ERROR(Status)) { | |
Status = gBS->OpenProtocol(TempHandle, &gEfiUsbIoProtocolGuid, (VOID**)&UsbIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); | |
} | |
if (!EFI_ERROR(Status)) { | |
ASSERT(UsbIo != NULL); | |
Status = UsbIo->UsbGetInterfaceDescriptor(UsbIo, &InterfaceDesc); | |
if (!EFI_ERROR(Status)) { | |
if (InterfaceDesc.InterfaceClass == USB_MASS_STORE_CLASS && MappingItem->Mtd == MTDTypeUnknown) { | |
switch (InterfaceDesc.InterfaceSubClass){ | |
case USB_MASS_STORE_SCSI: | |
MappingItem->Mtd = MTDTypeHardDisk; | |
break; | |
case USB_MASS_STORE_8070I: | |
case USB_MASS_STORE_UFI: | |
MappingItem->Mtd = MTDTypeFloppy; | |
break; | |
case USB_MASS_STORE_8020I: | |
MappingItem->Mtd = MTDTypeCDRom; | |
break; | |
} | |
} | |
} | |
} | |
} | |
return Status; | |
} | |
/** | |
DevicePathNode must be SerialVendor type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialVendor ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
EFI_STATUS Status; | |
VENDOR_DEVICE_PATH *Vendor; | |
SAS_DEVICE_PATH *Sas; | |
UINTN TargetNameLength; | |
UINTN Index; | |
CHAR16 *Buffer; | |
CHAR16 *NewBuffer; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Vendor = (VENDOR_DEVICE_PATH *) DevicePathNode; | |
Status = AppendCSDGuid (MappingItem, &Vendor->Guid); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
if (CompareGuid (&gEfiSasDevicePathGuid, &Vendor->Guid)) { | |
Sas = (SAS_DEVICE_PATH *) Vendor; | |
Status = AppendCSDNum (MappingItem, Sas->SasAddress); | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Sas->Lun); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Sas->DeviceTopology); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Sas->RelativeTargetPort); | |
} | |
} else { | |
TargetNameLength = MIN(DevicePathNodeLength (DevicePathNode) - sizeof (VENDOR_DEVICE_PATH), PcdGet32(PcdShellVendorExtendedDecode)); | |
if (TargetNameLength != 0) { | |
// | |
// String is 2 chars per data byte, plus NULL terminator | |
// | |
Buffer = AllocateZeroPool (((TargetNameLength * 2) + 1) * sizeof(CHAR16)); | |
if (Buffer == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
// | |
// Build the string data | |
// | |
for (Index = 0; Index < TargetNameLength; Index++) { | |
NewBuffer = CatSPrint (Buffer, L"%02x", *((UINT8*)Vendor + sizeof (VENDOR_DEVICE_PATH) + Index)); | |
if (NewBuffer == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
break; | |
} | |
Buffer = NewBuffer; | |
} | |
// | |
// Append the new data block | |
// | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDStr (MappingItem, Buffer); | |
} | |
FreePool(Buffer); | |
} | |
} | |
return Status; | |
} | |
/** | |
DevicePathNode must be SerialLun type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialLun ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
DEVICE_LOGICAL_UNIT_DEVICE_PATH *Lun; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Lun = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) DevicePathNode; | |
return AppendCSDNum (MappingItem, Lun->Lun); | |
} | |
/** | |
DevicePathNode must be SerialSata type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialSata ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
EFI_STATUS Status; | |
SATA_DEVICE_PATH *Sata; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Sata = (SATA_DEVICE_PATH *) DevicePathNode; | |
Status = AppendCSDNum (MappingItem, Sata->HBAPortNumber); | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Sata->PortMultiplierPortNumber); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Sata->Lun); | |
} | |
return Status; | |
} | |
/** | |
DevicePathNode must be SerialSCSI type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialIScsi ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
EFI_STATUS Status; | |
ISCSI_DEVICE_PATH *IScsi; | |
UINT8 *IScsiTargetName; | |
CHAR16 *TargetName; | |
UINTN TargetNameLength; | |
UINTN Index; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Status = EFI_SUCCESS; | |
if (PcdGetBool(PcdShellDecodeIScsiMapNames)) { | |
IScsi = (ISCSI_DEVICE_PATH *) DevicePathNode; | |
Status = AppendCSDNum (MappingItem, IScsi->NetworkProtocol); | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, IScsi->LoginOption); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, IScsi->Lun); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, IScsi->TargetPortalGroupTag); | |
} | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
TargetNameLength = DevicePathNodeLength (DevicePathNode) - sizeof (ISCSI_DEVICE_PATH); | |
if (TargetNameLength > 0) { | |
TargetName = AllocateZeroPool ((TargetNameLength + 1) * sizeof (CHAR16)); | |
if (TargetName == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
} else { | |
IScsiTargetName = (UINT8 *) (IScsi + 1); | |
for (Index = 0; Index < TargetNameLength; Index++) { | |
TargetName[Index] = (CHAR16) IScsiTargetName[Index]; | |
} | |
Status = AppendCSDStr (MappingItem, TargetName); | |
FreePool (TargetName); | |
} | |
} | |
} | |
return Status; | |
} | |
/** | |
DevicePathNode must be SerialI20 type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialI2O ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
I2O_DEVICE_PATH *DevicePath_I20; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
DevicePath_I20 = (I2O_DEVICE_PATH *) DevicePathNode; | |
return AppendCSDNum (MappingItem, DevicePath_I20->Tid); | |
} | |
/** | |
DevicePathNode must be Mac Address type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialMacAddr ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
MAC_ADDR_DEVICE_PATH *Mac; | |
UINTN HwAddressSize; | |
UINTN Index; | |
CHAR16 Buffer[64]; | |
CHAR16 *PBuffer; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Mac = (MAC_ADDR_DEVICE_PATH *) DevicePathNode; | |
HwAddressSize = sizeof (EFI_MAC_ADDRESS); | |
if (Mac->IfType == 0x01 || Mac->IfType == 0x00) { | |
HwAddressSize = 6; | |
} | |
for (Index = 0, PBuffer = Buffer; Index < HwAddressSize; Index++, PBuffer += 2) { | |
UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Mac->MacAddress.Addr[Index]); | |
} | |
return AppendCSDStr (MappingItem, Buffer); | |
} | |
/** | |
DevicePathNode must be InfiniBand type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialInfiniBand ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
EFI_STATUS Status; | |
INFINIBAND_DEVICE_PATH *InfiniBand; | |
UINTN Index; | |
CHAR16 Buffer[64]; | |
CHAR16 *PBuffer; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
InfiniBand = (INFINIBAND_DEVICE_PATH *) DevicePathNode; | |
for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) { | |
UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) InfiniBand->PortGid[Index]); | |
} | |
Status = AppendCSDStr (MappingItem, Buffer); | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, InfiniBand->ServiceId); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, InfiniBand->TargetPortId); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, InfiniBand->DeviceId); | |
} | |
return Status; | |
} | |
/** | |
DevicePathNode must be IPv4 type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialIPv4 ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
EFI_STATUS Status; | |
IPv4_DEVICE_PATH *Ip; | |
CHAR16 Buffer[10]; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Ip = (IPv4_DEVICE_PATH *) DevicePathNode; | |
UnicodeSPrint ( | |
Buffer, | |
0, | |
L"%02x%02x%02x%02x", | |
(UINTN) Ip->LocalIpAddress.Addr[0], | |
(UINTN) Ip->LocalIpAddress.Addr[1], | |
(UINTN) Ip->LocalIpAddress.Addr[2], | |
(UINTN) Ip->LocalIpAddress.Addr[3] | |
); | |
Status = AppendCSDStr (MappingItem, Buffer); | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Ip->LocalPort); | |
} | |
if (!EFI_ERROR (Status)) { | |
UnicodeSPrint ( | |
Buffer, | |
0, | |
L"%02x%02x%02x%02x", | |
(UINTN) Ip->RemoteIpAddress.Addr[0], | |
(UINTN) Ip->RemoteIpAddress.Addr[1], | |
(UINTN) Ip->RemoteIpAddress.Addr[2], | |
(UINTN) Ip->RemoteIpAddress.Addr[3] | |
); | |
Status = AppendCSDStr (MappingItem, Buffer); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Ip->RemotePort); | |
} | |
return Status; | |
} | |
/** | |
DevicePathNode must be IPv6 type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialIPv6 ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
EFI_STATUS Status; | |
IPv6_DEVICE_PATH *Ip; | |
UINTN Index; | |
CHAR16 Buffer[64]; | |
CHAR16 *PBuffer; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Ip = (IPv6_DEVICE_PATH *) DevicePathNode; | |
for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) { | |
UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->LocalIpAddress.Addr[Index]); | |
} | |
Status = AppendCSDStr (MappingItem, Buffer); | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Ip->LocalPort); | |
} | |
if (!EFI_ERROR (Status)) { | |
for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) { | |
UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->RemoteIpAddress.Addr[Index]); | |
} | |
Status = AppendCSDStr (MappingItem, Buffer); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Ip->RemotePort); | |
} | |
return Status; | |
} | |
/** | |
DevicePathNode must be SCSI type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialScsi ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
EFI_STATUS Status; | |
SCSI_DEVICE_PATH *Scsi; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Scsi = (SCSI_DEVICE_PATH *) DevicePathNode; | |
Status = AppendCSDNum (MappingItem, Scsi->Pun); | |
if (!EFI_ERROR (Status)) { | |
Status = AppendCSDNum (MappingItem, Scsi->Lun); | |
} | |
return Status; | |
} | |
/** | |
DevicePathNode must be 1394 type and this will populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerial1394 ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
F1394_DEVICE_PATH *DevicePath_F1394; | |
CHAR16 Buffer[20]; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
DevicePath_F1394 = (F1394_DEVICE_PATH *) DevicePathNode; | |
UnicodeSPrint (Buffer, 0, L"%lx", DevicePath_F1394->Guid); | |
return AppendCSDStr (MappingItem, Buffer); | |
} | |
/** | |
If the node is floppy type then populate the MappingItem. | |
@param[in] DevicePathNode The node to get info on. | |
@param[in] MappingItem The info item to populate. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialAcpi ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
ACPI_HID_DEVICE_PATH *Acpi; | |
ASSERT(DevicePathNode != NULL); | |
ASSERT(MappingItem != NULL); | |
Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode; | |
if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { | |
if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) { | |
MappingItem->Mtd = MTDTypeFloppy; | |
return AppendCSDNum (MappingItem, Acpi->UID); | |
} | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Empty function used for unknown devices. | |
@param[in] DevicePathNode Ignored. | |
@param[in] MappingItem Ignored. | |
@param[in] DevicePath Ignored. | |
@retval EFI_OUT_OF_RESOURCES Out of resources. | |
@retval EFI_SUCCESS The appending was successful. | |
**/ | |
EFI_STATUS | |
DevPathSerialDefault ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
return EFI_SUCCESS; | |
} | |
DEV_PATH_CONSIST_MAPPING_TABLE DevPathConsistMappingTable[] = { | |
{ | |
HARDWARE_DEVICE_PATH, | |
HW_PCI_DP, | |
DevPathSerialDefault, | |
DevPathComparePci | |
}, | |
{ | |
ACPI_DEVICE_PATH, | |
ACPI_DP, | |
DevPathSerialAcpi, | |
DevPathCompareAcpi | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_ATAPI_DP, | |
DevPathSerialAtapi, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_SCSI_DP, | |
DevPathSerialScsi, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_FIBRECHANNEL_DP, | |
DevPathSerialFibre, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_1394_DP, | |
DevPathSerial1394, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_USB_DP, | |
DevPathSerialUsb, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_I2O_DP, | |
DevPathSerialI2O, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_MAC_ADDR_DP, | |
DevPathSerialMacAddr, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_IPv4_DP, | |
DevPathSerialIPv4, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_IPv6_DP, | |
DevPathSerialIPv6, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_INFINIBAND_DP, | |
DevPathSerialInfiniBand, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_UART_DP, | |
DevPathSerialUart, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_VENDOR_DP, | |
DevPathSerialVendor, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_DEVICE_LOGICAL_UNIT_DP, | |
DevPathSerialLun, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_SATA_DP, | |
DevPathSerialSata, | |
DevPathCompareDefault | |
}, | |
{ | |
MESSAGING_DEVICE_PATH, | |
MSG_ISCSI_DP, | |
DevPathSerialIScsi, | |
DevPathCompareDefault | |
}, | |
{ | |
MEDIA_DEVICE_PATH, | |
MEDIA_HARDDRIVE_DP, | |
DevPathSerialHardDrive, | |
DevPathCompareDefault | |
}, | |
{ | |
MEDIA_DEVICE_PATH, | |
MEDIA_CDROM_DP, | |
DevPathSerialCdRom, | |
DevPathCompareDefault | |
}, | |
{ | |
MEDIA_DEVICE_PATH, | |
MEDIA_VENDOR_DP, | |
DevPathSerialVendor, | |
DevPathCompareDefault | |
}, | |
{ | |
0, | |
0, | |
NULL, | |
NULL | |
} | |
}; | |
/** | |
Function to determine if a device path node is Hi or not. | |
@param[in] DevicePathNode The node to check. | |
@retval TRUE The node is Hi. | |
@retval FALSE The node is not Hi. | |
**/ | |
BOOLEAN | |
IsHIDevicePathNode ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode | |
) | |
{ | |
ACPI_HID_DEVICE_PATH *Acpi; | |
ASSERT(DevicePathNode != NULL); | |
if (DevicePathNode->Type == HARDWARE_DEVICE_PATH) { | |
return TRUE; | |
} | |
if (DevicePathNode->Type == ACPI_DEVICE_PATH) { | |
Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode; | |
switch (EISA_ID_TO_NUM (Acpi->HID)) { | |
case 0x0301: | |
case 0x0401: | |
case 0x0501: | |
case 0x0604: | |
return FALSE; | |
} | |
return TRUE; | |
} | |
return FALSE; | |
} | |
/** | |
Function to convert a standard device path structure into a Hi version. | |
@param[in] DevicePath The device path to convert. | |
@return the device path portion that is Hi. | |
**/ | |
EFI_DEVICE_PATH_PROTOCOL * | |
GetHIDevicePath ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
UINTN NonHIDevicePathNodeCount; | |
UINTN Index; | |
EFI_DEV_PATH Node; | |
EFI_DEVICE_PATH_PROTOCOL *HIDevicePath; | |
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; | |
ASSERT(DevicePath != NULL); | |
NonHIDevicePathNodeCount = 0; | |
HIDevicePath = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL)); | |
SetDevicePathEndNode (HIDevicePath); | |
Node.DevPath.Type = END_DEVICE_PATH_TYPE; | |
Node.DevPath.SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; | |
Node.DevPath.Length[0] = (UINT8)sizeof (EFI_DEVICE_PATH_PROTOCOL); | |
Node.DevPath.Length[1] = 0; | |
while (!IsDevicePathEnd (DevicePath)) { | |
if (IsHIDevicePathNode (DevicePath)) { | |
for (Index = 0; Index < NonHIDevicePathNodeCount; Index++) { | |
TempDevicePath = AppendDevicePathNode (HIDevicePath, &Node.DevPath); | |
FreePool (HIDevicePath); | |
HIDevicePath = TempDevicePath; | |
} | |
TempDevicePath = AppendDevicePathNode (HIDevicePath, DevicePath); | |
FreePool (HIDevicePath); | |
HIDevicePath = TempDevicePath; | |
} else { | |
NonHIDevicePathNodeCount++; | |
} | |
// | |
// Next device path node | |
// | |
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath); | |
} | |
return HIDevicePath; | |
} | |
/** | |
Function to walk the device path looking for a dumpable node. | |
@param[in] MappingItem The Item to fill with data. | |
@param[in] DevicePath The path of the item to get data on. | |
@return EFI_SUCCESS Always returns success. | |
**/ | |
EFI_STATUS | |
GetDeviceConsistMappingInfo ( | |
IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
EFI_STATUS Status; | |
SERIAL_DECODE_FUNCTION SerialFun; | |
UINTN Index; | |
EFI_DEVICE_PATH_PROTOCOL *OriginalDevicePath; | |
ASSERT(DevicePath != NULL); | |
ASSERT(MappingItem != NULL); | |
SetMem (&MappingItem->Csd, sizeof (POOL_PRINT), 0); | |
OriginalDevicePath = DevicePath; | |
while (!IsDevicePathEnd (DevicePath)) { | |
// | |
// Find the handler to dump this device path node and | |
// initialize with generic function in case nothing is found | |
// | |
for (SerialFun = DevPathSerialDefault, Index = 0; DevPathConsistMappingTable[Index].SerialFun != NULL; Index += 1) { | |
if (DevicePathType (DevicePath) == DevPathConsistMappingTable[Index].Type && | |
DevicePathSubType (DevicePath) == DevPathConsistMappingTable[Index].SubType | |
) { | |
SerialFun = DevPathConsistMappingTable[Index].SerialFun; | |
break; | |
} | |
} | |
Status = SerialFun (DevicePath, MappingItem, OriginalDevicePath); | |
if (EFI_ERROR (Status)) { | |
SHELL_FREE_NON_NULL (MappingItem->Csd.Str); | |
return Status; | |
} | |
// | |
// Next device path node | |
// | |
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath); | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Function to initialize the table for creating consistent map names. | |
@param[out] Table The pointer to pointer to pointer to DevicePathProtocol object. | |
@retval EFI_SUCCESS The table was created successfully. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ShellCommandConsistMappingInitialize ( | |
OUT EFI_DEVICE_PATH_PROTOCOL ***Table | |
) | |
{ | |
EFI_HANDLE *HandleBuffer; | |
UINTN HandleNum; | |
UINTN HandleLoop; | |
EFI_DEVICE_PATH_PROTOCOL **TempTable; | |
EFI_DEVICE_PATH_PROTOCOL *DevicePath; | |
EFI_DEVICE_PATH_PROTOCOL *HIDevicePath; | |
EFI_BLOCK_IO_PROTOCOL *BlockIo; | |
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; | |
UINTN Index; | |
EFI_STATUS Status; | |
HandleBuffer = NULL; | |
Status = gBS->LocateHandleBuffer ( | |
ByProtocol, | |
&gEfiDevicePathProtocolGuid, | |
NULL, | |
&HandleNum, | |
&HandleBuffer | |
); | |
ASSERT_EFI_ERROR(Status); | |
TempTable = AllocateZeroPool ((HandleNum + 1) * sizeof (EFI_DEVICE_PATH_PROTOCOL *)); | |
if (TempTable == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
for (HandleLoop = 0 ; HandleLoop < HandleNum ; HandleLoop++) { | |
DevicePath = DevicePathFromHandle (HandleBuffer[HandleLoop]); | |
if (DevicePath == NULL) { | |
continue; | |
} | |
HIDevicePath = GetHIDevicePath (DevicePath); | |
if (HIDevicePath == NULL) { | |
continue; | |
} | |
Status = gBS->HandleProtocol( HandleBuffer[HandleLoop], | |
&gEfiBlockIoProtocolGuid, | |
(VOID **)&BlockIo | |
); | |
if (EFI_ERROR(Status)) { | |
Status = gBS->HandleProtocol( HandleBuffer[HandleLoop], | |
&gEfiSimpleFileSystemProtocolGuid, | |
(VOID **)&SimpleFileSystem | |
); | |
if (EFI_ERROR(Status)) { | |
FreePool (HIDevicePath); | |
continue; | |
} | |
} | |
for (Index = 0; TempTable[Index] != NULL; Index++) { | |
if (DevicePathCompare (&TempTable[Index], &HIDevicePath) == 0) { | |
FreePool (HIDevicePath); | |
break; | |
} | |
} | |
if (TempTable[Index] == NULL) { | |
TempTable[Index] = HIDevicePath; | |
} | |
} | |
for (Index = 0; TempTable[Index] != NULL; Index++); | |
PerformQuickSort(TempTable, Index, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare); | |
*Table = TempTable; | |
if (HandleBuffer != NULL) { | |
FreePool (HandleBuffer); | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Function to uninitialize the table for creating consistent map names. | |
The parameter must have been received from ShellCommandConsistMappingInitialize. | |
@param[out] Table The pointer to pointer to DevicePathProtocol object. | |
@retval EFI_SUCCESS The table was deleted successfully. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ShellCommandConsistMappingUnInitialize ( | |
EFI_DEVICE_PATH_PROTOCOL **Table | |
) | |
{ | |
UINTN Index; | |
ASSERT(Table != NULL); | |
for (Index = 0; Table[Index] != NULL; Index++) { | |
FreePool (Table[Index]); | |
} | |
FreePool (Table); | |
return EFI_SUCCESS; | |
} | |
/** | |
Create a consistent mapped name for the device specified by DevicePath | |
based on the Table. | |
This must be called after ShellCommandConsistMappingInitialize() and | |
before ShellCommandConsistMappingUnInitialize() is called. | |
@param[in] DevicePath The pointer to the dev path for the device. | |
@param[in] Table The Table of mapping information. | |
@retval NULL A consistent mapped name could not be created. | |
@return A pointer to a string allocated from pool with the device name. | |
**/ | |
CHAR16 * | |
EFIAPI | |
ShellCommandConsistMappingGenMappingName ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, | |
IN EFI_DEVICE_PATH_PROTOCOL **Table | |
) | |
{ | |
EFI_STATUS Status; | |
POOL_PRINT Str; | |
DEVICE_CONSIST_MAPPING_INFO MappingInfo; | |
EFI_DEVICE_PATH_PROTOCOL *HIDevicePath; | |
UINTN Index; | |
ASSERT(DevicePath != NULL); | |
ASSERT(Table != NULL); | |
HIDevicePath = GetHIDevicePath (DevicePath); | |
if (HIDevicePath == NULL) { | |
return NULL; | |
} | |
for (Index = 0; Table[Index] != NULL; Index++) { | |
if (DevicePathCompare (&Table[Index], &HIDevicePath) == 0) { | |
break; | |
} | |
} | |
FreePool (HIDevicePath); | |
if (Table[Index] == NULL) { | |
return NULL; | |
} | |
MappingInfo.Hi = Index; | |
MappingInfo.Mtd = MTDTypeUnknown; | |
MappingInfo.Digital = FALSE; | |
Status = GetDeviceConsistMappingInfo (&MappingInfo, DevicePath); | |
if (EFI_ERROR (Status)) { | |
return NULL; | |
} | |
SetMem (&Str, sizeof (Str), 0); | |
for (Index = 0; mMTDName[Index].MTDType != MTDTypeEnd; Index++) { | |
if (MappingInfo.Mtd == mMTDName[Index].MTDType) { | |
break; | |
} | |
} | |
if (mMTDName[Index].MTDType != MTDTypeEnd) { | |
Status = CatPrint (&Str, L"%s", mMTDName[Index].Name); | |
} | |
if (!EFI_ERROR (Status)) { | |
Status = CatPrint (&Str, L"%d", (UINTN) MappingInfo.Hi); | |
} | |
if (!EFI_ERROR (Status) && MappingInfo.Csd.Str != NULL) { | |
Status = CatPrint (&Str, L"%s", MappingInfo.Csd.Str); | |
FreePool (MappingInfo.Csd.Str); | |
} | |
if (!EFI_ERROR (Status) && Str.Str != NULL) { | |
Status = CatPrint (&Str, L":"); | |
} | |
if (EFI_ERROR (Status)) { | |
SHELL_FREE_NON_NULL (Str.Str); | |
return NULL; | |
} | |
return Str.Str; | |
} | |
/** | |
Function to search the list of mappings for the node on the list based on the key. | |
@param[in] MapKey String Key to search for on the map | |
@return the node on the list. | |
**/ | |
SHELL_MAP_LIST * | |
EFIAPI | |
ShellCommandFindMapItem ( | |
IN CONST CHAR16 *MapKey | |
) | |
{ | |
SHELL_MAP_LIST *MapListItem; | |
for ( MapListItem = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) | |
; !IsNull(&gShellMapList.Link, &MapListItem->Link) | |
; MapListItem = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &MapListItem->Link) | |
){ | |
if (gUnicodeCollation->StriColl(gUnicodeCollation,MapListItem->MapName,(CHAR16*)MapKey) == 0) { | |
return (MapListItem); | |
} | |
} | |
return (NULL); | |
} | |