There is potential problem with PEI Core's usage of the
TemporaryRamMigration PPI. When the TemporaryRamMigration function is
called, it returns to C based code after changing the stack to the new
permanent memory copy of the stack. But, the C compiler may have
stored pointers to addresses on the old temporary RAM stack. Even
though the stack is copied to a new permanent memory location, it is
not possible to adjust all pointers that the C compiler may have added
within the stack data.

For this reason, it is only safe to return to assembly code after
calling TemporaryRamMigration. The assembly code can make sure the old
temporary RAM stack is not used before calling a new C function. When
the new function is called, it will use the new permanent memory
stack, so it is safe to use C code again.

This code adds new function named PeiTemporaryRamMigration which can
be implemented in assembly code as described above.
PeiTemporaryRamMigration must call the TemporaryRamMigration function,
and then calls a new C PeiTemporaryRamMigrated function. This
guanantees PeiTemporaryRamMigrated will only use the permanent memory
stack.

For now, this patch should have no effect, since it still uses C to
implement PeiTemporaryRamMigration. But, PeiTemporaryRamMigration can
then be changed into an assembly code function to fix the issue
described above.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jordan Justen <jordan.l.jus...@intel.com>
Cc: Jian J Wang <jian.j.w...@intel.com>
Cc: Hao Wu <hao.a...@intel.com>
Cc: Ray Ni <ray...@intel.com>
Cc: Star Zeng <star.z...@intel.com>
---
 MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 59 ++++++++++++-------
 .../Pei/Dispatcher/TemporaryRamMigration.c    | 52 ++++++++++++++++
 MdeModulePkg/Core/Pei/PeiMain.h               | 52 ++++++++++++++++
 MdeModulePkg/Core/Pei/PeiMain.inf             |  1 +
 4 files changed, 143 insertions(+), 21 deletions(-)
 create mode 100644 MdeModulePkg/Core/Pei/Dispatcher/TemporaryRamMigration.c

diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c 
b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
index 68670f43e0..8e3fa161dd 100644
--- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -688,6 +688,7 @@ PeiCheckAndSwitchStack (
   EFI_PHYSICAL_ADDRESS                  TempBase2;
   UINTN                                 TempSize2;
   UINTN                                 Index;
+  PEI_CORE_TEMPORARY_RAM_TRANSITION     TempRamTransitionData;
 
   PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;
 
@@ -822,30 +823,20 @@ PeiCheckAndSwitchStack (
         Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset);
       }
 
-      //
-      // Temporary Ram Support PPI is provided by platform, it will copy
-      // temporary memory to permanent memory and do stack switching.
-      // After invoking Temporary Ram Support PPI, the following code's
-      // stack is in permanent memory.
-      //
-      TemporaryRamSupportPpi->TemporaryRamMigration (
-                                PeiServices,
-                                TemporaryRamBase,
-                                (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - 
TemporaryStackSize),
-                                TemporaryRamSize
-                                );
-
-      //
-      // Migrate memory pages allocated in pre-memory phase.
-      // It could not be called before calling 
TemporaryRamSupportPpi->TemporaryRamMigration()
-      // as the migrated memory pages may be overridden by 
TemporaryRamSupportPpi->TemporaryRamMigration().
-      //
-      MigrateMemoryPages (Private, TRUE);
+      TempRamTransitionData.TemporaryRamMigration =
+        TemporaryRamSupportPpi->TemporaryRamMigration;
+      TempRamTransitionData.PeiServices = PeiServices;
+      TempRamTransitionData.TemporaryMemoryBase = TemporaryRamBase;
+      TempRamTransitionData.PermanentMemoryBase =
+        (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize);
+      TempRamTransitionData.CopySize = TemporaryRamSize;
+      TempRamTransitionData.Private = Private;
+      TempRamTransitionData.SecCoreData = SecCoreData;
 
       //
-      // Entry PEI Phase 2
+      // Migrate Temporary RAM and enter PEI Phase 2
       //
-      PeiCore (SecCoreData, NULL, Private);
+      PeiTemporaryRamMigration(&TempRamTransitionData);
     } else {
       //
       // Migrate memory pages allocated in pre-memory phase.
@@ -958,6 +949,32 @@ PeiCheckAndSwitchStack (
   }
 }
 
