2010-01-15 00:47:50 +01:00
|
|
|
/** @file
|
|
|
|
Produces the CPU I/O PPI.
|
|
|
|
|
2010-04-24 14:25:26 +02:00
|
|
|
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
|
|
|
This program and the accompanying materials
|
2010-01-15 00:47:50 +01:00
|
|
|
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.
|
|
|
|
|
|
|
|
**/
|
|
|
|
|
2010-07-13 05:08:54 +02:00
|
|
|
#include "CpuIoPei.h"
|
2010-01-15 00:47:50 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// 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 (Width < 0 || 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
|
|
|
|
//
|
2010-01-15 03:54:46 +01:00
|
|
|
Width = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
|
2010-01-15 00:47:50 +01:00
|
|
|
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
|
2010-01-15 03:54:46 +01:00
|
|
|
// check must be adjusted to avoid all overflow conditions.
|
2010-01-15 00:47:50 +01:00
|
|
|
//
|
2010-01-15 03:54:46 +01:00
|
|
|
// The following form of the range check is equivalent but assumes that
|
2010-01-15 00:47:50 +01:00
|
|
|
// 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];
|
2010-01-15 03:54:46 +01:00
|
|
|
OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
|
2010-01-15 00:47:50 +01:00
|
|
|
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];
|
2010-01-15 03:54:46 +01:00
|
|
|
OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
|
2010-01-15 00:47:50 +01:00
|
|
|
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];
|
2010-01-15 03:54:46 +01:00
|
|
|
OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
|
2010-01-15 00:47:50 +01:00
|
|
|
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];
|
2010-01-15 03:54:46 +01:00
|
|
|
OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
|
2010-01-15 00:47:50 +01:00
|
|
|
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;
|
|
|
|
}
|