--- /dev/null
+/** @file\r
+ Switch Stack functions.\r
+\r
+ Copyright (c) 2006 - 2007, Intel Corporation<BR>\r
+ All rights reserved. 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
+//\r
+// Include common header file for this module.\r
+//\r
+\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+\r
+/**\r
+ Transfers control to a function starting with a new stack.\r
+\r
+ Transfers control to the function specified by EntryPoint using the new stack\r
+ specified by NewStack and passing in the parameters specified by Context1 and\r
+ Context2. Context1 and Context2 are optional and may be NULL. The function\r
+ EntryPoint must never return.\r
+\r
+ If EntryPoint is NULL, then ASSERT().\r
+ If NewStack is NULL, then ASSERT().\r
+\r
+ @param EntryPoint A pointer to function to call with the new stack.\r
+ @param Context1 A pointer to the context to pass into the EntryPoint\r
+ function.\r
+ @param Context2 A pointer to the context to pass into the EntryPoint\r
+ function.\r
+ @param NewStack A pointer to the new stack to use for the EntryPoint\r
+ function.\r
+ @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's\r
+ Reserved on other architectures.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+PeiSwitchStacks (\r
+ IN SWITCH_STACK_ENTRY_POINT EntryPoint,\r
+ IN VOID *Context1, OPTIONAL\r
+ IN VOID *Context2, OPTIONAL\r
+ IN VOID *Context3, OPTIONAL\r
+ IN VOID *OldTopOfStack,\r
+ IN VOID *NewStack\r
+ )\r
+{\r
+ BASE_LIBRARY_JUMP_BUFFER JumpBuffer;\r
+ \r
+ ASSERT (EntryPoint != NULL);\r
+ ASSERT (NewStack != NULL);\r
+\r
+ //\r
+ // Stack should be aligned with CPU_STACK_ALIGNMENT\r
+ //\r
+ ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0);\r
+\r
+ JumpBuffer.Eip = (UINTN)EntryPoint;\r
+ JumpBuffer.Esp = (UINTN)NewStack - sizeof (VOID*);\r
+ JumpBuffer.Esp -= sizeof (Context1) + sizeof (Context2) + sizeof(Context3);\r
+ ((VOID**)JumpBuffer.Esp)[1] = Context1;\r
+ ((VOID**)JumpBuffer.Esp)[2] = Context2;\r
+ ((VOID**)JumpBuffer.Esp)[3] = Context3;\r
+\r
+ LongJump (&JumpBuffer, (UINTN)-1);\r
+\r
+ //\r
+ // InternalSwitchStack () will never return\r
+ //\r
+ ASSERT (FALSE); \r
+}\r
+\r
+/**\r
+ Transfers control to a function starting with a new stack.\r
+\r
+ Transfers control to the function specified by EntryPoint using the new stack\r
+ specified by NewStack and passing in the parameters specified by Context1 and\r
+ Context2. Context1 and Context2 are optional and may be NULL. The function\r
+ EntryPoint must never return.\r
+\r
+ If EntryPoint is NULL, then ASSERT().\r
+ If NewStack is NULL, then ASSERT().\r
+\r
+ @param EntryPoint A pointer to function to call with the new stack.\r
+ @param Context1 A pointer to the context to pass into the EntryPoint\r
+ function.\r
+ @param Context2 A pointer to the context to pass into the EntryPoint\r
+ function.\r
+ @param NewStack A pointer to the new stack to use for the EntryPoint\r
+ function.\r
+ @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's\r
+ Reserved on other architectures.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SecSwitchStack (\r
+ IN UINTN TemporaryMemoryBase,\r
+ IN UINTN PermanentMemoryBase,\r
+ IN UINTN CopySize\r
+ )\r
+{\r
+ BASE_LIBRARY_JUMP_BUFFER JumpBuffer;\r
+ UINTN SetJumpFlag;\r
+\r
+ ASSERT ((VOID*)TemporaryMemoryBase != NULL);\r
+ ASSERT ((VOID*)PermanentMemoryBase != NULL);\r
+\r
+ SetJumpFlag = SetJump (&JumpBuffer);\r
+ //\r
+ // The initial call to SetJump() must always return 0.\r
+ // Subsequent calls to LongJump() may cause a non-zero value to be returned by SetJump().\r
+ //\r
+ if (SetJumpFlag == 0) {\r
+ DEBUG ((EFI_D_ERROR, "SecSwitchStack+%d: Esp: 0x%xL\n", __LINE__, JumpBuffer.Esp));\r
+ JumpBuffer.Esp =\r
+ (INTN)JumpBuffer.Esp -\r
+ (INTN)TemporaryMemoryBase +\r
+ (INTN)PermanentMemoryBase;\r
+ MemoryFence ();\r
+ CopyMem((VOID*)PermanentMemoryBase, (VOID*)TemporaryMemoryBase, CopySize);\r
+ LongJump (&JumpBuffer, (UINTN)-1);\r
+ }\r
+\r
+}\r
+\r