1 /** @file 2 * Main file supporting the SEC Phase on ARM Platforms 3 * 4 * Copyright (c) 2011-2014, ARM Limited. All rights reserved. 5 * 6 * This program and the accompanying materials 7 * are licensed and made available under the terms and conditions of the BSD License 8 * which accompanies this distribution. The full text of the license may be found at 9 * http://opensource.org/licenses/bsd-license.php 10 * 11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 * 14 **/ 15 16 #include <Library/ArmTrustedMonitorLib.h> 17 #include <Library/DebugAgentLib.h> 18 #include <Library/PrintLib.h> 19 #include <Library/BaseMemoryLib.h> 20 #include <Library/SerialPortLib.h> 21 #include <Library/ArmGicLib.h> 22 #include <Library/ArmPlatformLib.h> 23 24 #include "SecInternal.h" 25 26 #define SerialPrint(txt) SerialPortWrite ((UINT8*)txt, AsciiStrLen(txt)+1); 27 28 VOID 29 CEntryPoint ( 30 IN UINTN MpId, 31 IN UINTN SecBootMode 32 ) 33 { 34 CHAR8 Buffer[100]; 35 UINTN CharCount; 36 UINTN JumpAddress; 37 38 // Invalidate the data cache. Doesn't have to do the Data cache clean. 39 ArmInvalidateDataCache (); 40 41 // Invalidate Instruction Cache 42 ArmInvalidateInstructionCache (); 43 44 // Invalidate I & D TLBs 45 ArmInvalidateTlb (); 46 47 // CPU specific settings 48 ArmCpuSetup (MpId); 49 50 // Enable Floating Point Coprocessor if supported by the platform 51 if (FixedPcdGet32 (PcdVFPEnabled)) { 52 ArmEnableVFP (); 53 } 54 55 // Initialize peripherals that must be done at the early stage 56 // Example: Some L2 controller, interconnect, clock, DMC, etc 57 ArmPlatformSecInitialize (MpId); 58 59 // Primary CPU clears out the SCU tag RAMs, secondaries wait 60 if (ArmPlatformIsPrimaryCore (MpId) && (SecBootMode == ARM_SEC_COLD_BOOT)) { 61 if (ArmIsMpCore()) { 62 // Signal for the initial memory is configured (event: BOOT_MEM_INIT) 63 ArmCallSEV (); 64 } 65 66 // SEC phase needs to run library constructors by hand. This assumes we are linked against the SerialLib 67 // In non SEC modules the init call is in autogenerated code. 68 SerialPortInitialize (); 69 70 // Start talking 71 if (FixedPcdGetBool (PcdTrustzoneSupport)) { 72 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Secure firmware (version %s built at %a on %a)\n\r", 73 (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__); 74 } else { 75 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Boot firmware (version %s built at %a on %a)\n\r", 76 (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__); 77 } 78 SerialPortWrite ((UINT8 *) Buffer, CharCount); 79 80 // Initialize the Debug Agent for Source Level Debugging 81 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, NULL, NULL); 82 SaveAndSetDebugTimerInterrupt (TRUE); 83 84 // Enable the GIC distributor and CPU Interface 85 // - no other Interrupts are enabled, doesn't have to worry about the priority. 86 // - all the cores are in secure state, use secure SGI's 87 ArmGicEnableDistributor (PcdGet32(PcdGicDistributorBase)); 88 ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase)); 89 } else { 90 // Enable the GIC CPU Interface 91 ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase)); 92 } 93 94 // Enable Full Access to CoProcessors 95 ArmWriteCpacr (CPACR_CP_FULL_ACCESS); 96 97 // Test if Trustzone is supported on this platform 98 if (FixedPcdGetBool (PcdTrustzoneSupport)) { 99 if (ArmIsMpCore ()) { 100 // Setup SMP in Non Secure world 101 ArmCpuSetupSmpNonSecure (GET_CORE_ID(MpId)); 102 } 103 104 // Either we use the Secure Stacks for Secure Monitor (in this case (Base == 0) && (Size == 0)) 105 // Or we use separate Secure Monitor stacks (but (Base != 0) && (Size != 0)) 106 ASSERT (((PcdGet32(PcdCPUCoresSecMonStackBase) == 0) && (PcdGet32(PcdCPUCoreSecMonStackSize) == 0)) || 107 ((PcdGet32(PcdCPUCoresSecMonStackBase) != 0) && (PcdGet32(PcdCPUCoreSecMonStackSize) != 0))); 108 109 // Enter Monitor Mode 110 enter_monitor_mode ( 111 (UINTN)TrustedWorldInitialization, MpId, SecBootMode, 112 (VOID*) (PcdGet32 (PcdCPUCoresSecMonStackBase) + 113 (PcdGet32 (PcdCPUCoreSecMonStackSize) * (ArmPlatformGetCorePosition (MpId) + 1))) 114 ); 115 } else { 116 if (ArmPlatformIsPrimaryCore (MpId)) { 117 SerialPrint ("Trust Zone Configuration is disabled\n\r"); 118 } 119 120 // With Trustzone support the transition from Sec to Normal world is done by return_from_exception(). 121 // If we want to keep this function call we need to ensure the SVC's SPSR point to the same Program 122 // Status Register as the the current one (CPSR). 123 copy_cpsr_into_spsr (); 124 125 // Call the Platform specific function to execute additional actions if required 126 JumpAddress = PcdGet64 (PcdFvBaseAddress); 127 ArmPlatformSecExtraAction (MpId, &JumpAddress); 128 129 NonTrustedWorldTransition (MpId, JumpAddress); 130 } 131 ASSERT (0); // We must never return from the above function 132 } 133 134 VOID 135 TrustedWorldInitialization ( 136 IN UINTN MpId, 137 IN UINTN SecBootMode 138 ) 139 { 140 UINTN JumpAddress; 141 142 //-------------------- Monitor Mode --------------------- 143 144 // Set up Monitor World (Vector Table, etc) 145 ArmSecureMonitorWorldInitialize (); 146 147 // Transfer the interrupt to Non-secure World 148 ArmGicSetupNonSecure (MpId, PcdGet32(PcdGicDistributorBase), PcdGet32(PcdGicInterruptInterfaceBase)); 149 150 // Initialize platform specific security policy 151 ArmPlatformSecTrustzoneInit (MpId); 152 153 // Setup the Trustzone Chipsets 154 if (SecBootMode == ARM_SEC_COLD_BOOT) { 155 if (ArmPlatformIsPrimaryCore (MpId)) { 156 if (ArmIsMpCore()) { 157 // Signal the secondary core the Security settings is done (event: EVENT_SECURE_INIT) 158 ArmCallSEV (); 159 } 160 } else { 161 // The secondary cores need to wait until the Trustzone chipsets configuration is done 162 // before switching to Non Secure World 163 164 // Wait for the Primary Core to finish the initialization of the Secure World (event: EVENT_SECURE_INIT) 165 ArmCallWFE (); 166 } 167 } 168 169 // Call the Platform specific function to execute additional actions if required 170 JumpAddress = PcdGet64 (PcdFvBaseAddress); 171 ArmPlatformSecExtraAction (MpId, &JumpAddress); 172 173 // Initialize architecture specific security policy 174 ArmSecArchTrustzoneInit (); 175 176 // CP15 Secure Configuration Register 177 ArmWriteScr (PcdGet32 (PcdArmScr)); 178 179 NonTrustedWorldTransition (MpId, JumpAddress); 180 } 181 182 VOID 183 NonTrustedWorldTransition ( 184 IN UINTN MpId, 185 IN UINTN JumpAddress 186 ) 187 { 188 // If PcdArmNonSecModeTransition is defined then set this specific mode to CPSR before the transition 189 // By not set, the mode for Non Secure World is SVC 190 if (PcdGet32 (PcdArmNonSecModeTransition) != 0) { 191 set_non_secure_mode ((ARM_PROCESSOR_MODE)PcdGet32 (PcdArmNonSecModeTransition)); 192 } 193 194 return_from_exception (JumpAddress); 195 //-------------------- Non Secure Mode --------------------- 196 197 // PEI Core should always load and never return 198 ASSERT (FALSE); 199 } 200 201