summaryrefslogtreecommitdiff
path: root/ShellPkg/Library/UefiShellCommandLib
diff options
context:
space:
mode:
Diffstat (limited to 'ShellPkg/Library/UefiShellCommandLib')
-rwxr-xr-xShellPkg/Library/UefiShellCommandLib/ConsistMapping.c3450
-rw-r--r--ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c4656
-rw-r--r--ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h166
-rw-r--r--ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf130
4 files changed, 4201 insertions, 4201 deletions
diff --git a/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c b/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c
index 1767a7dc4a..db6a20146c 100755
--- a/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c
+++ b/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c
@@ -1,1725 +1,1725 @@
-/** @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);
-}
+/** @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);
+}
diff --git a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
index 75fbd50cbe..624322fe8a 100644
--- a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
+++ b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
@@ -1,2328 +1,2328 @@
-/** @file
- Provides interface to shell internal functions for shell commands.
-
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
- (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "UefiShellCommandLib.h"
-
-// STATIC local variables
-STATIC SHELL_COMMAND_INTERNAL_LIST_ENTRY mCommandList;
-STATIC SCRIPT_FILE_LIST mScriptList;
-STATIC ALIAS_LIST mAliasList;
-STATIC BOOLEAN mEchoState;
-STATIC BOOLEAN mExitRequested;
-STATIC UINT64 mExitCode;
-STATIC BOOLEAN mExitScript;
-STATIC CHAR16 *mProfileList;
-STATIC UINTN mProfileListSize;
-STATIC UINTN mFsMaxCount = 0;
-STATIC UINTN mBlkMaxCount = 0;
-STATIC BUFFER_LIST mFileHandleList;
-
-STATIC CONST CHAR8 Hex[] = {
- '0',
- '1',
- '2',
- '3',
- '4',
- '5',
- '6',
- '7',
- '8',
- '9',
- 'A',
- 'B',
- 'C',
- 'D',
- 'E',
- 'F'
-};
-
-// global variables required by library class.
-EFI_UNICODE_COLLATION_PROTOCOL *gUnicodeCollation = NULL;
-SHELL_MAP_LIST gShellMapList;
-SHELL_MAP_LIST *gShellCurMapping = NULL;
-
-CONST CHAR16 *SupportLevel[] = {
- L"Minimal",
- L"Scripting",
- L"Basic",
- L"Interactive"
-};
-
-/**
- Function to make sure that the global protocol pointers are valid.
- must be called after constructor before accessing the pointers.
-**/
-EFI_STATUS
-EFIAPI
-CommandInit (
- VOID
- )
-{
- UINTN NumHandles;
- EFI_HANDLE *Handles;
- EFI_UNICODE_COLLATION_PROTOCOL *Uc;
- CHAR8 *BestLanguage;
- UINTN Index;
- EFI_STATUS Status;
- CHAR8 *PlatformLang;
-
- if (gUnicodeCollation == NULL) {
- GetEfiGlobalVariable2 (EFI_PLATFORM_LANG_VARIABLE_NAME, (VOID **)&PlatformLang, NULL);
-
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiUnicodeCollation2ProtocolGuid,
- NULL,
- &NumHandles,
- &Handles
- );
- if (EFI_ERROR (Status)) {
- NumHandles = 0;
- Handles = NULL;
- }
-
- for (Index = 0; Index < NumHandles; Index++) {
- //
- // Open Unicode Collation Protocol
- //
- Status = gBS->OpenProtocol (
- Handles[Index],
- &gEfiUnicodeCollation2ProtocolGuid,
- (VOID **)&Uc,
- gImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- //
- // Without clue provided use the first Unicode Collation2 protocol.
- // This may happen when PlatformLang is NULL or when no installed Unicode
- // Collation2 protocol instance supports PlatformLang.
- //
- if (gUnicodeCollation == NULL) {
- gUnicodeCollation = Uc;
- }
-
- if (PlatformLang == NULL) {
- break;
- }
-
- //
- // Find the best matching matching language from the supported languages
- // of Unicode Collation2 protocol.
- //
- BestLanguage = GetBestLanguage (
- Uc->SupportedLanguages,
- FALSE,
- PlatformLang,
- NULL
- );
- if (BestLanguage != NULL) {
- FreePool (BestLanguage);
- gUnicodeCollation = Uc;
- break;
- }
- }
-
- if (Handles != NULL) {
- FreePool (Handles);
- }
-
- if (PlatformLang != NULL) {
- FreePool (PlatformLang);
- }
- }
-
- return (gUnicodeCollation == NULL) ? EFI_UNSUPPORTED : EFI_SUCCESS;
-}
-
-/**
- Constructor for the Shell Command library.
-
- Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell.
-
- @param ImageHandle the image handle of the process
- @param SystemTable the EFI System Table pointer
-
- @retval EFI_SUCCESS the initialization was complete successfully
-**/
-RETURN_STATUS
-EFIAPI
-ShellCommandLibConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
-
- InitializeListHead (&gShellMapList.Link);
- InitializeListHead (&mCommandList.Link);
- InitializeListHead (&mAliasList.Link);
- InitializeListHead (&mScriptList.Link);
- InitializeListHead (&mFileHandleList.Link);
- mEchoState = TRUE;
-
- mExitRequested = FALSE;
- mExitScript = FALSE;
- mProfileListSize = 0;
- mProfileList = NULL;
-
- Status = CommandInit ();
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- return (RETURN_SUCCESS);
-}
-
-/**
- Frees list of file handles.
-
- @param[in] List The list to free.
-**/
-VOID
-FreeFileHandleList (
- IN BUFFER_LIST *List
- )
-{
- BUFFER_LIST *BufferListEntry;
-
- if (List == NULL) {
- return;
- }
-
- //
- // enumerate through the buffer list and free all memory
- //
- for ( BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
- ; !IsListEmpty (&List->Link)
- ; BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
- )
- {
- RemoveEntryList (&BufferListEntry->Link);
- ASSERT (BufferListEntry->Buffer != NULL);
- SHELL_FREE_NON_NULL (((SHELL_COMMAND_FILE_HANDLE *)(BufferListEntry->Buffer))->Path);
- SHELL_FREE_NON_NULL (BufferListEntry->Buffer);
- SHELL_FREE_NON_NULL (BufferListEntry);
- }
-}
-
-/**
- Destructor for the library. free any resources.
-
- @param ImageHandle the image handle of the process
- @param SystemTable the EFI System Table pointer
-
- @retval RETURN_SUCCESS this function always returns success
-**/
-RETURN_STATUS
-EFIAPI
-ShellCommandLibDestructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
- ALIAS_LIST *Node2;
- SCRIPT_FILE_LIST *Node3;
- SHELL_MAP_LIST *MapNode;
-
- //
- // enumerate throught the list and free all the memory
- //
- while (!IsListEmpty (&mCommandList.Link)) {
- Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link);
- RemoveEntryList (&Node->Link);
- SHELL_FREE_NON_NULL (Node->CommandString);
- FreePool (Node);
- DEBUG_CODE (
- Node = NULL;
- );
- }
-
- //
- // enumerate through the alias list and free all memory
- //
- while (!IsListEmpty (&mAliasList.Link)) {
- Node2 = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link);
- RemoveEntryList (&Node2->Link);
- SHELL_FREE_NON_NULL (Node2->CommandString);
- SHELL_FREE_NON_NULL (Node2->Alias);
- SHELL_FREE_NON_NULL (Node2);
- DEBUG_CODE (
- Node2 = NULL;
- );
- }
-
- //
- // enumerate throught the list and free all the memory
- //
- while (!IsListEmpty (&mScriptList.Link)) {
- Node3 = (SCRIPT_FILE_LIST *)GetFirstNode (&mScriptList.Link);
- RemoveEntryList (&Node3->Link);
- DeleteScriptFileStruct (Node3->Data);
- FreePool (Node3);
- }
-
- //
- // enumerate throught the mappings list and free all the memory
- //
- if (!IsListEmpty (&gShellMapList.Link)) {
- for (MapNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
- ; !IsListEmpty (&gShellMapList.Link)
- ; MapNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
- )
- {
- ASSERT (MapNode != NULL);
- RemoveEntryList (&MapNode->Link);
- SHELL_FREE_NON_NULL (MapNode->DevicePath);
- SHELL_FREE_NON_NULL (MapNode->MapName);
- SHELL_FREE_NON_NULL (MapNode->CurrentDirectoryPath);
- FreePool (MapNode);
- }
- }
-
- if (!IsListEmpty (&mFileHandleList.Link)) {
- FreeFileHandleList (&mFileHandleList);
- }
-
- if (mProfileList != NULL) {
- FreePool (mProfileList);
- }
-
- gUnicodeCollation = NULL;
- gShellCurMapping = NULL;
-
- return (RETURN_SUCCESS);
-}
-
-/**
- Find a dynamic command protocol instance given a command name string.
-
- @param CommandString the command name string
-
- @return instance the command protocol instance, if dynamic command instance found
- @retval NULL no dynamic command protocol instance found for name
-**/
-CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *
-ShellCommandFindDynamicCommand (
- IN CONST CHAR16 *CommandString
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *CommandHandleList;
- EFI_HANDLE *NextCommand;
- EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
-
- CommandHandleList = GetHandleListByProtocol (&gEfiShellDynamicCommandProtocolGuid);
- if (CommandHandleList == NULL) {
- //
- // not found or out of resources
- //
- return NULL;
- }
-
- for (NextCommand = CommandHandleList; *NextCommand != NULL; NextCommand++) {
- Status = gBS->HandleProtocol (
- *NextCommand,
- &gEfiShellDynamicCommandProtocolGuid,
- (VOID **)&DynamicCommand
- );
-
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- if (gUnicodeCollation->StriColl (
- gUnicodeCollation,
- (CHAR16 *)CommandString,
- (CHAR16 *)DynamicCommand->CommandName
- ) == 0
- )
- {
- FreePool (CommandHandleList);
- return (DynamicCommand);
- }
- }
-
- FreePool (CommandHandleList);
- return (NULL);
-}
-
-/**
- Checks if a command exists as a dynamic command protocol instance
-
- @param[in] CommandString The command string to check for on the list.
-**/
-BOOLEAN
-ShellCommandDynamicCommandExists (
- IN CONST CHAR16 *CommandString
- )
-{
- return (BOOLEAN)((ShellCommandFindDynamicCommand (CommandString) != NULL));
-}
-
-/**
- Checks if a command is already on the internal command list.
-
- @param[in] CommandString The command string to check for on the list.
-**/
-BOOLEAN
-ShellCommandIsCommandOnInternalList (
- IN CONST CHAR16 *CommandString
- )
-{
- SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
-
- //
- // assert for NULL parameter
- //
- ASSERT (CommandString != NULL);
-
- //
- // check for the command
- //
- for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
- ; !IsNull (&mCommandList.Link, &Node->Link)
- ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
- )
- {
- ASSERT (Node->CommandString != NULL);
- if (gUnicodeCollation->StriColl (
- gUnicodeCollation,
- (CHAR16 *)CommandString,
- Node->CommandString
- ) == 0
- )
- {
- return (TRUE);
- }
- }
-
- return (FALSE);
-}
-
-/**
- Checks if a command exists, either internally or through the dynamic command protocol.
-
- @param[in] CommandString The command string to check for on the list.
-**/
-BOOLEAN
-EFIAPI
-ShellCommandIsCommandOnList (
- IN CONST CHAR16 *CommandString
- )
-{
- if (ShellCommandIsCommandOnInternalList (CommandString)) {
- return TRUE;
- }
-
- return ShellCommandDynamicCommandExists (CommandString);
-}
-
-/**
- Get the help text for a dynamic command.
-
- @param[in] CommandString The command name.
-
- @retval NULL No help text was found.
- @return String of help text. Caller required to free.
-**/
-CHAR16 *
-ShellCommandGetDynamicCommandHelp (
- IN CONST CHAR16 *CommandString
- )
-{
- EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
-
- DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand (CommandString);
- if (DynamicCommand == NULL) {
- return (NULL);
- }
-
- //
- // TODO: how to get proper language?
- //
- return DynamicCommand->GetHelp (DynamicCommand, "en");
-}
-
-/**
- Get the help text for an internal command.
-
- @param[in] CommandString The command name.
-
- @retval NULL No help text was found.
- @return String of help text. Caller reuiqred to free.
-**/
-CHAR16 *
-ShellCommandGetInternalCommandHelp (
- IN CONST CHAR16 *CommandString
- )
-{
- SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
-
- //
- // assert for NULL parameter
- //
- ASSERT (CommandString != NULL);
-
- //
- // check for the command
- //
- for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
- ; !IsNull (&mCommandList.Link, &Node->Link)
- ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
- )
- {
- ASSERT (Node->CommandString != NULL);
- if (gUnicodeCollation->StriColl (
- gUnicodeCollation,
- (CHAR16 *)CommandString,
- Node->CommandString
- ) == 0
- )
- {
- return (HiiGetString (Node->HiiHandle, Node->ManFormatHelp, NULL));
- }
- }
-
- return (NULL);
-}
-
-/**
- Get the help text for a command.
-
- @param[in] CommandString The command name.
-
- @retval NULL No help text was found.
- @return String of help text.Caller reuiqred to free.
-**/
-CHAR16 *
-EFIAPI
-ShellCommandGetCommandHelp (
- IN CONST CHAR16 *CommandString
- )
-{
- CHAR16 *HelpStr;
-
- HelpStr = ShellCommandGetInternalCommandHelp (CommandString);
-
- if (HelpStr == NULL) {
- HelpStr = ShellCommandGetDynamicCommandHelp (CommandString);
- }
-
- return HelpStr;
-}
-
-/**
- Registers handlers of type SHELL_RUN_COMMAND and
- SHELL_GET_MAN_FILENAME for each shell command.
-
- If the ShellSupportLevel is greater than the value of the
- PcdShellSupportLevel then return RETURN_UNSUPPORTED.
-
- Registers the handlers specified by GetHelpInfoHandler and CommandHandler
- with the command specified by CommandString. If the command named by
- CommandString has already been registered, then return
- RETURN_ALREADY_STARTED.
-
- If there are not enough resources available to register the handlers then
- RETURN_OUT_OF_RESOURCES is returned.
-
- If CommandString is NULL, then ASSERT().
- If GetHelpInfoHandler is NULL, then ASSERT().
- If CommandHandler is NULL, then ASSERT().
- If ProfileName is NULL, then ASSERT().
-
- @param[in] CommandString Pointer to the command name. This is the
- name to look for on the command line in
- the shell.
- @param[in] CommandHandler Pointer to a function that runs the
- specified command.
- @param[in] GetManFileName Pointer to a function that provides man
- filename.
- @param[in] ShellMinSupportLevel minimum Shell Support Level which has this
- function.
- @param[in] ProfileName profile name to require for support of this
- function.
- @param[in] CanAffectLE indicates whether this command's return value
- can change the LASTERROR environment variable.
- @param[in] HiiHandle Handle of this command's HII entry.
- @param[in] ManFormatHelp HII locator for the help text.
-
- @retval RETURN_SUCCESS The handlers were registered.
- @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
- register the shell command.
- @retval RETURN_UNSUPPORTED the ShellMinSupportLevel was higher than the
- currently allowed support level.
- @retval RETURN_ALREADY_STARTED The CommandString represents a command that
- is already registered. Only 1 handler set for
- a given command is allowed.
- @sa SHELL_GET_MAN_FILENAME
- @sa SHELL_RUN_COMMAND
-**/
-RETURN_STATUS
-EFIAPI
-ShellCommandRegisterCommandName (
- IN CONST CHAR16 *CommandString,
- IN SHELL_RUN_COMMAND CommandHandler,
- IN SHELL_GET_MAN_FILENAME GetManFileName,
- IN UINT32 ShellMinSupportLevel,
- IN CONST CHAR16 *ProfileName,
- IN CONST BOOLEAN CanAffectLE,
- IN CONST EFI_HII_HANDLE HiiHandle,
- IN CONST EFI_STRING_ID ManFormatHelp
- )
-{
- SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
- SHELL_COMMAND_INTERNAL_LIST_ENTRY *Command;
- SHELL_COMMAND_INTERNAL_LIST_ENTRY *PrevCommand;
- INTN LexicalMatchValue;
-
- //
- // Initialize local variables.
- //
- Command = NULL;
- PrevCommand = NULL;
- LexicalMatchValue = 0;
-
- //
- // ASSERTs for NULL parameters
- //
- ASSERT (CommandString != NULL);
- ASSERT (GetManFileName != NULL);
- ASSERT (CommandHandler != NULL);
- ASSERT (ProfileName != NULL);
-
- //
- // check for shell support level
- //
- if (PcdGet8 (PcdShellSupportLevel) < ShellMinSupportLevel) {
- return (RETURN_UNSUPPORTED);
- }
-
- //
- // check for already on the list
- //
- if (ShellCommandIsCommandOnList (CommandString)) {
- return (RETURN_ALREADY_STARTED);
- }
-
- //
- // allocate memory for new struct
- //
- Node = AllocateZeroPool (sizeof (SHELL_COMMAND_INTERNAL_LIST_ENTRY));
- if (Node == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
-
- Node->CommandString = AllocateCopyPool (StrSize (CommandString), CommandString);
- if (Node->CommandString == NULL) {
- FreePool (Node);
- return RETURN_OUT_OF_RESOURCES;
- }
-
- Node->GetManFileName = GetManFileName;
- Node->CommandHandler = CommandHandler;
- Node->LastError = CanAffectLE;
- Node->HiiHandle = HiiHandle;
- Node->ManFormatHelp = ManFormatHelp;
-
- if ( (StrLen (ProfileName) > 0)
- && (( (mProfileList != NULL)
- && (StrStr (mProfileList, ProfileName) == NULL)) || (mProfileList == NULL))
- )
- {
- ASSERT ((mProfileList == NULL && mProfileListSize == 0) || (mProfileList != NULL));
- if (mProfileList == NULL) {
- //
- // If this is the first make a leading ';'
- //
- StrnCatGrow (&mProfileList, &mProfileListSize, L";", 0);
- }
-
- StrnCatGrow (&mProfileList, &mProfileListSize, ProfileName, 0);
- StrnCatGrow (&mProfileList, &mProfileListSize, L";", 0);
- }
-
- //
- // Insert a new entry on top of the list
- //
- InsertHeadList (&mCommandList.Link, &Node->Link);
-
- //
- // Move a new registered command to its sorted ordered location in the list
- //
- for (Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link),
- PrevCommand = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
- ; !IsNull (&mCommandList.Link, &Command->Link)
- ; Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Command->Link))
- {
- //
- // Get Lexical Comparison Value between PrevCommand and Command list entry
- //
- LexicalMatchValue = gUnicodeCollation->StriColl (
- gUnicodeCollation,
- PrevCommand->CommandString,
- Command->CommandString
- );
-
- //
- // Swap PrevCommand and Command list entry if PrevCommand list entry
- // is alphabetically greater than Command list entry
- //
- if (LexicalMatchValue > 0) {
- Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)SwapListEntries (&PrevCommand->Link, &Command->Link);
- } else if (LexicalMatchValue < 0) {
- //
- // PrevCommand entry is lexically lower than Command entry
- //
- break;
- }
- }
-
- return (RETURN_SUCCESS);
-}
-
-/**
- Function to get the current Profile string.
-
- @retval NULL There are no installed profiles.
- @return A semi-colon delimited list of profiles.
-**/
-CONST CHAR16 *
-EFIAPI
-ShellCommandGetProfileList (
- VOID
- )
-{
- return (mProfileList);
-}
-
-/**
- Checks if a command string has been registered for CommandString and if so it runs
- the previously registered handler for that command with the command line.
-
- If CommandString is NULL, then ASSERT().
-
- If Sections is specified, then each section name listed will be compared in a casesensitive
- manner, to the section names described in Appendix B UEFI Shell 2.0 spec. If the section exists,
- it will be appended to the returned help text. If the section does not exist, no
- information will be returned. If Sections is NULL, then all help text information
- available will be returned.
-
- @param[in] CommandString Pointer to the command name. This is the name
- found on the command line in the shell.
- @param[in, out] RetVal Pointer to the return vaule from the command handler.
-
- @param[in, out] CanAffectLE indicates whether this command's return value
- needs to be placed into LASTERROR environment variable.
-
- @retval RETURN_SUCCESS The handler was run.
- @retval RETURN_NOT_FOUND The CommandString did not match a registered
- command name.
- @sa SHELL_RUN_COMMAND
-**/
-RETURN_STATUS
-EFIAPI
-ShellCommandRunCommandHandler (
- IN CONST CHAR16 *CommandString,
- IN OUT SHELL_STATUS *RetVal,
- IN OUT BOOLEAN *CanAffectLE OPTIONAL
- )
-{
- SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
- EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
-
- //
- // assert for NULL parameters
- //
- ASSERT (CommandString != NULL);
-
- //
- // check for the command
- //
- for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
- ; !IsNull (&mCommandList.Link, &Node->Link)
- ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
- )
- {
- ASSERT (Node->CommandString != NULL);
- if (gUnicodeCollation->StriColl (
- gUnicodeCollation,
- (CHAR16 *)CommandString,
- Node->CommandString
- ) == 0
- )
- {
- if (CanAffectLE != NULL) {
- *CanAffectLE = Node->LastError;
- }
-
- if (RetVal != NULL) {
- *RetVal = Node->CommandHandler (NULL, gST);
- } else {
- Node->CommandHandler (NULL, gST);
- }
-
- return (RETURN_SUCCESS);
- }
- }
-
- //
- // An internal command was not found, try to find a dynamic command
- //
- DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand (CommandString);
- if (DynamicCommand != NULL) {
- if (RetVal != NULL) {
- *RetVal = DynamicCommand->Handler (DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol);
- } else {
- DynamicCommand->Handler (DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol);
- }
-
- return (RETURN_SUCCESS);
- }
-
- return (RETURN_NOT_FOUND);
-}
-
-/**
- Checks if a command string has been registered for CommandString and if so it
- returns the MAN filename specified for that command.
-
- If CommandString is NULL, then ASSERT().
-
- @param[in] CommandString Pointer to the command name. This is the name
- found on the command line in the shell.\
-
- @retval NULL the commandString was not a registered command.
- @return other the name of the MAN file.
- @sa SHELL_GET_MAN_FILENAME
-**/
-CONST CHAR16 *
-EFIAPI
-ShellCommandGetManFileNameHandler (
- IN CONST CHAR16 *CommandString
- )
-{
- SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
-
- //
- // assert for NULL parameters
- //
- ASSERT (CommandString != NULL);
-
- //
- // check for the command
- //
- for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
- ; !IsNull (&mCommandList.Link, &Node->Link)
- ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
- )
- {
- ASSERT (Node->CommandString != NULL);
- if (gUnicodeCollation->StriColl (
- gUnicodeCollation,
- (CHAR16 *)CommandString,
- Node->CommandString
- ) == 0
- )
- {
- return (Node->GetManFileName ());
- }
- }
-
- return (NULL);
-}
-
-/**
- Get the list of all available shell internal commands. This is a linked list
- (via LIST_ENTRY structure). enumerate through it using the BaseLib linked
- list functions. do not modify the values.
-
- @param[in] Sort TRUE to alphabetically sort the values first. FALSE otherwise.
-
- @return a Linked list of all available shell commands.
-**/
-CONST COMMAND_LIST *
-EFIAPI
-ShellCommandGetCommandList (
- IN CONST BOOLEAN Sort
- )
-{
- // if (!Sort) {
- // return ((COMMAND_LIST*)(&mCommandList));
- // }
- return ((COMMAND_LIST *)(&mCommandList));
-}
-
-/**
- Registers aliases to be set as part of the initialization of the shell application.
-
- If Command is NULL, then ASSERT().
- If Alias is NULL, then ASSERT().
-
- @param[in] Command Pointer to the Command
- @param[in] Alias Pointer to Alias
-
- @retval RETURN_SUCCESS The handlers were registered.
- @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
- register the shell command.
-**/
-RETURN_STATUS
-EFIAPI
-ShellCommandRegisterAlias (
- IN CONST CHAR16 *Command,
- IN CONST CHAR16 *Alias
- )
-{
- ALIAS_LIST *Node;
- ALIAS_LIST *CommandAlias;
- ALIAS_LIST *PrevCommandAlias;
- INTN LexicalMatchValue;
-
- //
- // Asserts for NULL
- //
- ASSERT (Command != NULL);
- ASSERT (Alias != NULL);
-
- //
- // allocate memory for new struct
- //
- Node = AllocateZeroPool (sizeof (ALIAS_LIST));
- if (Node == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
-
- Node->CommandString = AllocateCopyPool (StrSize (Command), Command);
- if (Node->CommandString == NULL) {
- FreePool (Node);
- return RETURN_OUT_OF_RESOURCES;
- }
-
- Node->Alias = AllocateCopyPool (StrSize (Alias), Alias);
- if (Node->Alias == NULL) {
- FreePool (Node->CommandString);
- FreePool (Node);
- return RETURN_OUT_OF_RESOURCES;
- }
-
- InsertHeadList (&mAliasList.Link, &Node->Link);
-
- //
- // Move a new pre-defined registered alias to its sorted ordered location in the list
- //
- for ( CommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link),
- PrevCommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link)
- ; !IsNull (&mAliasList.Link, &CommandAlias->Link)
- ; CommandAlias = (ALIAS_LIST *)GetNextNode (&mAliasList.Link, &CommandAlias->Link))
- {
- //
- // Get Lexical comparison value between PrevCommandAlias and CommandAlias List Entry
- //
- LexicalMatchValue = gUnicodeCollation->StriColl (
- gUnicodeCollation,
- PrevCommandAlias->Alias,
- CommandAlias->Alias
- );
-
- //
- // Swap PrevCommandAlias and CommandAlias list entry if PrevCommandAlias list entry
- // is alphabetically greater than CommandAlias list entry
- //
- if (LexicalMatchValue > 0) {
- CommandAlias = (ALIAS_LIST *)SwapListEntries (&PrevCommandAlias->Link, &CommandAlias->Link);
- } else if (LexicalMatchValue < 0) {
- //
- // PrevCommandAlias entry is lexically lower than CommandAlias entry
- //
- break;
- }
- }
-
- return (RETURN_SUCCESS);
-}
-
-/**
- Get the list of all shell alias commands. This is a linked list
- (via LIST_ENTRY structure). enumerate through it using the BaseLib linked
- list functions. do not modify the values.
-
- @return a Linked list of all requested shell alias'.
-**/
-CONST ALIAS_LIST *
-EFIAPI
-ShellCommandGetInitAliasList (
- VOID
- )
-{
- return (&mAliasList);
-}
-
-/**
- Determine if a given alias is on the list of built in alias'.
-
- @param[in] Alias The alias to test for
-
- @retval TRUE The alias is a built in alias
- @retval FALSE The alias is not a built in alias
-**/
-BOOLEAN
-EFIAPI
-ShellCommandIsOnAliasList (
- IN CONST CHAR16 *Alias
- )
-{
- ALIAS_LIST *Node;
-
- //
- // assert for NULL parameter
- //
- ASSERT (Alias != NULL);
-
- //
- // check for the Alias
- //
- for ( Node = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link)
- ; !IsNull (&mAliasList.Link, &Node->Link)
- ; Node = (ALIAS_LIST *)GetNextNode (&mAliasList.Link, &Node->Link)
- )
- {
- ASSERT (Node->CommandString != NULL);
- ASSERT (Node->Alias != NULL);
- if (gUnicodeCollation->StriColl (
- gUnicodeCollation,
- (CHAR16 *)Alias,
- Node->CommandString
- ) == 0
- )
- {
- return (TRUE);
- }
-
- if (gUnicodeCollation->StriColl (
- gUnicodeCollation,
- (CHAR16 *)Alias,
- Node->Alias
- ) == 0
- )
- {
- return (TRUE);
- }
- }
-
- return (FALSE);
-}
-
-/**
- Function to determine current state of ECHO. Echo determines if lines from scripts
- and ECHO commands are enabled.
-
- @retval TRUE Echo is currently enabled
- @retval FALSE Echo is currently disabled
-**/
-BOOLEAN
-EFIAPI
-ShellCommandGetEchoState (
- VOID
- )
-{
- return (mEchoState);
-}
-
-/**
- Function to set current state of ECHO. Echo determines if lines from scripts
- and ECHO commands are enabled.
-
- If State is TRUE, Echo will be enabled.
- If State is FALSE, Echo will be disabled.
-
- @param[in] State How to set echo.
-**/
-VOID
-EFIAPI
-ShellCommandSetEchoState (
- IN BOOLEAN State
- )
-{
- mEchoState = State;
-}
-
-/**
- Indicate that the current shell or script should exit.
-
- @param[in] ScriptOnly TRUE if exiting a script; FALSE otherwise.
- @param[in] ErrorCode The 64 bit error code to return.
-**/
-VOID
-EFIAPI
-ShellCommandRegisterExit (
- IN BOOLEAN ScriptOnly,
- IN CONST UINT64 ErrorCode
- )
-{
- mExitRequested = (BOOLEAN)(!mExitRequested);
- if (mExitRequested) {
- mExitScript = ScriptOnly;
- } else {
- mExitScript = FALSE;
- }
-
- mExitCode = ErrorCode;
-}
-
-/**
- Retrieve the Exit indicator.
-
- @retval TRUE Exit was indicated.
- @retval FALSE Exis was not indicated.
-**/
-BOOLEAN
-EFIAPI
-ShellCommandGetExit (
- VOID
- )
-{
- return (mExitRequested);
-}
-
-/**
- Retrieve the Exit code.
-
- If ShellCommandGetExit returns FALSE than the return from this is undefined.
-
- @return the value passed into RegisterExit.
-**/
-UINT64
-EFIAPI
-ShellCommandGetExitCode (
- VOID
- )
-{
- return (mExitCode);
-}
-
-/**
- Retrieve the Exit script indicator.
-
- If ShellCommandGetExit returns FALSE than the return from this is undefined.
-
- @retval TRUE ScriptOnly was indicated.
- @retval FALSE ScriptOnly was not indicated.
-**/
-BOOLEAN
-EFIAPI
-ShellCommandGetScriptExit (
- VOID
- )
-{
- return (mExitScript);
-}
-
-/**
- Function to cleanup all memory from a SCRIPT_FILE structure.
-
- @param[in] Script The pointer to the structure to cleanup.
-**/
-VOID
-EFIAPI
-DeleteScriptFileStruct (
- IN SCRIPT_FILE *Script
- )
-{
- UINT8 LoopVar;
-
- if (Script == NULL) {
- return;
- }
-
- for (LoopVar = 0; LoopVar < Script->Argc; LoopVar++) {
- SHELL_FREE_NON_NULL (Script->Argv[LoopVar]);
- }
-
- if (Script->Argv != NULL) {
- SHELL_FREE_NON_NULL (Script->Argv);
- }
-
- Script->CurrentCommand = NULL;
- while (!IsListEmpty (&Script->CommandList)) {
- Script->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetFirstNode (&Script->CommandList);
- if (Script->CurrentCommand != NULL) {
- RemoveEntryList (&Script->CurrentCommand->Link);
- if (Script->CurrentCommand->Cl != NULL) {
- SHELL_FREE_NON_NULL (Script->CurrentCommand->Cl);
- }
-
- if (Script->CurrentCommand->Data != NULL) {
- SHELL_FREE_NON_NULL (Script->CurrentCommand->Data);
- }
-
- SHELL_FREE_NON_NULL (Script->CurrentCommand);
- }
- }
-
- SHELL_FREE_NON_NULL (Script->ScriptName);
- SHELL_FREE_NON_NULL (Script);
-}
-
-/**
- Function to return a pointer to the currently running script file object.
-
- @retval NULL A script file is not currently running.
- @return A pointer to the current script file object.
-**/
-SCRIPT_FILE *
-EFIAPI
-ShellCommandGetCurrentScriptFile (
- VOID
- )
-{
- SCRIPT_FILE_LIST *List;
-
- if (IsListEmpty (&mScriptList.Link)) {
- return (NULL);
- }
-
- List = ((SCRIPT_FILE_LIST *)GetFirstNode (&mScriptList.Link));
- return (List->Data);
-}
-
-/**
- Function to set a new script as the currently running one.
-
- This function will correctly stack and unstack nested scripts.
-
- @param[in] Script Pointer to new script information structure. if NULL
- will remove and de-allocate the top-most Script structure.
-
- @return A pointer to the current running script file after this
- change. NULL if removing the final script.
-**/
-SCRIPT_FILE *
-EFIAPI
-ShellCommandSetNewScript (
- IN SCRIPT_FILE *Script OPTIONAL
- )
-{
- SCRIPT_FILE_LIST *Node;
-
- if (Script == NULL) {
- if (IsListEmpty (&mScriptList.Link)) {
- return (NULL);
- }
-
- Node = (SCRIPT_FILE_LIST *)GetFirstNode (&mScriptList.Link);
- RemoveEntryList (&Node->Link);
- DeleteScriptFileStruct (Node->Data);
- FreePool (Node);
- } else {
- Node = AllocateZeroPool (sizeof (SCRIPT_FILE_LIST));
- if (Node == NULL) {
- return (NULL);
- }
-
- Node->Data = Script;
- InsertHeadList (&mScriptList.Link, &Node->Link);
- }
-
- return (ShellCommandGetCurrentScriptFile ());
-}
-
-/**
- Function to generate the next default mapping name.
-
- If the return value is not NULL then it must be callee freed.
-
- @param Type What kind of mapping name to make.
-
- @retval NULL a memory allocation failed.
- @return a new map name string
-**/
-CHAR16 *
-EFIAPI
-ShellCommandCreateNewMappingName (
- IN CONST SHELL_MAPPING_TYPE Type
- )
-{
- CHAR16 *String;
-
- ASSERT (Type < MappingTypeMax);
-
- String = NULL;
-
- String = AllocateZeroPool (PcdGet8 (PcdShellMapNameLength) * sizeof (String[0]));
- UnicodeSPrint (
- String,
- PcdGet8 (PcdShellMapNameLength) * sizeof (String[0]),
- Type == MappingTypeFileSystem ? L"FS%d:" : L"BLK%d:",
- Type == MappingTypeFileSystem ? mFsMaxCount++ : mBlkMaxCount++
- );
-
- return (String);
-}
-
-/**
- Function to add a map node to the list of map items and update the "path" environment variable (optionally).
-
- If Path is TRUE (during initialization only), the path environment variable will also be updated to include
- default paths on the new map name...
-
- Path should be FALSE when this function is called from the protocol SetMap function.
-
- @param[in] Name The human readable mapped name.
- @param[in] DevicePath The Device Path for this map.
- @param[in] Flags The Flags attribute for this map item.
- @param[in] Path TRUE to update path, FALSE to skip this step (should only be TRUE during initialization).
-
- @retval EFI_SUCCESS The addition was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_INVALID_PARAMETER A parameter was invalid.
-**/
-EFI_STATUS
-EFIAPI
-ShellCommandAddMapItemAndUpdatePath (
- IN CONST CHAR16 *Name,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN CONST UINT64 Flags,
- IN CONST BOOLEAN Path
- )
-{
- EFI_STATUS Status;
- SHELL_MAP_LIST *MapListNode;
- CONST CHAR16 *OriginalPath;
- CHAR16 *NewPath;
- UINTN NewPathSize;
-
- NewPathSize = 0;
- NewPath = NULL;
- OriginalPath = NULL;
- Status = EFI_SUCCESS;
-
- MapListNode = AllocateZeroPool (sizeof (SHELL_MAP_LIST));
- if (MapListNode == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- } else {
- MapListNode->Flags = Flags;
- MapListNode->MapName = AllocateCopyPool (StrSize (Name), Name);
- MapListNode->DevicePath = DuplicateDevicePath (DevicePath);
- if ((MapListNode->MapName == NULL) || (MapListNode->DevicePath == NULL)) {
- Status = EFI_OUT_OF_RESOURCES;
- } else {
- InsertTailList (&gShellMapList.Link, &MapListNode->Link);
- }
- }
-
- if (EFI_ERROR (Status)) {
- if (MapListNode != NULL) {
- if (MapListNode->DevicePath != NULL) {
- FreePool (MapListNode->DevicePath);
- }
-
- if (MapListNode->MapName != NULL) {
- FreePool (MapListNode->MapName);
- }
-
- FreePool (MapListNode);
- }
- } else if (Path) {
- //
- // Since there was no error and Path was TRUE
- // Now add the correct path for that mapping
- //
- OriginalPath = gEfiShellProtocol->GetEnv (L"path");
- ASSERT ((NewPath == NULL && NewPathSize == 0) || (NewPath != NULL));
- if (OriginalPath != NULL) {
- StrnCatGrow (&NewPath, &NewPathSize, OriginalPath, 0);
- StrnCatGrow (&NewPath, &NewPathSize, L";", 0);
- }
-
- StrnCatGrow (&NewPath, &NewPathSize, Name, 0);
- StrnCatGrow (&NewPath, &NewPathSize, L"\\efi\\tools\\;", 0);
- StrnCatGrow (&NewPath, &NewPathSize, Name, 0);
- StrnCatGrow (&NewPath, &NewPathSize, L"\\efi\\boot\\;", 0);
- StrnCatGrow (&NewPath, &NewPathSize, Name, 0);
- StrnCatGrow (&NewPath, &NewPathSize, L"\\", 0);
-
- Status = gEfiShellProtocol->SetEnv (L"path", NewPath, TRUE);
- ASSERT_EFI_ERROR (Status);
- FreePool (NewPath);
- }
-
- return (Status);
-}
-
-/**
- Creates the default map names for each device path in the system with
- a protocol depending on the Type.
-
- Creates the consistent map names for each device path in the system with
- a protocol depending on the Type.
-
- Note: This will reset all mappings in the system("map -r").
-
- Also sets up the default path environment variable if Type is FileSystem.
-
- @retval EFI_SUCCESS All map names were created successfully.
- @retval EFI_NOT_FOUND No protocols were found in the system.
- @return Error returned from gBS->LocateHandle().
-
- @sa LocateHandle
-**/
-EFI_STATUS
-EFIAPI
-ShellCommandCreateInitialMappingsAndPaths (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleList;
- UINTN Count;
- EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
- CHAR16 *NewDefaultName;
- CHAR16 *NewConsistName;
- EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
- SHELL_MAP_LIST *MapListNode;
- CONST CHAR16 *CurDir;
- CHAR16 *SplitCurDir;
- CHAR16 *MapName;
- SHELL_MAP_LIST *MapListItem;
-
- ConsistMappingTable = NULL;
- SplitCurDir = NULL;
- MapName = NULL;
- MapListItem = NULL;
- HandleList = NULL;
-
- //
- // Reset the static members back to zero
- //
- mFsMaxCount = 0;
- mBlkMaxCount = 0;
-
- gEfiShellProtocol->SetEnv (L"path", L"", TRUE);
-
- //
- // First empty out the existing list.
- //
- if (!IsListEmpty (&gShellMapList.Link)) {
- for ( MapListNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
- ; !IsListEmpty (&gShellMapList.Link)
- ; MapListNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
- )
- {
- RemoveEntryList (&MapListNode->Link);
- SHELL_FREE_NON_NULL (MapListNode->DevicePath);
- SHELL_FREE_NON_NULL (MapListNode->MapName);
- SHELL_FREE_NON_NULL (MapListNode->CurrentDirectoryPath);
- FreePool (MapListNode);
- } // for loop
- }
-
- //
- // Find each handle with Simple File System
- //
- HandleList = GetHandleListByProtocol (&gEfiSimpleFileSystemProtocolGuid);
- if (HandleList != NULL) {
- //
- // Do a count of the handles
- //
- for (Count = 0; HandleList[Count] != NULL; Count++) {
- }
-
- //
- // Get all Device Paths
- //
- DevicePathList = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL *) * Count);
- if (DevicePathList == NULL) {
- SHELL_FREE_NON_NULL (HandleList);
- return EFI_OUT_OF_RESOURCES;
- }
-
- for (Count = 0; HandleList[Count] != NULL; Count++) {
- DevicePathList[Count] = DevicePathFromHandle (HandleList[Count]);
- }
-
- //
- // Sort all DevicePaths
- //
- PerformQuickSort (DevicePathList, Count, sizeof (EFI_DEVICE_PATH_PROTOCOL *), DevicePathCompare);
-
- if (!EFI_ERROR (ShellCommandConsistMappingInitialize (&ConsistMappingTable))) {
- //
- // Assign new Mappings to all...
- //
- for (Count = 0; HandleList[Count] != NULL; Count++) {
- //
- // Get default name first
- //
- NewDefaultName = ShellCommandCreateNewMappingName (MappingTypeFileSystem);
- ASSERT (NewDefaultName != NULL);
- Status = ShellCommandAddMapItemAndUpdatePath (NewDefaultName, DevicePathList[Count], 0, TRUE);
- ASSERT_EFI_ERROR (Status);
- FreePool (NewDefaultName);
-
- //
- // Now do consistent name
- //
- NewConsistName = ShellCommandConsistMappingGenMappingName (DevicePathList[Count], ConsistMappingTable);
- if (NewConsistName != NULL) {
- Status = ShellCommandAddMapItemAndUpdatePath (NewConsistName, DevicePathList[Count], 0, FALSE);
- ASSERT_EFI_ERROR (Status);
- FreePool (NewConsistName);
- }
- }
- }
-
- if (ConsistMappingTable != NULL) {
- ShellCommandConsistMappingUnInitialize (ConsistMappingTable);
- }
-
- SHELL_FREE_NON_NULL (HandleList);
- SHELL_FREE_NON_NULL (DevicePathList);
-
- HandleList = NULL;
-
- //
- // gShellCurMapping point to node of current file system in the gShellMapList. When reset all mappings,
- // all nodes in the gShellMapList will be free. Then gShellCurMapping will be a dangling pointer, So,
- // after created new mappings, we should reset the gShellCurMapping pointer back to node of current file system.
- //
- if (gShellCurMapping != NULL) {
- gShellCurMapping = NULL;
- CurDir = gEfiShellProtocol->GetEnv (L"cwd");
- if (CurDir != NULL) {
- MapName = AllocateCopyPool (StrSize (CurDir), CurDir);
- if (MapName == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- SplitCurDir = StrStr (MapName, L":");
- if (SplitCurDir == NULL) {
- SHELL_FREE_NON_NULL (MapName);
- return EFI_UNSUPPORTED;
- }
-
- *(SplitCurDir + 1) = CHAR_NULL;
- MapListItem = ShellCommandFindMapItem (MapName);
- if (MapListItem != NULL) {
- gShellCurMapping = MapListItem;
- }
-
- SHELL_FREE_NON_NULL (MapName);
- }
- }
- } else {
- Count = (UINTN)-1;
- }
-
- //
- // Find each handle with Block Io
- //
- HandleList = GetHandleListByProtocol (&gEfiBlockIoProtocolGuid);
- if (HandleList != NULL) {
- for (Count = 0; HandleList[Count] != NULL; Count++) {
- }
-
- //
- // Get all Device Paths
- //
- DevicePathList = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL *) * Count);
- if (DevicePathList == NULL) {
- SHELL_FREE_NON_NULL (HandleList);
- return EFI_OUT_OF_RESOURCES;
- }
-
- for (Count = 0; HandleList[Count] != NULL; Count++) {
- DevicePathList[Count] = DevicePathFromHandle (HandleList[Count]);
- }
-
- //
- // Sort all DevicePaths
- //
- PerformQuickSort (DevicePathList, Count, sizeof (EFI_DEVICE_PATH_PROTOCOL *), DevicePathCompare);
-
- //
- // Assign new Mappings to all...
- //
- for (Count = 0; HandleList[Count] != NULL; Count++) {
- //
- // Get default name first
- //
- NewDefaultName = ShellCommandCreateNewMappingName (MappingTypeBlockIo);
- ASSERT (NewDefaultName != NULL);
- Status = ShellCommandAddMapItemAndUpdatePath (NewDefaultName, DevicePathList[Count], 0, FALSE);
- ASSERT_EFI_ERROR (Status);
- FreePool (NewDefaultName);
- }
-
- SHELL_FREE_NON_NULL (HandleList);
- SHELL_FREE_NON_NULL (DevicePathList);
- } else if (Count == (UINTN)-1) {
- return (EFI_NOT_FOUND);
- }
-
- return (EFI_SUCCESS);
-}
-
-/**
- Add mappings for any devices without one. Do not change any existing maps.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-EFIAPI
-ShellCommandUpdateMapping (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleList;
- UINTN Count;
- EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
- CHAR16 *NewDefaultName;
- CHAR16 *NewConsistName;
- EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
-
- HandleList = NULL;
- Status = EFI_SUCCESS;
-
- //
- // remove mappings that represent removed devices.
- //
-
- //
- // Find each handle with Simple File System
- //
- HandleList = GetHandleListByProtocol (&gEfiSimpleFileSystemProtocolGuid);
- if (HandleList != NULL) {
- //
- // Do a count of the handles
- //
- for (Count = 0; HandleList[Count] != NULL; Count++) {
- }
-
- //
- // Get all Device Paths
- //
- DevicePathList = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL *) * Count);
- if (DevicePathList == NULL) {
- return (EFI_OUT_OF_RESOURCES);
- }
-
- for (Count = 0; HandleList[Count] != NULL; Count++) {
- DevicePathList[Count] = DevicePathFromHandle (HandleList[Count]);
- }
-
- //
- // Sort all DevicePaths
- //
- PerformQuickSort (DevicePathList, Count, sizeof (EFI_DEVICE_PATH_PROTOCOL *), DevicePathCompare);
-
- Status = ShellCommandConsistMappingInitialize (&ConsistMappingTable);
-
- //
- // Assign new Mappings to remainders
- //
- for (Count = 0; !EFI_ERROR (Status) && HandleList[Count] != NULL; Count++) {
- //
- // Skip ones that already have
- //
- if (gEfiShellProtocol->GetMapFromDevicePath (&DevicePathList[Count]) != NULL) {
- continue;
- }
-
- //
- // Get default name
- //
- NewDefaultName = ShellCommandCreateNewMappingName (MappingTypeFileSystem);
- if (NewDefaultName == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- break;
- }
-
- //
- // Call shell protocol SetMap function now...
- //
- Status = gEfiShellProtocol->SetMap (DevicePathList[Count], NewDefaultName);
-
- if (!EFI_ERROR (Status)) {
- //
- // Now do consistent name
- //
- NewConsistName = ShellCommandConsistMappingGenMappingName (DevicePathList[Count], ConsistMappingTable);
- if (NewConsistName != NULL) {
- Status = gEfiShellProtocol->SetMap (DevicePathList[Count], NewConsistName);
- FreePool (NewConsistName);
- }
- }
-
- FreePool (NewDefaultName);
- }
-
- ShellCommandConsistMappingUnInitialize (ConsistMappingTable);
- SHELL_FREE_NON_NULL (HandleList);
- SHELL_FREE_NON_NULL (DevicePathList);
-
- HandleList = NULL;
- } else {
- Count = (UINTN)-1;
- }
-
- //
- // Do it all over again for gEfiBlockIoProtocolGuid
- //
-
- return (Status);
-}
-
-/**
- Converts a SHELL_FILE_HANDLE to an EFI_FILE_PROTOCOL*.
-
- @param[in] Handle The SHELL_FILE_HANDLE to convert.
-
- @return a EFI_FILE_PROTOCOL* representing the same file.
-**/
-EFI_FILE_PROTOCOL *
-EFIAPI
-ConvertShellHandleToEfiFileProtocol (
- IN CONST SHELL_FILE_HANDLE Handle
- )
-{
- return ((EFI_FILE_PROTOCOL *)(Handle));
-}
-
-/**
- Converts a EFI_FILE_PROTOCOL* to an SHELL_FILE_HANDLE.
-
- @param[in] Handle The pointer to EFI_FILE_PROTOCOL to convert.
- @param[in] Path The path to the file for verification.
-
- @return A SHELL_FILE_HANDLE representing the same file.
- @retval NULL There was not enough memory.
-**/
-SHELL_FILE_HANDLE
-EFIAPI
-ConvertEfiFileProtocolToShellHandle (
- IN CONST EFI_FILE_PROTOCOL *Handle,
- IN CONST CHAR16 *Path
- )
-{
- SHELL_COMMAND_FILE_HANDLE *Buffer;
- BUFFER_LIST *NewNode;
-
- if (Path != NULL) {
- Buffer = AllocateZeroPool (sizeof (SHELL_COMMAND_FILE_HANDLE));
- if (Buffer == NULL) {
- return (NULL);
- }
-
- NewNode = AllocateZeroPool (sizeof (BUFFER_LIST));
- if (NewNode == NULL) {
- SHELL_FREE_NON_NULL (Buffer);
- return (NULL);
- }
-
- Buffer->FileHandle = (EFI_FILE_PROTOCOL *)Handle;
- Buffer->Path = StrnCatGrow (&Buffer->Path, NULL, Path, 0);
- if (Buffer->Path == NULL) {
- SHELL_FREE_NON_NULL (NewNode);
- SHELL_FREE_NON_NULL (Buffer);
- return (NULL);
- }
-
- NewNode->Buffer = Buffer;
-
- InsertHeadList (&mFileHandleList.Link, &NewNode->Link);
- }
-
- return ((SHELL_FILE_HANDLE)(Handle));
-}
-
-/**
- Find the path that was logged with the specified SHELL_FILE_HANDLE.
-
- @param[in] Handle The SHELL_FILE_HANDLE to query on.
-
- @return A pointer to the path for the file.
-**/
-CONST CHAR16 *
-EFIAPI
-ShellFileHandleGetPath (
- IN CONST SHELL_FILE_HANDLE Handle
- )
-{
- BUFFER_LIST *Node;
-
- for (Node = (BUFFER_LIST *)GetFirstNode (&mFileHandleList.Link)
- ; !IsNull (&mFileHandleList.Link, &Node->Link)
- ; Node = (BUFFER_LIST *)GetNextNode (&mFileHandleList.Link, &Node->Link)
- )
- {
- if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)) {
- return (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path);
- }
- }
-
- return (NULL);
-}
-
-/**
- Remove a SHELL_FILE_HANDLE from the list of SHELL_FILE_HANDLES.
-
- @param[in] Handle The SHELL_FILE_HANDLE to remove.
-
- @retval TRUE The item was removed.
- @retval FALSE The item was not found.
-**/
-BOOLEAN
-EFIAPI
-ShellFileHandleRemove (
- IN CONST SHELL_FILE_HANDLE Handle
- )
-{
- BUFFER_LIST *Node;
-
- for (Node = (BUFFER_LIST *)GetFirstNode (&mFileHandleList.Link)
- ; !IsNull (&mFileHandleList.Link, &Node->Link)
- ; Node = (BUFFER_LIST *)GetNextNode (&mFileHandleList.Link, &Node->Link)
- )
- {
- if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)) {
- RemoveEntryList (&Node->Link);
- SHELL_FREE_NON_NULL (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path);
- SHELL_FREE_NON_NULL (Node->Buffer);
- SHELL_FREE_NON_NULL (Node);
- return (TRUE);
- }
- }
-
- return (FALSE);
-}
-
-/**
- Function to determine if a SHELL_FILE_HANDLE is at the end of the file.
-
- This will NOT work on directories.
-
- If Handle is NULL, then ASSERT.
-
- @param[in] Handle the file handle
-
- @retval TRUE the position is at the end of the file
- @retval FALSE the position is not at the end of the file
-**/
-BOOLEAN
-EFIAPI
-ShellFileHandleEof (
- IN SHELL_FILE_HANDLE Handle
- )
-{
- EFI_FILE_INFO *Info;
- UINT64 Pos;
- BOOLEAN RetVal;
-
- //
- // ASSERT if Handle is NULL
- //
- ASSERT (Handle != NULL);
-
- gEfiShellProtocol->GetFilePosition (Handle, &Pos);
- Info = gEfiShellProtocol->GetFileInfo (Handle);
- gEfiShellProtocol->SetFilePosition (Handle, Pos);
-
- if (Info == NULL) {
- return (FALSE);
- }
-
- if (Pos == Info->FileSize) {
- RetVal = TRUE;
- } else {
- RetVal = FALSE;
- }
-
- FreePool (Info);
-
- return (RetVal);
-}
-
-/**
- Frees any BUFFER_LIST defined type.
-
- @param[in] List The BUFFER_LIST object to free.
-**/
-VOID
-EFIAPI
-FreeBufferList (
- IN BUFFER_LIST *List
- )
-{
- BUFFER_LIST *BufferListEntry;
-
- if (List == NULL) {
- return;
- }
-
- //
- // enumerate through the buffer list and free all memory
- //
- for ( BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
- ; !IsListEmpty (&List->Link)
- ; BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
- )
- {
- RemoveEntryList (&BufferListEntry->Link);
- if (BufferListEntry->Buffer != NULL) {
- FreePool (BufferListEntry->Buffer);
- }
-
- FreePool (BufferListEntry);
- }
-}
-
-/**
- Dump some hexadecimal data to the screen.
-
- @param[in] Indent How many spaces to indent the output.
- @param[in] Offset The offset of the printing.
- @param[in] DataSize The size in bytes of UserData.
- @param[in] UserData The data to print out.
-**/
-VOID
-EFIAPI
-DumpHex (
- IN UINTN Indent,
- IN UINTN Offset,
- IN UINTN DataSize,
- IN VOID *UserData
- )
-{
- UINT8 *Data;
-
- CHAR8 Val[50];
-
- CHAR8 Str[20];
-
- UINT8 TempByte;
- UINTN Size;
- UINTN Index;
-
- Data = UserData;
- while (DataSize != 0) {
- Size = 16;
- if (Size > DataSize) {
- Size = DataSize;
- }
-
- for (Index = 0; Index < Size; Index += 1) {
- TempByte = Data[Index];
- Val[Index * 3 + 0] = Hex[TempByte >> 4];
- Val[Index * 3 + 1] = Hex[TempByte & 0xF];
- Val[Index * 3 + 2] = (CHAR8)((Index == 7) ? '-' : ' ');
- Str[Index] = (CHAR8)((TempByte < ' ' || TempByte > '~') ? '.' : TempByte);
- }
-
- Val[Index * 3] = 0;
- Str[Index] = 0;
- ShellPrintEx (-1, -1, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);
-
- Data += Size;
- Offset += Size;
- DataSize -= Size;
- }
-}
-
-/**
- Dump HEX data into buffer.
-
- @param[in] Buffer HEX data to be dumped in Buffer.
- @param[in] Indent How many spaces to indent the output.
- @param[in] Offset The offset of the printing.
- @param[in] DataSize The size in bytes of UserData.
- @param[in] UserData The data to print out.
-**/
-CHAR16 *
-EFIAPI
-CatSDumpHex (
- IN CHAR16 *Buffer,
- IN UINTN Indent,
- IN UINTN Offset,
- IN UINTN DataSize,
- IN VOID *UserData
- )
-{
- UINT8 *Data;
- UINT8 TempByte;
- UINTN Size;
- UINTN Index;
- CHAR8 Val[50];
- CHAR8 Str[20];
- CHAR16 *RetVal;
- CHAR16 *TempRetVal;
-
- Data = UserData;
- RetVal = Buffer;
- while (DataSize != 0) {
- Size = 16;
- if (Size > DataSize) {
- Size = DataSize;
- }
-
- for (Index = 0; Index < Size; Index += 1) {
- TempByte = Data[Index];
- Val[Index * 3 + 0] = Hex[TempByte >> 4];
- Val[Index * 3 + 1] = Hex[TempByte & 0xF];
- Val[Index * 3 + 2] = (CHAR8)((Index == 7) ? '-' : ' ');
- Str[Index] = (CHAR8)((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);
- }
-
- Val[Index * 3] = 0;
- Str[Index] = 0;
- TempRetVal = CatSPrint (RetVal, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);
- SHELL_FREE_NON_NULL (RetVal);
- RetVal = TempRetVal;
-
- Data += Size;
- Offset += Size;
- DataSize -= Size;
- }
-
- return RetVal;
-}
-
-/**
- ORDERED_COLLECTION_USER_COMPARE function for SHELL_SORT_UNIQUE_NAME objects.
-
- @param[in] Unique1AsVoid The first SHELL_SORT_UNIQUE_NAME object (Unique1),
- passed in as a pointer-to-VOID.
-
- @param[in] Unique2AsVoid The second SHELL_SORT_UNIQUE_NAME object (Unique2),
- passed in as a pointer-to-VOID.
-
- @retval <0 If Unique1 compares less than Unique2.
-
- @retval 0 If Unique1 compares equal to Unique2.
-
- @retval >0 If Unique1 compares greater than Unique2.
-**/
-STATIC
-INTN
-EFIAPI
-UniqueNameCompare (
- IN CONST VOID *Unique1AsVoid,
- IN CONST VOID *Unique2AsVoid
- )
-{
- CONST SHELL_SORT_UNIQUE_NAME *Unique1;
- CONST SHELL_SORT_UNIQUE_NAME *Unique2;
-
- Unique1 = Unique1AsVoid;
- Unique2 = Unique2AsVoid;
-
- //
- // We need to cast away CONST for EFI_UNICODE_COLLATION_STRICOLL.
- //
- return gUnicodeCollation->StriColl (
- gUnicodeCollation,
- (CHAR16 *)Unique1->Alias,
- (CHAR16 *)Unique2->Alias
- );
-}
-
-/**
- ORDERED_COLLECTION_KEY_COMPARE function for SHELL_SORT_UNIQUE_NAME objects.
-
- @param[in] UniqueAliasAsVoid The CHAR16 string UniqueAlias, passed in as a
- pointer-to-VOID.
-
- @param[in] UniqueAsVoid The SHELL_SORT_UNIQUE_NAME object (Unique),
- passed in as a pointer-to-VOID.
-
- @retval <0 If UniqueAlias compares less than Unique->Alias.
-
- @retval 0 If UniqueAlias compares equal to Unique->Alias.
-
- @retval >0 If UniqueAlias compares greater than Unique->Alias.
-**/
-STATIC
-INTN
-EFIAPI
-UniqueNameAliasCompare (
- IN CONST VOID *UniqueAliasAsVoid,
- IN CONST VOID *UniqueAsVoid
- )
-{
- CONST CHAR16 *UniqueAlias;
- CONST SHELL_SORT_UNIQUE_NAME *Unique;
-
- UniqueAlias = UniqueAliasAsVoid;
- Unique = UniqueAsVoid;
-
- //
- // We need to cast away CONST for EFI_UNICODE_COLLATION_STRICOLL.
- //
- return gUnicodeCollation->StriColl (
- gUnicodeCollation,
- (CHAR16 *)UniqueAlias,
- (CHAR16 *)Unique->Alias
- );
-}
-
-/**
- Sort an EFI_SHELL_FILE_INFO list, optionally moving duplicates to a separate
- list.
-
- @param[in,out] FileList The list of EFI_SHELL_FILE_INFO objects to sort.
-
- If FileList is NULL on input, then FileList is
- considered an empty, hence already sorted, list.
-
- Otherwise, if (*FileList) is NULL on input, then
- EFI_INVALID_PARAMETER is returned.
-
- Otherwise, the caller is responsible for having
- initialized (*FileList)->Link with
- InitializeListHead(). No other fields in the
- (**FileList) head element are accessed by this
- function.
-
- On output, (*FileList) is sorted according to Order.
- If Duplicates is NULL on input, then duplicate
- elements are preserved, sorted stably, on
- (*FileList). If Duplicates is not NULL on input,
- then duplicates are moved (stably sorted) to the
- new, dynamically allocated (*Duplicates) list.
-
- @param[out] Duplicates If Duplicates is NULL on input, (*FileList) will be
- a monotonically ordered list on output, with
- duplicates stably sorted.
-
- If Duplicates is not NULL on input, (*FileList) will
- be a strictly monotonically oredered list on output,
- with duplicates separated (stably sorted) to
- (*Duplicates). All fields except Link will be
- zero-initialized in the (**Duplicates) head element.
- If no duplicates exist, then (*Duplicates) is set to
- NULL on output.
-
- @param[in] Order Determines the comparison operation between
- EFI_SHELL_FILE_INFO objects.
-
- @retval EFI_INVALID_PARAMETER (UINTN)Order is greater than or equal to
- (UINTN)ShellSortFileListMax. Neither the
- (*FileList) nor the (*Duplicates) list has
- been modified.
-
- @retval EFI_INVALID_PARAMETER (*FileList) was NULL on input. Neither the
- (*FileList) nor the (*Duplicates) list has
- been modified.
-
- @retval EFI_OUT_OF_RESOURCES Memory allocation failed. Neither the
- (*FileList) nor the (*Duplicates) list has
- been modified.
-
- @retval EFI_SUCCESS Sorting successful, including the case when
- FileList is NULL on input.
-**/
-EFI_STATUS
-EFIAPI
-ShellSortFileList (
- IN OUT EFI_SHELL_FILE_INFO **FileList,
- OUT EFI_SHELL_FILE_INFO **Duplicates OPTIONAL,
- IN SHELL_SORT_FILE_LIST Order
- )
-{
- LIST_ENTRY *FilesHead;
- ORDERED_COLLECTION *Sort;
- LIST_ENTRY *FileEntry;
- EFI_SHELL_FILE_INFO *FileInfo;
- SHELL_SORT_UNIQUE_NAME *Unique;
- EFI_STATUS Status;
- EFI_SHELL_FILE_INFO *Dupes;
- LIST_ENTRY *NextFileEntry;
- CONST CHAR16 *Alias;
- ORDERED_COLLECTION_ENTRY *SortEntry;
- LIST_ENTRY *TargetFileList;
- ORDERED_COLLECTION_ENTRY *NextSortEntry;
- VOID *UniqueAsVoid;
-
- if ((UINTN)Order >= (UINTN)ShellSortFileListMax) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (FileList == NULL) {
- //
- // FileList is considered empty, hence already sorted, with no duplicates.
- //
- if (Duplicates != NULL) {
- *Duplicates = NULL;
- }
-
- return EFI_SUCCESS;
- }
-
- if (*FileList == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- FilesHead = &(*FileList)->Link;
-
- //
- // Collect all the unique names.
- //
- Sort = OrderedCollectionInit (UniqueNameCompare, UniqueNameAliasCompare);
- if (Sort == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- BASE_LIST_FOR_EACH (FileEntry, FilesHead) {
- FileInfo = (EFI_SHELL_FILE_INFO *)FileEntry;
-
- //
- // Try to record the name of this file as a unique name.
- //
- Unique = AllocatePool (sizeof (*Unique));
- if (Unique == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto UninitSort;
- }
-
- Unique->Alias = ((Order == ShellSortFileListByFileName) ?
- FileInfo->FileName :
- FileInfo->FullName);
- InitializeListHead (&Unique->SameNameList);
-
- Status = OrderedCollectionInsert (Sort, NULL, Unique);
- if (EFI_ERROR (Status)) {
- //
- // Only two errors are possible: memory allocation failed, or this name
- // has been encountered before. In either case, the
- // SHELL_SORT_UNIQUE_NAME object being constructed has to be released.
- //
- FreePool (Unique);
- //
- // Memory allocation failure is fatal, while having seen the same name
- // before is normal.
- //
- if (Status == EFI_OUT_OF_RESOURCES) {
- goto UninitSort;
- }
-
- ASSERT (Status == EFI_ALREADY_STARTED);
- }
- }
-
- //
- // Set Dupes to suppress incorrect compiler/analyzer warnings.
- //
- Dupes = NULL;
-
- //
- // If separation of duplicates has been requested, allocate the list for
- // them.
- //
- if (Duplicates != NULL) {
- Dupes = AllocateZeroPool (sizeof (*Dupes));
- if (Dupes == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto UninitSort;
- }
-
- InitializeListHead (&Dupes->Link);
- }
-
- //
- // No memory allocation beyond this point; thus, no chance to fail. We can
- // now migrate the EFI_SHELL_FILE_INFO objects from (*FileList) to Sort.
- //
- BASE_LIST_FOR_EACH_SAFE (FileEntry, NextFileEntry, FilesHead) {
- FileInfo = (EFI_SHELL_FILE_INFO *)FileEntry;
- //
- // Look up the SHELL_SORT_UNIQUE_NAME that matches FileInfo's name.
- //
- Alias = ((Order == ShellSortFileListByFileName) ?
- FileInfo->FileName :
- FileInfo->FullName);
- SortEntry = OrderedCollectionFind (Sort, Alias);
- ASSERT (SortEntry != NULL);
- Unique = OrderedCollectionUserStruct (SortEntry);
- //
- // Move FileInfo from (*FileList) to the end of the list of files whose
- // names all compare identical to FileInfo's name.
- //
- RemoveEntryList (&FileInfo->Link);
- InsertTailList (&Unique->SameNameList, &FileInfo->Link);
- }
-
- //
- // All EFI_SHELL_FILE_INFO objects originally in (*FileList) have been
- // distributed to Sort. Now migrate them back to (*FileList), advancing in
- // unique name order.
- //
- for (SortEntry = OrderedCollectionMin (Sort);
- SortEntry != NULL;
- SortEntry = OrderedCollectionNext (SortEntry))
- {
- Unique = OrderedCollectionUserStruct (SortEntry);
- //
- // The first FileInfo encountered for each unique name goes back on
- // (*FileList) unconditionally. Further FileInfo instances for the same
- // unique name -- that is, duplicates -- are either returned to (*FileList)
- // or separated, dependent on the caller's request.
- //
- TargetFileList = FilesHead;
- BASE_LIST_FOR_EACH_SAFE (FileEntry, NextFileEntry, &Unique->SameNameList) {
- RemoveEntryList (FileEntry);
- InsertTailList (TargetFileList, FileEntry);
- if (Duplicates != NULL) {
- TargetFileList = &Dupes->Link;
- }
- }
- }
-
- //
- // We're done. If separation of duplicates has been requested, output the
- // list of duplicates -- and free that list at once, if it's empty (i.e., if
- // no duplicates have been found).
- //
- if (Duplicates != NULL) {
- if (IsListEmpty (&Dupes->Link)) {
- FreePool (Dupes);
- *Duplicates = NULL;
- } else {
- *Duplicates = Dupes;
- }
- }
-
- Status = EFI_SUCCESS;
-
- //
- // Fall through.
- //
-UninitSort:
- for (SortEntry = OrderedCollectionMin (Sort);
- SortEntry != NULL;
- SortEntry = NextSortEntry)
- {
- NextSortEntry = OrderedCollectionNext (SortEntry);
- OrderedCollectionDelete (Sort, SortEntry, &UniqueAsVoid);
- Unique = UniqueAsVoid;
- ASSERT (IsListEmpty (&Unique->SameNameList));
- FreePool (Unique);
- }
-
- OrderedCollectionUninit (Sort);
-
- return Status;
-}
+/** @file
+ Provides interface to shell internal functions for shell commands.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiShellCommandLib.h"
+
+// STATIC local variables
+STATIC SHELL_COMMAND_INTERNAL_LIST_ENTRY mCommandList;
+STATIC SCRIPT_FILE_LIST mScriptList;
+STATIC ALIAS_LIST mAliasList;
+STATIC BOOLEAN mEchoState;
+STATIC BOOLEAN mExitRequested;
+STATIC UINT64 mExitCode;
+STATIC BOOLEAN mExitScript;
+STATIC CHAR16 *mProfileList;
+STATIC UINTN mProfileListSize;
+STATIC UINTN mFsMaxCount = 0;
+STATIC UINTN mBlkMaxCount = 0;
+STATIC BUFFER_LIST mFileHandleList;
+
+STATIC CONST CHAR8 Hex[] = {
+ '0',
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F'
+};
+
+// global variables required by library class.
+EFI_UNICODE_COLLATION_PROTOCOL *gUnicodeCollation = NULL;
+SHELL_MAP_LIST gShellMapList;
+SHELL_MAP_LIST *gShellCurMapping = NULL;
+
+CONST CHAR16 *SupportLevel[] = {
+ L"Minimal",
+ L"Scripting",
+ L"Basic",
+ L"Interactive"
+};
+
+/**
+ Function to make sure that the global protocol pointers are valid.
+ must be called after constructor before accessing the pointers.
+**/
+EFI_STATUS
+EFIAPI
+CommandInit (
+ VOID
+ )
+{
+ UINTN NumHandles;
+ EFI_HANDLE *Handles;
+ EFI_UNICODE_COLLATION_PROTOCOL *Uc;
+ CHAR8 *BestLanguage;
+ UINTN Index;
+ EFI_STATUS Status;
+ CHAR8 *PlatformLang;
+
+ if (gUnicodeCollation == NULL) {
+ GetEfiGlobalVariable2 (EFI_PLATFORM_LANG_VARIABLE_NAME, (VOID **)&PlatformLang, NULL);
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiUnicodeCollation2ProtocolGuid,
+ NULL,
+ &NumHandles,
+ &Handles
+ );
+ if (EFI_ERROR (Status)) {
+ NumHandles = 0;
+ Handles = NULL;
+ }
+
+ for (Index = 0; Index < NumHandles; Index++) {
+ //
+ // Open Unicode Collation Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Handles[Index],
+ &gEfiUnicodeCollation2ProtocolGuid,
+ (VOID **)&Uc,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Without clue provided use the first Unicode Collation2 protocol.
+ // This may happen when PlatformLang is NULL or when no installed Unicode
+ // Collation2 protocol instance supports PlatformLang.
+ //
+ if (gUnicodeCollation == NULL) {
+ gUnicodeCollation = Uc;
+ }
+
+ if (PlatformLang == NULL) {
+ break;
+ }
+
+ //
+ // Find the best matching matching language from the supported languages
+ // of Unicode Collation2 protocol.
+ //
+ BestLanguage = GetBestLanguage (
+ Uc->SupportedLanguages,
+ FALSE,
+ PlatformLang,
+ NULL
+ );
+ if (BestLanguage != NULL) {
+ FreePool (BestLanguage);
+ gUnicodeCollation = Uc;
+ break;
+ }
+ }
+
+ if (Handles != NULL) {
+ FreePool (Handles);
+ }
+
+ if (PlatformLang != NULL) {
+ FreePool (PlatformLang);
+ }
+ }
+
+ return (gUnicodeCollation == NULL) ? EFI_UNSUPPORTED : EFI_SUCCESS;
+}
+
+/**
+ Constructor for the Shell Command library.
+
+ Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the initialization was complete successfully
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ InitializeListHead (&gShellMapList.Link);
+ InitializeListHead (&mCommandList.Link);
+ InitializeListHead (&mAliasList.Link);
+ InitializeListHead (&mScriptList.Link);
+ InitializeListHead (&mFileHandleList.Link);
+ mEchoState = TRUE;
+
+ mExitRequested = FALSE;
+ mExitScript = FALSE;
+ mProfileListSize = 0;
+ mProfileList = NULL;
+
+ Status = CommandInit ();
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Frees list of file handles.
+
+ @param[in] List The list to free.
+**/
+VOID
+FreeFileHandleList (
+ IN BUFFER_LIST *List
+ )
+{
+ BUFFER_LIST *BufferListEntry;
+
+ if (List == NULL) {
+ return;
+ }
+
+ //
+ // enumerate through the buffer list and free all memory
+ //
+ for ( BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
+ ; !IsListEmpty (&List->Link)
+ ; BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
+ )
+ {
+ RemoveEntryList (&BufferListEntry->Link);
+ ASSERT (BufferListEntry->Buffer != NULL);
+ SHELL_FREE_NON_NULL (((SHELL_COMMAND_FILE_HANDLE *)(BufferListEntry->Buffer))->Path);
+ SHELL_FREE_NON_NULL (BufferListEntry->Buffer);
+ SHELL_FREE_NON_NULL (BufferListEntry);
+ }
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval RETURN_SUCCESS this function always returns success
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+ ALIAS_LIST *Node2;
+ SCRIPT_FILE_LIST *Node3;
+ SHELL_MAP_LIST *MapNode;
+
+ //
+ // enumerate throught the list and free all the memory
+ //
+ while (!IsListEmpty (&mCommandList.Link)) {
+ Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link);
+ RemoveEntryList (&Node->Link);
+ SHELL_FREE_NON_NULL (Node->CommandString);
+ FreePool (Node);
+ DEBUG_CODE (
+ Node = NULL;
+ );
+ }
+
+ //
+ // enumerate through the alias list and free all memory
+ //
+ while (!IsListEmpty (&mAliasList.Link)) {
+ Node2 = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link);
+ RemoveEntryList (&Node2->Link);
+ SHELL_FREE_NON_NULL (Node2->CommandString);
+ SHELL_FREE_NON_NULL (Node2->Alias);
+ SHELL_FREE_NON_NULL (Node2);
+ DEBUG_CODE (
+ Node2 = NULL;
+ );
+ }
+
+ //
+ // enumerate throught the list and free all the memory
+ //
+ while (!IsListEmpty (&mScriptList.Link)) {
+ Node3 = (SCRIPT_FILE_LIST *)GetFirstNode (&mScriptList.Link);
+ RemoveEntryList (&Node3->Link);
+ DeleteScriptFileStruct (Node3->Data);
+ FreePool (Node3);
+ }
+
+ //
+ // enumerate throught the mappings list and free all the memory
+ //
+ if (!IsListEmpty (&gShellMapList.Link)) {
+ for (MapNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
+ ; !IsListEmpty (&gShellMapList.Link)
+ ; MapNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
+ )
+ {
+ ASSERT (MapNode != NULL);
+ RemoveEntryList (&MapNode->Link);
+ SHELL_FREE_NON_NULL (MapNode->DevicePath);
+ SHELL_FREE_NON_NULL (MapNode->MapName);
+ SHELL_FREE_NON_NULL (MapNode->CurrentDirectoryPath);
+ FreePool (MapNode);
+ }
+ }
+
+ if (!IsListEmpty (&mFileHandleList.Link)) {
+ FreeFileHandleList (&mFileHandleList);
+ }
+
+ if (mProfileList != NULL) {
+ FreePool (mProfileList);
+ }
+
+ gUnicodeCollation = NULL;
+ gShellCurMapping = NULL;
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Find a dynamic command protocol instance given a command name string.
+
+ @param CommandString the command name string
+
+ @return instance the command protocol instance, if dynamic command instance found
+ @retval NULL no dynamic command protocol instance found for name
+**/
+CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *
+ShellCommandFindDynamicCommand (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *CommandHandleList;
+ EFI_HANDLE *NextCommand;
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
+
+ CommandHandleList = GetHandleListByProtocol (&gEfiShellDynamicCommandProtocolGuid);
+ if (CommandHandleList == NULL) {
+ //
+ // not found or out of resources
+ //
+ return NULL;
+ }
+
+ for (NextCommand = CommandHandleList; *NextCommand != NULL; NextCommand++) {
+ Status = gBS->HandleProtocol (
+ *NextCommand,
+ &gEfiShellDynamicCommandProtocolGuid,
+ (VOID **)&DynamicCommand
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)CommandString,
+ (CHAR16 *)DynamicCommand->CommandName
+ ) == 0
+ )
+ {
+ FreePool (CommandHandleList);
+ return (DynamicCommand);
+ }
+ }
+
+ FreePool (CommandHandleList);
+ return (NULL);
+}
+
+/**
+ Checks if a command exists as a dynamic command protocol instance
+
+ @param[in] CommandString The command string to check for on the list.
+**/
+BOOLEAN
+ShellCommandDynamicCommandExists (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ return (BOOLEAN)((ShellCommandFindDynamicCommand (CommandString) != NULL));
+}
+
+/**
+ Checks if a command is already on the internal command list.
+
+ @param[in] CommandString The command string to check for on the list.
+**/
+BOOLEAN
+ShellCommandIsCommandOnInternalList (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT (CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
+ ; !IsNull (&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
+ )
+ {
+ ASSERT (Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)CommandString,
+ Node->CommandString
+ ) == 0
+ )
+ {
+ return (TRUE);
+ }
+ }
+
+ return (FALSE);
+}
+
+/**
+ Checks if a command exists, either internally or through the dynamic command protocol.
+
+ @param[in] CommandString The command string to check for on the list.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandIsCommandOnList (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ if (ShellCommandIsCommandOnInternalList (CommandString)) {
+ return TRUE;
+ }
+
+ return ShellCommandDynamicCommandExists (CommandString);
+}
+
+/**
+ Get the help text for a dynamic command.
+
+ @param[in] CommandString The command name.
+
+ @retval NULL No help text was found.
+ @return String of help text. Caller required to free.
+**/
+CHAR16 *
+ShellCommandGetDynamicCommandHelp (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
+
+ DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand (CommandString);
+ if (DynamicCommand == NULL) {
+ return (NULL);
+ }
+
+ //
+ // TODO: how to get proper language?
+ //
+ return DynamicCommand->GetHelp (DynamicCommand, "en");
+}
+
+/**
+ Get the help text for an internal command.
+
+ @param[in] CommandString The command name.
+
+ @retval NULL No help text was found.
+ @return String of help text. Caller reuiqred to free.
+**/
+CHAR16 *
+ShellCommandGetInternalCommandHelp (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT (CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
+ ; !IsNull (&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
+ )
+ {
+ ASSERT (Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)CommandString,
+ Node->CommandString
+ ) == 0
+ )
+ {
+ return (HiiGetString (Node->HiiHandle, Node->ManFormatHelp, NULL));
+ }
+ }
+
+ return (NULL);
+}
+
+/**
+ Get the help text for a command.
+
+ @param[in] CommandString The command name.
+
+ @retval NULL No help text was found.
+ @return String of help text.Caller reuiqred to free.
+**/
+CHAR16 *
+EFIAPI
+ShellCommandGetCommandHelp (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ CHAR16 *HelpStr;
+
+ HelpStr = ShellCommandGetInternalCommandHelp (CommandString);
+
+ if (HelpStr == NULL) {
+ HelpStr = ShellCommandGetDynamicCommandHelp (CommandString);
+ }
+
+ return HelpStr;
+}
+
+/**
+ Registers handlers of type SHELL_RUN_COMMAND and
+ SHELL_GET_MAN_FILENAME for each shell command.
+
+ If the ShellSupportLevel is greater than the value of the
+ PcdShellSupportLevel then return RETURN_UNSUPPORTED.
+
+ Registers the handlers specified by GetHelpInfoHandler and CommandHandler
+ with the command specified by CommandString. If the command named by
+ CommandString has already been registered, then return
+ RETURN_ALREADY_STARTED.
+
+ If there are not enough resources available to register the handlers then
+ RETURN_OUT_OF_RESOURCES is returned.
+
+ If CommandString is NULL, then ASSERT().
+ If GetHelpInfoHandler is NULL, then ASSERT().
+ If CommandHandler is NULL, then ASSERT().
+ If ProfileName is NULL, then ASSERT().
+
+ @param[in] CommandString Pointer to the command name. This is the
+ name to look for on the command line in
+ the shell.
+ @param[in] CommandHandler Pointer to a function that runs the
+ specified command.
+ @param[in] GetManFileName Pointer to a function that provides man
+ filename.
+ @param[in] ShellMinSupportLevel minimum Shell Support Level which has this
+ function.
+ @param[in] ProfileName profile name to require for support of this
+ function.
+ @param[in] CanAffectLE indicates whether this command's return value
+ can change the LASTERROR environment variable.
+ @param[in] HiiHandle Handle of this command's HII entry.
+ @param[in] ManFormatHelp HII locator for the help text.
+
+ @retval RETURN_SUCCESS The handlers were registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
+ register the shell command.
+ @retval RETURN_UNSUPPORTED the ShellMinSupportLevel was higher than the
+ currently allowed support level.
+ @retval RETURN_ALREADY_STARTED The CommandString represents a command that
+ is already registered. Only 1 handler set for
+ a given command is allowed.
+ @sa SHELL_GET_MAN_FILENAME
+ @sa SHELL_RUN_COMMAND
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRegisterCommandName (
+ IN CONST CHAR16 *CommandString,
+ IN SHELL_RUN_COMMAND CommandHandler,
+ IN SHELL_GET_MAN_FILENAME GetManFileName,
+ IN UINT32 ShellMinSupportLevel,
+ IN CONST CHAR16 *ProfileName,
+ IN CONST BOOLEAN CanAffectLE,
+ IN CONST EFI_HII_HANDLE HiiHandle,
+ IN CONST EFI_STRING_ID ManFormatHelp
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Command;
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *PrevCommand;
+ INTN LexicalMatchValue;
+
+ //
+ // Initialize local variables.
+ //
+ Command = NULL;
+ PrevCommand = NULL;
+ LexicalMatchValue = 0;
+
+ //
+ // ASSERTs for NULL parameters
+ //
+ ASSERT (CommandString != NULL);
+ ASSERT (GetManFileName != NULL);
+ ASSERT (CommandHandler != NULL);
+ ASSERT (ProfileName != NULL);
+
+ //
+ // check for shell support level
+ //
+ if (PcdGet8 (PcdShellSupportLevel) < ShellMinSupportLevel) {
+ return (RETURN_UNSUPPORTED);
+ }
+
+ //
+ // check for already on the list
+ //
+ if (ShellCommandIsCommandOnList (CommandString)) {
+ return (RETURN_ALREADY_STARTED);
+ }
+
+ //
+ // allocate memory for new struct
+ //
+ Node = AllocateZeroPool (sizeof (SHELL_COMMAND_INTERNAL_LIST_ENTRY));
+ if (Node == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ Node->CommandString = AllocateCopyPool (StrSize (CommandString), CommandString);
+ if (Node->CommandString == NULL) {
+ FreePool (Node);
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ Node->GetManFileName = GetManFileName;
+ Node->CommandHandler = CommandHandler;
+ Node->LastError = CanAffectLE;
+ Node->HiiHandle = HiiHandle;
+ Node->ManFormatHelp = ManFormatHelp;
+
+ if ( (StrLen (ProfileName) > 0)
+ && (( (mProfileList != NULL)
+ && (StrStr (mProfileList, ProfileName) == NULL)) || (mProfileList == NULL))
+ )
+ {
+ ASSERT ((mProfileList == NULL && mProfileListSize == 0) || (mProfileList != NULL));
+ if (mProfileList == NULL) {
+ //
+ // If this is the first make a leading ';'
+ //
+ StrnCatGrow (&mProfileList, &mProfileListSize, L";", 0);
+ }
+
+ StrnCatGrow (&mProfileList, &mProfileListSize, ProfileName, 0);
+ StrnCatGrow (&mProfileList, &mProfileListSize, L";", 0);
+ }
+
+ //
+ // Insert a new entry on top of the list
+ //
+ InsertHeadList (&mCommandList.Link, &Node->Link);
+
+ //
+ // Move a new registered command to its sorted ordered location in the list
+ //
+ for (Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link),
+ PrevCommand = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
+ ; !IsNull (&mCommandList.Link, &Command->Link)
+ ; Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Command->Link))
+ {
+ //
+ // Get Lexical Comparison Value between PrevCommand and Command list entry
+ //
+ LexicalMatchValue = gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ PrevCommand->CommandString,
+ Command->CommandString
+ );
+
+ //
+ // Swap PrevCommand and Command list entry if PrevCommand list entry
+ // is alphabetically greater than Command list entry
+ //
+ if (LexicalMatchValue > 0) {
+ Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)SwapListEntries (&PrevCommand->Link, &Command->Link);
+ } else if (LexicalMatchValue < 0) {
+ //
+ // PrevCommand entry is lexically lower than Command entry
+ //
+ break;
+ }
+ }
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Function to get the current Profile string.
+
+ @retval NULL There are no installed profiles.
+ @return A semi-colon delimited list of profiles.
+**/
+CONST CHAR16 *
+EFIAPI
+ShellCommandGetProfileList (
+ VOID
+ )
+{
+ return (mProfileList);
+}
+
+/**
+ Checks if a command string has been registered for CommandString and if so it runs
+ the previously registered handler for that command with the command line.
+
+ If CommandString is NULL, then ASSERT().
+
+ If Sections is specified, then each section name listed will be compared in a casesensitive
+ manner, to the section names described in Appendix B UEFI Shell 2.0 spec. If the section exists,
+ it will be appended to the returned help text. If the section does not exist, no
+ information will be returned. If Sections is NULL, then all help text information
+ available will be returned.
+
+ @param[in] CommandString Pointer to the command name. This is the name
+ found on the command line in the shell.
+ @param[in, out] RetVal Pointer to the return vaule from the command handler.
+
+ @param[in, out] CanAffectLE indicates whether this command's return value
+ needs to be placed into LASTERROR environment variable.
+
+ @retval RETURN_SUCCESS The handler was run.
+ @retval RETURN_NOT_FOUND The CommandString did not match a registered
+ command name.
+ @sa SHELL_RUN_COMMAND
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRunCommandHandler (
+ IN CONST CHAR16 *CommandString,
+ IN OUT SHELL_STATUS *RetVal,
+ IN OUT BOOLEAN *CanAffectLE OPTIONAL
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
+
+ //
+ // assert for NULL parameters
+ //
+ ASSERT (CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
+ ; !IsNull (&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
+ )
+ {
+ ASSERT (Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)CommandString,
+ Node->CommandString
+ ) == 0
+ )
+ {
+ if (CanAffectLE != NULL) {
+ *CanAffectLE = Node->LastError;
+ }
+
+ if (RetVal != NULL) {
+ *RetVal = Node->CommandHandler (NULL, gST);
+ } else {
+ Node->CommandHandler (NULL, gST);
+ }
+
+ return (RETURN_SUCCESS);
+ }
+ }
+
+ //
+ // An internal command was not found, try to find a dynamic command
+ //
+ DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand (CommandString);
+ if (DynamicCommand != NULL) {
+ if (RetVal != NULL) {
+ *RetVal = DynamicCommand->Handler (DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol);
+ } else {
+ DynamicCommand->Handler (DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol);
+ }
+
+ return (RETURN_SUCCESS);
+ }
+
+ return (RETURN_NOT_FOUND);
+}
+
+/**
+ Checks if a command string has been registered for CommandString and if so it
+ returns the MAN filename specified for that command.
+
+ If CommandString is NULL, then ASSERT().
+
+ @param[in] CommandString Pointer to the command name. This is the name
+ found on the command line in the shell.\
+
+ @retval NULL the commandString was not a registered command.
+ @return other the name of the MAN file.
+ @sa SHELL_GET_MAN_FILENAME
+**/
+CONST CHAR16 *
+EFIAPI
+ShellCommandGetManFileNameHandler (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+
+ //
+ // assert for NULL parameters
+ //
+ ASSERT (CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
+ ; !IsNull (&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
+ )
+ {
+ ASSERT (Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)CommandString,
+ Node->CommandString
+ ) == 0
+ )
+ {
+ return (Node->GetManFileName ());
+ }
+ }
+
+ return (NULL);
+}
+
+/**
+ Get the list of all available shell internal commands. This is a linked list
+ (via LIST_ENTRY structure). enumerate through it using the BaseLib linked
+ list functions. do not modify the values.
+
+ @param[in] Sort TRUE to alphabetically sort the values first. FALSE otherwise.
+
+ @return a Linked list of all available shell commands.
+**/
+CONST COMMAND_LIST *
+EFIAPI
+ShellCommandGetCommandList (
+ IN CONST BOOLEAN Sort
+ )
+{
+ // if (!Sort) {
+ // return ((COMMAND_LIST*)(&mCommandList));
+ // }
+ return ((COMMAND_LIST *)(&mCommandList));
+}
+
+/**
+ Registers aliases to be set as part of the initialization of the shell application.
+
+ If Command is NULL, then ASSERT().
+ If Alias is NULL, then ASSERT().
+
+ @param[in] Command Pointer to the Command
+ @param[in] Alias Pointer to Alias
+
+ @retval RETURN_SUCCESS The handlers were registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
+ register the shell command.
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRegisterAlias (
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Alias
+ )
+{
+ ALIAS_LIST *Node;
+ ALIAS_LIST *CommandAlias;
+ ALIAS_LIST *PrevCommandAlias;
+ INTN LexicalMatchValue;
+
+ //
+ // Asserts for NULL
+ //
+ ASSERT (Command != NULL);
+ ASSERT (Alias != NULL);
+
+ //
+ // allocate memory for new struct
+ //
+ Node = AllocateZeroPool (sizeof (ALIAS_LIST));
+ if (Node == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ Node->CommandString = AllocateCopyPool (StrSize (Command), Command);
+ if (Node->CommandString == NULL) {
+ FreePool (Node);
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ Node->Alias = AllocateCopyPool (StrSize (Alias), Alias);
+ if (Node->Alias == NULL) {
+ FreePool (Node->CommandString);
+ FreePool (Node);
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ InsertHeadList (&mAliasList.Link, &Node->Link);
+
+ //
+ // Move a new pre-defined registered alias to its sorted ordered location in the list
+ //
+ for ( CommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link),
+ PrevCommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link)
+ ; !IsNull (&mAliasList.Link, &CommandAlias->Link)
+ ; CommandAlias = (ALIAS_LIST *)GetNextNode (&mAliasList.Link, &CommandAlias->Link))
+ {
+ //
+ // Get Lexical comparison value between PrevCommandAlias and CommandAlias List Entry
+ //
+ LexicalMatchValue = gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ PrevCommandAlias->Alias,
+ CommandAlias->Alias
+ );
+
+ //
+ // Swap PrevCommandAlias and CommandAlias list entry if PrevCommandAlias list entry
+ // is alphabetically greater than CommandAlias list entry
+ //
+ if (LexicalMatchValue > 0) {
+ CommandAlias = (ALIAS_LIST *)SwapListEntries (&PrevCommandAlias->Link, &CommandAlias->Link);
+ } else if (LexicalMatchValue < 0) {
+ //
+ // PrevCommandAlias entry is lexically lower than CommandAlias entry
+ //
+ break;
+ }
+ }
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Get the list of all shell alias commands. This is a linked list
+ (via LIST_ENTRY structure). enumerate through it using the BaseLib linked
+ list functions. do not modify the values.
+
+ @return a Linked list of all requested shell alias'.
+**/
+CONST ALIAS_LIST *
+EFIAPI
+ShellCommandGetInitAliasList (
+ VOID
+ )
+{
+ return (&mAliasList);
+}
+
+/**
+ Determine if a given alias is on the list of built in alias'.
+
+ @param[in] Alias The alias to test for
+
+ @retval TRUE The alias is a built in alias
+ @retval FALSE The alias is not a built in alias
+**/
+BOOLEAN
+EFIAPI
+ShellCommandIsOnAliasList (
+ IN CONST CHAR16 *Alias
+ )
+{
+ ALIAS_LIST *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT (Alias != NULL);
+
+ //
+ // check for the Alias
+ //
+ for ( Node = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link)
+ ; !IsNull (&mAliasList.Link, &Node->Link)
+ ; Node = (ALIAS_LIST *)GetNextNode (&mAliasList.Link, &Node->Link)
+ )
+ {
+ ASSERT (Node->CommandString != NULL);
+ ASSERT (Node->Alias != NULL);
+ if (gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)Alias,
+ Node->CommandString
+ ) == 0
+ )
+ {
+ return (TRUE);
+ }
+
+ if (gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)Alias,
+ Node->Alias
+ ) == 0
+ )
+ {
+ return (TRUE);
+ }
+ }
+
+ return (FALSE);
+}
+
+/**
+ Function to determine current state of ECHO. Echo determines if lines from scripts
+ and ECHO commands are enabled.
+
+ @retval TRUE Echo is currently enabled
+ @retval FALSE Echo is currently disabled
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetEchoState (
+ VOID
+ )
+{
+ return (mEchoState);
+}
+
+/**
+ Function to set current state of ECHO. Echo determines if lines from scripts
+ and ECHO commands are enabled.
+
+ If State is TRUE, Echo will be enabled.
+ If State is FALSE, Echo will be disabled.
+
+ @param[in] State How to set echo.
+**/
+VOID
+EFIAPI
+ShellCommandSetEchoState (
+ IN BOOLEAN State
+ )
+{
+ mEchoState = State;
+}
+
+/**
+ Indicate that the current shell or script should exit.
+
+ @param[in] ScriptOnly TRUE if exiting a script; FALSE otherwise.
+ @param[in] ErrorCode The 64 bit error code to return.
+**/
+VOID
+EFIAPI
+ShellCommandRegisterExit (
+ IN BOOLEAN ScriptOnly,
+ IN CONST UINT64 ErrorCode
+ )
+{
+ mExitRequested = (BOOLEAN)(!mExitRequested);
+ if (mExitRequested) {
+ mExitScript = ScriptOnly;
+ } else {
+ mExitScript = FALSE;
+ }
+
+ mExitCode = ErrorCode;
+}
+
+/**
+ Retrieve the Exit indicator.
+
+ @retval TRUE Exit was indicated.
+ @retval FALSE Exis was not indicated.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetExit (
+ VOID
+ )
+{
+ return (mExitRequested);
+}
+
+/**
+ Retrieve the Exit code.
+
+ If ShellCommandGetExit returns FALSE than the return from this is undefined.
+
+ @return the value passed into RegisterExit.
+**/
+UINT64
+EFIAPI
+ShellCommandGetExitCode (
+ VOID
+ )
+{
+ return (mExitCode);
+}
+
+/**
+ Retrieve the Exit script indicator.
+
+ If ShellCommandGetExit returns FALSE than the return from this is undefined.
+
+ @retval TRUE ScriptOnly was indicated.
+ @retval FALSE ScriptOnly was not indicated.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetScriptExit (
+ VOID
+ )
+{
+ return (mExitScript);
+}
+
+/**
+ Function to cleanup all memory from a SCRIPT_FILE structure.
+
+ @param[in] Script The pointer to the structure to cleanup.
+**/
+VOID
+EFIAPI
+DeleteScriptFileStruct (
+ IN SCRIPT_FILE *Script
+ )
+{
+ UINT8 LoopVar;
+
+ if (Script == NULL) {
+ return;
+ }
+
+ for (LoopVar = 0; LoopVar < Script->Argc; LoopVar++) {
+ SHELL_FREE_NON_NULL (Script->Argv[LoopVar]);
+ }
+
+ if (Script->Argv != NULL) {
+ SHELL_FREE_NON_NULL (Script->Argv);
+ }
+
+ Script->CurrentCommand = NULL;
+ while (!IsListEmpty (&Script->CommandList)) {
+ Script->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetFirstNode (&Script->CommandList);
+ if (Script->CurrentCommand != NULL) {
+ RemoveEntryList (&Script->CurrentCommand->Link);
+ if (Script->CurrentCommand->Cl != NULL) {
+ SHELL_FREE_NON_NULL (Script->CurrentCommand->Cl);
+ }
+
+ if (Script->CurrentCommand->Data != NULL) {
+ SHELL_FREE_NON_NULL (Script->CurrentCommand->Data);
+ }
+
+ SHELL_FREE_NON_NULL (Script->CurrentCommand);
+ }
+ }
+
+ SHELL_FREE_NON_NULL (Script->ScriptName);
+ SHELL_FREE_NON_NULL (Script);
+}
+
+/**
+ Function to return a pointer to the currently running script file object.
+
+ @retval NULL A script file is not currently running.
+ @return A pointer to the current script file object.
+**/
+SCRIPT_FILE *
+EFIAPI
+ShellCommandGetCurrentScriptFile (
+ VOID
+ )
+{
+ SCRIPT_FILE_LIST *List;
+
+ if (IsListEmpty (&mScriptList.Link)) {
+ return (NULL);
+ }
+
+ List = ((SCRIPT_FILE_LIST *)GetFirstNode (&mScriptList.Link));
+ return (List->Data);
+}
+
+/**
+ Function to set a new script as the currently running one.
+
+ This function will correctly stack and unstack nested scripts.
+
+ @param[in] Script Pointer to new script information structure. if NULL
+ will remove and de-allocate the top-most Script structure.
+
+ @return A pointer to the current running script file after this
+ change. NULL if removing the final script.
+**/
+SCRIPT_FILE *
+EFIAPI
+ShellCommandSetNewScript (
+ IN SCRIPT_FILE *Script OPTIONAL
+ )
+{
+ SCRIPT_FILE_LIST *Node;
+
+ if (Script == NULL) {
+ if (IsListEmpty (&mScriptList.Link)) {
+ return (NULL);
+ }
+
+ Node = (SCRIPT_FILE_LIST *)GetFirstNode (&mScriptList.Link);
+ RemoveEntryList (&Node->Link);
+ DeleteScriptFileStruct (Node->Data);
+ FreePool (Node);
+ } else {
+ Node = AllocateZeroPool (sizeof (SCRIPT_FILE_LIST));
+ if (Node == NULL) {
+ return (NULL);
+ }
+
+ Node->Data = Script;
+ InsertHeadList (&mScriptList.Link, &Node->Link);
+ }
+
+ return (ShellCommandGetCurrentScriptFile ());
+}
+
+/**
+ Function to generate the next default mapping name.
+
+ If the return value is not NULL then it must be callee freed.
+
+ @param Type What kind of mapping name to make.
+
+ @retval NULL a memory allocation failed.
+ @return a new map name string
+**/
+CHAR16 *
+EFIAPI
+ShellCommandCreateNewMappingName (
+ IN CONST SHELL_MAPPING_TYPE Type
+ )
+{
+ CHAR16 *String;
+
+ ASSERT (Type < MappingTypeMax);
+
+ String = NULL;
+
+ String = AllocateZeroPool (PcdGet8 (PcdShellMapNameLength) * sizeof (String[0]));
+ UnicodeSPrint (
+ String,
+ PcdGet8 (PcdShellMapNameLength) * sizeof (String[0]),
+ Type == MappingTypeFileSystem ? L"FS%d:" : L"BLK%d:",
+ Type == MappingTypeFileSystem ? mFsMaxCount++ : mBlkMaxCount++
+ );
+
+ return (String);
+}
+
+/**
+ Function to add a map node to the list of map items and update the "path" environment variable (optionally).
+
+ If Path is TRUE (during initialization only), the path environment variable will also be updated to include
+ default paths on the new map name...
+
+ Path should be FALSE when this function is called from the protocol SetMap function.
+
+ @param[in] Name The human readable mapped name.
+ @param[in] DevicePath The Device Path for this map.
+ @param[in] Flags The Flags attribute for this map item.
+ @param[in] Path TRUE to update path, FALSE to skip this step (should only be TRUE during initialization).
+
+ @retval EFI_SUCCESS The addition was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandAddMapItemAndUpdatePath (
+ IN CONST CHAR16 *Name,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST UINT64 Flags,
+ IN CONST BOOLEAN Path
+ )
+{
+ EFI_STATUS Status;
+ SHELL_MAP_LIST *MapListNode;
+ CONST CHAR16 *OriginalPath;
+ CHAR16 *NewPath;
+ UINTN NewPathSize;
+
+ NewPathSize = 0;
+ NewPath = NULL;
+ OriginalPath = NULL;
+ Status = EFI_SUCCESS;
+
+ MapListNode = AllocateZeroPool (sizeof (SHELL_MAP_LIST));
+ if (MapListNode == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ MapListNode->Flags = Flags;
+ MapListNode->MapName = AllocateCopyPool (StrSize (Name), Name);
+ MapListNode->DevicePath = DuplicateDevicePath (DevicePath);
+ if ((MapListNode->MapName == NULL) || (MapListNode->DevicePath == NULL)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ InsertTailList (&gShellMapList.Link, &MapListNode->Link);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (MapListNode != NULL) {
+ if (MapListNode->DevicePath != NULL) {
+ FreePool (MapListNode->DevicePath);
+ }
+
+ if (MapListNode->MapName != NULL) {
+ FreePool (MapListNode->MapName);
+ }
+
+ FreePool (MapListNode);
+ }
+ } else if (Path) {
+ //
+ // Since there was no error and Path was TRUE
+ // Now add the correct path for that mapping
+ //
+ OriginalPath = gEfiShellProtocol->GetEnv (L"path");
+ ASSERT ((NewPath == NULL && NewPathSize == 0) || (NewPath != NULL));
+ if (OriginalPath != NULL) {
+ StrnCatGrow (&NewPath, &NewPathSize, OriginalPath, 0);
+ StrnCatGrow (&NewPath, &NewPathSize, L";", 0);
+ }
+
+ StrnCatGrow (&NewPath, &NewPathSize, Name, 0);
+ StrnCatGrow (&NewPath, &NewPathSize, L"\\efi\\tools\\;", 0);
+ StrnCatGrow (&NewPath, &NewPathSize, Name, 0);
+ StrnCatGrow (&NewPath, &NewPathSize, L"\\efi\\boot\\;", 0);
+ StrnCatGrow (&NewPath, &NewPathSize, Name, 0);
+ StrnCatGrow (&NewPath, &NewPathSize, L"\\", 0);
+
+ Status = gEfiShellProtocol->SetEnv (L"path", NewPath, TRUE);
+ ASSERT_EFI_ERROR (Status);
+ FreePool (NewPath);
+ }
+
+ return (Status);
+}
+
+/**
+ Creates the default map names for each device path in the system with
+ a protocol depending on the Type.
+
+ Creates the consistent map names for each device path in the system with
+ a protocol depending on the Type.
+
+ Note: This will reset all mappings in the system("map -r").
+
+ Also sets up the default path environment variable if Type is FileSystem.
+
+ @retval EFI_SUCCESS All map names were created successfully.
+ @retval EFI_NOT_FOUND No protocols were found in the system.
+ @return Error returned from gBS->LocateHandle().
+
+ @sa LocateHandle
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandCreateInitialMappingsAndPaths (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleList;
+ UINTN Count;
+ EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
+ CHAR16 *NewDefaultName;
+ CHAR16 *NewConsistName;
+ EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
+ SHELL_MAP_LIST *MapListNode;
+ CONST CHAR16 *CurDir;
+ CHAR16 *SplitCurDir;
+ CHAR16 *MapName;
+ SHELL_MAP_LIST *MapListItem;
+
+ ConsistMappingTable = NULL;
+ SplitCurDir = NULL;
+ MapName = NULL;
+ MapListItem = NULL;
+ HandleList = NULL;
+
+ //
+ // Reset the static members back to zero
+ //
+ mFsMaxCount = 0;
+ mBlkMaxCount = 0;
+
+ gEfiShellProtocol->SetEnv (L"path", L"", TRUE);
+
+ //
+ // First empty out the existing list.
+ //
+ if (!IsListEmpty (&gShellMapList.Link)) {
+ for ( MapListNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
+ ; !IsListEmpty (&gShellMapList.Link)
+ ; MapListNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
+ )
+ {
+ RemoveEntryList (&MapListNode->Link);
+ SHELL_FREE_NON_NULL (MapListNode->DevicePath);
+ SHELL_FREE_NON_NULL (MapListNode->MapName);
+ SHELL_FREE_NON_NULL (MapListNode->CurrentDirectoryPath);
+ FreePool (MapListNode);
+ } // for loop
+ }
+
+ //
+ // Find each handle with Simple File System
+ //
+ HandleList = GetHandleListByProtocol (&gEfiSimpleFileSystemProtocolGuid);
+ if (HandleList != NULL) {
+ //
+ // Do a count of the handles
+ //
+ for (Count = 0; HandleList[Count] != NULL; Count++) {
+ }
+
+ //
+ // Get all Device Paths
+ //
+ DevicePathList = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL *) * Count);
+ if (DevicePathList == NULL) {
+ SHELL_FREE_NON_NULL (HandleList);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Count = 0; HandleList[Count] != NULL; Count++) {
+ DevicePathList[Count] = DevicePathFromHandle (HandleList[Count]);
+ }
+
+ //
+ // Sort all DevicePaths
+ //
+ PerformQuickSort (DevicePathList, Count, sizeof (EFI_DEVICE_PATH_PROTOCOL *), DevicePathCompare);
+
+ if (!EFI_ERROR (ShellCommandConsistMappingInitialize (&ConsistMappingTable))) {
+ //
+ // Assign new Mappings to all...
+ //
+ for (Count = 0; HandleList[Count] != NULL; Count++) {
+ //
+ // Get default name first
+ //
+ NewDefaultName = ShellCommandCreateNewMappingName (MappingTypeFileSystem);
+ ASSERT (NewDefaultName != NULL);
+ Status = ShellCommandAddMapItemAndUpdatePath (NewDefaultName, DevicePathList[Count], 0, TRUE);
+ ASSERT_EFI_ERROR (Status);
+ FreePool (NewDefaultName);
+
+ //
+ // Now do consistent name
+ //
+ NewConsistName = ShellCommandConsistMappingGenMappingName (DevicePathList[Count], ConsistMappingTable);
+ if (NewConsistName != NULL) {
+ Status = ShellCommandAddMapItemAndUpdatePath (NewConsistName, DevicePathList[Count], 0, FALSE);
+ ASSERT_EFI_ERROR (Status);
+ FreePool (NewConsistName);
+ }
+ }
+ }
+
+ if (ConsistMappingTable != NULL) {
+ ShellCommandConsistMappingUnInitialize (ConsistMappingTable);
+ }
+
+ SHELL_FREE_NON_NULL (HandleList);
+ SHELL_FREE_NON_NULL (DevicePathList);
+
+ HandleList = NULL;
+
+ //
+ // gShellCurMapping point to node of current file system in the gShellMapList. When reset all mappings,
+ // all nodes in the gShellMapList will be free. Then gShellCurMapping will be a dangling pointer, So,
+ // after created new mappings, we should reset the gShellCurMapping pointer back to node of current file system.
+ //
+ if (gShellCurMapping != NULL) {
+ gShellCurMapping = NULL;
+ CurDir = gEfiShellProtocol->GetEnv (L"cwd");
+ if (CurDir != NULL) {
+ MapName = AllocateCopyPool (StrSize (CurDir), CurDir);
+ if (MapName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SplitCurDir = StrStr (MapName, L":");
+ if (SplitCurDir == NULL) {
+ SHELL_FREE_NON_NULL (MapName);
+ return EFI_UNSUPPORTED;
+ }
+
+ *(SplitCurDir + 1) = CHAR_NULL;
+ MapListItem = ShellCommandFindMapItem (MapName);
+ if (MapListItem != NULL) {
+ gShellCurMapping = MapListItem;
+ }
+
+ SHELL_FREE_NON_NULL (MapName);
+ }
+ }
+ } else {
+ Count = (UINTN)-1;
+ }
+
+ //
+ // Find each handle with Block Io
+ //
+ HandleList = GetHandleListByProtocol (&gEfiBlockIoProtocolGuid);
+ if (HandleList != NULL) {
+ for (Count = 0; HandleList[Count] != NULL; Count++) {
+ }
+
+ //
+ // Get all Device Paths
+ //
+ DevicePathList = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL *) * Count);
+ if (DevicePathList == NULL) {
+ SHELL_FREE_NON_NULL (HandleList);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Count = 0; HandleList[Count] != NULL; Count++) {
+ DevicePathList[Count] = DevicePathFromHandle (HandleList[Count]);
+ }
+
+ //
+ // Sort all DevicePaths
+ //
+ PerformQuickSort (DevicePathList, Count, sizeof (EFI_DEVICE_PATH_PROTOCOL *), DevicePathCompare);
+
+ //
+ // Assign new Mappings to all...
+ //
+ for (Count = 0; HandleList[Count] != NULL; Count++) {
+ //
+ // Get default name first
+ //
+ NewDefaultName = ShellCommandCreateNewMappingName (MappingTypeBlockIo);
+ ASSERT (NewDefaultName != NULL);
+ Status = ShellCommandAddMapItemAndUpdatePath (NewDefaultName, DevicePathList[Count], 0, FALSE);
+ ASSERT_EFI_ERROR (Status);
+ FreePool (NewDefaultName);
+ }
+
+ SHELL_FREE_NON_NULL (HandleList);
+ SHELL_FREE_NON_NULL (DevicePathList);
+ } else if (Count == (UINTN)-1) {
+ return (EFI_NOT_FOUND);
+ }
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Add mappings for any devices without one. Do not change any existing maps.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandUpdateMapping (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleList;
+ UINTN Count;
+ EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
+ CHAR16 *NewDefaultName;
+ CHAR16 *NewConsistName;
+ EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
+
+ HandleList = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // remove mappings that represent removed devices.
+ //
+
+ //
+ // Find each handle with Simple File System
+ //
+ HandleList = GetHandleListByProtocol (&gEfiSimpleFileSystemProtocolGuid);
+ if (HandleList != NULL) {
+ //
+ // Do a count of the handles
+ //
+ for (Count = 0; HandleList[Count] != NULL; Count++) {
+ }
+
+ //
+ // Get all Device Paths
+ //
+ DevicePathList = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL *) * Count);
+ if (DevicePathList == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ for (Count = 0; HandleList[Count] != NULL; Count++) {
+ DevicePathList[Count] = DevicePathFromHandle (HandleList[Count]);
+ }
+
+ //
+ // Sort all DevicePaths
+ //
+ PerformQuickSort (DevicePathList, Count, sizeof (EFI_DEVICE_PATH_PROTOCOL *), DevicePathCompare);
+
+ Status = ShellCommandConsistMappingInitialize (&ConsistMappingTable);
+
+ //
+ // Assign new Mappings to remainders
+ //
+ for (Count = 0; !EFI_ERROR (Status) && HandleList[Count] != NULL; Count++) {
+ //
+ // Skip ones that already have
+ //
+ if (gEfiShellProtocol->GetMapFromDevicePath (&DevicePathList[Count]) != NULL) {
+ continue;
+ }
+
+ //
+ // Get default name
+ //
+ NewDefaultName = ShellCommandCreateNewMappingName (MappingTypeFileSystem);
+ if (NewDefaultName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+
+ //
+ // Call shell protocol SetMap function now...
+ //
+ Status = gEfiShellProtocol->SetMap (DevicePathList[Count], NewDefaultName);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Now do consistent name
+ //
+ NewConsistName = ShellCommandConsistMappingGenMappingName (DevicePathList[Count], ConsistMappingTable);
+ if (NewConsistName != NULL) {
+ Status = gEfiShellProtocol->SetMap (DevicePathList[Count], NewConsistName);
+ FreePool (NewConsistName);
+ }
+ }
+
+ FreePool (NewDefaultName);
+ }
+
+ ShellCommandConsistMappingUnInitialize (ConsistMappingTable);
+ SHELL_FREE_NON_NULL (HandleList);
+ SHELL_FREE_NON_NULL (DevicePathList);
+
+ HandleList = NULL;
+ } else {
+ Count = (UINTN)-1;
+ }
+
+ //
+ // Do it all over again for gEfiBlockIoProtocolGuid
+ //
+
+ return (Status);
+}
+
+/**
+ Converts a SHELL_FILE_HANDLE to an EFI_FILE_PROTOCOL*.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to convert.
+
+ @return a EFI_FILE_PROTOCOL* representing the same file.
+**/
+EFI_FILE_PROTOCOL *
+EFIAPI
+ConvertShellHandleToEfiFileProtocol (
+ IN CONST SHELL_FILE_HANDLE Handle
+ )
+{
+ return ((EFI_FILE_PROTOCOL *)(Handle));
+}
+
+/**
+ Converts a EFI_FILE_PROTOCOL* to an SHELL_FILE_HANDLE.
+
+ @param[in] Handle The pointer to EFI_FILE_PROTOCOL to convert.
+ @param[in] Path The path to the file for verification.
+
+ @return A SHELL_FILE_HANDLE representing the same file.
+ @retval NULL There was not enough memory.
+**/
+SHELL_FILE_HANDLE
+EFIAPI
+ConvertEfiFileProtocolToShellHandle (
+ IN CONST EFI_FILE_PROTOCOL *Handle,
+ IN CONST CHAR16 *Path
+ )
+{
+ SHELL_COMMAND_FILE_HANDLE *Buffer;
+ BUFFER_LIST *NewNode;
+
+ if (Path != NULL) {
+ Buffer = AllocateZeroPool (sizeof (SHELL_COMMAND_FILE_HANDLE));
+ if (Buffer == NULL) {
+ return (NULL);
+ }
+
+ NewNode = AllocateZeroPool (sizeof (BUFFER_LIST));
+ if (NewNode == NULL) {
+ SHELL_FREE_NON_NULL (Buffer);
+ return (NULL);
+ }
+
+ Buffer->FileHandle = (EFI_FILE_PROTOCOL *)Handle;
+ Buffer->Path = StrnCatGrow (&Buffer->Path, NULL, Path, 0);
+ if (Buffer->Path == NULL) {
+ SHELL_FREE_NON_NULL (NewNode);
+ SHELL_FREE_NON_NULL (Buffer);
+ return (NULL);
+ }
+
+ NewNode->Buffer = Buffer;
+
+ InsertHeadList (&mFileHandleList.Link, &NewNode->Link);
+ }
+
+ return ((SHELL_FILE_HANDLE)(Handle));
+}
+
+/**
+ Find the path that was logged with the specified SHELL_FILE_HANDLE.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to query on.
+
+ @return A pointer to the path for the file.
+**/
+CONST CHAR16 *
+EFIAPI
+ShellFileHandleGetPath (
+ IN CONST SHELL_FILE_HANDLE Handle
+ )
+{
+ BUFFER_LIST *Node;
+
+ for (Node = (BUFFER_LIST *)GetFirstNode (&mFileHandleList.Link)
+ ; !IsNull (&mFileHandleList.Link, &Node->Link)
+ ; Node = (BUFFER_LIST *)GetNextNode (&mFileHandleList.Link, &Node->Link)
+ )
+ {
+ if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)) {
+ return (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path);
+ }
+ }
+
+ return (NULL);
+}
+
+/**
+ Remove a SHELL_FILE_HANDLE from the list of SHELL_FILE_HANDLES.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to remove.
+
+ @retval TRUE The item was removed.
+ @retval FALSE The item was not found.
+**/
+BOOLEAN
+EFIAPI
+ShellFileHandleRemove (
+ IN CONST SHELL_FILE_HANDLE Handle
+ )
+{
+ BUFFER_LIST *Node;
+
+ for (Node = (BUFFER_LIST *)GetFirstNode (&mFileHandleList.Link)
+ ; !IsNull (&mFileHandleList.Link, &Node->Link)
+ ; Node = (BUFFER_LIST *)GetNextNode (&mFileHandleList.Link, &Node->Link)
+ )
+ {
+ if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)) {
+ RemoveEntryList (&Node->Link);
+ SHELL_FREE_NON_NULL (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path);
+ SHELL_FREE_NON_NULL (Node->Buffer);
+ SHELL_FREE_NON_NULL (Node);
+ return (TRUE);
+ }
+ }
+
+ return (FALSE);
+}
+
+/**
+ Function to determine if a SHELL_FILE_HANDLE is at the end of the file.
+
+ This will NOT work on directories.
+
+ If Handle is NULL, then ASSERT.
+
+ @param[in] Handle the file handle
+
+ @retval TRUE the position is at the end of the file
+ @retval FALSE the position is not at the end of the file
+**/
+BOOLEAN
+EFIAPI
+ShellFileHandleEof (
+ IN SHELL_FILE_HANDLE Handle
+ )
+{
+ EFI_FILE_INFO *Info;
+ UINT64 Pos;
+ BOOLEAN RetVal;
+
+ //
+ // ASSERT if Handle is NULL
+ //
+ ASSERT (Handle != NULL);
+
+ gEfiShellProtocol->GetFilePosition (Handle, &Pos);
+ Info = gEfiShellProtocol->GetFileInfo (Handle);
+ gEfiShellProtocol->SetFilePosition (Handle, Pos);
+
+ if (Info == NULL) {
+ return (FALSE);
+ }
+
+ if (Pos == Info->FileSize) {
+ RetVal = TRUE;
+ } else {
+ RetVal = FALSE;
+ }
+
+ FreePool (Info);
+
+ return (RetVal);
+}
+
+/**
+ Frees any BUFFER_LIST defined type.
+
+ @param[in] List The BUFFER_LIST object to free.
+**/
+VOID
+EFIAPI
+FreeBufferList (
+ IN BUFFER_LIST *List
+ )
+{
+ BUFFER_LIST *BufferListEntry;
+
+ if (List == NULL) {
+ return;
+ }
+
+ //
+ // enumerate through the buffer list and free all memory
+ //
+ for ( BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
+ ; !IsListEmpty (&List->Link)
+ ; BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
+ )
+ {
+ RemoveEntryList (&BufferListEntry->Link);
+ if (BufferListEntry->Buffer != NULL) {
+ FreePool (BufferListEntry->Buffer);
+ }
+
+ FreePool (BufferListEntry);
+ }
+}
+
+/**
+ Dump some hexadecimal data to the screen.
+
+ @param[in] Indent How many spaces to indent the output.
+ @param[in] Offset The offset of the printing.
+ @param[in] DataSize The size in bytes of UserData.
+ @param[in] UserData The data to print out.
+**/
+VOID
+EFIAPI
+DumpHex (
+ IN UINTN Indent,
+ IN UINTN Offset,
+ IN UINTN DataSize,
+ IN VOID *UserData
+ )
+{
+ UINT8 *Data;
+
+ CHAR8 Val[50];
+
+ CHAR8 Str[20];
+
+ UINT8 TempByte;
+ UINTN Size;
+ UINTN Index;
+
+ Data = UserData;
+ while (DataSize != 0) {
+ Size = 16;
+ if (Size > DataSize) {
+ Size = DataSize;
+ }
+
+ for (Index = 0; Index < Size; Index += 1) {
+ TempByte = Data[Index];
+ Val[Index * 3 + 0] = Hex[TempByte >> 4];
+ Val[Index * 3 + 1] = Hex[TempByte & 0xF];
+ Val[Index * 3 + 2] = (CHAR8)((Index == 7) ? '-' : ' ');
+ Str[Index] = (CHAR8)((TempByte < ' ' || TempByte > '~') ? '.' : TempByte);
+ }
+
+ Val[Index * 3] = 0;
+ Str[Index] = 0;
+ ShellPrintEx (-1, -1, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);
+
+ Data += Size;
+ Offset += Size;
+ DataSize -= Size;
+ }
+}
+
+/**
+ Dump HEX data into buffer.
+
+ @param[in] Buffer HEX data to be dumped in Buffer.
+ @param[in] Indent How many spaces to indent the output.
+ @param[in] Offset The offset of the printing.
+ @param[in] DataSize The size in bytes of UserData.
+ @param[in] UserData The data to print out.
+**/
+CHAR16 *
+EFIAPI
+CatSDumpHex (
+ IN CHAR16 *Buffer,
+ IN UINTN Indent,
+ IN UINTN Offset,
+ IN UINTN DataSize,
+ IN VOID *UserData
+ )
+{
+ UINT8 *Data;
+ UINT8 TempByte;
+ UINTN Size;
+ UINTN Index;
+ CHAR8 Val[50];
+ CHAR8 Str[20];
+ CHAR16 *RetVal;
+ CHAR16 *TempRetVal;
+
+ Data = UserData;
+ RetVal = Buffer;
+ while (DataSize != 0) {
+ Size = 16;
+ if (Size > DataSize) {
+ Size = DataSize;
+ }
+
+ for (Index = 0; Index < Size; Index += 1) {
+ TempByte = Data[Index];
+ Val[Index * 3 + 0] = Hex[TempByte >> 4];
+ Val[Index * 3 + 1] = Hex[TempByte & 0xF];
+ Val[Index * 3 + 2] = (CHAR8)((Index == 7) ? '-' : ' ');
+ Str[Index] = (CHAR8)((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);
+ }
+
+ Val[Index * 3] = 0;
+ Str[Index] = 0;
+ TempRetVal = CatSPrint (RetVal, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+
+ Data += Size;
+ Offset += Size;
+ DataSize -= Size;
+ }
+
+ return RetVal;
+}
+
+/**
+ ORDERED_COLLECTION_USER_COMPARE function for SHELL_SORT_UNIQUE_NAME objects.
+
+ @param[in] Unique1AsVoid The first SHELL_SORT_UNIQUE_NAME object (Unique1),
+ passed in as a pointer-to-VOID.
+
+ @param[in] Unique2AsVoid The second SHELL_SORT_UNIQUE_NAME object (Unique2),
+ passed in as a pointer-to-VOID.
+
+ @retval <0 If Unique1 compares less than Unique2.
+
+ @retval 0 If Unique1 compares equal to Unique2.
+
+ @retval >0 If Unique1 compares greater than Unique2.
+**/
+STATIC
+INTN
+EFIAPI
+UniqueNameCompare (
+ IN CONST VOID *Unique1AsVoid,
+ IN CONST VOID *Unique2AsVoid
+ )
+{
+ CONST SHELL_SORT_UNIQUE_NAME *Unique1;
+ CONST SHELL_SORT_UNIQUE_NAME *Unique2;
+
+ Unique1 = Unique1AsVoid;
+ Unique2 = Unique2AsVoid;
+
+ //
+ // We need to cast away CONST for EFI_UNICODE_COLLATION_STRICOLL.
+ //
+ return gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)Unique1->Alias,
+ (CHAR16 *)Unique2->Alias
+ );
+}
+
+/**
+ ORDERED_COLLECTION_KEY_COMPARE function for SHELL_SORT_UNIQUE_NAME objects.
+
+ @param[in] UniqueAliasAsVoid The CHAR16 string UniqueAlias, passed in as a
+ pointer-to-VOID.
+
+ @param[in] UniqueAsVoid The SHELL_SORT_UNIQUE_NAME object (Unique),
+ passed in as a pointer-to-VOID.
+
+ @retval <0 If UniqueAlias compares less than Unique->Alias.
+
+ @retval 0 If UniqueAlias compares equal to Unique->Alias.
+
+ @retval >0 If UniqueAlias compares greater than Unique->Alias.
+**/
+STATIC
+INTN
+EFIAPI
+UniqueNameAliasCompare (
+ IN CONST VOID *UniqueAliasAsVoid,
+ IN CONST VOID *UniqueAsVoid
+ )
+{
+ CONST CHAR16 *UniqueAlias;
+ CONST SHELL_SORT_UNIQUE_NAME *Unique;
+
+ UniqueAlias = UniqueAliasAsVoid;
+ Unique = UniqueAsVoid;
+
+ //
+ // We need to cast away CONST for EFI_UNICODE_COLLATION_STRICOLL.
+ //
+ return gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)UniqueAlias,
+ (CHAR16 *)Unique->Alias
+ );
+}
+
+/**
+ Sort an EFI_SHELL_FILE_INFO list, optionally moving duplicates to a separate
+ list.
+
+ @param[in,out] FileList The list of EFI_SHELL_FILE_INFO objects to sort.
+
+ If FileList is NULL on input, then FileList is
+ considered an empty, hence already sorted, list.
+
+ Otherwise, if (*FileList) is NULL on input, then
+ EFI_INVALID_PARAMETER is returned.
+
+ Otherwise, the caller is responsible for having
+ initialized (*FileList)->Link with
+ InitializeListHead(). No other fields in the
+ (**FileList) head element are accessed by this
+ function.
+
+ On output, (*FileList) is sorted according to Order.
+ If Duplicates is NULL on input, then duplicate
+ elements are preserved, sorted stably, on
+ (*FileList). If Duplicates is not NULL on input,
+ then duplicates are moved (stably sorted) to the
+ new, dynamically allocated (*Duplicates) list.
+
+ @param[out] Duplicates If Duplicates is NULL on input, (*FileList) will be
+ a monotonically ordered list on output, with
+ duplicates stably sorted.
+
+ If Duplicates is not NULL on input, (*FileList) will
+ be a strictly monotonically oredered list on output,
+ with duplicates separated (stably sorted) to
+ (*Duplicates). All fields except Link will be
+ zero-initialized in the (**Duplicates) head element.
+ If no duplicates exist, then (*Duplicates) is set to
+ NULL on output.
+
+ @param[in] Order Determines the comparison operation between
+ EFI_SHELL_FILE_INFO objects.
+
+ @retval EFI_INVALID_PARAMETER (UINTN)Order is greater than or equal to
+ (UINTN)ShellSortFileListMax. Neither the
+ (*FileList) nor the (*Duplicates) list has
+ been modified.
+
+ @retval EFI_INVALID_PARAMETER (*FileList) was NULL on input. Neither the
+ (*FileList) nor the (*Duplicates) list has
+ been modified.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed. Neither the
+ (*FileList) nor the (*Duplicates) list has
+ been modified.
+
+ @retval EFI_SUCCESS Sorting successful, including the case when
+ FileList is NULL on input.
+**/
+EFI_STATUS
+EFIAPI
+ShellSortFileList (
+ IN OUT EFI_SHELL_FILE_INFO **FileList,
+ OUT EFI_SHELL_FILE_INFO **Duplicates OPTIONAL,
+ IN SHELL_SORT_FILE_LIST Order
+ )
+{
+ LIST_ENTRY *FilesHead;
+ ORDERED_COLLECTION *Sort;
+ LIST_ENTRY *FileEntry;
+ EFI_SHELL_FILE_INFO *FileInfo;
+ SHELL_SORT_UNIQUE_NAME *Unique;
+ EFI_STATUS Status;
+ EFI_SHELL_FILE_INFO *Dupes;
+ LIST_ENTRY *NextFileEntry;
+ CONST CHAR16 *Alias;
+ ORDERED_COLLECTION_ENTRY *SortEntry;
+ LIST_ENTRY *TargetFileList;
+ ORDERED_COLLECTION_ENTRY *NextSortEntry;
+ VOID *UniqueAsVoid;
+
+ if ((UINTN)Order >= (UINTN)ShellSortFileListMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FileList == NULL) {
+ //
+ // FileList is considered empty, hence already sorted, with no duplicates.
+ //
+ if (Duplicates != NULL) {
+ *Duplicates = NULL;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ if (*FileList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FilesHead = &(*FileList)->Link;
+
+ //
+ // Collect all the unique names.
+ //
+ Sort = OrderedCollectionInit (UniqueNameCompare, UniqueNameAliasCompare);
+ if (Sort == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BASE_LIST_FOR_EACH (FileEntry, FilesHead) {
+ FileInfo = (EFI_SHELL_FILE_INFO *)FileEntry;
+
+ //
+ // Try to record the name of this file as a unique name.
+ //
+ Unique = AllocatePool (sizeof (*Unique));
+ if (Unique == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UninitSort;
+ }
+
+ Unique->Alias = ((Order == ShellSortFileListByFileName) ?
+ FileInfo->FileName :
+ FileInfo->FullName);
+ InitializeListHead (&Unique->SameNameList);
+
+ Status = OrderedCollectionInsert (Sort, NULL, Unique);
+ if (EFI_ERROR (Status)) {
+ //
+ // Only two errors are possible: memory allocation failed, or this name
+ // has been encountered before. In either case, the
+ // SHELL_SORT_UNIQUE_NAME object being constructed has to be released.
+ //
+ FreePool (Unique);
+ //
+ // Memory allocation failure is fatal, while having seen the same name
+ // before is normal.
+ //
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ goto UninitSort;
+ }
+
+ ASSERT (Status == EFI_ALREADY_STARTED);
+ }
+ }
+
+ //
+ // Set Dupes to suppress incorrect compiler/analyzer warnings.
+ //
+ Dupes = NULL;
+
+ //
+ // If separation of duplicates has been requested, allocate the list for
+ // them.
+ //
+ if (Duplicates != NULL) {
+ Dupes = AllocateZeroPool (sizeof (*Dupes));
+ if (Dupes == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UninitSort;
+ }
+
+ InitializeListHead (&Dupes->Link);
+ }
+
+ //
+ // No memory allocation beyond this point; thus, no chance to fail. We can
+ // now migrate the EFI_SHELL_FILE_INFO objects from (*FileList) to Sort.
+ //
+ BASE_LIST_FOR_EACH_SAFE (FileEntry, NextFileEntry, FilesHead) {
+ FileInfo = (EFI_SHELL_FILE_INFO *)FileEntry;
+ //
+ // Look up the SHELL_SORT_UNIQUE_NAME that matches FileInfo's name.
+ //
+ Alias = ((Order == ShellSortFileListByFileName) ?
+ FileInfo->FileName :
+ FileInfo->FullName);
+ SortEntry = OrderedCollectionFind (Sort, Alias);
+ ASSERT (SortEntry != NULL);
+ Unique = OrderedCollectionUserStruct (SortEntry);
+ //
+ // Move FileInfo from (*FileList) to the end of the list of files whose
+ // names all compare identical to FileInfo's name.
+ //
+ RemoveEntryList (&FileInfo->Link);
+ InsertTailList (&Unique->SameNameList, &FileInfo->Link);
+ }
+
+ //
+ // All EFI_SHELL_FILE_INFO objects originally in (*FileList) have been
+ // distributed to Sort. Now migrate them back to (*FileList), advancing in
+ // unique name order.
+ //
+ for (SortEntry = OrderedCollectionMin (Sort);
+ SortEntry != NULL;
+ SortEntry = OrderedCollectionNext (SortEntry))
+ {
+ Unique = OrderedCollectionUserStruct (SortEntry);
+ //
+ // The first FileInfo encountered for each unique name goes back on
+ // (*FileList) unconditionally. Further FileInfo instances for the same
+ // unique name -- that is, duplicates -- are either returned to (*FileList)
+ // or separated, dependent on the caller's request.
+ //
+ TargetFileList = FilesHead;
+ BASE_LIST_FOR_EACH_SAFE (FileEntry, NextFileEntry, &Unique->SameNameList) {
+ RemoveEntryList (FileEntry);
+ InsertTailList (TargetFileList, FileEntry);
+ if (Duplicates != NULL) {
+ TargetFileList = &Dupes->Link;
+ }
+ }
+ }
+
+ //
+ // We're done. If separation of duplicates has been requested, output the
+ // list of duplicates -- and free that list at once, if it's empty (i.e., if
+ // no duplicates have been found).
+ //
+ if (Duplicates != NULL) {
+ if (IsListEmpty (&Dupes->Link)) {
+ FreePool (Dupes);
+ *Duplicates = NULL;
+ } else {
+ *Duplicates = Dupes;
+ }
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Fall through.
+ //
+UninitSort:
+ for (SortEntry = OrderedCollectionMin (Sort);
+ SortEntry != NULL;
+ SortEntry = NextSortEntry)
+ {
+ NextSortEntry = OrderedCollectionNext (SortEntry);
+ OrderedCollectionDelete (Sort, SortEntry, &UniqueAsVoid);
+ Unique = UniqueAsVoid;
+ ASSERT (IsListEmpty (&Unique->SameNameList));
+ FreePool (Unique);
+ }
+
+ OrderedCollectionUninit (Sort);
+
+ return Status;
+}
diff --git a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h
index beffdd67b2..fd287c6f31 100644
--- a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h
+++ b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h
@@ -1,83 +1,83 @@
-/** @file
- Provides interface to shell internal functions for shell commands.
-
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved. <BR>
- (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _UEFI_COMMAND_LIB_INTERNAL_HEADER_
-#define _UEFI_COMMAND_LIB_INTERNAL_HEADER_
-
-#include <Uefi.h>
-
-#include <Guid/FileInfo.h>
-#include <Guid/GlobalVariable.h>
-
-#include <Protocol/SimpleFileSystem.h>
-#include <Protocol/LoadedImage.h>
-#include <Protocol/EfiShellInterface.h>
-#include <Protocol/EfiShellEnvironment2.h>
-#include <Protocol/Shell.h>
-#include <Protocol/ShellParameters.h>
-#include <Protocol/UnicodeCollation.h>
-#include <Protocol/BlockIo.h>
-#include <Protocol/ShellDynamicCommand.h>
-
-#include <Library/DevicePathLib.h>
-#include <Library/SortLib.h>
-#include <Library/HandleParsingLib.h>
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/DebugLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/PcdLib.h>
-#include <Library/ShellCommandLib.h>
-#include <Library/PrintLib.h>
-#include <Library/ShellLib.h>
-#include <Library/HiiLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiLib.h>
-#include <Library/OrderedCollectionLib.h>
-
-typedef struct {
- LIST_ENTRY Link;
- CHAR16 *CommandString;
- SHELL_GET_MAN_FILENAME GetManFileName;
- SHELL_RUN_COMMAND CommandHandler;
- BOOLEAN LastError;
- EFI_HII_HANDLE HiiHandle;
- EFI_STRING_ID ManFormatHelp;
-} SHELL_COMMAND_INTERNAL_LIST_ENTRY;
-
-typedef struct {
- LIST_ENTRY Link;
- SCRIPT_FILE *Data;
-} SCRIPT_FILE_LIST;
-
-typedef struct {
- EFI_FILE_PROTOCOL *FileHandle;
- CHAR16 *Path;
-} SHELL_COMMAND_FILE_HANDLE;
-
-//
-// Collects multiple EFI_SHELL_FILE_INFO objects that share the same name.
-//
-typedef struct {
- //
- // A string that compares equal to either the FileName or the FullName fields
- // of all EFI_SHELL_FILE_INFO objects on SameNameList, according to
- // gUnicodeCollation->StriColl(). The string is not dynamically allocated;
- // instead, it *aliases* the FileName or FullName field of the
- // EFI_SHELL_FILE_INFO object that was first encountered with this name.
- //
- CONST CHAR16 *Alias;
- //
- // A list of EFI_SHELL_FILE_INFO objects whose FileName or FullName fields
- // compare equal to Alias, according to gUnicodeCollation->StriColl().
- //
- LIST_ENTRY SameNameList;
-} SHELL_SORT_UNIQUE_NAME;
-
-#endif //_UEFI_COMMAND_LIB_INTERNAL_HEADER_
+/** @file
+ Provides interface to shell internal functions for shell commands.
+
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved. <BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _UEFI_COMMAND_LIB_INTERNAL_HEADER_
+#define _UEFI_COMMAND_LIB_INTERNAL_HEADER_
+
+#include <Uefi.h>
+
+#include <Guid/FileInfo.h>
+#include <Guid/GlobalVariable.h>
+
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/EfiShellInterface.h>
+#include <Protocol/EfiShellEnvironment2.h>
+#include <Protocol/Shell.h>
+#include <Protocol/ShellParameters.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/ShellDynamicCommand.h>
+
+#include <Library/DevicePathLib.h>
+#include <Library/SortLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ShellLib.h>
+#include <Library/HiiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/OrderedCollectionLib.h>
+
+typedef struct {
+ LIST_ENTRY Link;
+ CHAR16 *CommandString;
+ SHELL_GET_MAN_FILENAME GetManFileName;
+ SHELL_RUN_COMMAND CommandHandler;
+ BOOLEAN LastError;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_STRING_ID ManFormatHelp;
+} SHELL_COMMAND_INTERNAL_LIST_ENTRY;
+
+typedef struct {
+ LIST_ENTRY Link;
+ SCRIPT_FILE *Data;
+} SCRIPT_FILE_LIST;
+
+typedef struct {
+ EFI_FILE_PROTOCOL *FileHandle;
+ CHAR16 *Path;
+} SHELL_COMMAND_FILE_HANDLE;
+
+//
+// Collects multiple EFI_SHELL_FILE_INFO objects that share the same name.
+//
+typedef struct {
+ //
+ // A string that compares equal to either the FileName or the FullName fields
+ // of all EFI_SHELL_FILE_INFO objects on SameNameList, according to
+ // gUnicodeCollation->StriColl(). The string is not dynamically allocated;
+ // instead, it *aliases* the FileName or FullName field of the
+ // EFI_SHELL_FILE_INFO object that was first encountered with this name.
+ //
+ CONST CHAR16 *Alias;
+ //
+ // A list of EFI_SHELL_FILE_INFO objects whose FileName or FullName fields
+ // compare equal to Alias, according to gUnicodeCollation->StriColl().
+ //
+ LIST_ENTRY SameNameList;
+} SHELL_SORT_UNIQUE_NAME;
+
+#endif //_UEFI_COMMAND_LIB_INTERNAL_HEADER_
diff --git a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
index 08ca7cb788..f27eb4fa3d 100644
--- a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+++ b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
@@ -1,65 +1,65 @@
-## @file
-# Provides interface to shell internal functions for shell commands.
-#
-# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010006
- BASE_NAME = UefiShellCommandLib
- FILE_GUID = 5C12F31F-EBAC-466e-A400-FCA8C9EA3A05
- MODULE_TYPE = UEFI_DRIVER
- VERSION_STRING = 1.1
- LIBRARY_CLASS = ShellCommandLib|UEFI_APPLICATION UEFI_DRIVER DXE_RUNTIME_DRIVER
- CONSTRUCTOR = ShellCommandLibConstructor
- DESTRUCTOR = ShellCommandLibDestructor
-
-#
-# VALID_ARCHITECTURES = IA32 X64 EBC
-#
-
-[Sources.common]
- UefiShellCommandLib.c
- UefiShellCommandLib.h
- ConsistMapping.c
-
-[Packages]
- MdePkg/MdePkg.dec
- ShellPkg/ShellPkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-[LibraryClasses]
- MemoryAllocationLib
- BaseLib
- BaseMemoryLib
- DebugLib
- PrintLib
- UefiBootServicesTableLib
- ShellLib
- HiiLib
- HandleParsingLib
- OrderedCollectionLib
-
-[Protocols]
- gEfiUnicodeCollation2ProtocolGuid ## CONSUMES
- gEfiShellProtocolGuid ## CONSUMES
- gEfiShellParametersProtocolGuid ## CONSUMES
- gEfiShellDynamicCommandProtocolGuid ## SOMETIMES_CONSUMES
- gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES
-
-[Guids]
- gEfiSasDevicePathGuid ## SOMETIMES_CONSUMES ## GUID
-
-[Pcd.common]
- gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES
- gEfiShellPkgTokenSpaceGuid.PcdShellMapNameLength ## CONSUMES
- gEfiShellPkgTokenSpaceGuid.PcdUsbExtendedDecode ## SOMETIMES_CONSUMES
- gEfiShellPkgTokenSpaceGuid.PcdShellDecodeIScsiMapNames ## SOMETIMES_CONSUMES
- gEfiShellPkgTokenSpaceGuid.PcdShellVendorExtendedDecode ## SOMETIMES_CONSUMES
-
-[Depex]
- gEfiUnicodeCollation2ProtocolGuid
+## @file
+# Provides interface to shell internal functions for shell commands.
+#
+# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellCommandLib
+ FILE_GUID = 5C12F31F-EBAC-466e-A400-FCA8C9EA3A05
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = ShellCommandLib|UEFI_APPLICATION UEFI_DRIVER DXE_RUNTIME_DRIVER
+ CONSTRUCTOR = ShellCommandLibConstructor
+ DESTRUCTOR = ShellCommandLibDestructor
+
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources.common]
+ UefiShellCommandLib.c
+ UefiShellCommandLib.h
+ ConsistMapping.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ UefiBootServicesTableLib
+ ShellLib
+ HiiLib
+ HandleParsingLib
+ OrderedCollectionLib
+
+[Protocols]
+ gEfiUnicodeCollation2ProtocolGuid ## CONSUMES
+ gEfiShellProtocolGuid ## CONSUMES
+ gEfiShellParametersProtocolGuid ## CONSUMES
+ gEfiShellDynamicCommandProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gEfiSasDevicePathGuid ## SOMETIMES_CONSUMES ## GUID
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellMapNameLength ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdUsbExtendedDecode ## SOMETIMES_CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellDecodeIScsiMapNames ## SOMETIMES_CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellVendorExtendedDecode ## SOMETIMES_CONSUMES
+
+[Depex]
+ gEfiUnicodeCollation2ProtocolGuid