[edk2-devel] [PATCH v1 03/11] MdePkg: Base Memory Lib instance using MMIO

Sami Mujawar sami.mujawar at arm.com
Thu May 14 08:40:11 UTC 2020


Some device drivers perform copy operations on
device memory, e.g. device drivers for a Flash
device. On some architectures unaligned access
to device memory regions is not permitted. To
add to this if the device is virtualised then
there are further restrictions on the type of
load/store operations that can be performed
on the device memory regions, e.g. on AARCH64,
Pre/Post index or LDP operations cannot be
used, as a trap to EL2 does not provide the
syndrome information to the hypervisor.

To address these issues this patch introduces
BaseMemoryLibMmio library which provides an
implementation of Base memory library that
uses aligned MMIO accesses.

Signed-off-by: Sami Mujawar <sami.mujawar at arm.com>
---
 MdePkg/Library/BaseMemoryLibMmio/BaseMemoryLibMmio.inf |  50 ++++
 MdePkg/Library/BaseMemoryLibMmio/BaseMemoryLibMmio.uni |  15 +
 MdePkg/Library/BaseMemoryLibMmio/CompareMemWrapper.c   |  62 ++++
 MdePkg/Library/BaseMemoryLibMmio/CopyMem.c             | 149 ++++++++++
 MdePkg/Library/BaseMemoryLibMmio/CopyMemWrapper.c      |  59 ++++
 MdePkg/Library/BaseMemoryLibMmio/IsZeroBufferWrapper.c |  50 ++++
 MdePkg/Library/BaseMemoryLibMmio/MemLibGeneric.c       | 304 ++++++++++++++++++++
 MdePkg/Library/BaseMemoryLibMmio/MemLibGuid.c          | 143 +++++++++
 MdePkg/Library/BaseMemoryLibMmio/MemLibInternals.h     | 248 ++++++++++++++++
 MdePkg/Library/BaseMemoryLibMmio/ScanMem16Wrapper.c    |  63 ++++
 MdePkg/Library/BaseMemoryLibMmio/ScanMem32Wrapper.c    |  62 ++++
 MdePkg/Library/BaseMemoryLibMmio/ScanMem64Wrapper.c    |  63 ++++
 MdePkg/Library/BaseMemoryLibMmio/ScanMem8Wrapper.c     |  95 ++++++
 MdePkg/Library/BaseMemoryLibMmio/SetMem.c              |  83 ++++++
 MdePkg/Library/BaseMemoryLibMmio/SetMem16Wrapper.c     |  60 ++++
 MdePkg/Library/BaseMemoryLibMmio/SetMem32Wrapper.c     |  60 ++++
 MdePkg/Library/BaseMemoryLibMmio/SetMem64Wrapper.c     |  60 ++++
 MdePkg/Library/BaseMemoryLibMmio/SetMemWrapper.c       |  87 ++++++
 MdePkg/Library/BaseMemoryLibMmio/ZeroMemWrapper.c      |  52 ++++
 19 files changed, 1765 insertions(+)

