| /** @file | |
| Main file for Mm shell Debug1 function. | |
| (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR> | |
| Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include "UefiShellDebug1CommandsLib.h" | |
| #include <Library/ShellLib.h> | |
| #include <Library/IoLib.h> | |
| #include <Protocol/PciRootBridgeIo.h> | |
| #include <Protocol/DeviceIo.h> | |
| typedef enum { | |
| ShellMmMemory, | |
| ShellMmMemoryMappedIo, | |
| ShellMmIo, | |
| ShellMmPci, | |
| ShellMmPciExpress | |
| } SHELL_MM_ACCESS_TYPE; | |
| CONST UINT16 mShellMmAccessTypeStr[] = { | |
| STRING_TOKEN (STR_MM_MEM), | |
| STRING_TOKEN (STR_MM_MMIO), | |
| STRING_TOKEN (STR_MM_IO), | |
| STRING_TOKEN (STR_MM_PCI), | |
| STRING_TOKEN (STR_MM_PCIE) | |
| }; | |
| STATIC CONST SHELL_PARAM_ITEM ParamList[] = { | |
| {L"-mmio", TypeFlag}, | |
| {L"-mem", TypeFlag}, | |
| {L"-io", TypeFlag}, | |
| {L"-pci", TypeFlag}, | |
| {L"-pcie", TypeFlag}, | |
| {L"-n", TypeFlag}, | |
| {L"-w", TypeValue}, | |
| {NULL, TypeMax} | |
| }; | |
| CONST UINT64 mShellMmMaxNumber[] = { | |
| 0, MAX_UINT8, MAX_UINT16, 0, MAX_UINT32, 0, 0, 0, MAX_UINT64 | |
| }; | |
| CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH mShellMmRootBridgeIoWidth[] = { | |
| 0, EfiPciWidthUint8, EfiPciWidthUint16, 0, EfiPciWidthUint32, 0, 0, 0, EfiPciWidthUint64 | |
| }; | |
| CONST EFI_CPU_IO_PROTOCOL_WIDTH mShellMmCpuIoWidth[] = { | |
| 0, EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, 0, EfiCpuIoWidthUint32, 0, 0, 0, EfiCpuIoWidthUint64 | |
| }; | |
| /** | |
| Extract the PCI segment, bus, device, function, register from | |
| from a SHELL_MM_PCI or SHELL_MM_PCIE format of address.. | |
| @param[in] PciFormat Whether the address is of PCI format of PCIE format. | |
| @param[in] Address SHELL_MM_PCI or SHELL_MM_PCIE address. | |
| @param[out] Segment PCI segment number. | |
| @param[out] Bus PCI bus number. | |
| @param[out] Device PCI device number. | |
| @param[out] Function PCI function number. | |
| @param[out] Register PCI register offset. | |
| **/ | |
| VOID | |
| EFIAPI | |
| ShellMmDecodePciAddress ( | |
| IN BOOLEAN PciFormat, | |
| IN UINT64 Address, | |
| OUT UINT32 *Segment, | |
| OUT UINT8 *Bus, | |
| OUT UINT8 *Device, OPTIONAL | |
| OUT UINT8 *Function, OPTIONAL | |
| OUT UINT32 *Register OPTIONAL | |
| ) | |
| { | |
| if (PciFormat) { | |
| // | |
| // PCI Configuration Space.The address will have the format 0x000000ssbbddffrr, | |
| // where ss = Segment, bb = Bus, dd = Device, ff = Function and rr = Register. | |
| // | |
| *Segment = (UINT32) (RShiftU64 (Address, 32) & 0xFF); | |
| *Bus = (UINT8) (((UINT32) Address) >> 24); | |
| if (Device != NULL) { | |
| *Device = (UINT8) (((UINT32) Address) >> 16); | |
| } | |
| if (Function != NULL) { | |
| *Function = (UINT8) (((UINT32) Address) >> 8); | |
| } | |
| if (Register != NULL) { | |
| *Register = (UINT8) Address; | |
| } | |
| } else { | |
| // | |
| // PCI Express Configuration Space.The address will have the format 0x0000000ssbbddffrrr, | |
| // where ss = Segment, bb = Bus, dd = Device, ff = Function and rrr = Register. | |
| // | |
| *Segment = (UINT32) (RShiftU64 (Address, 36) & 0xFF); | |
| *Bus = (UINT8) RShiftU64 (Address, 28); | |
| if (Device != NULL) { | |
| *Device = (UINT8) (((UINT32) Address) >> 20); | |
| } | |
| if (Function != NULL) { | |
| *Function = (UINT8) (((UINT32) Address) >> 12); | |
| } | |
| if (Register != NULL) { | |
| *Register = (UINT32) (Address & 0xFFF); | |
| } | |
| } | |
| } | |
| /** | |
| Read or write some data from or into the Address. | |
| @param[in] AccessType Access type. | |
| @param[in] PciRootBridgeIo PciRootBridgeIo instance. | |
| @param[in] CpuIo CpuIo instance. | |
| @param[in] Read TRUE for read, FALSE for write. | |
| @param[in] Addresss The memory location to access. | |
| @param[in] Size The size of Buffer in Width sized units. | |
| @param[in, out] Buffer The buffer to read into or write from. | |
| **/ | |
| VOID | |
| ShellMmAccess ( | |
| IN SHELL_MM_ACCESS_TYPE AccessType, | |
| IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, | |
| IN EFI_CPU_IO2_PROTOCOL *CpuIo, | |
| IN BOOLEAN Read, | |
| IN UINT64 Address, | |
| IN UINTN Size, | |
| IN OUT VOID *Buffer | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM RootBridgeIoMem; | |
| EFI_CPU_IO_PROTOCOL_IO_MEM CpuIoMem; | |
| UINT32 Segment; | |
| UINT8 Bus; | |
| UINT8 Device; | |
| UINT8 Function; | |
| UINT32 Register; | |
| if (AccessType == ShellMmMemory) { | |
| if (Read) { | |
| CopyMem (Buffer, (VOID *) (UINTN) Address, Size); | |
| } else { | |
| CopyMem ((VOID *) (UINTN) Address, Buffer, Size); | |
| } | |
| } else { | |
| RootBridgeIoMem = NULL; | |
| CpuIoMem = NULL; | |
| switch (AccessType) { | |
| case ShellMmPci: | |
| case ShellMmPciExpress: | |
| ASSERT (PciRootBridgeIo != NULL); | |
| ShellMmDecodePciAddress ((BOOLEAN) (AccessType == ShellMmPci), Address, &Segment, &Bus, &Device, &Function, &Register); | |
| if (Read) { | |
| Status = PciRootBridgeIo->Pci.Read ( | |
| PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size], | |
| EFI_PCI_ADDRESS (Bus, Device, Function, Register), | |
| 1, Buffer | |
| ); | |
| } else { | |
| Status = PciRootBridgeIo->Pci.Write ( | |
| PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size], | |
| EFI_PCI_ADDRESS (Bus, Device, Function, Register), | |
| 1, Buffer | |
| ); | |
| } | |
| ASSERT_EFI_ERROR (Status); | |
| return; | |
| case ShellMmMemoryMappedIo: | |
| if (PciRootBridgeIo != NULL) { | |
| RootBridgeIoMem = Read ? PciRootBridgeIo->Mem.Read : PciRootBridgeIo->Mem.Write; | |
| } | |
| if (CpuIo != NULL) { | |
| CpuIoMem = Read ? CpuIo->Mem.Read : CpuIo->Mem.Write; | |
| } | |
| break; | |
| case ShellMmIo: | |
| if (PciRootBridgeIo != NULL) { | |
| RootBridgeIoMem = Read ? PciRootBridgeIo->Io.Read : PciRootBridgeIo->Io.Write; | |
| } | |
| if (CpuIo != NULL) { | |
| CpuIoMem = Read ? CpuIo->Io.Read : CpuIo->Io.Write; | |
| } | |
| break; | |
| default: | |
| ASSERT (FALSE); | |
| break; | |
| } | |
| Status = EFI_UNSUPPORTED; | |
| if (RootBridgeIoMem != NULL) { | |
| Status = RootBridgeIoMem (PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size], Address, 1, Buffer); | |
| } | |
| if (EFI_ERROR (Status) && (CpuIoMem != NULL)) { | |
| Status = CpuIoMem (CpuIo, mShellMmCpuIoWidth[Size], Address, 1, Buffer); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| if (AccessType == ShellMmIo) { | |
| switch (Size) { | |
| case 1: | |
| if (Read) { | |
| *(UINT8 *) Buffer = IoRead8 ((UINTN) Address); | |
| } else { | |
| IoWrite8 ((UINTN) Address, *(UINT8 *) Buffer); | |
| } | |
| break; | |
| case 2: | |
| if (Read) { | |
| *(UINT16 *) Buffer = IoRead16 ((UINTN) Address); | |
| } else { | |
| IoWrite16 ((UINTN) Address, *(UINT16 *) Buffer); | |
| } | |
| break; | |
| case 4: | |
| if (Read) { | |
| *(UINT32 *) Buffer = IoRead32 ((UINTN) Address); | |
| } else { | |
| IoWrite32 ((UINTN) Address, *(UINT32 *) Buffer); | |
| } | |
| break; | |
| case 8: | |
| if (Read) { | |
| *(UINT64 *) Buffer = IoRead64 ((UINTN) Address); | |
| } else { | |
| IoWrite64 ((UINTN) Address, *(UINT64 *) Buffer); | |
| } | |
| break; | |
| default: | |
| ASSERT (FALSE); | |
| break; | |
| } | |
| } else { | |
| switch (Size) { | |
| case 1: | |
| if (Read) { | |
| *(UINT8 *) Buffer = MmioRead8 ((UINTN) Address); | |
| } else { | |
| MmioWrite8 ((UINTN) Address, *(UINT8 *) Buffer); | |
| } | |
| break; | |
| case 2: | |
| if (Read) { | |
| *(UINT16 *) Buffer = MmioRead16 ((UINTN) Address); | |
| } else { | |
| MmioWrite16 ((UINTN) Address, *(UINT16 *) Buffer); | |
| } | |
| break; | |
| case 4: | |
| if (Read) { | |
| *(UINT32 *) Buffer = MmioRead32 ((UINTN) Address); | |
| } else { | |
| MmioWrite32 ((UINTN) Address, *(UINT32 *) Buffer); | |
| } | |
| break; | |
| case 8: | |
| if (Read) { | |
| *(UINT64 *) Buffer = MmioRead64 ((UINTN) Address); | |
| } else { | |
| MmioWrite64 ((UINTN) Address, *(UINT64 *) Buffer); | |
| } | |
| break; | |
| default: | |
| ASSERT (FALSE); | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| Find the CpuIo instance and PciRootBridgeIo instance in the platform. | |
| If there are multiple PciRootBridgeIo instances, the instance which manages | |
| the Address is returned. | |
| @param[in] AccessType Access type. | |
| @param[in] Address Address to access. | |
| @param[out] CpuIo Return the CpuIo instance. | |
| @param[out] PciRootBridgeIo Return the proper PciRootBridgeIo instance. | |
| @retval TRUE There are PciRootBridgeIo instances in the platform. | |
| @retval FALSE There isn't PciRootBridgeIo instance in the platform. | |
| **/ | |
| BOOLEAN | |
| ShellMmLocateIoProtocol ( | |
| IN SHELL_MM_ACCESS_TYPE AccessType, | |
| IN UINT64 Address, | |
| OUT EFI_CPU_IO2_PROTOCOL **CpuIo, | |
| OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **PciRootBridgeIo | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINTN Index; | |
| UINTN HandleCount; | |
| EFI_HANDLE *HandleBuffer; | |
| EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Io; | |
| UINT32 Segment; | |
| UINT8 Bus; | |
| EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; | |
| Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) CpuIo); | |
| if (EFI_ERROR (Status)) { | |
| *CpuIo = NULL; | |
| } | |
| *PciRootBridgeIo = NULL; | |
| HandleBuffer = NULL; | |
| Status = gBS->LocateHandleBuffer ( | |
| ByProtocol, | |
| &gEfiPciRootBridgeIoProtocolGuid, | |
| NULL, | |
| &HandleCount, | |
| &HandleBuffer | |
| ); | |
| if (EFI_ERROR (Status) || (HandleCount == 0) || (HandleBuffer == NULL)) { | |
| return FALSE; | |
| } | |
| Segment = 0; | |
| Bus = 0; | |
| if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) { | |
| ShellMmDecodePciAddress ((BOOLEAN) (AccessType == ShellMmPci), Address, &Segment, &Bus, NULL, NULL, NULL); | |
| } | |
| // | |
| // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment & bus number | |
| // | |
| for (Index = 0; (Index < HandleCount) && (*PciRootBridgeIo == NULL); Index++) { | |
| Status = gBS->HandleProtocol ( | |
| HandleBuffer[Index], | |
| &gEfiPciRootBridgeIoProtocolGuid, | |
| (VOID *) &Io | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| continue; | |
| } | |
| if ((((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) && (Io->SegmentNumber == Segment)) || | |
| ((AccessType == ShellMmIo) || (AccessType == ShellMmMemoryMappedIo)) | |
| ) { | |
| Status = Io->Configuration (Io, (VOID **) &Descriptors); | |
| if (!EFI_ERROR (Status)) { | |
| while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) { | |
| // | |
| // Compare the segment and bus range for PCI/PCIE access | |
| // | |
| if ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) && | |
| ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) && | |
| ((Bus >= Descriptors->AddrRangeMin) && (Bus <= Descriptors->AddrRangeMax)) | |
| ) { | |
| *PciRootBridgeIo = Io; | |
| break; | |
| // | |
| // Compare the address range for MMIO/IO access | |
| // | |
| } else if ((((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) && (AccessType == ShellMmIo)) || | |
| ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) && (AccessType == ShellMmMemoryMappedIo)) | |
| ) && ((Address >= Descriptors->AddrRangeMin) && (Address <= Descriptors->AddrRangeMax)) | |
| ) { | |
| *PciRootBridgeIo = Io; | |
| break; | |
| } | |
| Descriptors++; | |
| } | |
| } | |
| } | |
| } | |
| if (HandleBuffer != NULL) { | |
| FreePool (HandleBuffer); | |
| } | |
| return TRUE; | |
| } | |
| /** | |
| Function for 'mm' command. | |
| @param[in] ImageHandle Handle to the Image (NULL if Internal). | |
| @param[in] SystemTable Pointer to the System Table (NULL if Internal). | |
| **/ | |
| SHELL_STATUS | |
| EFIAPI | |
| ShellCommandRunMm ( | |
| IN EFI_HANDLE ImageHandle, | |
| IN EFI_SYSTEM_TABLE *SystemTable | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; | |
| EFI_CPU_IO2_PROTOCOL *CpuIo; | |
| UINT64 Address; | |
| UINT64 Value; | |
| SHELL_MM_ACCESS_TYPE AccessType; | |
| UINT64 Buffer; | |
| UINTN Index; | |
| UINTN Size; | |
| BOOLEAN Complete; | |
| CHAR16 *InputStr; | |
| BOOLEAN Interactive; | |
| LIST_ENTRY *Package; | |
| CHAR16 *ProblemParam; | |
| SHELL_STATUS ShellStatus; | |
| CONST CHAR16 *Temp; | |
| BOOLEAN HasPciRootBridgeIo; | |
| Value = 0; | |
| Address = 0; | |
| ShellStatus = SHELL_SUCCESS; | |
| InputStr = NULL; | |
| Size = 1; | |
| AccessType = ShellMmMemory; | |
| // | |
| // Parse arguments | |
| // | |
| Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); | |
| if (EFI_ERROR (Status)) { | |
| if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"mm", ProblemParam); | |
| FreePool (ProblemParam); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } else { | |
| ASSERT (FALSE); | |
| } | |
| } else { | |
| if (ShellCommandLineGetCount (Package) < 2) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"mm"); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } else if (ShellCommandLineGetCount (Package) > 3) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } else if (ShellCommandLineGetFlag (Package, L"-w") && ShellCommandLineGetValue (Package, L"-w") == NULL) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"mm", L"-w"); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } else { | |
| if (ShellCommandLineGetFlag (Package, L"-mmio")) { | |
| AccessType = ShellMmMemoryMappedIo; | |
| if (ShellCommandLineGetFlag (Package, L"-mem") | |
| || ShellCommandLineGetFlag (Package, L"-io") | |
| || ShellCommandLineGetFlag (Package, L"-pci") | |
| || ShellCommandLineGetFlag (Package, L"-pcie") | |
| ) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| } else if (ShellCommandLineGetFlag (Package, L"-mem")) { | |
| AccessType = ShellMmMemory; | |
| if (ShellCommandLineGetFlag (Package, L"-io") | |
| || ShellCommandLineGetFlag (Package, L"-pci") | |
| || ShellCommandLineGetFlag (Package, L"-pcie") | |
| ) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| } else if (ShellCommandLineGetFlag (Package, L"-io")) { | |
| AccessType = ShellMmIo; | |
| if (ShellCommandLineGetFlag (Package, L"-pci") | |
| || ShellCommandLineGetFlag (Package, L"-pcie") | |
| ) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| } else if (ShellCommandLineGetFlag (Package, L"-pci")) { | |
| AccessType = ShellMmPci; | |
| if (ShellCommandLineGetFlag (Package, L"-pcie") | |
| ) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| } else if (ShellCommandLineGetFlag (Package, L"-pcie")) { | |
| AccessType = ShellMmPciExpress; | |
| } | |
| } | |
| // | |
| // Non interactive for a script file or for the specific parameter | |
| // | |
| Interactive = TRUE; | |
| if (gEfiShellProtocol->BatchIsActive () || ShellCommandLineGetFlag (Package, L"-n")) { | |
| Interactive = FALSE; | |
| } | |
| Temp = ShellCommandLineGetValue (Package, L"-w"); | |
| if (Temp != NULL) { | |
| Size = ShellStrToUintn (Temp); | |
| } | |
| if ((Size != 1) && (Size != 2) && (Size != 4) && (Size != 8)) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"mm", Temp, L"-w"); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| Temp = ShellCommandLineGetRawValue (Package, 1); | |
| Status = ShellConvertStringToUint64 (Temp, &Address, TRUE, FALSE); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| if ((Address & (Size - 1)) != 0) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_NOT_ALIGNED), gShellDebug1HiiHandle, L"mm", Address); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| if ((AccessType == ShellMmIo) && (Address + Size > MAX_UINT16 + 1)) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_IO_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm"); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| // | |
| // locate IO protocol interface | |
| // | |
| HasPciRootBridgeIo = ShellMmLocateIoProtocol (AccessType, Address, &CpuIo, &PciRootBridgeIo); | |
| if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) { | |
| if (!HasPciRootBridgeIo) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"mm"); | |
| ShellStatus = SHELL_NOT_FOUND; | |
| goto Done; | |
| } | |
| if (PciRootBridgeIo == NULL) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm", Address); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| } | |
| // | |
| // Mode 1: Directly set a value | |
| // | |
| Temp = ShellCommandLineGetRawValue (Package, 2); | |
| if (Temp != NULL) { | |
| Status = ShellConvertStringToUint64 (Temp, &Value, TRUE, FALSE); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| if (Value > mShellMmMaxNumber[Size]) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Value); | |
| goto Done; | |
| } | |
| // | |
| // Mode 2: Directly show a value | |
| // | |
| if (!Interactive) { | |
| if (!gEfiShellProtocol->BatchIsActive ()) { | |
| ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle); | |
| } | |
| ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer); | |
| if (!gEfiShellProtocol->BatchIsActive ()) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address); | |
| } | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]); | |
| ShellPrintEx (-1, -1, L"\r\n"); | |
| goto Done; | |
| } | |
| // | |
| // Mode 3: Show or set values in interactive mode | |
| // | |
| Complete = FALSE; | |
| do { | |
| if ((AccessType == ShellMmIo) && (Address + Size > MAX_UINT16 + 1)) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE2), gShellDebug1HiiHandle, L"mm"); | |
| break; | |
| } | |
| ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer); | |
| ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle); | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address); | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]); | |
| ShellPrintEx (-1, -1, L" > "); | |
| // | |
| // wait user input to modify | |
| // | |
| if (InputStr != NULL) { | |
| FreePool (InputStr); | |
| InputStr = NULL; | |
| } | |
| ShellPromptForResponse (ShellPromptResponseTypeFreeform, NULL, (VOID**) &InputStr); | |
| if (InputStr != NULL) { | |
| // | |
| // skip space characters | |
| // | |
| for (Index = 0; InputStr[Index] == ' '; Index++); | |
| if (InputStr[Index] != CHAR_NULL) { | |
| if ((InputStr[Index] == '.') || (InputStr[Index] == 'q') || (InputStr[Index] == 'Q')) { | |
| Complete = TRUE; | |
| } else if (!EFI_ERROR (ShellConvertStringToUint64 (InputStr + Index, &Buffer, TRUE, TRUE)) && | |
| (Buffer <= mShellMmMaxNumber[Size]) | |
| ) { | |
| ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Buffer); | |
| } else { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle, L"mm"); | |
| continue; | |
| } | |
| } | |
| } | |
| Address += Size; | |
| ShellPrintEx (-1, -1, L"\r\n"); | |
| } while (!Complete); | |
| } | |
| ASSERT (ShellStatus == SHELL_SUCCESS); | |
| Done: | |
| if (InputStr != NULL) { | |
| FreePool (InputStr); | |
| } | |
| if (Package != NULL) { | |
| ShellCommandLineFreeVarList (Package); | |
| } | |
| return ShellStatus; | |
| } |