From b7c51c9cf4864df6aabb99a1ae843becd577237c Mon Sep 17 00:00:00 2001 From: raywu Date: Fri, 15 Jun 2018 00:00:50 +0800 Subject: init. 1AQQW051 --- Library/IO.c | 664 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 664 insertions(+) create mode 100644 Library/IO.c (limited to 'Library/IO.c') diff --git a/Library/IO.c b/Library/IO.c new file mode 100644 index 0000000..532ff94 --- /dev/null +++ b/Library/IO.c @@ -0,0 +1,664 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/SOURCE/Core/Library/IO.c 4 7/10/09 3:49p Felixp $ +// +// $Revision: 4 $ +// +// $Date: 7/10/09 3:49p $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Library/IO.c $ +// +// 4 7/10/09 3:49p Felixp +// Function headers added +// +// 3 8/24/06 9:26a Felixp +// Preliminary x64 support (work in progress): +// 1. Processor architecture specific functions moved to a processor +// library +// 2. Makefile removed (AmiLib files are build by the AmiPeiLib and +// AmeDxeLib makefile) +// 3. Tokens.c added +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/23/04 9:42a Felixp +// +// 7 4/09/04 12:47p Markw +// Fixed IoWrites. +// +// 6 3/23/04 4:56p Felixp +// +// 5 3/08/04 5:44p Markw +// +// +// 4 3/05/04 5:48p Markw +// Added IoRead, IoWrite, IoRead, MemRead, MemWrite, MemReadWrite to +// support BootScript. +// +// 3 2/20/04 11:37a Felixp +// read functions simplified (return value passed via eax) +// +// 2 2/19/04 1:27p Markw +// Added include +// +// 1 2/19/04 12:54p Markw +// +//************************************************************************* +// +// +// Name: IO.c +// +// Description: +// Contains generic I/O read/write functions. +// +// +//************************************************************************* +#include + +//************************************************************************* +// +// +// Name: IO_Read_Write_Functions +// +// Description: +// Generic I/O read/write functions. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// AmiLib IoRead Read value(s) from an I/O address or an entire region. +// AmiLib IoRead8 Read 8-bit value from an I/O address. +// AmiLib IoRead16 Read 16-bit value from an I/O address. +// AmiLib IoRead32 Read 32-bit value from an I/O address. +// AmiLib IoReadWrite Read value from an I/O address then write back a value. +// AmiLib IoWrite Write buffer to an I/O address or region. +// AmiLib IoWrite8 Write 8-bit value to an I/O address. +// AmiLib IoWrite16 Write 16-bit value to an I/O address. +// AmiLib IoWrite32 Write 32-bit value to an I/O address. +// AmiLib MemRead Read value(s) from a memory mapped I/O address or an entire region. +// AmiLib MemReadWrite Read value from a memory mapped I/O address then write back a value. +// AmiLib MemWrite Write buffer to an I/O address or region. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions. Append .h to the given name. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: IoRead +// +// Description: +// EFI_STATUS IoRead(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN UINTN Count, OUT VOID *Buffer) performs Count I/O reads of the defined +// Width at the Address and stores the result in Buffer. After every I/O +// operation, Address and Buffer are updated according to the Width. See +// notes for details. +// +// Input: +// IN CPU_IO_WIDTH Width +// Number of bits to read from I/O. Supports at most 32-bits. +// +// IN UINT64 Address +// I/O address to read from. +// +// IN UINTN Count +// Number of reads to perform. +// +// OUT VOID *Buffer +// Buffer where the read results will be stored. User is responsible for +// properly allocating the necessary memory resources. +// +// Output: +// EFI_INVALID_PARAMETER, if Count = 0, Width > 32-bits, or the range of +// Address > 0xffff. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// IoRead8 +// IoRead16 +// IoRead32 +// +// Notes: +// Address and Buffer are updated according to the Width as follows: +// CpuIoWidthUint8 - Both Address and Buffer are incremented by 1. +// CpuIoWidthUint16 - Both Address and Buffer are incremented by 2. +// CpuIoWidthUint32 - Both Address and Buffer are incremented by 4. +// CpuIoWidthFifoUint8 - Only Buffer is incremented by 1. +// CpuIoWidthFifoUint16 - Only Buffer is incremented by 2. +// CpuIoWidthFifoUint32 - Only Buffer is incremented by 4. +// CpuIoWidthFillUint8 - Only Address is incremented by 1. +// CpuIoWidthFillUint16 - Only Address is incremented by 2. +// CpuIoWidthFillUint32 - Only Address is incremented by 4. +// +// +//************************************************************************* +EFI_STATUS IoRead( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT8 ValueWidth = 1 << (Width & 3); + UINT8 AddrInc, BuffInc; + UINTN AddrCount; + + AddrInc = BuffInc = ValueWidth; + + switch (Width & ~3) + { + case CpuIoWidthFifoUint8: AddrInc = 0; break; + case CpuIoWidthFillUint8: BuffInc = 0; break; + } + + AddrCount = (Count-1) * AddrInc + ValueWidth; + + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + if (Address + AddrCount > 0xffff) return EFI_INVALID_PARAMETER; + if ((Width & 3) > CpuIoWidthUint32) return EFI_INVALID_PARAMETER; + + + while (Count--) + { + switch(Width & 3) + { + case CpuIoWidthUint8: + *(UINT8*)Buffer = IoRead8((UINT16)Address); + break; + case CpuIoWidthUint16: + *(UINT16*)Buffer = IoRead16((UINT16)Address); + break; + default: + *(UINT32*)Buffer = IoRead32((UINT16)Address); + } + Address = Address + AddrInc; + Buffer = (UINT8*) Buffer + BuffInc; + } + + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: IoWrite +// +// Description: +// EFI_STATUS IoWrite(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN UINTN Count, IN VOID *Buffer) performs Count I/O writes of the defined +// Width at the Address from the Buffer. After every I/O operation, Address +// and Buffer are updated according to the Width. See notes for details. +// +// Input: +// IN CPU_IO_WIDTH Width +// Number of bits to read from I/O. Supports at most 32-bits. +// +// IN UINT64 Address +// I/O address to write to. +// +// IN UINTN Count +// Number of writes to perform. +// +// IN VOID *Buffer +// Buffer where the data to be written is located. +// +// Output: +// EFI_INVALID_PARAMETER, if Count = 0, Width > 32-bits, or the range of +// Address > 0xffff. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// IoWrite8 +// IoWrite16 +// IoWrite32 +// +// Notes: +// Address and Buffer are updated according to the Width as follows: +// CpuIoWidthUint8 - Both Address and Buffer are incremented by 1. +// CpuIoWidthUint16 - Both Address and Buffer are incremented by 2. +// CpuIoWidthUint32 - Both Address and Buffer are incremented by 4. +// CpuIoWidthFifoUint8 - Only Buffer is incremented by 1. +// CpuIoWidthFifoUint16 - Only Buffer is incremented by 2. +// CpuIoWidthFifoUint32 - Only Buffer is incremented by 4. +// CpuIoWidthFillUint8 - Only Address is incremented by 1. +// CpuIoWidthFillUint16 - Only Address is incremented by 2. +// CpuIoWidthFillUint32 - Only Address is incremented by 4. +// +// +//************************************************************************* +EFI_STATUS IoWrite( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT8 ValueWidth = 1 << (Width & 3); + UINT8 AddrInc, BuffInc; + UINTN AddrCount; + + AddrInc = BuffInc = ValueWidth; + + switch (Width & ~3) + { + case CpuIoWidthFifoUint8: AddrInc = 0; break; + case CpuIoWidthFillUint8: BuffInc = 0; break; + } + + AddrCount = (Count-1) * AddrInc + ValueWidth; + + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + if (Address + AddrCount > 0xffff) return EFI_INVALID_PARAMETER; + if ((Width & 3) > CpuIoWidthUint32) return EFI_INVALID_PARAMETER; + + + while (Count--) + { + switch(Width & 3) + { + case CpuIoWidthUint8: + IoWrite8((UINT16)Address, *(UINT8*) Buffer); + break; + case CpuIoWidthUint16: + IoWrite16((UINT16)Address, *(UINT16*) Buffer); + break; + default: + IoWrite32((UINT16)Address, *(UINT32*) Buffer); + } + Address = Address + AddrInc; + Buffer = (UINT8*) Buffer + BuffInc; + } + + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: IoReadWrite +// +// Description: +// EFI_STATUS IoReadWrite(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN VOID *DataValue, IN VOID *DataMask) reads the specified I/O Address, +// ANDs the result with DataMask, then ORs the modified result with DataValue +// and writes the value back to Address. +// +// Input: +// IN CPU_IO_WIDTH Width +// Number of bits to read/write from I/O. Only supports: CpuIoWidthUint8, +// CpuIoWidthUint16, and CpuIoWidthUint32. +// +// IN UINT64 Address +// I/O address to read and write to. +// +// IN VOID *DataValue +// UINT32 OR mask value. +// +// IN VOID *DataMask +// UINT32 AND mask value. +// +// Output: +// EFI_INVALID_PARAMETER, if Width not supported, or the range of +// Address > 0xffff. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// IoWrite +// IoRead +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS IoReadWrite( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN VOID *DataValue, + IN VOID *DataMask + ) +{ + EFI_STATUS Status; + UINT32 Value32; + UINT32 Mask; + UINT32 Data; + +#if defined(EFI64) || defined(EFIx64) + //In case of aligment issues. + Mask = *((UINT8*)DataMask + 3) + *((UINT8*)DataMask + 2) + *((UINT8*)DataMask + 1) + *(UINT8*)DataMask; + Data = *((UINT8*)DataValue + 3) + *((UINT8*)DataValue + 2) + *((UINT8*)DataValue + 1) + *(UINT8*)DataValue; + ///////////////////////////// +#else + Mask = *(UINT32*)DataMask; + Data = *(UINT32*)DataValue; +#endif + + if ((Width & ~3) != CpuIoWidthUint8) return EFI_INVALID_PARAMETER; //Only CpuIoWidthUintxx Supported + + + if ((Status = IoRead(Width, Address, 1, &Value32) != EFI_SUCCESS)) return Status; + Value32 &= Mask; + Value32 |= Data; + return IoWrite(Width,Address,1,&Value32); +} + +//************************************************************************* +// +// +// Name: MemRead +// +// Description: +// EFI_STATUS MemRead(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN UINTN Count, IN VOID *Buffer) performs Count MMIO reads of the size +// Width at the Address and stores the result in Buffer. After every MMIO +// operation, Address and Buffer are updated according to Width. +// +// Input: +// IN CPU_IO_WIDTH Width +// The width of the access. +// +// IN UINT64 Address +// The physical address of the access. +// +// IN UINTN Count +// The number of accesses to perform. +// +// IN VOID *Buffer +// A pointer to the buffer of data. User is responsible for allocating the +// necessary memory resources. +// +// Output: +// EFI_INVALID_PARAMETER, if Count = 0, Width not supported, or the range of +// Address overflows the bounds of memory. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// Address and Buffer are updated according to Width as follows: +// CpuIoWidthUint8 - Both Address and Buffer are incremented by 1. +// CpuIoWidthUint16 - Both Address and Buffer are incremented by 2. +// CpuIoWidthUint32 - Both Address and Buffer are incremented by 4. +// CpuIoWidthUint64 - Both Address and Buffer are incremented by 8. +// CpuIoWidthFifoUint8 - Only Buffer is incremented by 1. +// CpuIoWidthFifoUint16 - Only Buffer is incremented by 2. +// CpuIoWidthFifoUint32 - Only Buffer is incremented by 4. +// CpuIoWidthFifoUint64 - Only Buffer is incremented by 8. +// CpuIoWidthFillUint8 - Only Address is incremented by 1. +// CpuIoWidthFillUint16 - Only Address is incremented by 2. +// CpuIoWidthFillUint32 - Only Address is incremented by 4. +// CpuIoWidthFillUint64 - Only Address is incremented by 8. +// +// +//************************************************************************* +EFI_STATUS MemRead( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT8 ValueWidth = 1 << (Width & 3); + UINT8 AddrInc, BuffInc; + UINTN AddrCount; + + AddrInc = BuffInc = ValueWidth; + + switch (Width & ~3) + { + case CpuIoWidthFifoUint8: AddrInc = 0; break; + case CpuIoWidthFillUint8: BuffInc = 0; break; + } + + AddrCount = (Count-1) * AddrInc + ValueWidth; + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + +#if defined(EFI64) || defined(EFIx64) + if (Address + AddrCount < Address) return EFI_INVALID_PARAMETER; //Overflow +#else + if (Address + AddrCount > 0xffffffff) return EFI_INVALID_PARAMETER; + if ((Width & 3) > CpuIoWidthUint32) return EFI_INVALID_PARAMETER; +#endif + + + while (Count--) + { + switch(Width & 3) + { + case CpuIoWidthUint8: + *(UINT8*)Buffer = *(UINT8*)Address; + break; + case CpuIoWidthUint16: + *(UINT16*)Buffer = *(UINT16*)Address; + break; + case CpuIoWidthUint32: + *(UINT32*)Buffer = *(UINT32*)Address; + break; + default: + *(UINT64*)Buffer = *(UINT64*)Address; + } + Address = Address + AddrInc; + Buffer = (UINT8*) Buffer + BuffInc; + } + + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: MemWrite +// +// Description: +// EFI_STATUS MemWrite(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN UINTN Count, OUT VOID *Buffer) performs Count MMIO writes of the size +// Width at the Address using the contents of Buffer. After every MMIO +// operation, Address and Buffer are updated according to Width. +// +// Input: +// IN CPU_IO_WIDTH Width +// The width of the access. +// +// IN UINT64 Address +// The physical address of the access. +// +// IN UINTN Count +// The number of accesses to perform. +// +// OUT VOID *Buffer +// A pointer to the buffer of data. +// +// Output: +// EFI_INVALID_PARAMETER, if Count = 0, Width not supported, or the range of +// Address overflows the bounds of memory. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// Address and Buffer are updated according to Width as follows: +// CpuIoWidthUint8 - Both Address and Buffer are incremented by 1. +// CpuIoWidthUint16 - Both Address and Buffer are incremented by 2. +// CpuIoWidthUint32 - Both Address and Buffer are incremented by 4. +// CpuIoWidthUint64 - Both Address and Buffer are incremented by 8. +// CpuIoWidthFifoUint8 - Only Buffer is incremented by 1. +// CpuIoWidthFifoUint16 - Only Buffer is incremented by 2. +// CpuIoWidthFifoUint32 - Only Buffer is incremented by 4. +// CpuIoWidthFifoUint64 - Only Buffer is incremented by 8. +// CpuIoWidthFillUint8 - Only Address is incremented by 1. +// CpuIoWidthFillUint16 - Only Address is incremented by 2. +// CpuIoWidthFillUint32 - Only Address is incremented by 4. +// CpuIoWidthFillUint64 - Only Address is incremented by 8. +// +// +//************************************************************************* +EFI_STATUS MemWrite( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT8 ValueWidth = 1 << (Width & 3); + UINT8 AddrInc, BuffInc; + UINTN AddrCount; + + AddrInc = BuffInc = ValueWidth; + + switch (Width & ~3) + { + case CpuIoWidthFifoUint8: AddrInc = 0; break; + case CpuIoWidthFillUint8: BuffInc = 0; break; + } + + AddrCount = (Count-1) * AddrInc + ValueWidth; + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + +#if defined(EFI64) || defined(EFIx64) + if (Address + AddrCount < Address) return EFI_INVALID_PARAMETER; //Overflow +#else + if (Address + AddrCount > 0xffffffff) return EFI_INVALID_PARAMETER; + if ((Width & 3) > CpuIoWidthUint32) return EFI_INVALID_PARAMETER; +#endif + + + while (Count--) + { + switch(Width & 3) + { + case CpuIoWidthUint8: + *(UINT8*)Address = *(UINT8*)Buffer; + break; + case CpuIoWidthUint16: + *(UINT16*)Address = *(UINT16*)Buffer; + break; + case CpuIoWidthUint32: + *(UINT32*)Address = *(UINT32*) Buffer; + break; + default: + *(UINT64*)Address = *(UINT64*) Buffer; + } + Address = Address + AddrInc; + Buffer = (UINT8*) Buffer + BuffInc; + } + + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: MemReadWrite +// +// Description: +// EFI_STATUS MemReadWrite(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN VOID *DataValue, IN VOID *DataMask) reads the specified physical +// Address, ANDs the result with DataMask, then ORs the modified result with +// DataValue and writes the value back to Address. +// +// Input: +// IN CPU_IO_WIDTH Width +// The width of the access. Only supports CpuIoWidthUintxx. +// +// IN UINT64 Address +// The physical address of the access. +// +// IN VOID *DataValue +// UINT64 OR mask value. +// +// IN VOID *DataMask +// UINT64 AND mask value. +// +// Output: +// EFI_INVALID_PARAMETER, if Width not supported, or the range of +// Address overflows the bounds of memory. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS MemReadWrite( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN VOID *DataValue, + IN VOID *DataMask + ) +{ + EFI_STATUS Status; + UINT64 Value64; + UINT64 Mask; + UINT64 Data; + +#if defined(EFI64) || defined(EFIx64) + //In case of aligment issues. + Mask = *((UINT8*)DataMask + 4) + *((UINT8*)DataMask + 3) + *((UINT8*)DataMask + 2) + *((UINT8*)DataMask + 1) + *(UINT8*)DataMask; + Data = *((UINT8*)DataValue + 4) + *((UINT8*)DataValue + 3) + *((UINT8*)DataValue + 2) + *((UINT8*)DataValue + 1) + *(UINT8*)DataValue; + ///////////////////////////// +#else + Mask = *(UINT64*)DataMask; + Data = *(UINT64*)DataValue; +#endif + + if ((Width & ~3) != CpuIoWidthUint8) return EFI_INVALID_PARAMETER; //Only CpuIoWidthUintxx Supported + + if ((Status = MemRead(Width, Address, 1, &Value64) != EFI_SUCCESS)) return Status; + Value64 &= Mask; + Value64 |= Data; + return MemWrite(Width,Address,1,&Value64); +} + + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* -- cgit v1.2.3