/** @file\r
Produces the CPU I/O 2 Protocol.\r
\r
-Copyright (c) 2009, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
\r
**/\r
\r
-#include "CpuIo2Dxe.h"\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/CpuIo2.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#define MAX_IO_PORT_ADDRESS 0xFFFF\r
+\r
+//\r
+// Function Prototypes\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+CpuMemoryServiceRead (\r
+ IN EFI_CPU_IO2_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuMemoryServiceWrite (\r
+ IN EFI_CPU_IO2_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuIoServiceRead (\r
+ IN EFI_CPU_IO2_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
+ );\r
\r
-EFI_HANDLE mHandle = NULL;\r
-EFI_CPU_IO2_PROTOCOL mCpuIo = {\r
+EFI_STATUS\r
+EFIAPI\r
+CpuIoServiceWrite (\r
+ IN EFI_CPU_IO2_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
+ );\r
+\r
+//\r
+// Handle for the CPU I/O 2 Protocol\r
+//\r
+EFI_HANDLE mHandle = NULL;\r
+\r
+//\r
+// CPU I/O 2 Protocol instance\r
+//\r
+EFI_CPU_IO2_PROTOCOL mCpuIo2 = {\r
{\r
CpuMemoryServiceRead,\r
CpuMemoryServiceWrite\r
}\r
};\r
\r
-/**\r
- Worker function to check the validation of parameters for CPU I/O interface functions.\r
+//\r
+// Lookup table for increment values based on transfer widths\r
+//\r
+UINT8 mInStride[] = {\r
+ 1, // EfiCpuIoWidthUint8\r
+ 2, // EfiCpuIoWidthUint16\r
+ 4, // EfiCpuIoWidthUint32\r
+ 8, // EfiCpuIoWidthUint64\r
+ 0, // EfiCpuIoWidthFifoUint8\r
+ 0, // EfiCpuIoWidthFifoUint16\r
+ 0, // EfiCpuIoWidthFifoUint32\r
+ 0, // EfiCpuIoWidthFifoUint64\r
+ 1, // EfiCpuIoWidthFillUint8\r
+ 2, // EfiCpuIoWidthFillUint16\r
+ 4, // EfiCpuIoWidthFillUint32\r
+ 8 // EfiCpuIoWidthFillUint64\r
+};\r
\r
- This function check the validation of parameters for CPU I/O interface functions.\r
+//\r
+// Lookup table for increment values based on transfer widths\r
+//\r
+UINT8 mOutStride[] = {\r
+ 1, // EfiCpuIoWidthUint8\r
+ 2, // EfiCpuIoWidthUint16\r
+ 4, // EfiCpuIoWidthUint32\r
+ 8, // EfiCpuIoWidthUint64\r
+ 1, // EfiCpuIoWidthFifoUint8\r
+ 2, // EfiCpuIoWidthFifoUint16\r
+ 4, // EfiCpuIoWidthFifoUint32\r
+ 8, // EfiCpuIoWidthFifoUint64\r
+ 0, // EfiCpuIoWidthFillUint8\r
+ 0, // EfiCpuIoWidthFillUint16\r
+ 0, // EfiCpuIoWidthFillUint32\r
+ 0 // EfiCpuIoWidthFillUint64\r
+};\r
\r
- @param Width Width of the Mmio/Io operation\r
- @param Address Base address of the Mmio/Io operation\r
- @param Count Count of the number of accesses to perform\r
- @param Buffer Pointer to the buffer to read from memory\r
- @param Limit Maximum address supported\r
+/**\r
+ Check parameters to a CPU I/O 2 Protocol service request.\r
\r
- @retval EFI_INVALID_PARAMETER Buffer is NULL\r
- @retval EFI_UNSUPPORTED The address range specified by Width, Address and Count is invalid\r
- @retval EFI_UNSUPPORTED The memory buffer is not aligned\r
- @retval EFI_SUCCESS Parameters are valid\r
+ The I/O operations are carried out exactly as requested. The caller is responsible \r
+ for satisfying any alignment and I/O width restrictions that a PI System on a \r
+ platform might require. For example on some platforms, width requests of \r
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will \r
+ be handled by the driver.\r
+ \r
+ @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.\r
+ @param[in] Width Signifies the width of the I/O or Memory operation.\r
+ @param[in] Address The base address of the I/O operation. \r
+ @param[in] Count The number of I/O operations to perform. The number of \r
+ bytes moved is Width size * Count, starting at Address.\r
+ @param[in] Buffer For read operations, the destination buffer to store the results.\r
+ For write operations, the source buffer from which to write data.\r
+\r
+ @retval EFI_SUCCESS The parameters for this request pass the checks.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width, \r
+ and Count is not valid for this PI system.\r
\r
**/\r
EFI_STATUS\r
CpuIoCheckParameter (\r
+ IN BOOLEAN MmioOperation,\r
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
IN UINT64 Address,\r
IN UINTN Count,\r
- IN VOID *Buffer,\r
- IN UINT64 Limit\r
+ IN VOID *Buffer\r
)\r
{\r
- UINTN AlignMask;\r
+ UINT64 MaxCount;\r
+ UINT64 Limit;\r
\r
+ //\r
+ // Check to see if Buffer is NULL\r
+ //\r
if (Buffer == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (Address > Limit) {\r
- return EFI_UNSUPPORTED;\r
+ //\r
+ // Check to see if Width is in the valid range\r
+ //\r
+ if (Width < 0 || Width >= EfiCpuIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
- // For FiFo type, the target address won't increase during the access,\r
- // so treat count as 1\r
+ // For FIFO type, the target address won't increase during the access,\r
+ // so treat Count as 1\r
//\r
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
Count = 1;\r
}\r
\r
+ //\r
+ // Check to see if Width is in the valid range for I/O Port operations\r
+ //\r
Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
- if (Address - 1 + (UINT32)(1 << Width) * Count > Limit) {\r
- return EFI_UNSUPPORTED;\r
+ if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
-\r
- AlignMask = (1 << Width) - 1;\r
- if ((UINTN) Buffer & AlignMask) {\r
+ \r
+ //\r
+ // Check to see if Address is aligned\r
+ //\r
+ if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {\r
return EFI_UNSUPPORTED;\r
}\r
\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Worker function to update access width and count for access to the unaligned address.\r
- Unaligned Io/MmIo address access, break up the request into word by word or byte by byte.\r
-\r
- @param Address Base address of the Mmio/Io operation\r
- @param PtrWidth Pointer to width of the Mmio/Io operation\r
- Out, this value will be updated for access to the unaligned address.\r
- @param PtrCount Pointer to count of the number of accesses to perform\r
- Out, this value will be updated for access to the unaligned address.\r
-**/\r
-VOID\r
-CpuIoUpdateWidthCount (\r
- IN UINT64 Address,\r
- IN OUT EFI_CPU_IO_PROTOCOL_WIDTH *PtrWidth,\r
- IN OUT UINTN *PtrCount\r
- )\r
-{\r
- EFI_CPU_IO_PROTOCOL_WIDTH BufferWidth;\r
- UINTN BufferCount;\r
-\r
- BufferWidth = *PtrWidth;\r
- BufferCount = *PtrCount;\r
- \r
- switch (BufferWidth) {\r
- case EfiCpuIoWidthUint8:\r
- break;\r
-\r
- case EfiCpuIoWidthUint16:\r
- if ((Address & 0x01) == 0) {\r
- break;\r
- } else {\r
- BufferCount = BufferCount * 2;\r
- BufferWidth = EfiCpuIoWidthUint8;\r
+ //\r
+ // Check to see if any address associated with this transfer exceeds the maximum \r
+ // allowed address. The maximum address implied by the parameters passed in is\r
+ // Address + Size * Count. If the following condition is met, then the transfer\r
+ // is not supported.\r
+ //\r
+ // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1\r
+ //\r
+ // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count \r
+ // can also be the maximum integer value supported by the CPU, this range\r
+ // check must be adjusted to avoid all oveflow conditions.\r
+ // \r
+ // The following form of the range check is equivalent but assumes that \r
+ // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).\r
+ //\r
+ Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);\r
+ if (Count == 0) {\r
+ if (Address > Limit) {\r
+ return EFI_UNSUPPORTED;\r
}\r
- break;\r
-\r
- case EfiCpuIoWidthUint32:\r
- if ((Address & 0x03) == 0) {\r
- break;\r
- } else if ((Address & 0x01) == 0) {\r
- BufferCount = BufferCount * 2;\r
- BufferWidth = EfiCpuIoWidthUint16;\r
- } else {\r
- BufferCount = BufferCount * 4;\r
- BufferWidth = EfiCpuIoWidthUint8;\r
+ } else { \r
+ MaxCount = RShiftU64 (Limit, Width);\r
+ if (MaxCount < (Count - 1)) {\r
+ return EFI_UNSUPPORTED;\r
}\r
- break;\r
-\r
- case EfiCpuIoWidthUint64:\r
- if ((Address & 0x07) == 0) {\r
- break;\r
- } else if ((Address & 0x03) == 0) {\r
- BufferCount = BufferCount * 2;\r
- BufferWidth = EfiCpuIoWidthUint32;\r
- } else if ((Address & 0x01) == 0) {\r
- BufferCount = BufferCount * 4;\r
- BufferWidth = EfiCpuIoWidthUint16;\r
- } else {\r
- BufferCount = BufferCount * 8;\r
- BufferWidth = EfiCpuIoWidthUint8;\r
+ if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {\r
+ return EFI_UNSUPPORTED;\r
}\r
- break;\r
-\r
- default:\r
- return;\r
}\r
\r
- *PtrWidth = BufferWidth;\r
- *PtrCount = BufferCount;\r
-\r
- return;\r
-}\r
-\r
-/**\r
- Worker function to perform memory mapped I/O read/write\r
-\r
- This function provides private services to perform memory mapped I/O read/write.\r
-\r
- @param Width Width of the memory mapped I/O operation\r
- @param Count Count of the number of accesses to perform\r
- @param DestinationStrideFlag Boolean flag indicates if the destination is to be incremented\r
- @param Destination Destination of the memory mapped I/O operation\r
- @param SourceStrideFlag Boolean flag indicates if the source is to be incremented\r
- @param Source Source of the memory mapped I/O operation\r
-\r
- @retval EFI_SUCCESS Successful operation\r
- @retval EFI_INVALID_PARAMETER Width is invalid\r
-\r
-**/\r
-EFI_STATUS\r
-CpuIoMemRW (\r
- IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
- IN UINTN Count,\r
- IN BOOLEAN DestinationStrideFlag,\r
- OUT PTR Destination,\r
- IN BOOLEAN SourceStrideFlag,\r
- IN PTR Source\r
- )\r
-{\r
- UINTN Stride;\r
- UINTN DestinationStride;\r
- UINTN SourceStride;\r
-\r
- Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
- Stride = (UINT32)(1 << Width);\r
- DestinationStride = DestinationStrideFlag ? Stride : 0;\r
- SourceStride = SourceStrideFlag ? Stride : 0;\r
-\r
//\r
- // Loop for each iteration and move the data\r
+ // Check to see if Buffer is aligned\r
//\r
- switch (Width) {\r
- case EfiCpuIoWidthUint8:\r
- for (; Count > 0; Count--, Destination.Buf += DestinationStride, Source.Buf += SourceStride) {\r
- MmioWrite8((UINTN)Destination.Ui8 , MmioRead8((UINTN)Source.Ui8));\r
- }\r
- break;\r
-\r
- case EfiCpuIoWidthUint16:\r
- for (; Count > 0; Count--, Destination.Buf += DestinationStride, Source.Buf += SourceStride) {\r
- MmioWrite16((UINTN)Destination.Ui16 , MmioRead16((UINTN)Source.Ui16));\r
- }\r
- break;\r
-\r
- case EfiCpuIoWidthUint32:\r
- for (; Count > 0; Count--, Destination.Buf += DestinationStride, Source.Buf += SourceStride) {\r
- MmioWrite32((UINTN)Destination.Ui32 , MmioRead32((UINTN)Source.Ui32));\r
- }\r
- break;\r
-\r
- case EfiCpuIoWidthUint64:\r
- for (; Count > 0; Count--, Destination.Buf += DestinationStride, Source.Buf += SourceStride) {\r
- MmioWrite64((UINTN)Destination.Ui64 , MmioRead64((UINTN)Source.Ui64));\r
- }\r
- break;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
+ if (((UINTN)Buffer & (mInStride[Width] - 1)) != 0) {\r
+ return EFI_UNSUPPORTED;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- Enables a driver to read memory-mapped registers in the PI System memory space.\r
-\r
- @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
- @param[in] Width Signifies the width of the memory operation.\r
- @param[in] Address The base address of the memory operation.\r
- @param[in] Count The number of memory operations to perform. The number of bytes moved\r
- is Width size * Count, starting at Address.\r
- @param[out] Buffer The destination buffer to store the results.\r
+ Reads memory-mapped registers.\r
\r
- @retval EFI_SUCCESS The data was read from or written to the EFI system.\r
- @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. Or Buffer is NULL.\r
- @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
- Or,The address range specified by Address, Width, and Count is not valid for this EFI system.\r
+ The I/O operations are carried out exactly as requested. The caller is responsible \r
+ for satisfying any alignment and I/O width restrictions that a PI System on a \r
+ platform might require. For example on some platforms, width requests of \r
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will \r
+ be handled by the driver.\r
+ \r
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, \r
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for \r
+ each of the Count operations that is performed.\r
+ \r
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, \r
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is \r
+ incremented for each of the Count operations that is performed. The read or \r
+ write operation is performed Count times on the same Address.\r
+ \r
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, \r
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is \r
+ incremented for each of the Count operations that is performed. The read or \r
+ write operation is performed Count times from the first element of Buffer.\r
+ \r
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
+ @param[in] Width Signifies the width of the I/O or Memory operation.\r
+ @param[in] Address The base address of the I/O operation. \r
+ @param[in] Count The number of I/O operations to perform. The number of \r
+ bytes moved is Width size * Count, starting at Address.\r
+ @param[out] Buffer For read operations, the destination buffer to store the results.\r
+ For write operations, the source buffer from which to write data.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PI system.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width, \r
+ and Count is not valid for this PI system.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
CpuMemoryServiceRead (\r
- IN EFI_CPU_IO2_PROTOCOL *This,\r
- IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 Address,\r
- IN UINTN Count,\r
- OUT VOID *Buffer\r
+ IN EFI_CPU_IO2_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
)\r
{\r
- PTR Source;\r
- PTR Destination;\r
- EFI_STATUS Status;\r
- EFI_CPU_IO_PROTOCOL_WIDTH BufferWidth;\r
+ EFI_STATUS Status;\r
+ UINT8 InStride;\r
+ UINT8 OutStride;\r
+ EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
+ UINT8 *Uint8Buffer;\r
\r
- Status = CpuIoCheckParameter (Width, Address, Count, Buffer, MAX_ADDRESS);\r
+ Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Destination.Buf = Buffer;\r
- Source.Buf = (VOID *) (UINTN) Address;\r
- \r
//\r
- // Support access to unaligned mmio address.\r
- // Break up the request into byte by byte\r
+ // Select loop based on the width of the transfer\r
//\r
- BufferWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
- CpuIoUpdateWidthCount (Address, &BufferWidth, &Count);\r
-\r
- if (Width >= EfiCpuIoWidthUint8 && Width <= EfiCpuIoWidthUint64) {\r
- return CpuIoMemRW (BufferWidth, Count, TRUE, Destination, TRUE, Source);\r
- }\r
-\r
- if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
- return CpuIoMemRW (BufferWidth, Count, TRUE, Destination, FALSE, Source);\r
- }\r
-\r
- if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
- return CpuIoMemRW (BufferWidth, Count, FALSE, Destination, TRUE, Source);\r
+ InStride = mInStride[Width];\r
+ OutStride = mOutStride[Width];\r
+ OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
+ if (OperationWidth == EfiCpuIoWidthUint8) {\r
+ *Uint8Buffer = MmioRead8 ((UINTN)Address);\r
+ } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
+ *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);\r
+ } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
+ *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);\r
+ } else if (OperationWidth == EfiCpuIoWidthUint64) {\r
+ *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);\r
+ }\r
}\r
-\r
- return EFI_INVALID_PARAMETER;\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
- Enables a driver to write memory-mapped registers in the PI System memory space.\r
-\r
- @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
- @param[in] Width Signifies the width of the memory operation.\r
- @param[in] Address The base address of the memory operation.\r
- @param[in] Count The number of memory operations to perform. The number of bytes moved\r
- is Width size * Count, starting at Address.\r
- @param[in] Buffer The source buffer from which to write data.\r
+ Writes memory-mapped registers.\r
\r
- @retval EFI_SUCCESS The data was read from or written to the EFI system.\r
- @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. Or Buffer is NULL.\r
- @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
- Or,The address range specified by Address, Width, and Count is not valid for this EFI system.\r
+ The I/O operations are carried out exactly as requested. The caller is responsible \r
+ for satisfying any alignment and I/O width restrictions that a PI System on a \r
+ platform might require. For example on some platforms, width requests of \r
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will \r
+ be handled by the driver.\r
+ \r
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, \r
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for \r
+ each of the Count operations that is performed.\r
+ \r
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, \r
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is \r
+ incremented for each of the Count operations that is performed. The read or \r
+ write operation is performed Count times on the same Address.\r
+ \r
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, \r
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is \r
+ incremented for each of the Count operations that is performed. The read or \r
+ write operation is performed Count times from the first element of Buffer.\r
+ \r
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
+ @param[in] Width Signifies the width of the I/O or Memory operation.\r
+ @param[in] Address The base address of the I/O operation. \r
+ @param[in] Count The number of I/O operations to perform. The number of \r
+ bytes moved is Width size * Count, starting at Address.\r
+ @param[in] Buffer For read operations, the destination buffer to store the results.\r
+ For write operations, the source buffer from which to write data.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PI system.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width, \r
+ and Count is not valid for this PI system.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
CpuMemoryServiceWrite (\r
- IN EFI_CPU_IO2_PROTOCOL *This,\r
- IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 Address,\r
- IN UINTN Count,\r
- IN VOID *Buffer\r
+ IN EFI_CPU_IO2_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
)\r
{\r
- PTR Source;\r
- PTR Destination;\r
EFI_STATUS Status;\r
- EFI_CPU_IO_PROTOCOL_WIDTH BufferWidth;\r
+ UINT8 InStride;\r
+ UINT8 OutStride;\r
+ EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
+ UINT8 *Uint8Buffer;\r
\r
- Status = CpuIoCheckParameter (Width, Address, Count, Buffer, MAX_ADDRESS);\r
+ Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Destination.Buf = (VOID *) (UINTN) Address;\r
- Source.Buf = Buffer;\r
-\r
//\r
- // Support access to unaligned mmio address.\r
- // Break up the request into byte by byte\r
+ // Select loop based on the width of the transfer\r
//\r
- BufferWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
- CpuIoUpdateWidthCount (Address, &BufferWidth, &Count);\r
-\r
- if (Width >= EfiCpuIoWidthUint8 && Width <= EfiCpuIoWidthUint64) {\r
- return CpuIoMemRW (BufferWidth, Count, TRUE, Destination, TRUE, Source);\r
- }\r
-\r
- if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
- return CpuIoMemRW (BufferWidth, Count, FALSE, Destination, TRUE, Source);\r
- }\r
-\r
- if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
- return CpuIoMemRW (BufferWidth, Count, TRUE, Destination, FALSE, Source);\r
+ InStride = mInStride[Width];\r
+ OutStride = mOutStride[Width];\r
+ OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
+ if (OperationWidth == EfiCpuIoWidthUint8) {\r
+ MmioWrite8 ((UINTN)Address, *Uint8Buffer);\r
+ } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
+ MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));\r
+ } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
+ MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));\r
+ } else if (OperationWidth == EfiCpuIoWidthUint64) {\r
+ MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));\r
+ }\r
}\r
-\r
- return EFI_INVALID_PARAMETER;\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
- Enables a driver to read registers in the PI CPU I/O space.\r
+ Reads I/O registers.\r
\r
- @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
- @param[in] Width Signifies the width of the I/O operation.\r
- @param[in] UserAddress The base address of the I/O operation. The caller is responsible\r
- for aligning the Address if required. \r
- @param[in] Count The number of I/O operations to perform. The number of bytes moved\r
- is Width size * Count, starting at Address.\r
- @param[out] UserBuffer The destination buffer to store the results.\r
-\r
- @retval EFI_SUCCESS The data was read from or written to the EFI system.\r
- @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. Or Buffer is NULL.\r
- @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
- Or,The address range specified by Address, Width, and Count is not valid for this EFI system.\r
+ The I/O operations are carried out exactly as requested. The caller is responsible \r
+ for satisfying any alignment and I/O width restrictions that a PI System on a \r
+ platform might require. For example on some platforms, width requests of \r
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will \r
+ be handled by the driver.\r
+ \r
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, \r
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for \r
+ each of the Count operations that is performed.\r
+ \r
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, \r
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is \r
+ incremented for each of the Count operations that is performed. The read or \r
+ write operation is performed Count times on the same Address.\r
+ \r
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, \r
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is \r
+ incremented for each of the Count operations that is performed. The read or \r
+ write operation is performed Count times from the first element of Buffer.\r
+ \r
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
+ @param[in] Width Signifies the width of the I/O or Memory operation.\r
+ @param[in] Address The base address of the I/O operation. \r
+ @param[in] Count The number of I/O operations to perform. The number of \r
+ bytes moved is Width size * Count, starting at Address.\r
+ @param[out] Buffer For read operations, the destination buffer to store the results.\r
+ For write operations, the source buffer from which to write data.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PI system.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width, \r
+ and Count is not valid for this PI system.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
CpuIoServiceRead (\r
- IN EFI_CPU_IO2_PROTOCOL *This,\r
- IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 UserAddress,\r
- IN UINTN Count,\r
- OUT VOID *UserBuffer\r
+ IN EFI_CPU_IO2_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
)\r
{\r
- UINTN InStride;\r
- UINTN OutStride;\r
- UINTN Address;\r
- PTR Buffer;\r
- EFI_STATUS Status;\r
- EFI_CPU_IO_PROTOCOL_WIDTH BufferWidth; \r
-\r
- Buffer.Buf = (UINT8 *) UserBuffer;\r
-\r
- if (Width >= EfiCpuIoWidthMaximum) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ EFI_STATUS Status;\r
+ UINT8 InStride;\r
+ UINT8 OutStride;\r
+ EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
+ UINT8 *Uint8Buffer;\r
\r
- Status = CpuIoCheckParameter (Width, UserAddress, Count, UserBuffer, IA32_MAX_IO_ADDRESS);\r
+ Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
//\r
- // Support access to unaligned IO address.\r
- // Break up the request into byte by byte\r
- //\r
- BufferWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
- CpuIoUpdateWidthCount (UserAddress, &BufferWidth, &Count);\r
-\r
- Address = (UINTN) UserAddress;\r
- InStride = (UINT32)(1 << (BufferWidth & 0x03));\r
- OutStride = InStride;\r
- if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
- InStride = 0;\r
- }\r
-\r
- if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
- OutStride = 0;\r
- }\r
-\r
- //\r
- // Loop for each iteration and move the data\r
+ // Select loop based on the width of the transfer\r
//\r
- switch (BufferWidth) {\r
- case EfiCpuIoWidthUint8:\r
- for (; Count > 0; Count--, Buffer.Buf += OutStride, Address += InStride) {\r
- *Buffer.Ui8 = IoRead8 (Address);\r
+ InStride = mInStride[Width];\r
+ OutStride = mOutStride[Width];\r
+ OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
+ if (OperationWidth == EfiCpuIoWidthUint8) {\r
+ *Uint8Buffer = IoRead8 ((UINTN)Address);\r
+ } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
+ *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);\r
+ } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
+ *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);\r
}\r
- break;\r
-\r
- case EfiCpuIoWidthUint16:\r
- for (; Count > 0; Count--, Buffer.Buf += OutStride, Address += InStride) {\r
- *Buffer.Ui16 = IoRead16 (Address);\r
- }\r
- break;\r
-\r
- case EfiCpuIoWidthUint32:\r
- for (; Count > 0; Count--, Buffer.Buf += OutStride, Address += InStride) {\r
- *Buffer.Ui32 = IoRead32 (Address);\r
- }\r
- break;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- Enables a driver to write registers in the PI CPU I/O space.\r
-\r
- @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
- @param[in] Width Signifies the width of the I/O operation.\r
- @param[in] UserAddress The base address of the I/O operation. The caller is responsible\r
- for aligning the Address if required. \r
- @param[in] Count The number of I/O operations to perform. The number of bytes moved\r
- is Width size * Count, starting at Address.\r
- @param[in] UserBuffer The source buffer from which to write data.\r
-\r
- @retval EFI_SUCCESS The data was read from or written to the EFI system.\r
- @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. Or Buffer is NULL.\r
- @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
- Or,The address range specified by Address, Width, and Count is not valid for this EFI system.\r
+ Write I/O registers.\r
\r
+ The I/O operations are carried out exactly as requested. The caller is responsible \r
+ for satisfying any alignment and I/O width restrictions that a PI System on a \r
+ platform might require. For example on some platforms, width requests of \r
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will \r
+ be handled by the driver.\r
+ \r
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, \r
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for \r
+ each of the Count operations that is performed.\r
+ \r
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, \r
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is \r
+ incremented for each of the Count operations that is performed. The read or \r
+ write operation is performed Count times on the same Address.\r
+ \r
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, \r
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is \r
+ incremented for each of the Count operations that is performed. The read or \r
+ write operation is performed Count times from the first element of Buffer.\r
+ \r
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
+ @param[in] Width Signifies the width of the I/O or Memory operation.\r
+ @param[in] Address The base address of the I/O operation. \r
+ @param[in] Count The number of I/O operations to perform. The number of \r
+ bytes moved is Width size * Count, starting at Address.\r
+ @param[in] Buffer For read operations, the destination buffer to store the results.\r
+ For write operations, the source buffer from which to write data.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PI system.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width, \r
+ and Count is not valid for this PI system.\r
+ \r
**/\r
EFI_STATUS\r
EFIAPI\r
CpuIoServiceWrite (\r
- IN EFI_CPU_IO2_PROTOCOL *This,\r
- IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 UserAddress,\r
- IN UINTN Count,\r
- IN VOID *UserBuffer\r
+ IN EFI_CPU_IO2_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
)\r
{\r
- UINTN InStride;\r
- UINTN OutStride;\r
- UINTN Address;\r
- PTR Buffer;\r
- EFI_STATUS Status;\r
- EFI_CPU_IO_PROTOCOL_WIDTH BufferWidth;\r
-\r
- Buffer.Buf = (UINT8 *) UserBuffer;\r
-\r
- if (Width >= EfiCpuIoWidthMaximum) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = CpuIoCheckParameter (Width, UserAddress, Count, UserBuffer, IA32_MAX_IO_ADDRESS);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ EFI_STATUS Status;\r
+ UINT8 InStride;\r
+ UINT8 OutStride;\r
+ EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
+ UINT8 *Uint8Buffer;\r
\r
//\r
- // Support access to unaligned IO address.\r
- // Break up the request into byte by byte\r
+ // Make sure the parameters are valid\r
//\r
- BufferWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
- CpuIoUpdateWidthCount (UserAddress, &BufferWidth, &Count);\r
-\r
- Address = (UINTN) UserAddress;\r
- InStride = (UINT32)(1 << (BufferWidth & 0x03));\r
- OutStride = InStride;\r
- if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
- InStride = 0;\r
- }\r
-\r
- if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
- OutStride = 0;\r
+ Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
//\r
- // Loop for each iteration and move the data\r
+ // Select loop based on the width of the transfer\r
//\r
- switch (BufferWidth) {\r
- case EfiCpuIoWidthUint8:\r
- for (; Count > 0; Count--, Buffer.Buf += OutStride, Address += InStride) {\r
- IoWrite8 (Address, *Buffer.Ui8);\r
- }\r
- break;\r
-\r
- case EfiCpuIoWidthUint16:\r
- for (; Count > 0; Count--, Buffer.Buf += OutStride, Address += InStride) {\r
- IoWrite16 (Address, *Buffer.Ui16);\r
+ InStride = mInStride[Width];\r
+ OutStride = mOutStride[Width];\r
+ OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+ for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
+ if (OperationWidth == EfiCpuIoWidthUint8) {\r
+ IoWrite8 ((UINTN)Address, *Uint8Buffer);\r
+ } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
+ IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));\r
+ } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
+ IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));\r
}\r
- break;\r
-\r
- case EfiCpuIoWidthUint32:\r
- for (; Count > 0; Count--, Buffer.Buf += OutStride, Address += InStride) {\r
- IoWrite32 (Address, *Buffer.Ui32);\r
- }\r
- break;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
}\r
-\r
+ \r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- Entrypoint of CPU I/O 2 DXE module.\r
- \r
- @param ImageHandle The firmware allocated handle for the EFI image.\r
- @param SystemTable A pointer to the EFI System Table.\r
+ The user Entry Point for module CpuIo2Dxe. The user code starts with this function.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
\r
- @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval other Some error occurs when executing this entry point.\r
\r
**/\r
EFI_STATUS\r
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
- Status = gBS->InstallProtocolInterface (\r
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
&mHandle,\r
- &gEfiCpuIo2ProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &mCpuIo\r
+ &gEfiCpuIo2ProtocolGuid, &mCpuIo2,\r
+ NULL\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r