diff --git a/ArmPlatformPkg/Include/Library/ArmPlatformSecLib.h b/ArmPlatformPkg/Include/Library/ArmPlatformSecLib.h index 477fd7d99f..32f1eb5088 100644 --- a/ArmPlatformPkg/Include/Library/ArmPlatformSecLib.h +++ b/ArmPlatformPkg/Include/Library/ArmPlatformSecLib.h @@ -15,6 +15,10 @@ #ifndef _ARMPLATFORMSECLIB_H_ #define _ARMPLATFORMSECLIB_H_ +#define ARM_SEC_BOOT_MASK ~0 +#define ARM_SEC_COLD_BOOT (1 << 0) +#define ARM_SEC_SECONDARY_COLD_BOOT (1 << 1) + /** Initialize the memory where the initial stacks will reside diff --git a/ArmPlatformPkg/Sec/Helper.S b/ArmPlatformPkg/Sec/Helper.S index 8bdb66ab87..4eede5faba 100644 --- a/ArmPlatformPkg/Sec/Helper.S +++ b/ArmPlatformPkg/Sec/Helper.S @@ -22,17 +22,18 @@ GCC_ASM_EXPORT(set_non_secure_mode) # r0: Monitor World EntryPoint # r1: MpId -# r2: Secure Monitor mode stack +# r2: SecBootMode +# r3: Secure Monitor mode stack ASM_PFX(enter_monitor_mode): - cmp r2, #0 @ If a Secure Monitor stack base has not been defined then use the Secure stack - moveq r2, sp + cmp r3, #0 @ If a Secure Monitor stack base has not been defined then use the Secure stack + moveq r3, sp mrs r4, cpsr @ Save current mode (SVC) in r4 - bic r3, r4, #0x1f @ Clear all mode bits - orr r3, r3, #0x16 @ Set bits for Monitor mode - msr cpsr_cxsf, r3 @ We are now in Monitor Mode + bic r5, r4, #0x1f @ Clear all mode bits + orr r5, r5, #0x16 @ Set bits for Monitor mode + msr cpsr_cxsf, r5 @ We are now in Monitor Mode - mov sp, r2 @ Set the stack of the Monitor Mode + mov sp, r3 @ Set the stack of the Monitor Mode mov lr, r0 @ Use the pass entrypoint as lr @@ -40,6 +41,8 @@ ASM_PFX(enter_monitor_mode): mov r4, r0 @ Swap EntryPoint and MpId registers mov r0, r1 + mov r1, r2 + mov r2, r3 bx r4 diff --git a/ArmPlatformPkg/Sec/Helper.asm b/ArmPlatformPkg/Sec/Helper.asm index a03a90626e..b31cc31a97 100644 --- a/ArmPlatformPkg/Sec/Helper.asm +++ b/ArmPlatformPkg/Sec/Helper.asm @@ -20,17 +20,18 @@ // r0: Monitor World EntryPoint // r1: MpId -// r2: Secure Monitor mode stack -enter_monitor_mode - cmp r2, #0 // If a Secure Monitor stack base has not been defined then use the Secure stack - moveq r2, sp +// r2: SecBootMode +// r3: Secure Monitor mode stack +enter_monitor_mode FUNCTION + cmp r3, #0 // If a Secure Monitor stack base has not been defined then use the Secure stack + moveq r3, sp mrs r4, cpsr // Save current mode (SVC) in r4 - bic r3, r4, #0x1f // Clear all mode bits - orr r3, r3, #0x16 // Set bits for Monitor mode - msr cpsr_cxsf, r3 // We are now in Monitor Mode + bic r5, r4, #0x1f // Clear all mode bits + orr r5, r5, #0x16 // Set bits for Monitor mode + msr cpsr_cxsf, r5 // We are now in Monitor Mode - mov sp, r2 // Set the stack of the Monitor Mode + mov sp, r3 // Set the stack of the Monitor Mode mov lr, r0 // Use the pass entrypoint as lr @@ -38,8 +39,11 @@ enter_monitor_mode mov r4, r0 // Swap EntryPoint and MpId registers mov r0, r1 + mov r1, r2 + mov r2, r3 bx r4 + ENDFUNC // We cannot use the instruction 'movs pc, lr' because the caller can be written either in ARM or Thumb2 assembler. // When we will jump into this function, we will set the CPSR flag to ARM assembler. By copying directly 'lr' into diff --git a/ArmPlatformPkg/Sec/Sec.c b/ArmPlatformPkg/Sec/Sec.c index f9746ad891..6734653c3e 100644 --- a/ArmPlatformPkg/Sec/Sec.c +++ b/ArmPlatformPkg/Sec/Sec.c @@ -26,7 +26,8 @@ VOID CEntryPoint ( - IN UINTN MpId + IN UINTN MpId, + IN UINTN SecBootMode ) { CHAR8 Buffer[100]; @@ -109,7 +110,7 @@ CEntryPoint ( ((PcdGet32(PcdCPUCoresSecMonStackBase) != 0) && (PcdGet32(PcdCPUCoreSecMonStackSize) != 0))); // Enter Monitor Mode - enter_monitor_mode ((UINTN)TrustedWorldInitialization, MpId, (VOID*)(PcdGet32(PcdCPUCoresSecMonStackBase) + (PcdGet32(PcdCPUCoreSecMonStackSize) * (GET_CORE_POS(MpId) + 1)))); + enter_monitor_mode ((UINTN)TrustedWorldInitialization, MpId, SecBootMode, (VOID*)(PcdGet32(PcdCPUCoresSecMonStackBase) + (PcdGet32(PcdCPUCoreSecMonStackSize) * (GET_CORE_POS(MpId) + 1)))); } else { if (IS_PRIMARY_CORE(MpId)) { SerialPrint ("Trust Zone Configuration is disabled\n\r"); @@ -131,7 +132,8 @@ CEntryPoint ( VOID TrustedWorldInitialization ( - IN UINTN MpId + IN UINTN MpId, + IN UINTN SecBootMode ) { UINTN JumpAddress; @@ -153,7 +155,7 @@ TrustedWorldInitialization ( // Signal the secondary core the Security settings is done (event: EVENT_SECURE_INIT) ArmCallSEV (); } - } else { + } else if ((SecBootMode & ARM_SEC_BOOT_MASK) == ARM_SEC_COLD_BOOT) { // The secondary cores need to wait until the Trustzone chipsets configuration is done // before switching to Non Secure World diff --git a/ArmPlatformPkg/Sec/SecEntryPoint.S b/ArmPlatformPkg/Sec/SecEntryPoint.S index 8266dad977..ed7448af21 100644 --- a/ArmPlatformPkg/Sec/SecEntryPoint.S +++ b/ArmPlatformPkg/Sec/SecEntryPoint.S @@ -38,6 +38,9 @@ ASM_PFX(_ModuleEntryPoint): // Ensure that the MMU and caches are off bl ASM_PFX(ArmDisableCachesAndMmu) + // By default, we are doing a cold boot + mov r10, #ARM_SEC_COLD_BOOT + // Jump to Platform Specific Boot Action function blx ASM_PFX(ArmPlatformSecBootAction) @@ -59,6 +62,11 @@ _IdentifyCpu: beq _InitMem _WaitInitMem: + // If we are not doing a cold boot in this case we should assume the Initial Memory to be already initialized + // Otherwise we have to wait the Primary Core to finish the initialization + cmp r10, #ARM_SEC_COLD_BOOT + bne _SetupSecondaryCoreStack + // Wait for the primary core to initialize the initial memory (event: BOOT_MEM_INIT) bl ASM_PFX(ArmCallWFE) // Now the Init Mem is initialized, we setup the secondary core stacks @@ -108,7 +116,9 @@ _PrepareArguments: // Jump to SEC C code // r0 = mp_id + // r1 = Boot Mode mov r0, r5 + mov r1, r10 blx r3 _NeverReturn: diff --git a/ArmPlatformPkg/Sec/SecEntryPoint.asm b/ArmPlatformPkg/Sec/SecEntryPoint.asm index a20a3fd9f6..30cf19245c 100644 --- a/ArmPlatformPkg/Sec/SecEntryPoint.asm +++ b/ArmPlatformPkg/Sec/SecEntryPoint.asm @@ -33,13 +33,16 @@ StartupAddr DCD CEntryPoint -_ModuleEntryPoint +_ModuleEntryPoint FUNCTION // First ensure all interrupts are disabled blx ArmDisableInterrupts // Ensure that the MMU and caches are off blx ArmDisableCachesAndMmu + // By default, we are doing a cold boot + mov r10, #ARM_SEC_COLD_BOOT + // Jump to Platform Specific Boot Action function blx ArmPlatformSecBootAction @@ -61,6 +64,11 @@ _IdentifyCpu beq _InitMem _WaitInitMem + // If we are not doing a cold boot in this case we should assume the Initial Memory to be already initialized + // Otherwise we have to wait the Primary Core to finish the initialization + cmp r10, #ARM_SEC_COLD_BOOT + bne _SetupSecondaryCoreStack + // Wait for the primary core to initialize the initial memory (event: BOOT_MEM_INIT) bl ArmCallWFE // Now the Init Mem is initialized, we setup the secondary core stacks @@ -110,8 +118,11 @@ _PrepareArguments // Jump to SEC C code // r0 = mp_id + // r1 = Boot Mode mov r0, r5 + mov r1, r10 blx r3 + ENDFUNC _NeverReturn b _NeverReturn diff --git a/ArmPlatformPkg/Sec/SecInternal.h b/ArmPlatformPkg/Sec/SecInternal.h index 0d6daf993a..34a6feab1e 100644 --- a/ArmPlatformPkg/Sec/SecInternal.h +++ b/ArmPlatformPkg/Sec/SecInternal.h @@ -28,7 +28,8 @@ VOID TrustedWorldInitialization ( - IN UINTN MpId + IN UINTN MpId, + IN UINTN SecBootMode ); VOID @@ -53,7 +54,8 @@ VOID enter_monitor_mode ( IN UINTN MonitorEntryPoint, IN UINTN MpId, - IN VOID* Stack + IN UINTN SecBootMode, + IN VOID* MonitorStackBase ); VOID