From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.8887.1589448142975873207 for ; Thu, 14 May 2020 02:22:23 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: ard.biesheuvel@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8AEF931B; Thu, 14 May 2020 02:22:21 -0700 (PDT) Received: from [192.168.1.81] (unknown [10.37.8.255]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2BF0F3F71E; Thu, 14 May 2020 02:22:18 -0700 (PDT) Subject: Re: [PATCH v1 03/11] MdePkg: Base Memory Lib instance using MMIO To: Sami Mujawar , devel@edk2.groups.io Cc: leif@nuviainc.com, michael.d.kinney@intel.com, liming.gao@intel.com, Alexandru.Elisei@arm.com, Andre.Przywara@arm.com, Matteo.Carlini@arm.com, Laura.Moretta@arm.com, nd@arm.com References: <20200514084019.71368-1-sami.mujawar@arm.com> <20200514084019.71368-4-sami.mujawar@arm.com> From: "Ard Biesheuvel" Message-ID: <97b8028a-018f-0f91-90ab-a336b0c2ba24@arm.com> Date: Thu, 14 May 2020 11:22:15 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0 MIME-Version: 1.0 In-Reply-To: <20200514084019.71368-4-sami.mujawar@arm.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit Hi Sami, On 5/14/20 10:40 AM, Sami Mujawar wrote: > 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. > We are conflating two different things here: - the use of unaligned accesses to read from device memory - the use of load/store instructions that have multiple output registers, making it very difficult to emulate them in a virtual machine context. I though that for the kvmtool port, we addressed the second issue by using a read-only memslot for the NOR flash when it is in array mode? IIRC, the issue only affects reads, as all writes to NOR flash device memory are already done using the proper MMIO accessors. If those MMIO accessors compile to something that does not work under emulation, you should be use the special IoLib implementation that exists for this use case: MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf So that leaves the issue of unaligned accesses to device memory. This should not happen unless you are using BaseMemoryLibOptDxe for AARCH64, which deliberately uses overlapping loads and stores for performance. Any BASE library is built with -mstrict-align, and so any other C code implementation of BaseMemoryLib should work fine for reading for a read-only memslot mapped using device attributes. So in summary, I don't think we need this library. > 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 > --- > 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.
> +# > +# 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.
> +// > +// 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2012 - 2020, ARM Ltd. All rights reserved.
> + Copyright (c) 2016, Linaro Ltd. All rights reserved.
> + > + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef __MEM_LIB_INTERNALS__ > +#define __MEM_LIB_INTERNALS__ > + > +#include > +#include > +#include > +#include > +#include > + > +/** > + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2012 - 2020, ARM Ltd. All rights reserved.
> + Copyright (c) 2016, Linaro Ltd. All rights reserved.
> + > + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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.
> + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + 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); > +} >