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: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			911 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			911 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Produces the CPU I/O PPI.
 | |
| 
 | |
| Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 | |
| 
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "CpuIoPei.h"
 | |
| 
 | |
| //
 | |
| // Instance of CPU I/O PPI
 | |
| //
 | |
| EFI_PEI_CPU_IO_PPI  gCpuIoPpi = {
 | |
|   {
 | |
|     CpuMemoryServiceRead,
 | |
|     CpuMemoryServiceWrite
 | |
|   },
 | |
|   {
 | |
|     CpuIoServiceRead,
 | |
|     CpuIoServiceWrite
 | |
|   },
 | |
|   CpuIoRead8,
 | |
|   CpuIoRead16,
 | |
|   CpuIoRead32,
 | |
|   CpuIoRead64,
 | |
|   CpuIoWrite8,
 | |
|   CpuIoWrite16,
 | |
|   CpuIoWrite32,
 | |
|   CpuIoWrite64,
 | |
|   CpuMemRead8,
 | |
|   CpuMemRead16,
 | |
|   CpuMemRead32,
 | |
|   CpuMemRead64,
 | |
|   CpuMemWrite8,
 | |
|   CpuMemWrite16,
 | |
|   CpuMemWrite32,
 | |
|   CpuMemWrite64
 | |
| };
 | |
| 
 | |
| //
 | |
| // PPI Descriptor used to install the CPU I/O PPI
 | |
| //
 | |
