From c79c04dabd571cfe794cb939471a862be14ab210 Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Fri, 3 Oct 2025 11:35:31 -0400 Subject: [PATCH 1/2] MdeModulePkg/Variable: Move RT cache buffer allocation to DXE Commit `d8f513de3e3ef228af7e6facf0ad3e35c3224032` added runtime memory allocation to VariablePei. That will cause runtime memory bucket fragmentation affecting hibernate stability as these runtime allocations are separate from the main runtime memory type bucket allocation made by the DXE Core. To preserve the existing functionality but allow the runtime buffer to come from the DXE bucket, the allocations in PEI are changed to boot services data allocations and the contents are moved to the runtime memory buffers (and those pages unblocked to MM) in the DXE variable driver after the bucket has been allocated by the DXE core. Signed-off-by: Michael Kubacki --- .../Universal/Variable/Pei/Variable.c | 45 ++----- .../Universal/Variable/Pei/Variable.h | 1 - .../Universal/Variable/Pei/VariablePei.inf | 1 - .../RuntimeDxe/VariableSmmRuntimeDxe.c | 116 +++++++++++++++++- .../RuntimeDxe/VariableSmmRuntimeDxe.inf | 1 + 5 files changed, 122 insertions(+), 42 deletions(-) diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.c b/MdeModulePkg/Universal/Variable/Pei/Variable.c index 8bd72f0ecf9c..8205a1413c8f 100644 --- a/MdeModulePkg/Universal/Variable/Pei/Variable.c +++ b/MdeModulePkg/Universal/Variable/Pei/Variable.c @@ -1433,7 +1433,6 @@ BuildVariableRuntimeCacheInfoHob ( { VARIABLE_RUNTIME_CACHE_INFO TempHobBuffer; VARIABLE_RUNTIME_CACHE_INFO *VariableRuntimeCacheInfo; - EFI_STATUS Status; VOID *Buffer; UINTN BufferSize; BOOLEAN NvAuthFlag; @@ -1442,18 +1441,11 @@ BuildVariableRuntimeCacheInfoHob ( ZeroMem (&TempHobBuffer, sizeof (VARIABLE_RUNTIME_CACHE_INFO)); // - // AllocateRuntimePages for CACHE_INFO_FLAG and unblock it. + // AllocatePages for CACHE_INFO_FLAG buffer (will be relocated to runtime by DXE). // Pages = EFI_SIZE_TO_PAGES (sizeof (CACHE_INFO_FLAG)); - Buffer = AllocateRuntimePages (Pages); + Buffer = AllocatePages (Pages); ASSERT (Buffer != NULL); - Status = MmUnblockMemoryRequest ( - (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, - Pages - ); - if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { - return Status; - } TempHobBuffer.CacheInfoFlagBuffer = (UINTN)Buffer; DEBUG (( @@ -1464,20 +1456,13 @@ BuildVariableRuntimeCacheInfoHob ( )); // - // AllocateRuntimePages for VolatileCache and unblock it. + // AllocatePages for VolatileCache buffer (will be relocated to runtime by DXE). // BufferSize = PcdGet32 (PcdVariableStoreSize); if (BufferSize > 0) { Pages = EFI_SIZE_TO_PAGES (BufferSize); - Buffer = AllocateRuntimePages (Pages); + Buffer = AllocatePages (Pages); ASSERT (Buffer != NULL); - Status = MmUnblockMemoryRequest ( - (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, - Pages - ); - if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { - return Status; - } TempHobBuffer.RuntimeVolatileCacheBuffer = (UINTN)Buffer; TempHobBuffer.RuntimeVolatileCachePages = Pages; @@ -1491,20 +1476,13 @@ BuildVariableRuntimeCacheInfoHob ( )); // - // AllocateRuntimePages for NVCache and unblock it. + // AllocatePages for NVCache buffer (will be relocated to runtime by DXE). // BufferSize = CalculateNvVariableCacheSize (&NvAuthFlag); if (BufferSize > 0) { Pages = EFI_SIZE_TO_PAGES (BufferSize); - Buffer = AllocateRuntimePages (Pages); + Buffer = AllocatePages (Pages); ASSERT (Buffer != NULL); - Status = MmUnblockMemoryRequest ( - (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, - Pages - ); - if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { - return Status; - } TempHobBuffer.RuntimeNvCacheBuffer = (UINTN)Buffer; TempHobBuffer.RuntimeNvCachePages = Pages; @@ -1518,20 +1496,13 @@ BuildVariableRuntimeCacheInfoHob ( )); // - // AllocateRuntimePages for HobCache and unblock it. + // AllocatePages for HobCache buffer (will be relocated to runtime by DXE). // BufferSize = CalculateHobVariableCacheSize (NvAuthFlag); if (BufferSize > 0) { Pages = EFI_SIZE_TO_PAGES (BufferSize); - Buffer = AllocateRuntimePages (Pages); + Buffer = AllocatePages (Pages); ASSERT (Buffer != NULL); - Status = MmUnblockMemoryRequest ( - (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, - Pages - ); - if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { - return Status; - } TempHobBuffer.RuntimeHobCacheBuffer = (UINTN)Buffer; TempHobBuffer.RuntimeHobCachePages = Pages; diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.h b/MdeModulePkg/Universal/Variable/Pei/Variable.h index aa0d79f16621..2e023783c2fc 100644 --- a/MdeModulePkg/Universal/Variable/Pei/Variable.h +++ b/MdeModulePkg/Universal/Variable/Pei/Variable.h @@ -22,7 +22,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include -#include #include #include diff --git a/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf b/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf index f2dc7c042c7a..576dc112bad4 100644 --- a/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf +++ b/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf @@ -41,7 +41,6 @@ PeiServicesLib SafeIntLib VariableFlashInfoLib - MmUnblockMemoryLib MemoryAllocationLib [Guids] diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c index 47f14c59c7f0..6f65dc0f9636 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c @@ -37,6 +37,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include @@ -1642,6 +1643,9 @@ InitVariableCache ( UINTN AllocatedNvCacheSize; UINTN AllocatedVolatileCacheSize; VARIABLE_RUNTIME_CACHE_INFO *VariableRuntimeCacheInfo; + VOID *RuntimeBuffer; + EFI_PHYSICAL_ADDRESS RuntimeBufferPhysicalAddress; + UINTN Pages; // // Get needed runtime cache buffer size and check if auth variables are to be used from SMM @@ -1665,9 +1669,115 @@ InitVariableCache ( ); CopyMem (&mVariableRtCacheInfo, VariableRuntimeCacheInfo, sizeof (VARIABLE_RUNTIME_CACHE_INFO)); - InitVariableStoreHeader ((VOID *)(UINTN)mVariableRtCacheInfo.RuntimeHobCacheBuffer, AllocatedHobCacheSize); - InitVariableStoreHeader ((VOID *)(UINTN)mVariableRtCacheInfo.RuntimeNvCacheBuffer, AllocatedNvCacheSize); - InitVariableStoreHeader ((VOID *)(UINTN)mVariableRtCacheInfo.RuntimeVolatileCacheBuffer, AllocatedVolatileCacheSize); + + // + // Relocate runtime cache buffers from boot services to runtime services + // This prevents runtime memory fragmentation by consolidating allocations in DXE + // + // Relocate CacheInfoFlag buffer from boot services to runtime services + // + if (mVariableRtCacheInfo.CacheInfoFlagBuffer != 0) { + Pages = EFI_SIZE_TO_PAGES (sizeof (CACHE_INFO_FLAG)); + Status = gBS->AllocatePages ( + AllocateAnyPages, + EfiRuntimeServicesData, + Pages, + &RuntimeBufferPhysicalAddress + ); + if (!EFI_ERROR (Status)) { + RuntimeBuffer = (VOID *)(UINTN)RuntimeBufferPhysicalAddress; + CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer, sizeof (CACHE_INFO_FLAG)); + mVariableRtCacheInfo.CacheInfoFlagBuffer = (UINTN)RuntimeBuffer; + + Status = MmUnblockMemoryRequest (RuntimeBufferPhysicalAddress, Pages); + if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { + return Status; + } + } else { + return Status; + } + } + + // + // Relocate RuntimeHobCache buffer from boot services to runtime services + // + if ((mVariableRtCacheInfo.RuntimeHobCacheBuffer != 0) && (AllocatedHobCacheSize > 0)) { + Pages = EFI_SIZE_TO_PAGES (AllocatedHobCacheSize); + Status = gBS->AllocatePages ( + AllocateAnyPages, + EfiRuntimeServicesData, + Pages, + &RuntimeBufferPhysicalAddress + ); + if (!EFI_ERROR (Status)) { + RuntimeBuffer = (VOID *)(UINTN)RuntimeBufferPhysicalAddress; + CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.RuntimeHobCacheBuffer, AllocatedHobCacheSize); + mVariableRtCacheInfo.RuntimeHobCacheBuffer = (UINTN)RuntimeBuffer; + + Status = MmUnblockMemoryRequest (RuntimeBufferPhysicalAddress, Pages); + if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { + return Status; + } + + InitVariableStoreHeader (RuntimeBuffer, AllocatedHobCacheSize); + } else { + return Status; + } + } + + // + // Relocate RuntimeNvCache buffer from boot services to runtime services + // + if ((mVariableRtCacheInfo.RuntimeNvCacheBuffer != 0) && (AllocatedNvCacheSize > 0)) { + Pages = EFI_SIZE_TO_PAGES (AllocatedNvCacheSize); + Status = gBS->AllocatePages ( + AllocateAnyPages, + EfiRuntimeServicesData, + Pages, + &RuntimeBufferPhysicalAddress + ); + if (!EFI_ERROR (Status)) { + RuntimeBuffer = (VOID *)(UINTN)RuntimeBufferPhysicalAddress; + CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.RuntimeNvCacheBuffer, AllocatedNvCacheSize); + mVariableRtCacheInfo.RuntimeNvCacheBuffer = (UINTN)RuntimeBuffer; + + Status = MmUnblockMemoryRequest (RuntimeBufferPhysicalAddress, Pages); + if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { + return Status; + } + + InitVariableStoreHeader (RuntimeBuffer, AllocatedNvCacheSize); + } else { + return Status; + } + } + + // + // Relocate RuntimeVolatileCache buffer from boot services to runtime services + // + if ((mVariableRtCacheInfo.RuntimeVolatileCacheBuffer != 0) && (AllocatedVolatileCacheSize > 0)) { + Pages = EFI_SIZE_TO_PAGES (AllocatedVolatileCacheSize); + Status = gBS->AllocatePages ( + AllocateAnyPages, + EfiRuntimeServicesData, + Pages, + &RuntimeBufferPhysicalAddress + ); + if (!EFI_ERROR (Status)) { + RuntimeBuffer = (VOID *)(UINTN)RuntimeBufferPhysicalAddress; + CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.RuntimeVolatileCacheBuffer, AllocatedVolatileCacheSize); + mVariableRtCacheInfo.RuntimeVolatileCacheBuffer = (UINTN)RuntimeBuffer; + + Status = MmUnblockMemoryRequest (RuntimeBufferPhysicalAddress, Pages); + if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { + return Status; + } + + InitVariableStoreHeader (RuntimeBuffer, AllocatedVolatileCacheSize); + } else { + return Status; + } + } } return Status; diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf index af8a32a7540e..2a8e955f1e76 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf @@ -61,6 +61,7 @@ SafeIntLib PcdLib HobLib + MmUnblockMemoryLib [Protocols] gEfiVariableWriteArchProtocolGuid ## PRODUCES From af31c5cd77d3fce7a0f08e974cf0a391faadd5a2 Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Tue, 7 Oct 2025 22:37:53 -0700 Subject: [PATCH 2/2] MdeModulePkg/VariableSmmRuntimeDxe: Disable var RT cache on alloc failure If a RT data buffer fails to be allocated or unblocked, clean up the RT cache state by (1) freeing any allocated buffers and (2) resetting the buffer addresses back to zero to indicate the RT cache is not available. Signed-off-by: Michael Kubacki --- .../RuntimeDxe/VariableSmmRuntimeDxe.c | 177 ++++++++++++------ 1 file changed, 120 insertions(+), 57 deletions(-) diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c index 6f65dc0f9636..3788636ac537 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c @@ -1621,6 +1621,21 @@ InitVariableStoreHeader ( } } +/** + Invalidates all runtime cache pointers to prevent access to boot services memory. + +**/ +VOID +InvalidateAllRuntimeCaches ( + VOID + ) +{ + mVariableRtCacheInfo.CacheInfoFlagBuffer = 0; + mVariableRtCacheInfo.RuntimeHobCacheBuffer = 0; + mVariableRtCacheInfo.RuntimeNvCacheBuffer = 0; + mVariableRtCacheInfo.RuntimeVolatileCacheBuffer = 0; +} + /** Initialize the runtime variable cache related content. @@ -1644,9 +1659,15 @@ InitVariableCache ( UINTN AllocatedVolatileCacheSize; VARIABLE_RUNTIME_CACHE_INFO *VariableRuntimeCacheInfo; VOID *RuntimeBuffer; - EFI_PHYSICAL_ADDRESS RuntimeBufferPhysicalAddress; UINTN Pages; + // Storage for temporary allocations - only committed to mVariableRtCacheInfo if all succeed + EFI_PHYSICAL_ADDRESS TempCacheInfoBuffer = 0; + EFI_PHYSICAL_ADDRESS TempHobCacheBuffer = 0; + EFI_PHYSICAL_ADDRESS TempNvCacheBuffer = 0; + EFI_PHYSICAL_ADDRESS TempVolatileCacheBuffer = 0; + BOOLEAN AllRtBufferAllocationsSucceeded = TRUE; + // // Get needed runtime cache buffer size and check if auth variables are to be used from SMM // @@ -1682,101 +1703,143 @@ InitVariableCache ( AllocateAnyPages, EfiRuntimeServicesData, Pages, - &RuntimeBufferPhysicalAddress + &TempCacheInfoBuffer ); - if (!EFI_ERROR (Status)) { - RuntimeBuffer = (VOID *)(UINTN)RuntimeBufferPhysicalAddress; - CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer, sizeof (CACHE_INFO_FLAG)); - mVariableRtCacheInfo.CacheInfoFlagBuffer = (UINTN)RuntimeBuffer; - - Status = MmUnblockMemoryRequest (RuntimeBufferPhysicalAddress, Pages); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "Failed to allocate runtime CacheInfoFlag buffer: %r\n", Status)); + AllRtBufferAllocationsSucceeded = FALSE; + } else { + Status = MmUnblockMemoryRequest (TempCacheInfoBuffer, Pages); if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { - return Status; + DEBUG ((DEBUG_WARN, "Failed to unblock CacheInfoFlag buffer: %r\n", Status)); + gBS->FreePages (TempCacheInfoBuffer, Pages); + TempCacheInfoBuffer = 0; + AllRtBufferAllocationsSucceeded = FALSE; } - } else { - return Status; } } - // - // Relocate RuntimeHobCache buffer from boot services to runtime services - // - if ((mVariableRtCacheInfo.RuntimeHobCacheBuffer != 0) && (AllocatedHobCacheSize > 0)) { + if (AllRtBufferAllocationsSucceeded && (mVariableRtCacheInfo.RuntimeHobCacheBuffer != 0) && (AllocatedHobCacheSize > 0)) { Pages = EFI_SIZE_TO_PAGES (AllocatedHobCacheSize); Status = gBS->AllocatePages ( AllocateAnyPages, EfiRuntimeServicesData, Pages, - &RuntimeBufferPhysicalAddress + &TempHobCacheBuffer ); - if (!EFI_ERROR (Status)) { - RuntimeBuffer = (VOID *)(UINTN)RuntimeBufferPhysicalAddress; - CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.RuntimeHobCacheBuffer, AllocatedHobCacheSize); - mVariableRtCacheInfo.RuntimeHobCacheBuffer = (UINTN)RuntimeBuffer; - - Status = MmUnblockMemoryRequest (RuntimeBufferPhysicalAddress, Pages); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "Failed to allocate runtime HOB cache buffer: %r\n", Status)); + AllRtBufferAllocationsSucceeded = FALSE; + } else { + Status = MmUnblockMemoryRequest (TempHobCacheBuffer, Pages); if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { - return Status; + DEBUG ((DEBUG_WARN, "Failed to unblock HOB cache buffer: %r\n", Status)); + gBS->FreePages (TempHobCacheBuffer, Pages); + TempHobCacheBuffer = 0; + AllRtBufferAllocationsSucceeded = FALSE; } - - InitVariableStoreHeader (RuntimeBuffer, AllocatedHobCacheSize); - } else { - return Status; } } - // - // Relocate RuntimeNvCache buffer from boot services to runtime services - // - if ((mVariableRtCacheInfo.RuntimeNvCacheBuffer != 0) && (AllocatedNvCacheSize > 0)) { + if (AllRtBufferAllocationsSucceeded && (mVariableRtCacheInfo.RuntimeNvCacheBuffer != 0) && (AllocatedNvCacheSize > 0)) { Pages = EFI_SIZE_TO_PAGES (AllocatedNvCacheSize); Status = gBS->AllocatePages ( AllocateAnyPages, EfiRuntimeServicesData, Pages, - &RuntimeBufferPhysicalAddress + &TempNvCacheBuffer ); - if (!EFI_ERROR (Status)) { - RuntimeBuffer = (VOID *)(UINTN)RuntimeBufferPhysicalAddress; - CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.RuntimeNvCacheBuffer, AllocatedNvCacheSize); - mVariableRtCacheInfo.RuntimeNvCacheBuffer = (UINTN)RuntimeBuffer; - - Status = MmUnblockMemoryRequest (RuntimeBufferPhysicalAddress, Pages); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "Failed to allocate runtime NV cache buffer: %r\n", Status)); + AllRtBufferAllocationsSucceeded = FALSE; + } else { + Status = MmUnblockMemoryRequest (TempNvCacheBuffer, Pages); if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { - return Status; + DEBUG ((DEBUG_WARN, "Failed to unblock NV cache buffer: %r\n", Status)); + gBS->FreePages (TempNvCacheBuffer, Pages); + TempNvCacheBuffer = 0; + AllRtBufferAllocationsSucceeded = FALSE; } - - InitVariableStoreHeader (RuntimeBuffer, AllocatedNvCacheSize); - } else { - return Status; } } - // - // Relocate RuntimeVolatileCache buffer from boot services to runtime services - // - if ((mVariableRtCacheInfo.RuntimeVolatileCacheBuffer != 0) && (AllocatedVolatileCacheSize > 0)) { + if (AllRtBufferAllocationsSucceeded && (mVariableRtCacheInfo.RuntimeVolatileCacheBuffer != 0) && (AllocatedVolatileCacheSize > 0)) { Pages = EFI_SIZE_TO_PAGES (AllocatedVolatileCacheSize); Status = gBS->AllocatePages ( AllocateAnyPages, EfiRuntimeServicesData, Pages, - &RuntimeBufferPhysicalAddress + &TempVolatileCacheBuffer ); - if (!EFI_ERROR (Status)) { - RuntimeBuffer = (VOID *)(UINTN)RuntimeBufferPhysicalAddress; - CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.RuntimeVolatileCacheBuffer, AllocatedVolatileCacheSize); - mVariableRtCacheInfo.RuntimeVolatileCacheBuffer = (UINTN)RuntimeBuffer; - - Status = MmUnblockMemoryRequest (RuntimeBufferPhysicalAddress, Pages); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "Failed to allocate runtime volatile cache buffer: %r\n", Status)); + AllRtBufferAllocationsSucceeded = FALSE; + } else { + Status = MmUnblockMemoryRequest (TempVolatileCacheBuffer, Pages); if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) { - return Status; + DEBUG ((DEBUG_WARN, "Failed to unblock volatile cache buffer: %r\n", Status)); + gBS->FreePages (TempVolatileCacheBuffer, Pages); + TempVolatileCacheBuffer = 0; + AllRtBufferAllocationsSucceeded = FALSE; } + } + } + + if (AllRtBufferAllocationsSucceeded) { + if (TempCacheInfoBuffer != 0) { + RuntimeBuffer = (VOID *)(UINTN)TempCacheInfoBuffer; + CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer, sizeof (CACHE_INFO_FLAG)); + mVariableRtCacheInfo.CacheInfoFlagBuffer = TempCacheInfoBuffer; + } + + if (TempHobCacheBuffer != 0) { + RuntimeBuffer = (VOID *)(UINTN)TempHobCacheBuffer; + CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.RuntimeHobCacheBuffer, AllocatedHobCacheSize); + mVariableRtCacheInfo.RuntimeHobCacheBuffer = TempHobCacheBuffer; + InitVariableStoreHeader (RuntimeBuffer, AllocatedHobCacheSize); + } + + if (TempNvCacheBuffer != 0) { + RuntimeBuffer = (VOID *)(UINTN)TempNvCacheBuffer; + CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.RuntimeNvCacheBuffer, AllocatedNvCacheSize); + mVariableRtCacheInfo.RuntimeNvCacheBuffer = TempNvCacheBuffer; + InitVariableStoreHeader (RuntimeBuffer, AllocatedNvCacheSize); + } + if (TempVolatileCacheBuffer != 0) { + RuntimeBuffer = (VOID *)(UINTN)TempVolatileCacheBuffer; + CopyMem (RuntimeBuffer, (VOID *)(UINTN)mVariableRtCacheInfo.RuntimeVolatileCacheBuffer, AllocatedVolatileCacheSize); + mVariableRtCacheInfo.RuntimeVolatileCacheBuffer = TempVolatileCacheBuffer; InitVariableStoreHeader (RuntimeBuffer, AllocatedVolatileCacheSize); - } else { - return Status; } + + DEBUG ((DEBUG_INFO, "Runtime variable cache buffers successfully relocated\n")); + } else { + // + // One or more allocations failed - clean up any successful allocations + // and disable runtime caching entirely + // + if (TempCacheInfoBuffer != 0) { + gBS->FreePages (TempCacheInfoBuffer, EFI_SIZE_TO_PAGES (sizeof (CACHE_INFO_FLAG))); + } + + if (TempHobCacheBuffer != 0) { + gBS->FreePages (TempHobCacheBuffer, EFI_SIZE_TO_PAGES (AllocatedHobCacheSize)); + } + + if (TempNvCacheBuffer != 0) { + gBS->FreePages (TempNvCacheBuffer, EFI_SIZE_TO_PAGES (AllocatedNvCacheSize)); + } + + if (TempVolatileCacheBuffer != 0) { + gBS->FreePages (TempVolatileCacheBuffer, EFI_SIZE_TO_PAGES (AllocatedVolatileCacheSize)); + } + + InvalidateAllRuntimeCaches (); + + DEBUG ((DEBUG_WARN, "Runtime variable cache disabled due to allocation failure.\n")); + + // Don't return failure - the variable service can function without the runtime cache } }