--- /dev/null
+/** @file\r
+ Sample to provide SecTemporaryRamSupport function.\r
+\r
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+\r
+#include <Ppi/TemporaryRamSupport.h>\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DebugAgentLib.h>\r
+\r
+/**\r
+ Switch the stack in the temporary memory to the one in the permanent memory.\r
+\r
+ This function must be invoked after the memory migration immediately. The relative\r
+ position of the stack in the temporary and permanent memory is same.\r
+\r
+ @param[in] TemporaryMemoryBase Base address of the temporary memory.\r
+ @param[in] PermenentMemoryBase Base address of the permanent memory.\r
+**/\r
+VOID\r
+EFIAPI\r
+SecSwitchStack (\r
+ IN UINT32 TemporaryMemoryBase,\r
+ IN UINT32 PermenentMemoryBase\r
+ );\r
+\r
+/**\r
+ This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into\r
+ permanent memory.\r
+\r
+ @param[in] PeiServices Pointer to the PEI Services Table.\r
+ @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the\r
+ Temporary RAM contents.\r
+ @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the\r
+ Temporary RAM contents.\r
+ @param[in] CopySize Amount of memory to migrate from temporary to permanent memory.\r
+\r
+ @retval EFI_SUCCESS The data was successfully returned.\r
+ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when\r
+ TemporaryMemoryBase > PermanentMemoryBase.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SecTemporaryRamSupport (\r
+ IN CONST EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
+ IN UINTN CopySize\r
+ )\r
+{\r
+ IA32_DESCRIPTOR IdtDescriptor;\r
+ VOID* OldHeap;\r
+ VOID* NewHeap;\r
+ VOID* OldStack;\r
+ VOID* NewStack;\r
+ DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;\r
+ BOOLEAN OldStatus;\r
+ UINTN PeiStackSize;\r
+\r
+ PeiStackSize = (UINTN)PcdGet32 (PcdPeiTemporaryRamStackSize);\r
+ if (PeiStackSize == 0) {\r
+ PeiStackSize = (CopySize >> 1);\r
+ }\r
+\r
+ ASSERT (PeiStackSize < CopySize);\r
+\r
+ //\r
+ // |-------------------|---->\r
+ // | Stack | PeiStackSize\r
+ // |-------------------|---->\r
+ // | Heap | PeiTemporayRamSize\r
+ // |-------------------|----> TempRamBase\r
+ //\r
+ // |-------------------|---->\r
+ // | Heap | PeiTemporayRamSize\r
+ // |-------------------|---->\r
+ // | Stack | PeiStackSize\r
+ // |-------------------|----> PermanentMemoryBase\r
+ //\r
+\r
+ OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;\r
+ NewHeap = (VOID*)((UINTN)PermanentMemoryBase + PeiStackSize);\r
+\r
+ OldStack = (VOID*)((UINTN)TemporaryMemoryBase + CopySize - PeiStackSize);\r
+ NewStack = (VOID*)(UINTN)PermanentMemoryBase;\r
+\r
+ DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;\r
+ DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;\r
+\r
+ OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);\r
+ //\r
+ // Initialize Debug Agent to support source level debug in PEI phase after memory ready.\r
+ // It will build HOB and fix up the pointer in IDT table.\r
+ //\r
+ InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);\r
+\r
+ //\r
+ // Migrate Heap\r
+ //\r
+ CopyMem (NewHeap, OldHeap, CopySize - PeiStackSize);\r
+\r
+ //\r
+ // Migrate Stack\r
+ //\r
+ CopyMem (NewStack, OldStack, PeiStackSize);\r
+\r
+\r
+ //\r
+ // We need *not* fix the return address because currently,\r
+ // The PeiCore is executed in flash.\r
+ //\r
+\r
+ //\r
+ // Rebase IDT table in permanent memory\r
+ //\r
+ AsmReadIdtr (&IdtDescriptor);\r
+ IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;\r
+\r
+ AsmWriteIdtr (&IdtDescriptor);\r
+\r
+\r
+ //\r
+ // Program MTRR\r
+ //\r
+\r
+ //\r
+ // SecSwitchStack function must be invoked after the memory migration\r
+ // immediatly, also we need fixup the stack change caused by new call into\r
+ // permenent memory.\r
+ //\r
+ SecSwitchStack (\r
+ (UINT32) (UINTN) OldStack,\r
+ (UINT32) (UINTN) NewStack\r
+ );\r
+\r
+ SaveAndSetDebugTimerInterrupt (OldStatus);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r