+VOID
+EFIAPI
+PeiTemporaryRamMigrated (
+  IN  VOID  *CallbackContext
+  )
+{
+  PEI_CORE_TEMPORARY_RAM_TRANSITION *TempRamTransitionData =
+    (PEI_CORE_TEMPORARY_RAM_TRANSITION*)CallbackContext;
+
+  //
+  // Migrate memory pages allocated in pre-memory phase.
+  // It could not be called before calling 
TemporaryRamSupportPpi->TemporaryRamMigration()
+  // as the migrated memory pages may be overridden by 
TemporaryRamSupportPpi->TemporaryRamMigration().
+  //
+  MigrateMemoryPages (TempRamTransitionData->Private, TRUE);
+
+  //
+  // Entry PEI Phase 2
+  //
+  PeiCore (
+    TempRamTransitionData->SecCoreData,
+    NULL,
+    TempRamTransitionData->Private
+    );
+}
+
 /**
   Conduct PEIM dispatch.
 
diff --git a/MdeModulePkg/Core/Pei/Dispatcher/TemporaryRamMigration.c 
b/MdeModulePkg/Core/Pei/Dispatcher/TemporaryRamMigration.c
new file mode 100644
index 0000000000..9e9d0854ed
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Dispatcher/TemporaryRamMigration.c
@@ -0,0 +1,52 @@
+/** @file
+  EFI PEI Core temporary RAM migration
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PeiMain.h"
+
+/**
+  To call the TemporaryRamMigration PPI, we might not be able to rely
+  on C code's handling of the stack. In these cases we use an assembly
+  function to make sure the old stack is not used after the
+  TemporaryRamMigration PPI is used.
+
+  After calling the TemporaryRamMigration PPI, this function calls
+  PeiTemporaryRamMigrated.
+
+  This C based function provides an implementation that may work for
+  some architectures.
+
+  @param TempRamTransitionData
+**/
+VOID
+EFIAPI
+PeiTemporaryRamMigration (
+  IN  PEI_CORE_TEMPORARY_RAM_TRANSITION  *TempRamTransitionData
+  )
+{
+  //
+  // Temporary Ram Support PPI is provided by platform, it will copy
+  // temporary memory to permanent memory and do stack switching.
+  // After invoking Temporary Ram Support PPI, the following code's
+  // stack is in permanent memory.
+  //
+  TempRamTransitionData->TemporaryRamMigration (
+                           TempRamTransitionData->PeiServices,
+                           TempRamTransitionData->TemporaryMemoryBase,
+                           TempRamTransitionData->PermanentMemoryBase,
+                           TempRamTransitionData->CopySize
+                           );
+
+  PeiTemporaryRamMigrated(TempRamTransitionData);
+}
diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h
index a61da73fd8..2d48f8d5d1 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.h
+++ b/MdeModulePkg/Core/Pei/PeiMain.h
@@ -1871,4 +1871,56 @@ PeiReinitializeFv (
   IN  PEI_CORE_INSTANCE           *PrivateData
   );
 
+#pragma pack(1)
+typedef struct {
+  /**
+    These fields are used by PeiTemporaryRamMigration to call the
+    TemporaryRamMigration PPI.
+  **/
+  TEMPORARY_RAM_MIGRATION       TemporaryRamMigration;
+  CONST EFI_PEI_SERVICES        **PeiServices;
+  EFI_PHYSICAL_ADDRESS          TemporaryMemoryBase;
+  EFI_PHYSICAL_ADDRESS          PermanentMemoryBase;
+  UINTN                         CopySize;
+
+  /**
+    These fields are used by PeiTemporaryRamMigrated.
+  **/
+  PEI_CORE_INSTANCE             *Private;
+  CONST EFI_SEC_PEI_HAND_OFF    *SecCoreData;
+} PEI_CORE_TEMPORARY_RAM_TRANSITION;
+#pragma pack()
+
+/**
+  To call the TemporaryRamMigration PPI, we might not be able to rely
+  on C code's handling of the stack. In these cases we use an assembly
+  function to make sure the old stack is not used after the
+  TemporaryRamMigration PPI is used.
+
+  After calling the TemporaryRamMigration PPI, this function calls
+  PeiTemporaryRamMigrated.
+
+  @param TempRamTransitionData
+**/
+VOID
+EFIAPI
+PeiTemporaryRamMigration (
+  IN  PEI_CORE_TEMPORARY_RAM_TRANSITION  *TempRamTransitionData
+  );
+
+/**
+  After PeiTemporaryRamMigration has called the TemporaryRamMigration
+  PPI, it will call this C based function to allow PEI to continue
+  after the migration using the new stack in the migrated RAM.
+
+  @param CallbackContext   Pointer to PEI_CORE_TEMPORARY_RAM_TRANSITION
+                           data.
+**/
+VOID
+EFIAPI
+PeiTemporaryRamMigrated (
+  IN  VOID  *CallbackContext
+  );
+
+
 #endif
diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf 
b/MdeModulePkg/Core/Pei/PeiMain.inf
index 5bab2aab8c..94b26b3572 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.inf
+++ b/MdeModulePkg/Core/Pei/PeiMain.inf
@@ -45,6 +45,7 @@
   FwVol/FwVol.c
   FwVol/FwVol.h
   Dispatcher/Dispatcher.c
+  Dispatcher/TemporaryRamMigration.c
   Dependency/Dependency.c
   Dependency/Dependency.h
   BootMode/BootMode.c
-- 
2.20.0.rc1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to