diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
commit | f215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch) | |
tree | 6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib | |
parent | Initial commit. (diff) | |
download | virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip |
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib')
4 files changed, 595 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c new file mode 100644 index 00000000..8f92a997 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c @@ -0,0 +1,70 @@ +/** @file + Internal ARCH Specific file of MM memory check library. + + MM memory check library implementation. This library consumes MM_ACCESS_PROTOCOL + to get MMRAM information. In order to use this library instance, the platform should produce + all MMRAM range via MM_ACCESS_PROTOCOL, including the range for firmware (like MM Core + and MM driver) and/or specific dedicated hardware. + + Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +// +// Maximum support address used to check input buffer +// +extern EFI_PHYSICAL_ADDRESS mMmMemLibInternalMaximumSupportAddress; + +/** + Calculate and save the maximum support address. + +**/ +VOID +MmMemLibInternalCalculateMaximumSupportAddress ( + VOID + ) +{ + UINT8 PhysicalAddressBits; + + PhysicalAddressBits = 36; + + // + // Save the maximum support address in one global variable + // + mMmMemLibInternalMaximumSupportAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, PhysicalAddressBits) - 1); + DEBUG ((DEBUG_INFO, "mMmMemLibInternalMaximumSupportAddress = 0x%lx\n", mMmMemLibInternalMaximumSupportAddress)); +} + +/** + Initialize cached Mmram Ranges from HOB. + + @retval EFI_UNSUPPORTED The routine is unable to extract MMRAM information. + @retval EFI_SUCCESS MmRanges are populated successfully. + +**/ +EFI_STATUS +MmMemLibInternalPopulateMmramRanges ( + VOID + ) +{ + // Not implemented for AARCH64. + return EFI_SUCCESS; +} + +/** + Deinitialize cached Mmram Ranges. + +**/ +VOID +MmMemLibInternalFreeMmramRanges ( + VOID + ) +{ + // Not implemented for AARCH64. +} + diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c new file mode 100644 index 00000000..38117ea6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c @@ -0,0 +1,315 @@ +/** @file + Instance of MM memory check library. + + MM memory check library library implementation. This library consumes MM_ACCESS_PROTOCOL + to get MMRAM information. In order to use this library instance, the platform should produce + all MMRAM range via MM_ACCESS_PROTOCOL, including the range for firmware (like MM Core + and MM driver) and/or specific dedicated hardware. + + Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include <PiMm.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> + +EFI_MMRAM_DESCRIPTOR *mMmMemLibInternalMmramRanges; +UINTN mMmMemLibInternalMmramCount; + +// +// Maximum support address used to check input buffer +// +EFI_PHYSICAL_ADDRESS mMmMemLibInternalMaximumSupportAddress = 0; + +/** + Calculate and save the maximum support address. + +**/ +VOID +MmMemLibInternalCalculateMaximumSupportAddress ( + VOID + ); + +/** + Initialize cached Mmram Ranges from HOB. + + @retval EFI_UNSUPPORTED The routine is unable to extract MMRAM information. + @retval EFI_SUCCESS MmRanges are populated successfully. + +**/ +EFI_STATUS +MmMemLibInternalPopulateMmramRanges ( + VOID + ); + +/** + Deinitialize cached Mmram Ranges. + +**/ +VOID +MmMemLibInternalFreeMmramRanges ( + VOID + ); + +/** + This function check if the buffer is valid per processor architecture and not overlap with MMRAM. + + @param Buffer The buffer start address to be checked. + @param Length The buffer length to be checked. + + @retval TRUE This buffer is valid per processor architecture and not overlap with MMRAM. + @retval FALSE This buffer is not valid per processor architecture or overlap with MMRAM. +**/ +BOOLEAN +EFIAPI +MmIsBufferOutsideMmValid ( + IN EFI_PHYSICAL_ADDRESS Buffer, + IN UINT64 Length + ) +{ + UINTN Index; + + // + // Check override. + // NOTE: (B:0->L:4G) is invalid for IA32, but (B:1->L:4G-1)/(B:4G-1->L:1) is valid. + // + if ((Length > mMmMemLibInternalMaximumSupportAddress) || + (Buffer > mMmMemLibInternalMaximumSupportAddress) || + ((Length != 0) && (Buffer > (mMmMemLibInternalMaximumSupportAddress - (Length - 1)))) ) { + // + // Overflow happen + // + DEBUG (( + DEBUG_ERROR, + "MmIsBufferOutsideMmValid: Overflow: Buffer (0x%lx) - Length (0x%lx), MaximumSupportAddress (0x%lx)\n", + Buffer, + Length, + mMmMemLibInternalMaximumSupportAddress + )); + return FALSE; + } + + for (Index = 0; Index < mMmMemLibInternalMmramCount; Index ++) { + if (((Buffer >= mMmMemLibInternalMmramRanges[Index].CpuStart) && + (Buffer < mMmMemLibInternalMmramRanges[Index].CpuStart + mMmMemLibInternalMmramRanges[Index].PhysicalSize)) || + ((mMmMemLibInternalMmramRanges[Index].CpuStart >= Buffer) && + (mMmMemLibInternalMmramRanges[Index].CpuStart < Buffer + Length))) { + DEBUG (( + DEBUG_ERROR, + "MmIsBufferOutsideMmValid: Overlap: Buffer (0x%lx) - Length (0x%lx), ", + Buffer, + Length + )); + DEBUG (( + DEBUG_ERROR, + "CpuStart (0x%lx) - PhysicalSize (0x%lx)\n", + mMmMemLibInternalMmramRanges[Index].CpuStart, + mMmMemLibInternalMmramRanges[Index].PhysicalSize + )); + return FALSE; + } + } + + return TRUE; +} + +/** + Copies a source buffer (non-MMRAM) to a destination buffer (MMRAM). + + This function copies a source buffer (non-MMRAM) to a destination buffer (MMRAM). + It checks if source buffer is valid per processor architecture and not overlap with MMRAM. + If the check passes, it copies memory and returns EFI_SUCCESS. + If the check fails, it return EFI_SECURITY_VIOLATION. + The implementation must be reentrant. + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with MMRAM. + @retval EFI_SUCCESS Memory is copied. + +**/ +EFI_STATUS +EFIAPI +MmCopyMemToMmram ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) { + DEBUG ((DEBUG_ERROR, "MmCopyMemToMmram: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + CopyMem (DestinationBuffer, SourceBuffer, Length); + return EFI_SUCCESS; +} + +/** + Copies a source buffer (MMRAM) to a destination buffer (NON-MMRAM). + + This function copies a source buffer (non-MMRAM) to a destination buffer (MMRAM). + It checks if destination buffer is valid per processor architecture and not overlap with MMRAM. + If the check passes, it copies memory and returns EFI_SUCCESS. + If the check fails, it returns EFI_SECURITY_VIOLATION. + The implementation must be reentrant. + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with MMRAM. + @retval EFI_SUCCESS Memory is copied. + +**/ +EFI_STATUS +EFIAPI +MmCopyMemFromMmram ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) { + DEBUG ((DEBUG_ERROR, "MmCopyMemFromMmram: Security Violation: Destination (0x%x), Length (0x%x)\n", + DestinationBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + CopyMem (DestinationBuffer, SourceBuffer, Length); + return EFI_SUCCESS; +} + +/** + Copies a source buffer (NON-MMRAM) to a destination buffer (NON-MMRAM). + + This function copies a source buffer (non-MMRAM) to a destination buffer (MMRAM). + It checks if source buffer and destination buffer are valid per processor architecture and not overlap with MMRAM. + If the check passes, it copies memory and returns EFI_SUCCESS. + If the check fails, it returns EFI_SECURITY_VIOLATION. + The implementation must be reentrant, and it must handle the case where source buffer overlaps destination buffer. + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with MMRAM. + @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with MMRAM. + @retval EFI_SUCCESS Memory is copied. + +**/ +EFI_STATUS +EFIAPI +MmCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) { + DEBUG ((DEBUG_ERROR, "MmCopyMem: Security Violation: Destination (0x%x), Length (0x%x)\n", + DestinationBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) { + DEBUG ((DEBUG_ERROR, "MmCopyMem: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + CopyMem (DestinationBuffer, SourceBuffer, Length); + return EFI_SUCCESS; +} + +/** + Fills a target buffer (NON-MMRAM) with a byte value. + + This function fills a target buffer (non-MMRAM) with a byte value. + It checks if target buffer is valid per processor architecture and not overlap with MMRAM. + If the check passes, it fills memory and returns EFI_SUCCESS. + If the check fails, it returns EFI_SECURITY_VIOLATION. + + @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. + + @retval EFI_SECURITY_VIOLATION The Buffer is invalid per processor architecture or overlap with MMRAM. + @retval EFI_SUCCESS Memory is set. + +**/ +EFI_STATUS +EFIAPI +MmSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, Length)) { + DEBUG ((DEBUG_ERROR, "MmSetMem: Security Violation: Source (0x%x), Length (0x%x)\n", Buffer, Length)); + return EFI_SECURITY_VIOLATION; + } + SetMem (Buffer, Length, Value); + return EFI_SUCCESS; +} + +/** + The constructor function initializes the Mm Mem library + + @param [in] ImageHandle The firmware allocated handle for the EFI image. + @param [in] MmSystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +MemLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_MM_SYSTEM_TABLE *MmSystemTable + ) +{ + EFI_STATUS Status; + + // + // Calculate and save maximum support address + // + MmMemLibInternalCalculateMaximumSupportAddress (); + + // + // Initialize cached Mmram Ranges from HOB. + // + Status = MmMemLibInternalPopulateMmramRanges (); + + return Status; +} + +/** + Destructor for Mm Mem library. + + @param ImageHandle The image handle of the process. + @param MmSystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +MemLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_MM_SYSTEM_TABLE *MmSystemTable + ) +{ + + // + // Deinitialize cached Mmram Ranges. + // + MmMemLibInternalFreeMmramRanges (); + + return EFI_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf new file mode 100644 index 00000000..bc2f3eea --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf @@ -0,0 +1,55 @@ +## @file +# Instance of MM memory check library. +# +# MM memory check library library implementation. This library consumes MM_ACCESS_PROTOCOL +# to get MMRAM information. In order to use this library instance, the platform should produce +# all MMRAM range via MM_ACCESS_PROTOCOL, including the range for firmware (like MM Core +# and MM driver) and/or specific dedicated hardware. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR> +# Copyright (c) Microsoft Corporation. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = MemLib + FILE_GUID = EA355F14-6409-4716-829F-37B3BC7C7F26 + MODULE_TYPE = MM_STANDALONE + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x00010032 + LIBRARY_CLASS = MemLib|MM_STANDALONE MM_CORE_STANDALONE + CONSTRUCTOR = MemLibConstructor + DESTRUCTOR = MemLibDestructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 AARCH64 +# + +[Sources.Common] + StandaloneMmMemLib.c + +[Sources.IA32, Sources.X64] + X86StandaloneMmMemLibInternal.c + +[Sources.AARCH64] + AArch64/StandaloneMmMemLibInternal.c + +[Packages] + MdePkg/MdePkg.dec + StandaloneMmPkg/StandaloneMmPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + HobLib + MemoryAllocationLib + +[Guids] + gMmCoreDataHobGuid ## SOMETIMES_CONSUMES ## HOB + gEfiMmPeiMmramMemoryReserveGuid ## SOMETIMES_CONSUMES ## HOB diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c new file mode 100644 index 00000000..530105a6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c @@ -0,0 +1,155 @@ +/** @file + Internal ARCH Specific file of MM memory check library. + + MM memory check library implementation. This library consumes MM_ACCESS_PROTOCOL + to get MMRAM information. In order to use this library instance, the platform should produce + all MMRAM range via MM_ACCESS_PROTOCOL, including the range for firmware (like MM Core + and MM driver) and/or specific dedicated hardware. + + Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR> + Copyright (c) Microsoft Corporation. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include <PiMm.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DebugLib.h> +#include <Library/HobLib.h> + +#include <Guid/MmCoreData.h> +#include <Guid/MmramMemoryReserve.h> + +// +// Maximum support address used to check input buffer +// +extern EFI_PHYSICAL_ADDRESS mMmMemLibInternalMaximumSupportAddress; +extern EFI_MMRAM_DESCRIPTOR *mMmMemLibInternalMmramRanges; +extern UINTN mMmMemLibInternalMmramCount; + +/** + Calculate and save the maximum support address. + +**/ +VOID +MmMemLibInternalCalculateMaximumSupportAddress ( + VOID + ) +{ + VOID *Hob; + UINT32 RegEax; + UINT8 PhysicalAddressBits; + + // + // Get physical address bits supported. + // + Hob = GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob != NULL) { + PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; + } else { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + PhysicalAddressBits = (UINT8) RegEax; + } else { + PhysicalAddressBits = 36; + } + } + // + // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. + // + ASSERT (PhysicalAddressBits <= 52); + if (PhysicalAddressBits > 48) { + PhysicalAddressBits = 48; + } + + // + // Save the maximum support address in one global variable + // + mMmMemLibInternalMaximumSupportAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, PhysicalAddressBits) - 1); + DEBUG ((DEBUG_INFO, "mMmMemLibInternalMaximumSupportAddress = 0x%lx\n", mMmMemLibInternalMaximumSupportAddress)); +} + +/** + Initialize cached Mmram Ranges from HOB. + + @retval EFI_UNSUPPORTED The routine is unable to extract MMRAM information. + @retval EFI_SUCCESS MmRanges are populated successfully. + +**/ +EFI_STATUS +MmMemLibInternalPopulateMmramRanges ( + VOID + ) +{ + VOID *HobStart; + EFI_HOB_GUID_TYPE *GuidHob; + MM_CORE_DATA_HOB_DATA *DataInHob; + MM_CORE_PRIVATE_DATA *MmCorePrivateData; + EFI_HOB_GUID_TYPE *MmramRangesHob; + EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHobData; + EFI_MMRAM_DESCRIPTOR *MmramDescriptors; + + HobStart = GetHobList (); + DEBUG ((DEBUG_INFO, "%a - 0x%x\n", __FUNCTION__, HobStart)); + + // + // Extract MM Core Private context from the Hob. If absent search for + // a Hob containing the MMRAM ranges + // + GuidHob = GetNextGuidHob (&gMmCoreDataHobGuid, HobStart); + if (GuidHob == NULL) { + MmramRangesHob = GetFirstGuidHob (&gEfiMmPeiMmramMemoryReserveGuid); + if (MmramRangesHob == NULL) { + return EFI_UNSUPPORTED; + } + + MmramRangesHobData = GET_GUID_HOB_DATA (MmramRangesHob); + if (MmramRangesHobData == NULL || MmramRangesHobData->Descriptor == NULL) { + return EFI_UNSUPPORTED; + } + + mMmMemLibInternalMmramCount = MmramRangesHobData->NumberOfMmReservedRegions; + MmramDescriptors = MmramRangesHobData->Descriptor; + } else { + DataInHob = GET_GUID_HOB_DATA (GuidHob); + if (DataInHob == NULL) { + return EFI_UNSUPPORTED; + } + + MmCorePrivateData = (MM_CORE_PRIVATE_DATA *) (UINTN) DataInHob->Address; + if (MmCorePrivateData == NULL || MmCorePrivateData->MmramRanges == 0) { + return EFI_UNSUPPORTED; + } + + mMmMemLibInternalMmramCount = (UINTN) MmCorePrivateData->MmramRangeCount; + MmramDescriptors = (EFI_MMRAM_DESCRIPTOR *) (UINTN) MmCorePrivateData->MmramRanges; + } + + mMmMemLibInternalMmramRanges = AllocatePool (mMmMemLibInternalMmramCount * sizeof (EFI_MMRAM_DESCRIPTOR)); + if (mMmMemLibInternalMmramRanges) { + CopyMem (mMmMemLibInternalMmramRanges, + MmramDescriptors, + mMmMemLibInternalMmramCount * sizeof (EFI_MMRAM_DESCRIPTOR)); + } + + return EFI_SUCCESS; +} + +/** + Deinitialize cached Mmram Ranges. + +**/ +VOID +MmMemLibInternalFreeMmramRanges ( + VOID + ) +{ + if (mMmMemLibInternalMmramRanges != NULL) { + FreePool (mMmMemLibInternalMmramRanges); + } +} + |