diff --git a/StandaloneMmPkg/Library/StandaloneMmMemLib/ArmStandaloneMmMemLibInternal.c b/StandaloneMmPkg/Library/StandaloneMmMemLib/ArmStandaloneMmMemLibInternal.c index f1e1ec3103..c3fa8b1674 100644 --- a/StandaloneMmPkg/Library/StandaloneMmMemLib/ArmStandaloneMmMemLibInternal.c +++ b/StandaloneMmPkg/Library/StandaloneMmMemLib/ArmStandaloneMmMemLibInternal.c @@ -59,3 +59,45 @@ MmMemLibInternalFreeMmramRanges ( { // Not implemented for AARCH64. } + +/** + Initialize valid non-Mmram Ranges from Resource HOB. + +**/ +VOID +MmMemLibInitializeValidNonMmramRanges ( + VOID + ) +{ + // Not implemented for AARCH64. +} + +/** + Deinitialize cached non-Mmram Ranges. + +**/ +VOID +MmMemLibFreeValidNonMmramRanges ( + VOID + ) +{ + // Not implemented for AARCH64. +} + +/** + 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 + ) +{ + return TRUE; +} diff --git a/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c b/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c index e8b50c5a59..0f5d6d1b10 100644 --- a/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c +++ b/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c @@ -84,7 +84,7 @@ MmIsBufferOutsideMmValid ( } } - return TRUE; + return MmMemLibIsValidNonMmramRange (Buffer, Length); } /** @@ -261,6 +261,11 @@ MemLibConstructor ( // MmMemLibCalculateMaximumSupportAddress (); + // + // Initialize valid non-Mmram Ranges from Resource HOB. + // + MmMemLibInitializeValidNonMmramRanges (); + // // Initialize cached Mmram Ranges from HOB. // @@ -290,5 +295,9 @@ MemLibDestructor ( // MmMemLibInternalFreeMmramRanges (); + // + // Deinitialize cached non-Mmram Ranges. + // + MmMemLibFreeValidNonMmramRanges (); return EFI_SUCCESS; } diff --git a/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLibInternal.h b/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLibInternal.h index d2fba8f909..527f1ac9c4 100644 --- a/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLibInternal.h +++ b/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLibInternal.h @@ -45,4 +45,37 @@ MmMemLibInternalFreeMmramRanges ( VOID ); +/** + Initialize valid non-Mmram Ranges from Resource HOB. + +**/ +VOID +MmMemLibInitializeValidNonMmramRanges ( + VOID + ); + +/** + Deinitialize cached non-Mmram Ranges. + +**/ +VOID +MmMemLibFreeValidNonMmramRanges ( + VOID + ); + +/** + 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 + ); + #endif diff --git a/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c b/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c index 81b959230f..8f87e7803d 100644 --- a/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c +++ b/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c @@ -20,6 +20,14 @@ #include +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 // @@ -135,3 +143,194 @@ MmMemLibInternalFreeMmramRanges ( FreePool (mMmMemLibInternalMmramRanges); } } + +/** + 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; +}