--- /dev/null
+//\r
+// Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
+//\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 <AsmMacroIoLibV8.h>\r
+#include <Base.h>\r
+#include <Library/PcdLib.h>\r
+#include <AutoGen.h>\r
+\r
+.text\r
+.align 3\r
+\r
+GCC_ASM_IMPORT(CEntryPoint)\r
+GCC_ASM_IMPORT(ArmPlatformGetCorePosition)\r
+GCC_ASM_IMPORT(ArmPlatformIsPrimaryCore)\r
+GCC_ASM_IMPORT(ArmReadMpidr)\r
+GCC_ASM_IMPORT(ArmPlatformPeiBootAction)\r
+GCC_ASM_EXPORT(_ModuleEntryPoint)\r
+\r
+StartupAddr: .dword CEntryPoint\r
+\r
+ASM_PFX(_ModuleEntryPoint):\r
+ // Do early platform specific actions\r
+ bl ASM_PFX(ArmPlatformPeiBootAction)\r
+\r
+// NOTE: We could be booting from EL3, EL2 or EL1. Need to correctly detect\r
+// and configure the system accordingly. EL2 is default if possible.\r
+// If we started in EL3 we need to switch and run at EL2.\r
+// If we are running at EL2 stay in EL2\r
+// If we are starting at EL1 stay in EL1.\r
+\r
+// If started at EL3 Sec is run and switches to EL2 before jumping to PEI.\r
+// If started at EL1 or EL2 Sec jumps directly to PEI without making any\r
+// changes.\r
+\r
+// Which EL are we running at? Every EL needs some level of setup...\r
+ EL1_OR_EL2_OR_EL3(x0)\r
+1:bl ASM_PFX(SetupExceptionLevel1)\r
+ b ASM_PFX(MainEntryPoint)\r
+2:bl ASM_PFX(SetupExceptionLevel2)\r
+ b ASM_PFX(MainEntryPoint)\r
+3:// If we are at EL3 we die.\r
+ b dead\r
+\r
+ASM_PFX(MainEntryPoint):\r
+ // Identify CPU ID\r
+ bl ASM_PFX(ArmReadMpidr)\r
+ // Keep a copy of the MpId register value\r
+ mov x5, x0\r
+\r
+ // Is it the Primary Core ?\r
+ bl ASM_PFX(ArmPlatformIsPrimaryCore)\r
+\r
+ // Get the top of the primary stacks (and the base of the secondary stacks)\r
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoresStackBase), x1)\r
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), x2)\r
+ add x1, x1, x2\r
+\r
+ // x0 is equal to 1 if I am the primary core\r
+ cmp x0, #1\r
+ b.eq _SetupPrimaryCoreStack\r
+\r
+_SetupSecondaryCoreStack:\r
+ // x1 contains the base of the secondary stacks\r
+\r
+ // Get the Core Position\r
+ mov x6, x1 // Save base of the secondary stacks\r
+ mov x0, x5\r
+ bl ASM_PFX(ArmPlatformGetCorePosition)\r
+ // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack\r
+ add x0, x0, #1\r
+\r
+ // StackOffset = CorePos * StackSize\r
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), x2)\r
+ mul x0, x0, x2\r
+ // SP = StackBase + StackOffset\r
+ add sp, x6, x0\r
+\r
+_PrepareArguments:\r
+ // The PEI Core Entry Point has been computed by GenFV and stored in the second entry of the Reset Vector\r
+ LoadConstantToReg (FixedPcdGet64(PcdFvBaseAddress), x2)\r
+ add x2, x2, #8\r
+ ldr x1, [x2]\r
+\r
+ // Move sec startup address into a data register\r
+ // Ensure we're jumping to FV version of the code (not boot remapped alias)\r
+ ldr x3, StartupAddr\r
+\r
+ // Jump to PrePeiCore C code\r
+ // x0 = mp_id\r
+ // x1 = pei_core_address\r
+ mov x0, x5\r
+ blr x3\r
+\r
+_SetupPrimaryCoreStack:\r
+ // x1 contains the top of the primary stack\r
+ LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), x2)\r
+\r
+ // The reserved space for global variable must be 16-bytes aligned for pushing\r
+ // 128-bit variable on the stack\r
+ SetPrimaryStack (x1, x2, x3, x4)\r
+ b _PrepareArguments\r
+\r
+dead:\r
+ b dead\r