/** Call before jumping to Normal World This function allows the firmware platform to do extra actions before jumping to the Normal World **/ VOID ArmPlatformSecExtraAction ( IN UINTN MpId, OUT UINTN* JumpAddress ) { CHAR8 Buffer[100]; UINTN CharCount; if (FeaturePcdGet (PcdStandalone) == FALSE) { // // Warning: This code assumes the DRAM has already been initialized by ArmPlatformSecLib // if (IS_PRIMARY_CORE(MpId)) { UINTN* StartAddress = (UINTN*)PcdGet32(PcdFvBaseAddress); // Patch the DRAM to make an infinite loop at the start address *StartAddress = 0xEAFFFFFE; // opcode for while(1) CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Waiting for firmware at 0x%08X ...\n\r",StartAddress); SerialPortWrite ((UINT8 *) Buffer, CharCount); *JumpAddress = PcdGet32(PcdFvBaseAddress); } else { // When the primary core is stopped by the hardware debugger to copy the firmware // into DRAM. The secondary cores are still running. As soon as the first bytes of // the firmware are written into DRAM, the secondary cores will start to execute the // code even if the firmware is not entirely written into the memory. // That's why the secondary cores need to be parked in WFI and wake up once the // firmware is ready. *JumpAddress = (UINTN)NonSecureWaitForFirmware; } } else if (FeaturePcdGet (PcdSystemMemoryInitializeInSec)) { // // Warning: This code assumes the DRAM has already been initialized by ArmPlatformSecLib // if (IS_PRIMARY_CORE(MpId)) { // Signal the secondary cores they can jump to PEI phase ArmGicSendSgiTo (PcdGet32(PcdGicDistributorBase), ARM_GIC_ICDSGIR_FILTER_EVERYONEELSE, 0x0E, PcdGet32 (PcdGicSgiIntId)); // To enter into Non Secure state, we need to make a return from exception *JumpAddress = PcdGet32(PcdFvBaseAddress); } else { // We wait for the primary core to finish to initialize the System Memory. Otherwise the secondary // cores would make crash the system by setting their stacks in DRAM before the primary core has not // finished to initialize the system memory. *JumpAddress = (UINTN)NonSecureWaitForFirmware; } } else { *JumpAddress = PcdGet32(PcdFvBaseAddress); } }
/** Initialize the Secure peripherals and memory regions If Trustzone is supported by your platform then this function makes the required initialization of the secure peripherals and memory regions. **/ VOID ArmPlatformSecTrustzoneInit ( IN UINTN MpId ) { // Secondary cores might have to set the Secure SGIs into the GICD_IGROUPR0 if (!IS_PRIMARY_CORE(MpId)) { return; } ASSERT(FALSE); }
/** Initialize controllers that must setup in the normal world This function is called by the ArmPlatformPkg/Pei or ArmPlatformPkg/Pei/PlatformPeim in the PEI phase. **/ RETURN_STATUS ArmPlatformInitialize ( IN UINTN MpId ) { if (!IS_PRIMARY_CORE(MpId)) { return RETURN_SUCCESS; } // Nothing to do here return RETURN_SUCCESS; }
/** Initialize controllers that must setup at the early stage Some peripherals must be initialized in Secure World. For example, some L2x0 requires to be initialized in Secure World **/ RETURN_STATUS ArmPlatformSecInitialize ( IN UINTN MpId ) { // If it is not the primary core then there is nothing to do if (!IS_PRIMARY_CORE(MpId)) { return RETURN_SUCCESS; } // Do nothing yet return RETURN_SUCCESS; }
/** Initialize controllers that must setup in the normal world This function is called by the ArmPlatformPkg/Pei or ArmPlatformPkg/Pei/PlatformPeim in the PEI phase. **/ RETURN_STATUS ArmPlatformInitialize ( IN UINTN MpId ) { if (!IS_PRIMARY_CORE(MpId)) { return RETURN_SUCCESS; } // Disable memory remapping and return to normal mapping MmioOr32 (SP810_CTRL_BASE, BIT8); return RETURN_SUCCESS; }
/* * This function configures the all interrupts to be Non-secure. * */ VOID EFIAPI ArmGicSetupNonSecure ( IN UINTN MpId, IN INTN GicDistributorBase, IN INTN GicInterruptInterfaceBase ) { UINTN InterruptId; UINTN CachedPriorityMask; UINTN Index; CachedPriorityMask = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR); // Set priority Mask so that no interrupts get through to CPU MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0); // Check if there are any pending interrupts //TODO: could be extended to take Peripheral interrupts into consideration, but at the moment only SGI's are taken into consideration. while(0 != (MmioRead32 (GicDistributorBase + ARM_GIC_ICDICPR) & 0xF)) { // Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR); // Write to End of interrupt signal MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, InterruptId); } // Only the primary core should set the Non Secure bit to the SPIs (Shared Peripheral Interrupt). if (IS_PRIMARY_CORE(MpId)) { // Ensure all GIC interrupts are Non-Secure for (Index = 0; Index < (ArmGicGetMaxNumInterrupts (GicDistributorBase) / 32); Index++) { MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), 0xffffffff); } } else { // The secondary cores only set the Non Secure bit to their banked PPIs MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR, 0xffffffff); } // Ensure all interrupts can get through the priority mask MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, CachedPriorityMask); }