diff options
Diffstat (limited to 'roms/edk2/ShellPkg/Library/UefiShellCommandLib')
4 files changed, 3732 insertions, 0 deletions
diff --git a/roms/edk2/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c b/roms/edk2/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c new file mode 100755 index 000000000..8278388f3 --- /dev/null +++ b/roms/edk2/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c @@ -0,0 +1,1692 @@ +/** @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/roms/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c b/roms/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c new file mode 100644 index 000000000..345808a1e --- /dev/null +++ b/roms/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c @@ -0,0 +1,1911 @@ +/** @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 sucessfully
+**/
+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 sucessful.
+ @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 sucessfully.
+ @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;
+
+ 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);
+
+ 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);
+ }
+ }
+
+ 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);
+
+ ShellCommandConsistMappingInitialize(&ConsistMappingTable);
+
+ //
+ // Assign new Mappings to remainders
+ //
+ for (Count = 0 ; !EFI_ERROR(Status) && HandleList[Count] != NULL && !EFI_ERROR(Status); 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;
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h b/roms/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h new file mode 100644 index 000000000..8ecc2f6bf --- /dev/null +++ b/roms/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h @@ -0,0 +1,65 @@ +/** @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>
+
+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;
+
+
+#endif //_UEFI_COMMAND_LIB_INTERNAL_HEADER_
+
diff --git a/roms/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf b/roms/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf new file mode 100644 index 000000000..a1b5601c9 --- /dev/null +++ b/roms/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf @@ -0,0 +1,64 @@ +## @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
+
+[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
|