diff options
Diffstat (limited to 'UefiCpuPkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLib.c')
-rw-r--r-- | UefiCpuPkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLib.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/UefiCpuPkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLib.c b/UefiCpuPkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLib.c index 790392b19d..c42ca106eb 100644 --- a/UefiCpuPkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLib.c +++ b/UefiCpuPkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLib.c @@ -18,6 +18,85 @@ #include <Library/BaseMemoryLib.h>
#include <Library/PeiServicesLib.h>
#include <Base.h>
+#include <PiPei.h>
+
+/**
+ This function checks if the input buffer range [UnblockBase, UnblockEnd] is unblockable.
+ The input range should be covered by the EfiRuntimeServicesData, EfiACPIMemoryNVS or
+ EfiReservedMemoryType memory allocation HOB.
+
+ @param[in] HobStart The starting HOB pointer to search from.
+ @param[in] UnblockAddress Base address of the range to unblock.
+ @param[in] UnblockEnd End address of the range to unblock.
+
+ @retval RETURN_SUCCESS The range is unblockable.
+ @retval RETURN_INVALID_PARAMETER The range to unblock contains invalid memory.
+**/
+EFI_STATUS
+MmUnblockMemoryLibIsUnblockableRegion (
+ IN VOID *HobStart,
+ IN EFI_PHYSICAL_ADDRESS UnblockBase,
+ IN EFI_PHYSICAL_ADDRESS UnblockEnd
+ )
+{
+ EFI_PHYSICAL_ADDRESS HobBase;
+ EFI_PHYSICAL_ADDRESS HobEnd;
+ EFI_STATUS Status;
+ EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
+
+ while ((MemoryAllocationHob = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, HobStart)) != NULL) {
+ HobBase = MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress;
+ HobEnd = MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress +
+ MemoryAllocationHob->AllocDescriptor.MemoryLength;
+ if ((UnblockBase < HobEnd) && (UnblockEnd > HobBase)) {
+ //
+ // The overlapped memory allocation HOB type must be one of the three specific types.
+ //
+ if ((MemoryAllocationHob->AllocDescriptor.MemoryType != EfiRuntimeServicesData) &&
+ (MemoryAllocationHob->AllocDescriptor.MemoryType != EfiACPIMemoryNVS) &&
+ (MemoryAllocationHob->AllocDescriptor.MemoryType != EfiReservedMemoryType))
+ {
+ DEBUG ((DEBUG_ERROR, "Error: range [0x%lx, 0x%lx] to unblock contains invalid type memory\n", UnblockBase, UnblockEnd));
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (UnblockBase < HobBase) {
+ //
+ // Recursively call to check [UnblockBase, HobBase]
+ //
+ Status = MmUnblockMemoryLibIsUnblockableRegion (
+ GET_NEXT_HOB (MemoryAllocationHob),
+ UnblockBase,
+ HobBase
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ if (UnblockEnd > HobEnd) {
+ //
+ // Recursively call to check [HobEnd, UnblockEnd]
+ //
+ Status = MmUnblockMemoryLibIsUnblockableRegion (
+ GET_NEXT_HOB (MemoryAllocationHob),
+ HobEnd,
+ UnblockEnd
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ HobStart = GET_NEXT_HOB (MemoryAllocationHob);
+ }
+
+ DEBUG ((DEBUG_ERROR, "Error: range [0x%lx, 0x%lx] to unblock doesn't belong to any memory allocation HOB\n", UnblockBase, UnblockEnd));
+ return RETURN_INVALID_PARAMETER;
+}
/**
This API provides a way to unblock certain data pages to be accessible inside MM environment.
@@ -32,6 +111,10 @@ @retval RETURN_SECURITY_VIOLATION The requested address failed to pass security check for
unblocking.
@retval RETURN_INVALID_PARAMETER Input address either NULL pointer or not page aligned.
+ @retval RETURN_INVALID_PARAMETER Input range to unblock contains invalid types memory other than
+ EfiRuntimeServicesData, EfiACPIMemoryNVS, and EfiReservedMemory.
+ @retval RETURN_INVALID_PARAMETER Input range to unblock contains memory that doesn't belong to
+ any memory allocation HOB.
@retval RETURN_ACCESS_DENIED The request is rejected due to system has passed certain boot
phase.
**/
@@ -45,12 +128,19 @@ MmUnblockMemoryRequest ( EFI_STATUS Status;
MM_UNBLOCK_REGION *MmUnblockMemoryHob;
EFI_PEI_MM_COMMUNICATION_PPI *MmCommunicationPpi;
+ VOID *HobList;
if (!IS_ALIGNED (UnblockAddress, SIZE_4KB)) {
DEBUG ((DEBUG_ERROR, "Error: UnblockAddress is not 4KB aligned: %p\n", UnblockAddress));
return EFI_INVALID_PARAMETER;
}
+ HobList = GetHobList ();
+ Status = MmUnblockMemoryLibIsUnblockableRegion (HobList, UnblockAddress, UnblockAddress + EFI_PAGES_TO_SIZE (NumberOfPages));
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
//
// Unblock requests are rejected when MmIpl finishes execution.
//
|