diff --git a/MdePkg/Library/BaseMemoryLibMmio/BaseMemoryLibMmio.inf b/MdePkg/Library/BaseMemoryLibMmio/BaseMemoryLibMmio.inf
new file mode 100644
index 0000000000000000000000000000000000000000..3a61cb985a242a4ce7a2446c4efb9b78fb1d7b5d
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/BaseMemoryLibMmio.inf
@@ -0,0 +1,50 @@
+## @file
+#  Instance of Base Memory Library using Mmio operations.
+#
+#
+#  Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = BaseMemoryLibMmio
+  MODULE_UNI_FILE                = BaseMemoryLibMmio.uni
+  FILE_GUID                      = 5724063D-9855-4B3A-8DEE-1F80ED07E096
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = BaseMemoryLib
+
+#
+#  VALID_ARCHITECTURES           = ARM AARCH64
+#
+
+[Sources]
+  SetMem.c
+  ScanMem64Wrapper.c
+  ScanMem32Wrapper.c
+  ScanMem16Wrapper.c
+  ScanMem8Wrapper.c
+  ZeroMemWrapper.c
+  CompareMemWrapper.c
+  SetMem64Wrapper.c
+  SetMem32Wrapper.c
+  SetMem16Wrapper.c
+  SetMemWrapper.c
+  CopyMemWrapper.c
+  IsZeroBufferWrapper.c
+  MemLibGeneric.c
+  MemLibGuid.c
+  CopyMem.c
+  MemLibInternals.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  DebugLib
+  BaseLib
+  IoLib
+
diff --git a/MdePkg/Library/BaseMemoryLibMmio/BaseMemoryLibMmio.uni b/MdePkg/Library/BaseMemoryLibMmio/BaseMemoryLibMmio.uni
new file mode 100644
index 0000000000000000000000000000000000000000..3dc99103e9a673902abcefe824d5cf5c19b258b8
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/BaseMemoryLibMmio.uni
@@ -0,0 +1,15 @@
+// /** @file
+// Instance of Base Memory Library using Mmio operations.
+//
+//
+// Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Instance of Base Memory Library using Mmio operations"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Base Memory Library using Mmio operations"
+
diff --git a/MdePkg/Library/BaseMemoryLibMmio/CompareMemWrapper.c b/MdePkg/Library/BaseMemoryLibMmio/CompareMemWrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..63e0e3ea583cb242a9242f483e8c952e48122e77
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/CompareMemWrapper.c
@@ -0,0 +1,62 @@
+/** @file
+  CompareMem() implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Compares the contents of two buffers.
+
+  This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer.
+  If all Length bytes of the two buffers are identical, then 0 is returned.  Otherwise, the
+  value returned is the first mismatched byte in SourceBuffer subtracted from the first
+  mismatched byte in DestinationBuffer.
+
+  If Length > 0 and DestinationBuffer is NULL, then ASSERT().
+  If Length > 0 and SourceBuffer is NULL, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT().
+  If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT().
+
+  @param  DestinationBuffer A pointer to the destination buffer to compare.
+  @param  SourceBuffer      A pointer to the source buffer to compare.
+  @param  Length            The number of bytes to compare.
+
+  @return 0                 All Length bytes of the two buffers are identical.
+  @retval Non-zero          The first mismatched byte in SourceBuffer subtracted from the first
+                            mismatched byte in DestinationBuffer.
+
+**/
+INTN
+EFIAPI
+CompareMem (
+  IN CONST VOID  *DestinationBuffer,
+  IN CONST VOID  *SourceBuffer,
+  IN UINTN       Length
+  )
+{
+  if (Length == 0 || DestinationBuffer == SourceBuffer) {
+    return 0;
+  }
+  ASSERT (DestinationBuffer != NULL);
+  ASSERT (SourceBuffer != NULL);
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer));
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer));
+
+  return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length);
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/CopyMem.c b/MdePkg/Library/BaseMemoryLibMmio/CopyMem.c
new file mode 100644
index 0000000000000000000000000000000000000000..84a207bf0f8a537b0832b5c4c9f6735122ee7851
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/CopyMem.c
@@ -0,0 +1,149 @@
+/** @file
+  Implementation of the InternalMemCopyMem routine. This function is broken
+  out into its own source file so that it can be excluded from a build for a
+  particular platform easily if an optimized version is desired.
+
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2012 - 2020, ARM Ltd. All rights reserved.<BR>
+  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Copy Length bytes from Source to Destination.
+
+  @param  DestinationBuffer The target of the copy request.
+  @param  SourceBuffer      The place to copy from.
+  @param  Length            The number of bytes to copy.
+
+  @return Destination
+
+**/
+VOID *
+EFIAPI
+InternalMemCopyMem (
+  OUT     VOID                      *DestinationBuffer,
+  IN      CONST VOID                *SourceBuffer,
+  IN      UINTN                     Length
+  )
+{
+  //
+  // Declare the local variables that actually move the data elements as
+  // volatile to prevent the optimizer from replacing this function with
+  // the intrinsic memcpy()
+  //
+  volatile UINT8                    *Destination8;
+  CONST UINT8                       *Source8;
+  volatile UINT32                   *Destination32;
+  CONST UINT32                      *Source32;
+  volatile UINT64                   *Destination64;
+  CONST UINT64                      *Source64;
+  UINTN                             Alignment;
+
+  if ((((UINTN)DestinationBuffer & 0x7) == 0) &&
+      (((UINTN)SourceBuffer & 0x7) == 0)      &&
+      (Length >= 8)) {
+    if (SourceBuffer > DestinationBuffer) {
+      Destination64 = (UINT64*)DestinationBuffer;
+      Source64 = (CONST UINT64*)SourceBuffer;
+      while (Length >= 8) {
+        MmioWrite64 ((UINTN)Destination64++, MmioRead64 ((UINTN)Source64++));
+        Length -= 8;
+      }
+
+      // Finish if there are still some bytes to copy
+      Destination8 = (UINT8*)Destination64;
+      Source8 = (CONST UINT8*)Source64;
+      while (Length-- != 0) {
+        MmioWrite8 ((UINTN)Destination8++, MmioRead8 ((UINTN)Source8++));
+      }
+    } else if (SourceBuffer < DestinationBuffer) {
+      Destination64 = (UINT64*)((UINTN)DestinationBuffer + Length);
+      Source64 = (CONST UINT64*)((UINTN)SourceBuffer + Length);
+
+      // Destination64 and Source64 were aligned on a 64-bit boundary
+      // but if length is not a multiple of 8 bytes then they won't be
+      // anymore.
+
+      Alignment = Length & 0x7;
+      if (Alignment != 0) {
+        Destination8 = (UINT8*)Destination64;
+        Source8 = (CONST UINT8*)Source64;
+
+        while (Alignment-- != 0) {
+          MmioWrite8 ((UINTN)--Destination8, MmioRead8 ((UINTN)--Source8));
+          --Length;
+        }
+        Destination64 = (UINT64*)Destination8;
+        Source64 = (CONST UINT64*)Source8;
+      }
+
+      while (Length > 0) {
+        MmioWrite64 ((UINTN)--Destination64, MmioRead64 ((UINTN)--Source64));
+        Length -= 8;
+      }
+    }
+  } else if ((((UINTN)DestinationBuffer & 0x3) == 0)  &&
+             (((UINTN)SourceBuffer & 0x3) == 0)       &&
+             (Length >= 4)) {
+    if (SourceBuffer > DestinationBuffer) {
+      Destination32 = (UINT32*)DestinationBuffer;
+      Source32 = (CONST UINT32*)SourceBuffer;
+      while (Length >= 4) {
+        MmioWrite32 ((UINTN)Destination32++, MmioRead32 ((UINTN)Source32++));
+        Length -= 4;
+      }
+
+      // Finish if there are still some bytes to copy
+      Destination8 = (UINT8*)Destination32;
+      Source8 = (CONST UINT8*)Source32;
+      while (Length-- != 0) {
+        MmioWrite8 ((UINTN)Destination8++, MmioRead8 ((UINTN)Source8++));
+      }
+    } else if (SourceBuffer < DestinationBuffer) {
+      Destination32 = (UINT32*)((UINTN)DestinationBuffer + Length);
+      Source32 = (CONST UINT32*)((UINTN)SourceBuffer + Length);
+
+      // Destination32 and Source32 were aligned on a 32-bit boundary
+      // but if length is not a multiple of 4 bytes then they won't be
+      // anymore.
+
+      Alignment = Length & 0x3;
+      if (Alignment != 0) {
+        Destination8 = (UINT8*)Destination32;
+        Source8 = (CONST UINT8*)Source32;
+
+        while (Alignment-- != 0) {
+          MmioWrite8 ((UINTN)--Destination8, MmioRead8 ((UINTN)--Source8));
+          --Length;
+        }
+        Destination32 = (UINT32*)Destination8;
+        Source32 = (CONST UINT32*)Source8;
+      }
+
+      while (Length > 0) {
+        MmioWrite32 ((UINTN)--Destination32, MmioRead32 ((UINTN)--Source32));
+        Length -= 4;
+      }
+    }
+  } else {
+    if (SourceBuffer > DestinationBuffer) {
+      Destination8 = (UINT8*)DestinationBuffer;
+      Source8 = (CONST UINT8*)SourceBuffer;
+      while (Length-- != 0) {
+        MmioWrite8 ((UINTN)Destination8++, MmioRead8 ((UINTN)Source8++));
+      }
+    } else if (SourceBuffer < DestinationBuffer) {
+      Destination8 = (UINT8*)DestinationBuffer + (Length - 1);
+      Source8 = (CONST UINT8*)SourceBuffer + (Length - 1);
+      while (Length-- != 0) {
+        MmioWrite8 ((UINTN)Destination8--, MmioRead8 ((UINTN)Source8--));
+      }
+    }
+  }
+  return DestinationBuffer;
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/CopyMemWrapper.c b/MdePkg/Library/BaseMemoryLibMmio/CopyMemWrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..d557bbb8904c2b07c644261290a62be6fc831c08
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/CopyMemWrapper.c
@@ -0,0 +1,59 @@
+/** @file
+  CopyMem() implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Copies a source buffer to a destination buffer, and returns the destination buffer.
+
+  This function copies Length bytes from SourceBuffer to DestinationBuffer, and returns
+  DestinationBuffer.  The implementation must be reentrant, and it must handle the case
+  where SourceBuffer overlaps DestinationBuffer.
+
+  If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT().
+  If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT().
+
+  @param  DestinationBuffer   A pointer to the destination buffer of the memory copy.
+  @param  SourceBuffer        A pointer to the source buffer of the memory copy.
+  @param  Length              The number of bytes to copy from SourceBuffer to DestinationBuffer.
+
+  @return DestinationBuffer.
+
+**/
+VOID *
+EFIAPI
+CopyMem (
+  OUT VOID       *DestinationBuffer,
+  IN CONST VOID  *SourceBuffer,
+  IN UINTN       Length
+  )
+{
+  if (Length == 0) {
+    return DestinationBuffer;
+  }
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer));
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer));
+
+  if (DestinationBuffer == SourceBuffer) {
+    return DestinationBuffer;
+  }
+  return InternalMemCopyMem (DestinationBuffer, SourceBuffer, Length);
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/IsZeroBufferWrapper.c b/MdePkg/Library/BaseMemoryLibMmio/IsZeroBufferWrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c3133c668c434839b0d9bf105bc7265eeb76a5b
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/IsZeroBufferWrapper.c
@@ -0,0 +1,50 @@
+/** @file
+  Implementation of IsZeroBuffer function.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Checks if the contents of a buffer are all zeros.
+
+  This function checks whether the contents of a buffer are all zeros. If the
+  contents are all zeros, return TRUE. Otherwise, return FALSE.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  Buffer      The pointer to the buffer to be checked.
+  @param  Length      The size of the buffer (in bytes) to be checked.
+
+  @retval TRUE        Contents of the buffer are all zeros.
+  @retval FALSE       Contents of the buffer are not all zeros.
+
+**/
+BOOLEAN
+EFIAPI
+IsZeroBuffer (
+  IN CONST VOID  *Buffer,
+  IN UINTN       Length
+  )
+{
+  ASSERT (!(Buffer == NULL && Length > 0));
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer));
+  return InternalMemIsZeroBuffer (Buffer, Length);
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/MemLibGeneric.c b/MdePkg/Library/BaseMemoryLibMmio/MemLibGeneric.c
new file mode 100644
index 0000000000000000000000000000000000000000..1c65b674230795e956c9d22f2b9c151c41839706
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/MemLibGeneric.c
@@ -0,0 +1,304 @@
+/** @file
+  Architecture Independent Base Memory Library Implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Fills a target buffer with a 16-bit value, and returns the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to fill.
+  @param  Length  The count of 16-bit value to fill.
+  @param  Value   The value with which to fill Length bytes of Buffer.
+
+  @return Buffer
+
+**/
+VOID *
+EFIAPI
+InternalMemSetMem16 (
+  OUT     VOID                      *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT16                    Value
+  )
+{
+  volatile UINT16  *Destination16;
+
+  Destination16 = (UINT16*)Buffer;
+  while (Length > 0) {
+    MmioWrite16 ((UINTN)--Destination16, Value);
+    Length -= 2;
+  }
+
+  return Buffer;
+}
+
+/**
+  Fills a target buffer with a 32-bit value, and returns the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to fill.
+  @param  Length  The count of 32-bit value to fill.
+  @param  Value   The value with which to fill Length bytes of Buffer.
+
+  @return Buffer
+
+**/
+VOID *
+EFIAPI
+InternalMemSetMem32 (
+  OUT     VOID                      *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT32                    Value
+  )
+{
+  volatile UINT32  *Destination32;
+
+  Destination32 = (UINT32*)Buffer;
+  while (Length > 0) {
+    MmioWrite32 ((UINTN)--Destination32, Value);
+    Length -= 4;
+  }
+  return Buffer;
+}
+
+/**
+  Fills a target buffer with a 64-bit value, and returns the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to fill.
+  @param  Length  The count of 64-bit value to fill.
+  @param  Value   The value with which to fill Length bytes of Buffer.
+
+  @return Buffer
+
+**/
+VOID *
+EFIAPI
+InternalMemSetMem64 (
+  OUT     VOID                      *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT64                    Value
+  )
+{
+  volatile UINT64  *Destination64;
+
+  Destination64 = (UINT64*)Buffer;
+  while (Length > 0) {
+    MmioWrite64 ((UINTN)--Destination64, Value);
+    Length -= 8;
+  }
+  return Buffer;
+}
+
+/**
+  Set Buffer to 0 for Size bytes.
+
+  @param  Buffer Memory to set.
+  @param  Length The number of bytes to set.
+
+  @return Buffer
+
+**/
+VOID *
+EFIAPI
+InternalMemZeroMem (
+  OUT     VOID                      *Buffer,
+  IN      UINTN                     Length
+  )
+{
+  return InternalMemSetMem (Buffer, Length, 0);
+}
+
+/**
+  Compares two memory buffers of a given length.
+
+  @param  DestinationBuffer The first memory buffer.
+  @param  SourceBuffer      The second memory buffer.
+  @param  Length            Length of DestinationBuffer and SourceBuffer memory
+                            regions to compare. Must be non-zero.
+
+  @return 0                 All Length bytes of the two buffers are identical.
+  @retval Non-zero          The first mismatched byte in SourceBuffer subtracted from the first
+                            mismatched byte in DestinationBuffer.
+
+**/
+INTN
+EFIAPI
+InternalMemCompareMem (
+  IN      CONST VOID                *DestinationBuffer,
+  IN      CONST VOID                *SourceBuffer,
+  IN      UINTN                     Length
+  )
+{
+  while ((--Length != 0) &&
+         (MmioRead8 ((UINTN)DestinationBuffer) ==
+          MmioRead8 ((UINTN)SourceBuffer))) {
+    DestinationBuffer = (INT8*)DestinationBuffer + 1;
+    SourceBuffer = (INT8*)SourceBuffer + 1;
+  }
+  return (INTN)MmioRead8 ((UINTN)DestinationBuffer) -
+         (INTN)MmioRead8 ((UINTN)SourceBuffer);
+}
+
+/**
+  Scans a target buffer for an 8-bit value, and returns a pointer to the
+  matching 8-bit value in the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to scan.
+  @param  Length  The count of 8-bit value to scan. Must be non-zero.
+  @param  Value   The value to search for in the target buffer.
+
+  @return The pointer to the first occurrence, or NULL if not found.
+
+**/
+CONST VOID *
+EFIAPI
+InternalMemScanMem8 (
+  IN      CONST VOID                *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT8                     Value
+  )
+{
+  CONST UINT8                       *Pointer;
+
+  Pointer = (CONST UINT8*)Buffer;
+  do {
+    if (MmioRead8 ((UINTN)Pointer) == Value) {
+      return Pointer;
+    }
+    ++Pointer;
+  } while (--Length != 0);
+  return NULL;
+}
+
+/**
+  Scans a target buffer for a 16-bit value, and returns a pointer to the
+  matching 16-bit value in the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to scan.
+  @param  Length  The count of 16-bit value to scan. Must be non-zero.
+  @param  Value   The value to search for in the target buffer.
+
+  @return The pointer to the first occurrence, or NULL if not found.
+
+**/
+CONST VOID *
+EFIAPI
+InternalMemScanMem16 (
+  IN      CONST VOID                *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT16                    Value
+  )
+{
+  CONST UINT16                      *Pointer;
+
+  Pointer = (CONST UINT16*)Buffer;
+  do {
+    if (MmioRead16 ((UINTN)Pointer) == Value) {
+      return Pointer;
+    }
+    ++Pointer;
+  } while (--Length != 0);
+  return NULL;
+}
+
+/**
+  Scans a target buffer for a 32-bit value, and returns a pointer to the
+  matching 32-bit value in the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to scan.
+  @param  Length  The count of 32-bit value to scan. Must be non-zero.
+  @param  Value   The value to search for in the target buffer.
+
+  @return The pointer to the first occurrence, or NULL if not found.
+
+**/
+CONST VOID *
+EFIAPI
+InternalMemScanMem32 (
+  IN      CONST VOID                *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT32                    Value
+  )
+{
+  CONST UINT32                      *Pointer;
+
+  Pointer = (CONST UINT32*)Buffer;
+  do {
+    if (MmioRead32 ((UINTN)Pointer) == Value) {
+      return Pointer;
+    }
+    ++Pointer;
+  } while (--Length != 0);
+  return NULL;
+}
+
+/**
+  Scans a target buffer for a 64-bit value, and returns a pointer to the
+  matching 64-bit value in the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to scan.
+  @param  Length  The count of 64-bit value to scan. Must be non-zero.
+  @param  Value   The value to search for in the target buffer.
+
+  @return The pointer to the first occurrence, or NULL if not found.
+
+**/
+CONST VOID *
+EFIAPI
+InternalMemScanMem64 (
+  IN      CONST VOID                *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT64                    Value
+  )
+{
+  CONST UINT64                      *Pointer;
+
+  Pointer = (CONST UINT64*)Buffer;
+  do {
+    if (MmioRead64 ((UINTN)Pointer) == Value) {
+      return Pointer;
+    }
+    ++Pointer;
+  } while (--Length != 0);
+  return NULL;
+}
+
+/**
+  Checks whether the contents of a buffer are all zeros.
+
+  @param  Buffer  The pointer to the buffer to be checked.
+  @param  Length  The size of the buffer (in bytes) to be checked.
+
+  @retval TRUE    Contents of the buffer are all zeros.
+  @retval FALSE   Contents of the buffer are not all zeros.
+
+**/
+BOOLEAN
+EFIAPI
+InternalMemIsZeroBuffer (
+  IN CONST VOID  *Buffer,
+  IN UINTN       Length
+  )
+{
+  CONST UINT8 *BufferData;
+  UINTN       Index;
+
+  BufferData = Buffer;
+  for (Index = 0; Index < Length; Index++) {
+    if (MmioRead8 ((UINTN)(BufferData + Index)) != 0) {
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/MemLibGuid.c b/MdePkg/Library/BaseMemoryLibMmio/MemLibGuid.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce69e431309f4447a4e99251a86b5182123e5b97
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/MemLibGuid.c
@@ -0,0 +1,143 @@
+/** @file
+  Implementation of GUID functions.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Copies a source GUID to a destination GUID.
+
+  This function copies the contents of the 128-bit GUID specified by SourceGuid
+  to DestinationGuid, and returns DestinationGuid.
+
+  If DestinationGuid is NULL, then ASSERT().
+  If SourceGuid is NULL, then ASSERT().
+
+  @param  DestinationGuid   A pointer to the destination GUID.
+  @param  SourceGuid        A pointer to the source GUID.
+
+  @return DestinationGuid.
+
+**/
+GUID *
+EFIAPI
+CopyGuid (
+  OUT GUID       *DestinationGuid,
+  IN CONST GUID  *SourceGuid
+  )
+{
+  return InternalMemCopyMem (DestinationGuid, SourceGuid, sizeof (GUID));
+}
+
+/**
+  Compares two GUIDs.
+
+  This function compares Guid1 to Guid2.  If the GUIDs are identical then TRUE is returned.
+  If there are any bit differences in the two GUIDs, then FALSE is returned.
+
+  If Guid1 is NULL, then ASSERT().
+  If Guid2 is NULL, then ASSERT().
+
+  @param  Guid1       A pointer to a 128 bit GUID.
+  @param  Guid2       A pointer to a 128 bit GUID.
+
+  @retval TRUE        Guid1 and Guid2 are identical.
+  @retval FALSE       Guid1 and Guid2 are not identical.
+
+**/
+BOOLEAN
+EFIAPI
+CompareGuid (
+  IN CONST GUID  *Guid1,
+  IN CONST GUID  *Guid2
+  )
+{
+  return (0 == InternalMemCompareMem (Guid1, Guid2, sizeof (GUID)));
+}
+
+/**
+  Scans a target buffer for a GUID, and returns a pointer to the matching GUID
+  in the target buffer.
+
+  This function searches the target buffer specified by Buffer and Length from
+  the lowest address to the highest address at 128-bit increments for the 128-bit
+  GUID value that matches Guid.  If a match is found, then a pointer to the matching
+  GUID in the target buffer is returned.  If no match is found, then NULL is returned.
+  If Length is 0, then NULL is returned.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Buffer is not aligned on a 32-bit boundary, then ASSERT().
+  If Length is not aligned on a 128-bit boundary, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  Buffer  The pointer to the target buffer to scan.
+  @param  Length  The number of bytes in Buffer to scan.
+  @param  Guid    The value to search for in the target buffer.
+
+  @return A pointer to the matching Guid in the target buffer or NULL otherwise.
+
+**/
+VOID *
+EFIAPI
+ScanGuid (
+  IN CONST VOID  *Buffer,
+  IN UINTN       Length,
+  IN CONST GUID  *Guid
+  )
+{
+  CONST GUID                        *GuidPtr;
+
+  ASSERT (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0);
+  ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1));
+  ASSERT ((Length & (sizeof (*GuidPtr) - 1)) == 0);
+
+  GuidPtr = (GUID*)Buffer;
+  Buffer  = GuidPtr + Length / sizeof (*GuidPtr);
+  while (GuidPtr < (CONST GUID*)Buffer) {
+    if (CompareGuid (GuidPtr, Guid)) {
+      return (VOID*)GuidPtr;
+    }
+    GuidPtr++;
+  }
+  return NULL;
+}
+
+/**
+  Checks if the given GUID is a zero GUID.
+
+  This function checks whether the given GUID is a zero GUID. If the GUID is
+  identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned.
+
+  If Guid is NULL, then ASSERT().
+
+  @param  Guid        The pointer to a 128 bit GUID.
+
+  @retval TRUE        Guid is a zero GUID.
+  @retval FALSE       Guid is not a zero GUID.
+
+**/
+BOOLEAN
+EFIAPI
+IsZeroGuid (
+  IN CONST GUID  *Guid
+  )
+{
+  return InternalMemIsZeroBuffer (Guid, sizeof (GUID));
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/MemLibInternals.h b/MdePkg/Library/BaseMemoryLibMmio/MemLibInternals.h
new file mode 100644
index 0000000000000000000000000000000000000000..dc28a9078a8a707af8a83517d3756c6126093079
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/MemLibInternals.h
@@ -0,0 +1,248 @@
+/** @file
+  Declaration of internal functions for Base Memory Library.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __MEM_LIB_INTERNALS__
+#define __MEM_LIB_INTERNALS__
+
+#include <Base.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+
+/**
+  Copy Length bytes from Source to Destination.
+
+  @param  DestinationBuffer Target of copy
+  @param  SourceBuffer      Place to copy from
+  @param  Length            The number of bytes to copy
+
+  @return Destination
+
+**/
+VOID *
+EFIAPI
+InternalMemCopyMem (
+  OUT     VOID                      *DestinationBuffer,
+  IN      CONST VOID                *SourceBuffer,
+  IN      UINTN                     Length
+  );
+
+/**
+  Set Buffer to Value for Size bytes.
+
+  @param  Buffer   The memory to set.
+  @param  Length   The number of bytes to set
+  @param  Value    The value of the set operation.
+
+  @return Buffer
+
+**/
+VOID *
+EFIAPI
+InternalMemSetMem (
+  OUT     VOID                      *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT8                     Value
+  );
+
+/**
+  Fills a target buffer with a 16-bit value, and returns the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to fill.
+  @param  Length  The count of 16-bit value to fill.
+  @param  Value   The value with which to fill Length bytes of Buffer.
+
+  @return Buffer
+
+**/
+VOID *
+EFIAPI
+InternalMemSetMem16 (
+  OUT     VOID                      *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT16                    Value
+  );
+
+/**
+  Fills a target buffer with a 32-bit value, and returns the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to fill.
+  @param  Length  The count of 32-bit value to fill.
+  @param  Value   The value with which to fill Length bytes of Buffer.
+
+  @return Buffer
+
+**/
+VOID *
+EFIAPI
+InternalMemSetMem32 (
+  OUT     VOID                      *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT32                    Value
+  );
+
+/**
+  Fills a target buffer with a 64-bit value, and returns the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to fill.
+  @param  Length  The count of 64-bit value to fill.
+  @param  Value   The value with which to fill Length bytes of Buffer.
+
+  @return Buffer
+
+**/
+VOID *
+EFIAPI
+InternalMemSetMem64 (
+  OUT     VOID                      *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT64                    Value
+  );
+
+/**
+  Set Buffer to 0 for Size bytes.
+
+  @param  Buffer The memory to set.
+  @param  Length The number of bytes to set.
+
+  @return Buffer
+
+**/
+VOID *
+EFIAPI
+InternalMemZeroMem (
+  OUT     VOID                      *Buffer,
+  IN      UINTN                     Length
+  );
+
+/**
+  Compares two memory buffers of a given length.
+
+  @param  DestinationBuffer The first memory buffer.
+  @param  SourceBuffer      The second memory buffer.
+  @param  Length            The length of DestinationBuffer and SourceBuffer memory
+                            regions to compare. Must be non-zero.
+
+  @return 0                 All Length bytes of the two buffers are identical.
+  @retval Non-zero          The first mismatched byte in SourceBuffer subtracted from the first
+                            mismatched byte in DestinationBuffer.
+
+**/
+INTN
+EFIAPI
+InternalMemCompareMem (
+  IN      CONST VOID                *DestinationBuffer,
+  IN      CONST VOID                *SourceBuffer,
+  IN      UINTN                     Length
+  );
+
+/**
+  Scans a target buffer for an 8-bit value, and returns a pointer to the
+  matching 8-bit value in the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to scan.
+  @param  Length  The count of 8-bit value to scan. Must be non-zero.
+  @param  Value   The value to search for in the target buffer.
+
+  @return The pointer to the first occurrence, or NULL if not found.
+
+**/
+CONST VOID *
+EFIAPI
+InternalMemScanMem8 (
+  IN      CONST VOID                *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT8                     Value
+  );
+
+/**
+  Scans a target buffer for a 16-bit value, and returns a pointer to the
+  matching 16-bit value in the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to scan.
+  @param  Length  The count of 16-bit value to scan. Must be non-zero.
+  @param  Value   The value to search for in the target buffer.
+
+  @return The pointer to the first occurrence, or NULL if not found.
+
+**/
+CONST VOID *
+EFIAPI
+InternalMemScanMem16 (
+  IN      CONST VOID                *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT16                    Value
+  );
+
+/**
+  Scans a target buffer for a 32-bit value, and returns a pointer to the
+  matching 32-bit value in the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to scan.
+  @param  Length  The count of 32-bit value to scan. Must be non-zero.
+  @param  Value   The value to search for in the target buffer.
+
+  @return The pointer to the first occurrence, or NULL if not found.
+
+**/
+CONST VOID *
+EFIAPI
+InternalMemScanMem32 (
+  IN      CONST VOID                *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT32                    Value
+  );
+
+/**
+  Scans a target buffer for a 64-bit value, and returns a pointer to the
+  matching 64-bit value in the target buffer.
+
+  @param  Buffer  The pointer to the target buffer to scan.
+  @param  Length  The count of 64-bit value to scan. Must be non-zero.
+  @param  Value   The calue to search for in the target buffer.
+
+  @return The pointer to the first occurrence, or NULL if not found.
+
+**/
+CONST VOID *
+EFIAPI
+InternalMemScanMem64 (
+  IN      CONST VOID                *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT64                    Value
+  );
+
+/**
+  Checks whether the contents of a buffer are all zeros.
+
+  @param  Buffer  The pointer to the buffer to be checked.
+  @param  Length  The size of the buffer (in bytes) to be checked.
+
+  @retval TRUE    Contents of the buffer are all zeros.
+  @retval FALSE   Contents of the buffer are not all zeros.
+
+**/
+BOOLEAN
+EFIAPI
+InternalMemIsZeroBuffer (
+  IN CONST VOID  *Buffer,
+  IN UINTN       Length
+  );
+
+#endif
diff --git a/MdePkg/Library/BaseMemoryLibMmio/ScanMem16Wrapper.c b/MdePkg/Library/BaseMemoryLibMmio/ScanMem16Wrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..ad9330b9938df9995a597dbabc1aa2744aa0d8c1
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/ScanMem16Wrapper.c
@@ -0,0 +1,63 @@
+/** @file
+  ScanMem16() implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Scans a target buffer for a 16-bit value, and returns a pointer to the matching 16-bit value
+  in the target buffer.
+
+  This function searches the target buffer specified by Buffer and Length from the lowest
+  address to the highest address for a 16-bit value that matches Value.  If a match is found,
+  then a pointer to the matching byte in the target buffer is returned.  If no match is found,
+  then NULL is returned.  If Length is 0, then NULL is returned.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Buffer is not aligned on a 16-bit boundary, then ASSERT().
+  If Length is not aligned on a 16-bit boundary, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  Buffer      The pointer to the target buffer to scan.
+  @param  Length      The number of bytes in Buffer to scan.
+  @param  Value       The value to search for in the target buffer.
+
+  @return A pointer to the matching byte in the target buffer or NULL otherwise.
+
+**/
+VOID *
+EFIAPI
+ScanMem16 (
+  IN CONST VOID  *Buffer,
+  IN UINTN       Length,
+  IN UINT16      Value
+  )
+{
+  if (Length == 0) {
+    return NULL;
+  }
+
+  ASSERT (Buffer != NULL);
+  ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0);
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer));
+  ASSERT ((Length & (sizeof (Value) - 1)) == 0);
+
+  return (VOID*)InternalMemScanMem16 (Buffer, Length / sizeof (Value), Value);
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/ScanMem32Wrapper.c b/MdePkg/Library/BaseMemoryLibMmio/ScanMem32Wrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..84675697d12016f92c46c08c65aca647288a8b99
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/ScanMem32Wrapper.c
@@ -0,0 +1,62 @@
+/** @file
+  ScanMem32() implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Scans a target buffer for a 32-bit value, and returns a pointer to the matching 32-bit value
+  in the target buffer.
+
+  This function searches the target buffer specified by Buffer and Length from the lowest
+  address to the highest address for a 32-bit value that matches Value.  If a match is found,
+  then a pointer to the matching byte in the target buffer is returned.  If no match is found,
+  then NULL is returned.  If Length is 0, then NULL is returned.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Buffer is not aligned on a 32-bit boundary, then ASSERT().
+  If Length is not aligned on a 32-bit boundary, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  Buffer      The pointer to the target buffer to scan.
+  @param  Length      The number of bytes in Buffer to scan.
+  @param  Value       The value to search for in the target buffer.
+
+  @return A pointer to the matching byte in the target buffer or NULL otherwise.
+
+**/
+VOID *
+EFIAPI
+ScanMem32 (
+  IN CONST VOID  *Buffer,
+  IN UINTN       Length,
+  IN UINT32      Value
+  )
+{
+  if (Length == 0) {
+    return NULL;
+  }
+
+  ASSERT (Buffer != NULL);
+  ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0);
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer));
+  ASSERT ((Length & (sizeof (Value) - 1)) == 0);
+
+  return (VOID*)InternalMemScanMem32 (Buffer, Length / sizeof (Value), Value);
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/ScanMem64Wrapper.c b/MdePkg/Library/BaseMemoryLibMmio/ScanMem64Wrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..df749dce457827fe070bad8b7c6071aae29ebb02
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/ScanMem64Wrapper.c
@@ -0,0 +1,63 @@
+/** @file
+  ScanMem64() implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Scans a target buffer for a 64-bit value, and returns a pointer to the matching 64-bit value
+  in the target buffer.
+
+  This function searches the target buffer specified by Buffer and Length from the lowest
+  address to the highest address for a 64-bit value that matches Value.  If a match is found,
+  then a pointer to the matching byte in the target buffer is returned.  If no match is found,
+  then NULL is returned.  If Length is 0, then NULL is returned.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Buffer is not aligned on a 64-bit boundary, then ASSERT().
+  If Length is not aligned on a 64-bit boundary, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  Buffer      The pointer to the target buffer to scan.
+  @param  Length      The number of bytes in Buffer to scan.
+  @param  Value       The value to search for in the target buffer.
+
+  @return A pointer to the matching byte in the target buffer or NULL otherwise.
+
+**/
+VOID *
+EFIAPI
+ScanMem64 (
+  IN CONST VOID  *Buffer,
+  IN UINTN       Length,
+  IN UINT64      Value
+  )
+{
+  if (Length == 0) {
+    return NULL;
+  }
+
+  ASSERT (Buffer != NULL);
+  ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0);
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer));
+  ASSERT ((Length & (sizeof (Value) - 1)) == 0);
+
+  return (VOID*)InternalMemScanMem64 (Buffer, Length / sizeof (Value), Value);
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/ScanMem8Wrapper.c b/MdePkg/Library/BaseMemoryLibMmio/ScanMem8Wrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..170981017dbe31cf5e0c3dabf26a4fea33f7a7d7
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/ScanMem8Wrapper.c
@@ -0,0 +1,95 @@
+/** @file
+  ScanMem8() and ScanMemN() implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Scans a target buffer for an 8-bit value, and returns a pointer to the matching 8-bit value
+  in the target buffer.
+
+  This function searches the target buffer specified by Buffer and Length from the lowest
+  address to the highest address for an 8-bit value that matches Value.  If a match is found,
+  then a pointer to the matching byte in the target buffer is returned.  If no match is found,
+  then NULL is returned.  If Length is 0, then NULL is returned.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  Buffer      The pointer to the target buffer to scan.
+  @param  Length      The number of bytes in Buffer to scan.
+  @param  Value       The value to search for in the target buffer.
+
+  @return A pointer to the matching byte in the target buffer, or NULL otherwise.
+
+**/
+VOID *
+EFIAPI
+ScanMem8 (
+  IN CONST VOID  *Buffer,
+  IN UINTN       Length,
+  IN UINT8       Value
+  )
+{
+  if (Length == 0) {
+    return NULL;
+  }
+  ASSERT (Buffer != NULL);
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer));
+
+  return (VOID*)InternalMemScanMem8 (Buffer, Length, Value);
+}
+
+/**
+  Scans a target buffer for a UINTN sized value, and returns a pointer to the matching
+  UINTN sized value in the target buffer.
+
+  This function searches the target buffer specified by Buffer and Length from the lowest
+  address to the highest address for a UINTN sized value that matches Value.  If a match is found,
+  then a pointer to the matching byte in the target buffer is returned.  If no match is found,
+  then NULL is returned.  If Length is 0, then NULL is returned.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Buffer is not aligned on a UINTN boundary, then ASSERT().
+  If Length is not aligned on a UINTN boundary, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  Buffer      The pointer to the target buffer to scan.
+  @param  Length      The number of bytes in Buffer to scan.
+  @param  Value       The value to search for in the target buffer.
+
+  @return A pointer to the matching byte in the target buffer, or NULL otherwise.
+
+**/
+VOID *
+EFIAPI
+ScanMemN (
+  IN CONST VOID  *Buffer,
+  IN UINTN       Length,
+  IN UINTN       Value
+  )
+{
+  if (sizeof (UINTN) == sizeof (UINT64)) {
+    return ScanMem64 (Buffer, Length, (UINT64)Value);
+  } else {
+    return ScanMem32 (Buffer, Length, (UINT32)Value);
+  }
+}
+
diff --git a/MdePkg/Library/BaseMemoryLibMmio/SetMem.c b/MdePkg/Library/BaseMemoryLibMmio/SetMem.c
new file mode 100644
index 0000000000000000000000000000000000000000..40255670c6f26eb72a82568f035720fc6fe75546
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/SetMem.c
@@ -0,0 +1,83 @@
+/** @file
+  Implementation of the EfiSetMem routine. This function is broken
+  out into its own source file so that it can be excluded from a
+  build for a particular platform easily if an optimized version
+  is desired.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+
+    BaseMemoryLib
+    BaseMemoryLibMmio
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2012 - 2020, ARM Ltd. All rights reserved.<BR>
+  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Set Buffer to Value for Size bytes.
+
+  @param  Buffer   The memory to set.
+  @param  Length   The number of bytes to set.
+  @param  Value    The value of the set operation.
+
+  @return Buffer
+
+**/
+VOID *
+EFIAPI
+InternalMemSetMem (
+  OUT     VOID                      *Buffer,
+  IN      UINTN                     Length,
+  IN      UINT8                     Value
+  )
+{
+  //
+  // Declare the local variables that actually move the data elements as
+  // volatile to prevent the optimizer from replacing this function with
+  // the intrinsic memset()
+  //
+  volatile UINT8                    *Pointer8;
+  volatile UINT32                   *Pointer32;
+  volatile UINT64                   *Pointer64;
+  UINT32                            Value32;
+  UINT64                            Value64;
+
+  if ((((UINTN)Buffer & 0x7) == 0) && (Length >= 8)) {
+    // Generate the 64bit value
+    Value32 = (Value << 24) | (Value << 16) | (Value << 8) | Value;
+    Value64 = LShiftU64 (Value32, 32) | Value32;
+
+    Pointer64 = (UINT64*)Buffer;
+    while (Length >= 8) {
+      MmioWrite64 ((UINTN)Pointer64++, Value64);
+      Length -= 8;
+    }
+
+    // Finish with bytes if needed
+    Pointer8 = (UINT8*)Pointer64;
+  } else if ((((UINTN)Buffer & 0x3) == 0) && (Length >= 4)) {
+    // Generate the 32bit value
+    Value32 = (Value << 24) | (Value << 16) | (Value << 8) | Value;
+
+    Pointer32 = (UINT32*)Buffer;
+    while (Length >= 4) {
+      MmioWrite32 ((UINTN)Pointer32++, Value32);
+      Length -= 4;
+    }
+
+    // Finish with bytes if needed
+    Pointer8 = (UINT8*)Pointer32;
+  } else {
+    Pointer8 = (UINT8*)Buffer;
+  }
+  while (Length-- > 0) {
+    MmioWrite8 ((UINTN)Pointer8++, Value);
+  }
+  return Buffer;
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/SetMem16Wrapper.c b/MdePkg/Library/BaseMemoryLibMmio/SetMem16Wrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..be785c5eb696ef6b913bf7bc0081a5f414c6f141
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/SetMem16Wrapper.c
@@ -0,0 +1,60 @@
+/** @file
+  SetMem16() implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Fills a target buffer with a 16-bit value, and returns the target buffer.
+
+  This function fills Length bytes of Buffer with the 16-bit value specified by
+  Value, and returns Buffer. Value is repeated every 16-bits in for Length
+  bytes of Buffer.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+  If Buffer is not aligned on a 16-bit boundary, then ASSERT().
+  If Length is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Buffer  The pointer to the target buffer to fill.
+  @param  Length  The number of bytes in Buffer to fill.
+  @param  Value   The value with which to fill Length bytes of Buffer.
+
+  @return Buffer.
+
+**/
+VOID *
+EFIAPI
+SetMem16 (
+  OUT VOID   *Buffer,
+  IN UINTN   Length,
+  IN UINT16  Value
+  )
+{
+  if (Length == 0) {
+    return Buffer;
+  }
+
+  ASSERT (Buffer != NULL);
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer));
+  ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0);
+  ASSERT ((Length & (sizeof (Value) - 1)) == 0);
+
+  return InternalMemSetMem16 (Buffer, Length / sizeof (Value), Value);
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/SetMem32Wrapper.c b/MdePkg/Library/BaseMemoryLibMmio/SetMem32Wrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..622c6eddccc88e846921782efc29e40f816ae499
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/SetMem32Wrapper.c
@@ -0,0 +1,60 @@
+/** @file
+  SetMem32() implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Fills a target buffer with a 32-bit value, and returns the target buffer.
+
+  This function fills Length bytes of Buffer with the 32-bit value specified by
+  Value, and returns Buffer. Value is repeated every 32-bits in for Length
+  bytes of Buffer.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+  If Buffer is not aligned on a 32-bit boundary, then ASSERT().
+  If Length is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Buffer  The pointer to the target buffer to fill.
+  @param  Length  The number of bytes in Buffer to fill.
+  @param  Value   The value with which to fill Length bytes of Buffer.
+
+  @return Buffer.
+
+**/
+VOID *
+EFIAPI
+SetMem32 (
+  OUT VOID   *Buffer,
+  IN UINTN   Length,
+  IN UINT32  Value
+  )
+{
+  if (Length == 0) {
+    return Buffer;
+  }
+
+  ASSERT (Buffer != NULL);
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer));
+  ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0);
+  ASSERT ((Length & (sizeof (Value) - 1)) == 0);
+
+  return InternalMemSetMem32 (Buffer, Length / sizeof (Value), Value);
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/SetMem64Wrapper.c b/MdePkg/Library/BaseMemoryLibMmio/SetMem64Wrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..7653eed85cd633be5aea439cf4ab62958dd62c47
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/SetMem64Wrapper.c
@@ -0,0 +1,60 @@
+/** @file
+  SetMem64() implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Fills a target buffer with a 64-bit value, and returns the target buffer.
+
+  This function fills Length bytes of Buffer with the 64-bit value specified by
+  Value, and returns Buffer. Value is repeated every 64-bits in for Length
+  bytes of Buffer.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+  If Buffer is not aligned on a 64-bit boundary, then ASSERT().
+  If Length is not aligned on a 64-bit boundary, then ASSERT().
+
+  @param  Buffer  The pointer to the target buffer to fill.
+  @param  Length  The number of bytes in Buffer to fill.
+  @param  Value   The value with which to fill Length bytes of Buffer.
+
+  @return Buffer.
+
+**/
+VOID *
+EFIAPI
+SetMem64 (
+  OUT VOID   *Buffer,
+  IN UINTN   Length,
+  IN UINT64  Value
+  )
+{
+  if (Length == 0) {
+    return Buffer;
+  }
+
+  ASSERT (Buffer != NULL);
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer));
+  ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0);
+  ASSERT ((Length & (sizeof (Value) - 1)) == 0);
+
+  return InternalMemSetMem64 (Buffer, Length / sizeof (Value), Value);
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/SetMemWrapper.c b/MdePkg/Library/BaseMemoryLibMmio/SetMemWrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..96dd956686d15b4b4cb25157d764849043d1b57b
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/SetMemWrapper.c
@@ -0,0 +1,87 @@
+/** @file
+  SetMem() and SetMemN() implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Fills a target buffer with a byte value, and returns the target buffer.
+
+  This function fills Length bytes of Buffer with Value, and returns Buffer.
+
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  Buffer    The memory to set.
+  @param  Length    The number of bytes to set.
+  @param  Value     The value with which to fill Length bytes of Buffer.
+
+  @return Buffer.
+
+**/
+VOID *
+EFIAPI
+SetMem (
+  OUT VOID  *Buffer,
+  IN UINTN  Length,
+  IN UINT8  Value
+  )
+{
+  if (Length == 0) {
+    return Buffer;
+  }
+
+  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer));
+
+  return InternalMemSetMem (Buffer, Length, Value);
+}
+
+/**
+  Fills a target buffer with a value that is size UINTN, and returns the target buffer.
+
+  This function fills Length bytes of Buffer with the UINTN sized value specified by
+  Value, and returns Buffer. Value is repeated every sizeof(UINTN) bytes for Length
+  bytes of Buffer.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+  If Buffer is not aligned on a UINTN boundary, then ASSERT().
+  If Length is not aligned on a UINTN boundary, then ASSERT().
+
+  @param  Buffer  The pointer to the target buffer to fill.
+  @param  Length  The number of bytes in Buffer to fill.
+  @param  Value   The value with which to fill Length bytes of Buffer.
+
+  @return Buffer.
+
+**/
+VOID *
+EFIAPI
+SetMemN (
+  OUT VOID  *Buffer,
+  IN UINTN  Length,
+  IN UINTN  Value
+  )
+{
+  if (sizeof (UINTN) == sizeof (UINT64)) {
+    return SetMem64 (Buffer, Length, (UINT64)Value);
+  } else {
+    return SetMem32 (Buffer, Length, (UINT32)Value);
+  }
+}
diff --git a/MdePkg/Library/BaseMemoryLibMmio/ZeroMemWrapper.c b/MdePkg/Library/BaseMemoryLibMmio/ZeroMemWrapper.c
new file mode 100644
index 0000000000000000000000000000000000000000..55246d121c6820d371af463792614c1d73676e6f
--- /dev/null
+++ b/MdePkg/Library/BaseMemoryLibMmio/ZeroMemWrapper.c
@@ -0,0 +1,52 @@
+/** @file
+  ZeroMem() implementation.
+
+  The following BaseMemoryLib instances contain the same copy of this file:
+
+    BaseMemoryLib
+    BaseMemoryLibMmio
+    BaseMemoryLibMmx
+    BaseMemoryLibSse2
+    BaseMemoryLibRepStr
+    BaseMemoryLibOptDxe
+    BaseMemoryLibOptPei
+    PeiMemoryLib
+    UefiMemoryLib
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemLibInternals.h"
+
+/**
+  Fills a target buffer with zeros, and returns the target buffer.
+
+  This function fills Length bytes of Buffer with zeros, and returns Buffer.
+
+  If Length > 0 and Buffer is NULL, then ASSERT().
+  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  Buffer      The pointer to the target buffer to fill with zeros.
+  @param  Length      The number of bytes in Buffer to fill with zeros.
+
+  @return Buffer.
+
+**/
+VOID *
+EFIAPI
+ZeroMem (
+  OUT VOID  *Buffer,
+  IN UINTN  Length
+  )
+{
+  if (Length == 0) {
+    return Buffer;
+  }
+
+  ASSERT (Buffer != NULL);
+  ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1));
+  return InternalMemZeroMem (Buffer, Length);
+}
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#59506): https://edk2.groups.io/g/devel/message/59506
Mute This Topic: https://groups.io/mt/74200903/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list