| EFI_PEI_PPI_DESCRIPTOR gPpiList = {
 | |
|   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
 | |
|   &gEfiPeiCpuIoPpiInstalledGuid,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| //
 | |
| // Lookup table for increment values based on transfer widths
 | |
| //
 | |
| UINT8 mInStride[] = {
 | |
|   1, // EfiPeiCpuIoWidthUint8
 | |
|   2, // EfiPeiCpuIoWidthUint16
 | |
|   4, // EfiPeiCpuIoWidthUint32
 | |
|   8, // EfiPeiCpuIoWidthUint64
 | |
|   0, // EfiPeiCpuIoWidthFifoUint8
 | |
|   0, // EfiPeiCpuIoWidthFifoUint16
 | |
|   0, // EfiPeiCpuIoWidthFifoUint32
 | |
|   0, // EfiPeiCpuIoWidthFifoUint64
 | |
|   1, // EfiPeiCpuIoWidthFillUint8
 | |
|   2, // EfiPeiCpuIoWidthFillUint16
 | |
|   4, // EfiPeiCpuIoWidthFillUint32
 | |
|   8  // EfiPeiCpuIoWidthFillUint64
 | |
| };
 | |
| 
 | |
| //
 | |
| // Lookup table for increment values based on transfer widths
 | |
| //
 | |
| UINT8 mOutStride[] = {
 | |
|   1, // EfiPeiCpuIoWidthUint8
 | |
|   2, // EfiPeiCpuIoWidthUint16
 | |
|   4, // EfiPeiCpuIoWidthUint32
 | |
|   8, // EfiPeiCpuIoWidthUint64
 | |
|   1, // EfiPeiCpuIoWidthFifoUint8
 | |
|   2, // EfiPeiCpuIoWidthFifoUint16
 | |
|   4, // EfiPeiCpuIoWidthFifoUint32
 | |
|   8, // EfiPeiCpuIoWidthFifoUint64
 | |
|   0, // EfiPeiCpuIoWidthFillUint8
 | |
|   0, // EfiPeiCpuIoWidthFillUint16
 | |
|   0, // EfiPeiCpuIoWidthFillUint32
 | |
|   0  // EfiPeiCpuIoWidthFillUint64
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Check parameters to a CPU I/O PPI service request.
 | |
| 
 | |
|   @param[in]  MmioOperation  TRUE for an MMIO operation, FALSE for I/O Port operation.
 | |
|   @param[in]  Width          The width of the access. Enumerated in bytes.
 | |
|   @param[in]  Address        The physical address of the access.
 | |
|   @param[in]  Count          The number of accesses to perform.
 | |
|   @param[in]  Buffer         A pointer to the buffer of data.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The parameters for this request pass the checks.
 | |
|   @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
 | |
|   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
 | |
|   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
 | |
|                                  and Count is not valid for this EFI system.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| CpuIoCheckParameter (
 | |
|   IN BOOLEAN                   MmioOperation,
 | |
|   IN EFI_PEI_CPU_IO_PPI_WIDTH  Width,
 | |
|   IN UINT64                    Address,
 | |
|   IN UINTN                     Count,
 | |
|   IN VOID                      *Buffer
 | |
|   )
 | |
| {
 | |
|   UINT64  MaxCount;
 | |
|   UINT64  Limit;
 | |
| 
 | |
|   //
 | |
|   // Check to see if Buffer is NULL
 | |
|   //
 | |
|   if (Buffer == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check to see if Width is in the valid range
 | |
|   //
 | |
|   if ((UINT32)Width >= EfiPeiCpuIoWidthMaximum) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // For FIFO type, the target address won't increase during the access,
 | |
|   // so treat Count as 1
 | |
|   //
 | |
|   if (Width >= EfiPeiCpuIoWidthFifoUint8 && Width <= EfiPeiCpuIoWidthFifoUint64) {
 | |
|     Count = 1;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check to see if Width is in the valid range for I/O Port operations
 | |
|   //
 | |
|   Width = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
 | |
|   if (!MmioOperation && (Width == EfiPeiCpuIoWidthUint64)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check to see if any address associated with this transfer exceeds the maximum
 | |
|   // allowed address.  The maximum address implied by the parameters passed in is
 | |
|   // Address + Size * Count.  If the following condition is met, then the transfer
 | |
|   // is not supported.
 | |
|   //
 | |
|   //    Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
 | |
|   //
 | |
|   // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
 | |
|   // can also be the maximum integer value supported by the CPU, this range
 | |
|   // check must be adjusted to avoid all overflow conditions.
 | |
|   //
 | |
|   // The following form of the range check is equivalent but assumes that
 | |
|   // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
 | |
|   //
 | |
|   Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
 | |
|   if (Count == 0) {
 | |
|     if (Address > Limit) {
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
|   } else {
 | |
|     MaxCount = RShiftU64 (Limit, Width);
 | |
|     if (MaxCount < (Count - 1)) {
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
|     if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Reads memory-mapped registers.
 | |
| 
 | |
|   @param[in]  PeiServices  An indirect pointer to the PEI Services Table
 | |
|                            published by the PEI Foundation.
 | |
|   @param[in]  This         Pointer to local data for the interface.
 | |
|   @param[in]  Width        The width of the access. Enumerated in bytes.
 | |
|   @param[in]  Address      The physical address of the access.
 | |
|   @param[in]  Count        The number of accesses to perform.
 | |
|   @param[out] Buffer       A pointer to the buffer of data.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The function completed successfully.
 | |
|   @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
 | |
|   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
 | |
|   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
 | |
|                                  and Count is not valid for this EFI system.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| CpuMemoryServiceRead (
 | |
|   IN  CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN  CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN  EFI_PEI_CPU_IO_PPI_WIDTH  Width,
 | |
|   IN  UINT64                    Address,
 | |
|   IN  UINTN                     Count,
 | |
|   OUT VOID                      *Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   UINT8                     InStride;
 | |
|   UINT8                     OutStride;
 | |
|   EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
 | |
|   BOOLEAN                   Aligned;
 | |
|   UINT8                     *Uint8Buffer;
 | |
| 
 | |
|   Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Select loop based on the width of the transfer
 | |
|   //
 | |
|   InStride = mInStride[Width];
 | |
|   OutStride = mOutStride[Width];
 | |
|   OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
 | |
|   Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
 | |
|   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
 | |
|     if (OperationWidth == EfiPeiCpuIoWidthUint8) {
 | |
|       *Uint8Buffer = MmioRead8 ((UINTN)Address);
 | |
|     } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
 | |
|       if (Aligned) {
 | |
|         *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
 | |
|       } else {
 | |
|         WriteUnaligned16 ((UINT16 *)Uint8Buffer, MmioRead16 ((UINTN)Address));
 | |
|       }
 | |
|     } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
 | |
|       if (Aligned) {
 | |
|         *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
 | |
|       } else {
 | |
|         WriteUnaligned32 ((UINT32 *)Uint8Buffer, MmioRead32 ((UINTN)Address));
 | |
|       }
 | |
|     } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
 | |
|       if (Aligned) {
 | |
|         *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
 | |
|       } else {
 | |
|         WriteUnaligned64 ((UINT64 *)Uint8Buffer, MmioRead64 ((UINTN)Address));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Writes memory-mapped registers.
 | |
| 
 | |
|   @param[in]  PeiServices  An indirect pointer to the PEI Services Table
 | |
|                            published by the PEI Foundation.
 | |
|   @param[in]  This         Pointer to local data for the interface.
 | |
|   @param[in]  Width        The width of the access. Enumerated in bytes.
 | |
|   @param[in]  Address      The physical address of the access.
 | |
|   @param[in]  Count        The number of accesses to perform.
 | |
|   @param[in]  Buffer       A pointer to the buffer of data.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The function completed successfully.
 | |
|   @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
 | |
|   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
 | |
|   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
 | |
|                                  and Count is not valid for this EFI system.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| CpuMemoryServiceWrite (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN EFI_PEI_CPU_IO_PPI_WIDTH  Width,
 | |
|   IN UINT64                    Address,
 | |
|   IN UINTN                     Count,
 | |
|   IN VOID                      *Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   UINT8                     InStride;
 | |
|   UINT8                     OutStride;
 | |
|   EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
 | |
|   BOOLEAN                   Aligned;
 | |
|   UINT8                     *Uint8Buffer;
 | |
| 
 | |
|   Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Select loop based on the width of the transfer
 | |
|   //
 | |
|   InStride = mInStride[Width];
 | |
|   OutStride = mOutStride[Width];
 | |
|   OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
 | |
|   Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
 | |
|   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
 | |
|     if (OperationWidth == EfiPeiCpuIoWidthUint8) {
 | |
|       MmioWrite8 ((UINTN)Address, *Uint8Buffer);
 | |
|     } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
 | |
|       if (Aligned) {
 | |
|         MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
 | |
|       } else {
 | |
|         MmioWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
 | |
|       }
 | |
|     } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
 | |
|       if (Aligned) {
 | |
|         MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
 | |
|       } else {
 | |
|         MmioWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
 | |
|       }
 | |
|     } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
 | |
|       if (Aligned) {
 | |
|         MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
 | |
|       } else {
 | |
|         MmioWrite64 ((UINTN)Address, ReadUnaligned64 ((UINT64 *)Uint8Buffer));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Reads I/O registers.
 | |
| 
 | |
|   @param[in]  PeiServices  An indirect pointer to the PEI Services Table
 | |
|                            published by the PEI Foundation.
 | |
|   @param[in]  This         Pointer to local data for the interface.
 | |
|   @param[in]  Width        The width of the access. Enumerated in bytes.
 | |
|   @param[in]  Address      The physical address of the access.
 | |
|   @param[in]  Count        The number of accesses to perform.
 | |
|   @param[out] Buffer       A pointer to the buffer of data.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The function completed successfully.
 | |
|   @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
 | |
|   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
 | |
|   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
 | |
|                                  and Count is not valid for this EFI system.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| CpuIoServiceRead (
 | |
|   IN  CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN  CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN  EFI_PEI_CPU_IO_PPI_WIDTH  Width,
 | |
|   IN  UINT64                    Address,
 | |
|   IN  UINTN                     Count,
 | |
|   OUT VOID                      *Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   UINT8                     InStride;
 | |
|   UINT8                     OutStride;
 | |
|   EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
 | |
|   BOOLEAN                   Aligned;
 | |
|   UINT8                     *Uint8Buffer;
 | |
| 
 | |
|   Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Select loop based on the width of the transfer
 | |
|   //
 | |
|   InStride = mInStride[Width];
 | |
|   OutStride = mOutStride[Width];
 | |
|   OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
 | |
| 
 | |
|   //
 | |
|   // Fifo operations supported for (mInStride[Width] == 0)
 | |
|   //
 | |
|   if (InStride == 0) {
 | |
|     switch (OperationWidth) {
 | |
|     case EfiPeiCpuIoWidthUint8:
 | |
|       IoReadFifo8 ((UINTN)Address, Count, Buffer);
 | |
|       return EFI_SUCCESS;
 | |
|     case EfiPeiCpuIoWidthUint16:
 | |
|       IoReadFifo16 ((UINTN)Address, Count, Buffer);
 | |
|       return EFI_SUCCESS;
 | |
|     case EfiPeiCpuIoWidthUint32:
 | |
|       IoReadFifo32 ((UINTN)Address, Count, Buffer);
 | |
|       return EFI_SUCCESS;
 | |
|     default:
 | |
|       //
 | |
|       // The CpuIoCheckParameter call above will ensure that this
 | |
|       // path is not taken.
 | |
|       //
 | |
|       ASSERT (FALSE);
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
 | |
|   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
 | |
|     if (OperationWidth == EfiPeiCpuIoWidthUint8) {
 | |
|       *Uint8Buffer = IoRead8 ((UINTN)Address);
 | |
|     } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
 | |
|       if (Aligned) {
 | |
|         *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
 | |
|       } else {
 | |
|         WriteUnaligned16 ((UINT16 *)Uint8Buffer, IoRead16 ((UINTN)Address));
 | |
|       }
 | |
|     } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
 | |
|       if (Aligned) {
 | |
|         *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
 | |
|       } else {
 | |
|         WriteUnaligned32 ((UINT32 *)Uint8Buffer, IoRead32 ((UINTN)Address));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Write I/O registers.
 | |
| 
 | |
|   @param[in]  PeiServices  An indirect pointer to the PEI Services Table
 | |
|                            published by the PEI Foundation.
 | |
|   @param[in]  This         Pointer to local data for the interface.
 | |
|   @param[in]  Width        The width of the access. Enumerated in bytes.
 | |
|   @param[in]  Address      The physical address of the access.
 | |
|   @param[in]  Count        The number of accesses to perform.
 | |
|   @param[in]  Buffer       A pointer to the buffer of data.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The function completed successfully.
 | |
|   @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
 | |
|   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
 | |
|   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
 | |
|                                  and Count is not valid for this EFI system.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| CpuIoServiceWrite (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN EFI_PEI_CPU_IO_PPI_WIDTH  Width,
 | |
|   IN UINT64                    Address,
 | |
|   IN UINTN                     Count,
 | |
|   IN VOID                      *Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   UINT8                     InStride;
 | |
|   UINT8                     OutStride;
 | |
|   EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
 | |
|   BOOLEAN                   Aligned;
 | |
|   UINT8                     *Uint8Buffer;
 | |
| 
 | |
|   //
 | |
|   // Make sure the parameters are valid
 | |
|   //
 | |
|   Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Select loop based on the width of the transfer
 | |
|   //
 | |
|   InStride = mInStride[Width];
 | |
|   OutStride = mOutStride[Width];
 | |
|   OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
 | |
| 
 | |
|   //
 | |
|   // Fifo operations supported for (mInStride[Width] == 0)
 | |
|   //
 | |
|   if (InStride == 0) {
 | |
|     switch (OperationWidth) {
 | |
|     case EfiPeiCpuIoWidthUint8:
 | |
|       IoWriteFifo8 ((UINTN)Address, Count, Buffer);
 | |
|       return EFI_SUCCESS;
 | |
|     case EfiPeiCpuIoWidthUint16:
 | |
|       IoWriteFifo16 ((UINTN)Address, Count, Buffer);
 | |
|       return EFI_SUCCESS;
 | |
|     case EfiPeiCpuIoWidthUint32:
 | |
|       IoWriteFifo32 ((UINTN)Address, Count, Buffer);
 | |
|       return EFI_SUCCESS;
 | |
|     default:
 | |
|       //
 | |
|       // The CpuIoCheckParameter call above will ensure that this
 | |
|       // path is not taken.
 | |
|       //
 | |
|       ASSERT (FALSE);
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
 | |
|   for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
 | |
|     if (OperationWidth == EfiPeiCpuIoWidthUint8) {
 | |
|       IoWrite8 ((UINTN)Address, *Uint8Buffer);
 | |
|     } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
 | |
|       if (Aligned) {
 | |
|         IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
 | |
|       } else {
 | |
|         IoWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
 | |
|       }
 | |
|     } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
 | |
|       if (Aligned) {
 | |
|         IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
 | |
|       } else {
 | |
|         IoWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   8-bit I/O read operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
| 
 | |
|   @return  An 8-bit value returned from the I/O space.
 | |
| **/
 | |
| UINT8
 | |
| EFIAPI
 | |
| CpuIoRead8 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address
 | |
|   )
 | |
| {
 | |
|   return IoRead8 ((UINTN)Address);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   16-bit I/O read operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
| 
 | |
|   @return  A 16-bit value returned from the I/O space.
 | |
| 
 | |
| **/
 | |
| UINT16
 | |
| EFIAPI
 | |
| CpuIoRead16 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address
 | |
|   )
 | |
| {
 | |
|   return IoRead16 ((UINTN)Address);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   32-bit I/O read operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
| 
 | |
|   @return  A 32-bit value returned from the I/O space.
 | |
| 
 | |
| **/
 | |
| UINT32
 | |
| EFIAPI
 | |
| CpuIoRead32 (
 | |
|   IN CONST EFI_PEI_SERVICES     **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI   *This,
 | |
|   IN UINT64                     Address
 | |
|   )
 | |
| {
 | |
|   return IoRead32 ((UINTN)Address);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   64-bit I/O read operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
| 
 | |
|   @return  A 64-bit value returned from the I/O space.
 | |
| 
 | |
| **/
 | |
| UINT64
 | |
| EFIAPI
 | |
| CpuIoRead64 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address
 | |
|   )
 | |
| {
 | |
|   return IoRead64 ((UINTN)Address);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   8-bit I/O write operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
|   @param[in] Data         The data to write.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| CpuIoWrite8 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address,
 | |
|   IN UINT8                     Data
 | |
|   )
 | |
| {
 | |
|   IoWrite8 ((UINTN)Address, Data);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   16-bit I/O write operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
|   @param[in] Data         The data to write.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| CpuIoWrite16 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address,
 | |
|   IN UINT16                    Data
 | |
|   )
 | |
| {
 | |
|   IoWrite16 ((UINTN)Address, Data);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   32-bit I/O write operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
|   @param[in] Data         The data to write.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| CpuIoWrite32 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address,
 | |
|   IN UINT32                    Data
 | |
|   )
 | |
| {
 | |
|   IoWrite32 ((UINTN)Address, Data);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   64-bit I/O write operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
|   @param[in] Data         The data to write.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| CpuIoWrite64 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address,
 | |
|   IN UINT64                    Data
 | |
|   )
 | |
| {
 | |
|   IoWrite64 ((UINTN)Address, Data);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   8-bit memory read operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
| 
 | |
|   @return  An 8-bit value returned from the memory space.
 | |
| 
 | |
| **/
 | |
| UINT8
 | |
| EFIAPI
 | |
| CpuMemRead8 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address
 | |
|   )
 | |
| {
 | |
|   return MmioRead8 ((UINTN)Address);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   16-bit memory read operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
| 
 | |
|   @return  A 16-bit value returned from the memory space.
 | |
| 
 | |
| **/
 | |
| UINT16
 | |
| EFIAPI
 | |
| CpuMemRead16 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address
 | |
|   )
 | |
| {
 | |
|   return MmioRead16 ((UINTN)Address);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   32-bit memory read operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
| 
 | |
|   @return  A 32-bit value returned from the memory space.
 | |
| 
 | |
| **/
 | |
| UINT32
 | |
| EFIAPI
 | |
| CpuMemRead32 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address
 | |
|   )
 | |
| {
 | |
|   return MmioRead32 ((UINTN)Address);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   64-bit memory read operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
| 
 | |
|   @return  A 64-bit value returned from the memory space.
 | |
| 
 | |
| **/
 | |
| UINT64
 | |
| EFIAPI
 | |
| CpuMemRead64 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address
 | |
|   )
 | |
| {
 | |
|   return MmioRead64 ((UINTN)Address);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   8-bit memory write operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
|   @param[in] Data         The data to write.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| CpuMemWrite8 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address,
 | |
|   IN  UINT8                    Data
 | |
|   )
 | |
| {
 | |
|   MmioWrite8 ((UINTN)Address, Data);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   16-bit memory write operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
|   @param[in] Data         The data to write.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| CpuMemWrite16 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address,
 | |
|   IN UINT16                    Data
 | |
|   )
 | |
| {
 | |
|   MmioWrite16 ((UINTN)Address, Data);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   32-bit memory write operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
|   @param[in] Data         The data to write.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| CpuMemWrite32 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address,
 | |
|   IN UINT32                    Data
 | |
|   )
 | |
| {
 | |
|   MmioWrite32 ((UINTN)Address, Data);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   64-bit memory write operations.
 | |
| 
 | |
|   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
 | |
|                           by the PEI Foundation.
 | |
|   @param[in] This         Pointer to local data for the interface.
 | |
|   @param[in] Address      The physical address of the access.
 | |
|   @param[in] Data         The data to write.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| CpuMemWrite64 (
 | |
|   IN CONST EFI_PEI_SERVICES    **PeiServices,
 | |
|   IN CONST EFI_PEI_CPU_IO_PPI  *This,
 | |
|   IN UINT64                    Address,
 | |
|   IN UINT64                    Data
 | |
|   )
 | |
| {
 | |
|   MmioWrite64 ((UINTN)Address, Data);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The Entry point of the CPU I/O PEIM
 | |
| 
 | |
|   This function is the Entry point of the CPU I/O PEIM which installs CpuIoPpi.
 | |
| 
 | |
|   @param[in]  FileHandle   Pointer to image file handle.
 | |
|   @param[in]  PeiServices  Pointer to PEI Services Table
 | |
| 
 | |
|   @retval EFI_SUCCESS  CPU I/O PPI successfully installed
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| CpuIoInitialize (
 | |
|   IN EFI_PEI_FILE_HANDLE     FileHandle,
 | |
|   IN CONST EFI_PEI_SERVICES  **PeiServices
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // Register so it will be automatically shadowed to memory
 | |
|   //
 | |
|   Status = PeiServicesRegisterForShadow (FileHandle);
 | |
| 
 | |
|   //
 | |
|   // Make CpuIo pointer in PeiService table point to gCpuIoPpi
 | |
|   //
 | |
|   (*((EFI_PEI_SERVICES **)PeiServices))->CpuIo = &gCpuIoPpi;
 | |
| 
 | |
|   if (Status == EFI_ALREADY_STARTED) {
 | |
|     //
 | |
|     // Shadow completed and running from memory
 | |
|     //
 | |
|     DEBUG ((EFI_D_INFO, "CpuIO PPI has been loaded into memory.  Reinstalled PPI=0x%x\n", &gCpuIoPpi));
 | |
|   } else {
 | |
|     Status = PeiServicesInstallPpi (&gPpiList);
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |