]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.c
Program SD Cards into 4-bit mode (support for this is required in the spec). This...
[mirror_edk2.git] / UefiCpuPkg / CpuIo2Dxe / CpuIo2Dxe.c
index a688f3bb8e2ffdc9d31742581921d5549ec8cfe2..c183748eea5c4f34d079dd76b291f59d52620b93 100644 (file)
@@ -1,21 +1,80 @@
 /** @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
@@ -26,519 +85,485 @@ EFI_CPU_IO2_PROTOCOL mCpuIo  = {
   }\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
@@ -548,13 +573,13 @@ CpuIo2Initialize (
   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