blob: 1767a7dc4af682b917de596986ad3c2c3375ad40 [file] [log] [blame]
/** @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);
}