mirror of
https://github.com/acidanthera/audk.git
synced 2025-08-18 08:08:09 +02:00
Remove unnecessary check in API MmIsBufferOutsideMmValid of StandaloneMmMemLib. The API is used to check if a input buffer is outside MMRAM and inside a valid non-MMRAM range. Previously, the API only checks if the input buffer is overlapped with MMRAM range. In the last commit, we add logic to check if the input buffer is inside valid non-MMRAM ranges reported by the resource HOB. Since the resource HOB only covers valid non-MMRAM ranges, we doesn't need to check if the input buffer is inside the MMRAM anymore. Signed-off-by: Dun Tan <dun.tan@intel.com>
268 lines
7.8 KiB
C
268 lines
7.8 KiB
C
/** @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 - 2024, 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 "StandaloneMmMemLibInternal.h"
|
|
#include <PiMm.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/HobLib.h>
|
|
|
|
typedef struct {
|
|
EFI_PHYSICAL_ADDRESS Base;
|
|
UINT64 Length;
|
|
} NON_MM_MEMORY_RANGE;
|
|
|
|
NON_MM_MEMORY_RANGE *mValidNonMmramRanges;
|
|
UINTN mValidNonMmramCount;
|
|
|
|
//
|
|
// Maximum support address used to check input buffer
|
|
//
|
|
extern EFI_PHYSICAL_ADDRESS mMmMemLibInternalMaximumSupportAddress;
|
|
|
|
/**
|
|
Calculate and save the maximum support address.
|
|
|
|
**/
|
|
VOID
|
|
MmMemLibCalculateMaximumSupportAddress (
|
|
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));
|
|
}
|
|
|
|
/**
|
|
Merge the overlapped or continuous ranges in input MemoryRange. This function is to optimize
|
|
the process of checking whether a buffer range belongs to the range reported by resource HOB,
|
|
since the buffer to be checked may be covered by multi resource HOB.
|
|
|
|
@param[in, out] MemoryRange A pointer to the NonMmramRanges reported by resource HOB.
|
|
@param[in, out] MemoryRangeSize A pointer to the size, in bytes, of the MemoryRange buffer.
|
|
On input, it is the size of the current memory map.
|
|
On output, it is the size of new memory map after merge.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
MergeOverlappedOrContinuousRanges (
|
|
IN OUT NON_MM_MEMORY_RANGE *MemoryRange,
|
|
IN OUT UINTN *MemoryRangeSize
|
|
)
|
|
{
|
|
NON_MM_MEMORY_RANGE *MemoryRangeEntry;
|
|
NON_MM_MEMORY_RANGE *MemoryRangeEnd;
|
|
NON_MM_MEMORY_RANGE *NewMemoryRangeEntry;
|
|
NON_MM_MEMORY_RANGE *NextMemoryRangeEntry;
|
|
EFI_PHYSICAL_ADDRESS End;
|
|
|
|
MemoryRangeEntry = MemoryRange;
|
|
NewMemoryRangeEntry = MemoryRange;
|
|
MemoryRangeEnd = (NON_MM_MEMORY_RANGE *)((UINT8 *)MemoryRange + *MemoryRangeSize);
|
|
while ((UINTN)MemoryRangeEntry < (UINTN)MemoryRangeEnd) {
|
|
NextMemoryRangeEntry = MemoryRangeEntry + 1;
|
|
|
|
do {
|
|
if (((UINTN)NextMemoryRangeEntry < (UINTN)MemoryRangeEnd) &&
|
|
((MemoryRangeEntry->Base + MemoryRangeEntry->Length) >= NextMemoryRangeEntry->Base))
|
|
{
|
|
//
|
|
// Merge the overlapped or continuous ranges.
|
|
//
|
|
End = MAX (
|
|
MemoryRangeEntry->Base + MemoryRangeEntry->Length,
|
|
NextMemoryRangeEntry->Base + NextMemoryRangeEntry->Length
|
|
);
|
|
MemoryRangeEntry->Length = End - MemoryRangeEntry->Base;
|
|
|
|
NextMemoryRangeEntry++;
|
|
continue;
|
|
} else {
|
|
//
|
|
// Copy the processed independent range to the new index location.
|
|
//
|
|
CopyMem (NewMemoryRangeEntry, MemoryRangeEntry, sizeof (NON_MM_MEMORY_RANGE));
|
|
break;
|
|
}
|
|
} while (TRUE);
|
|
|
|
MemoryRangeEntry = NextMemoryRangeEntry;
|
|
NewMemoryRangeEntry++;
|
|
}
|
|
|
|
*MemoryRangeSize = (UINTN)NewMemoryRangeEntry - (UINTN)MemoryRange;
|
|
}
|
|
|
|
/**
|
|
Function to compare 2 NON_MM_MEMORY_RANGE pointer based on Base.
|
|
|
|
@param[in] Buffer1 pointer to NON_MM_MEMORY_RANGE pointer to compare
|
|
@param[in] Buffer2 pointer to second NON_MM_MEMORY_RANGE pointer to compare
|
|
|
|
@retval 0 Buffer1 equal to Buffer2
|
|
@retval <0 Buffer1 is less than Buffer2
|
|
@retval >0 Buffer1 is greater than Buffer2
|
|
**/
|
|
INTN
|
|
EFIAPI
|
|
NonMmMapCompare (
|
|
IN CONST VOID *Buffer1,
|
|
IN CONST VOID *Buffer2
|
|
)
|
|
{
|
|
if (((NON_MM_MEMORY_RANGE *)Buffer1)->Base > ((NON_MM_MEMORY_RANGE *)Buffer2)->Base) {
|
|
return 1;
|
|
} else if (((NON_MM_MEMORY_RANGE *)Buffer1)->Base < ((NON_MM_MEMORY_RANGE *)Buffer2)->Base) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Initialize valid non-Mmram Ranges from Resource HOB.
|
|
|
|
**/
|
|
VOID
|
|
MmMemLibInitializeValidNonMmramRanges (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_PEI_HOB_POINTERS Hob;
|
|
UINTN Count;
|
|
UINTN Index;
|
|
UINTN RangeSize;
|
|
NON_MM_MEMORY_RANGE SortBuffer;
|
|
|
|
mValidNonMmramRanges = NULL;
|
|
mValidNonMmramCount = 0;
|
|
|
|
Count = 0;
|
|
Index = 0;
|
|
RangeSize = 0;
|
|
|
|
//
|
|
// 1. Get the count.
|
|
//
|
|
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
|
|
while (Hob.Raw != NULL) {
|
|
Count++;
|
|
Hob.Raw = GET_NEXT_HOB (Hob);
|
|
Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
|
|
}
|
|
|
|
//
|
|
// 2. Store the initial data.
|
|
//
|
|
RangeSize = sizeof (NON_MM_MEMORY_RANGE) * Count;
|
|
mValidNonMmramRanges = (NON_MM_MEMORY_RANGE *)AllocateZeroPool (RangeSize);
|
|
ASSERT (mValidNonMmramRanges != NULL);
|
|
|
|
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
|
|
while (Hob.Raw != NULL) {
|
|
mValidNonMmramRanges[Index].Base = Hob.ResourceDescriptor->PhysicalStart;
|
|
mValidNonMmramRanges[Index].Length = Hob.ResourceDescriptor->ResourceLength;
|
|
Index++;
|
|
|
|
Hob.Raw = GET_NEXT_HOB (Hob);
|
|
Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
|
|
}
|
|
|
|
ASSERT (Index == Count);
|
|
|
|
//
|
|
// 3. Sort the data.
|
|
//
|
|
QuickSort (mValidNonMmramRanges, Count, sizeof (NON_MM_MEMORY_RANGE), (BASE_SORT_COMPARE)NonMmMapCompare, &SortBuffer);
|
|
|
|
//
|
|
// 4. Merge the overlapped or continuous ranges.
|
|
//
|
|
MergeOverlappedOrContinuousRanges (mValidNonMmramRanges, &RangeSize);
|
|
mValidNonMmramCount = RangeSize/sizeof (NON_MM_MEMORY_RANGE);
|
|
}
|
|
|
|
/**
|
|
Deinitialize cached non-Mmram Ranges.
|
|
|
|
**/
|
|
VOID
|
|
MmMemLibFreeValidNonMmramRanges (
|
|
VOID
|
|
)
|
|
{
|
|
if (mValidNonMmramRanges != NULL) {
|
|
FreePool (mValidNonMmramRanges);
|
|
}
|
|
}
|
|
|
|
/**
|
|
This function check if the buffer is valid non-MMRAM memory range.
|
|
|
|
@param[in] Buffer The buffer start address to be checked.
|
|
@param[in] Length The buffer length to be checked.
|
|
|
|
@retval TRUE This buffer is valid non-MMRAM memory range.
|
|
@retval FALSE This buffer is not valid non-MMRAM memory range.
|
|
**/
|
|
BOOLEAN
|
|
MmMemLibIsValidNonMmramRange (
|
|
IN EFI_PHYSICAL_ADDRESS Buffer,
|
|
IN UINT64 Length
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
for (Index = 0; Index < mValidNonMmramCount; Index++) {
|
|
if ((Buffer >= mValidNonMmramRanges[Index].Base) &&
|
|
(Buffer + Length <= mValidNonMmramRanges[Index].Base + mValidNonMmramRanges[Index].Length))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|