https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>
		
			
				
	
	
		
			632 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			632 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Main file for Mm shell Debug1 function.
 | 
						|
 | 
						|
  (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
 | 
						|
  Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#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 PCI or PCIE format of address..
 | 
						|
 | 
						|
  @param[in]  PciFormat      Whether the address is of PCI format of PCIE format.
 | 
						|
  @param[in]  Address        PCI or 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
 | 
						|
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 ssssbbddffrr,
 | 
						|
    // where ssss = Segment, bb = Bus, dd = Device, ff = Function and rr = Register.
 | 
						|
    //
 | 
						|
    *Segment = (UINT32) (RShiftU64 (Address, 32) & 0xFFFF);
 | 
						|
    *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 ssssssbbddffrrr,
 | 
						|
    // where ssss = Segment, bb = Bus, dd = Device, ff = Function and rrr = Register.
 | 
						|
    //
 | 
						|
    *Segment = (UINT32) (RShiftU64 (Address, 36) & 0xFFFF);
 | 
						|
    *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;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 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 {
 | 
						|
      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;
 | 
						|
}
 |