2 * Main file supporting the SEC Phase for Versatile Express
4 * Copyright (c) 2011, ARM Limited. All rights reserved.
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
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.
16 #include <Library/DebugLib.h>
17 #include <Library/PcdLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/ArmLib.h>
21 #include <Chipset/ArmV7.h>
22 #include <Drivers/PL390Gic.h>
23 #include <Library/L2X0CacheLib.h>
24 #include <Library/SerialPortLib.h>
25 #include <Library/ArmPlatformLib.h>
27 extern VOID
*monitor_vector_table
;
29 VOID
ArmSetupGicNonSecure (
30 IN INTN GicDistributorBase
,
31 IN INTN GicInterruptInterfaceBase
34 // Vector Table for Sec Phase
35 VOID
SecVectorTable (VOID
);
37 VOID
NonSecureWaitForFirmware (
47 return_from_exception (
48 IN UINTN NonSecureBase
61 // Primary CPU clears out the SCU tag RAMs, secondaries wait
63 if (FixedPcdGet32(PcdMPCoreSupport
)) {
67 // SEC phase needs to run library constructors by hand. This assumes we are linked against the SerialLib
68 // In non SEC modules the init call is in autogenerated code.
69 SerialPortInitialize ();
71 DEBUG ((EFI_D_ERROR
, "UART Enabled\n"));
73 // Now we've got UART, make the check:
74 // - The Vector table must be 32-byte aligned
75 ASSERT(((UINT32
)SecVectorTable
& ((1 << 5)-1)) == 0);
78 // Invalidate the data cache. Doesn't have to do the Data cache clean.
79 ArmInvalidateDataCache();
81 //Invalidate Instruction Cache
82 ArmInvalidateInstructionCache();
84 //Invalidate I & D TLBs
85 ArmInvalidateInstructionAndDataTlb();
87 // Enable Full Access to CoProcessors
88 ArmWriteCPACR (CPACR_CP_FULL_ACCESS
);
90 // Enable SWP instructions
91 ArmEnableSWPInstruction();
93 // Enable program flow prediction, if supported.
94 ArmEnableBranchPrediction();
96 if (FixedPcdGet32(PcdVFPEnabled
)) {
101 // Initialize L2X0 but not enabled
102 L2x0CacheInit(PcdGet32(PcdL2x0ControllerBase
), FALSE
);
104 // If we skip the PEI Core we could want to initialize the DRAM in the SEC phase.
105 // If we are in standalone, we need the initialization to copy the UEFI firmware into DRAM
106 if (FeaturePcdGet(PcdSkipPeiCore
) || !FeaturePcdGet(PcdStandalone
)) {
107 // Initialize system memory (DRAM)
108 ArmPlatformInitializeSystemMemory();
111 // Turn Off NOR flash remapping to 0. We can will now see DRAM in low memory
112 ArmPlatformBootRemapping();
115 // Test if Trustzone is supported on this platform
116 if (ArmPlatformTrustzoneSupported()) {
117 if (FixedPcdGet32(PcdMPCoreSupport
)) {
118 // Setup SMP in Non Secure world
119 ArmSetupSmpNonSecure(CoreId
);
122 // Enter Monitor Mode
123 enter_monitor_mode((VOID
*)(PcdGet32(PcdCPUCoresSecMonStackBase
) + (PcdGet32(PcdCPUCoreSecMonStackSize
) * CoreId
)));
125 //Write the monitor mode vector table address
126 ArmWriteVMBar((UINT32
) &monitor_vector_table
);
128 //-------------------- Monitor Mode ---------------------
129 // setup the Trustzone Chipsets
131 ArmPlatformTrustzoneInit();
133 // Wake up the secondary cores by sending a interrupt to everyone else
134 // NOTE 1: The Software Generated Interrupts are always enabled on Cortex-A9
135 // MPcore test chip on Versatile Express board, So the Software doesn't have to
136 // enable SGI's explicitly.
137 // 2: As no other Interrupts are enabled, doesn't have to worry about the priority.
138 // 3: As all the cores are in secure state, use secure SGI's
141 PL390GicEnableDistributor (PcdGet32(PcdGicDistributorBase
));
142 PL390GicEnableInterruptInterface(PcdGet32(PcdGicInterruptInterfaceBase
));
144 // Send SGI to all Secondary core to wake them up from WFI state.
145 PL390GicSendSgiTo (PcdGet32(PcdGicDistributorBase
), GIC_ICDSGIR_FILTER_EVERYONEELSE
, 0x0E);
147 // The secondary cores need to wait until the Trustzone chipsets configuration is done
148 // before swtching to Non Secure World
150 // Enabled GIC CPU Interface
151 PL390GicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase
));
153 // Waiting for the SGI from the primary core
156 //Acknowledge the interrupt and send End of Interrupt signal.
157 PL390GicAcknowledgeSgiFrom(PcdGet32(PcdGicInterruptInterfaceBase
),0/*CoreId*/);
160 // Transfer the interrupt to Non-secure World
161 PL390GicSetupNonSecure(PcdGet32(PcdGicDistributorBase
),PcdGet32(PcdGicInterruptInterfaceBase
));
163 // Write to CP15 Non-secure Access Control Register :
164 // - Enable CP10 and CP11 accesses in NS World
165 // - Enable Access to Preload Engine in NS World
166 // - Enable lockable TLB entries allocation in NS world
167 // - Enable R/W access to SMP bit of Auxiliary Control Register in NS world
168 ArmWriteNsacr(NSACR_NS_SMP
| NSACR_TL
| NSACR_PLE
| NSACR_CP(10) | NSACR_CP(11));
170 // CP15 Secure Configuration Register with Non Secure bit (SCR_NS), CPSR.A modified in any
171 // security state (SCR_AW), CPSR.F modified in any security state (SCR_FW)
172 ArmWriteScr(SCR_NS
| SCR_FW
| SCR_AW
);
175 DEBUG ((EFI_D_ERROR
, "Trust Zone Configuration is disabled\n"));
178 //Trustzone is not enabled, just enable the Distributor and CPU interface
179 PL390GicEnableInterruptInterface(PcdGet32(PcdGicInterruptInterfaceBase
));
181 // With Trustzone support the transition from Sec to Normal world is done by return_from_exception().
182 // If we want to keep this function call we need to ensure the SVC's SPSR point to the same Program
183 // Status Register as the the current one (CPSR).
184 copy_cpsr_into_spsr();
187 // If ArmVe has not been built as Standalone then we need to patch the DRAM to add an infinite loop at the start address
188 if (FeaturePcdGet(PcdStandalone
) == FALSE
) {
190 UINTN
* StartAddress
= (UINTN
*)PcdGet32(PcdEmbeddedFdBaseAddress
);
192 DEBUG ((EFI_D_ERROR
, "Waiting for firmware at 0x%08X ...\n",StartAddress
));
194 // Patch the DRAM to make an infinite loop at the start address
195 *StartAddress
= 0xEAFFFFFE; // opcode for while(1)
197 // To enter into Non Secure state, we need to make a return from exception
198 return_from_exception(PcdGet32(PcdEmbeddedFdBaseAddress
));
200 // When the primary core is stopped by the hardware debugger to copy the firmware
201 // into DRAM. The secondary cores are still running. As soon as the first bytes of
202 // the firmware are written into DRAM, the secondary cores will start to execute the
203 // code even if the firmware is not entirely written into the memory.
204 // That's why the secondary cores need to be parked in WFI and wake up once the
205 // firmware is ready.
207 // Enter Secondary Cores into non Secure State. To enter into Non Secure state, we need to make a return from exception
208 return_from_exception((UINTN
)NonSecureWaitForFirmware
);
212 DEBUG ((EFI_D_ERROR
, "Standalone Firmware\n"));
215 // To enter into Non Secure state, we need to make a return from exception
216 return_from_exception(PcdGet32(PcdEmbeddedFdBaseAddress
));
218 //-------------------- Non Secure Mode ---------------------
220 // PEI Core should always load and never return
224 // When the firmware is built as not Standalone, the secondary cores need to wait the firmware
225 // entirely written into DRAM. It is the firmware from DRAM which will wake up the secondary cores.
226 VOID
NonSecureWaitForFirmware() {
227 VOID (*secondary_start
)(VOID
);
229 // The secondary cores will execute the fimrware once wake from WFI.
230 secondary_start
= (VOID (*)())PcdGet32(PcdEmbeddedFdBaseAddress
);
234 //Acknowledge the interrupt and send End of Interrupt signal.
235 PL390GicAcknowledgeSgiFrom(PcdGet32(PcdGicInterruptInterfaceBase
),0/*CoreId*/);
237 //Jump to secondary core entry point.
240 // PEI Core should always load and never return
244 VOID
SecCommonExceptionEntry(UINT32 Entry
, UINT32 LR
) {
247 DEBUG((EFI_D_ERROR
,"Reset Exception at 0x%X\n",LR
));
250 DEBUG((EFI_D_ERROR
,"Undefined Exception at 0x%X\n",LR
));
253 DEBUG((EFI_D_ERROR
,"SWI Exception at 0x%X\n",LR
));
256 DEBUG((EFI_D_ERROR
,"PrefetchAbort Exception at 0x%X\n",LR
));
259 DEBUG((EFI_D_ERROR
,"DataAbort Exception at 0x%X\n",LR
));
262 DEBUG((EFI_D_ERROR
,"Reserved Exception at 0x%X\n",LR
));
265 DEBUG((EFI_D_ERROR
,"IRQ Exception at 0x%X\n",LR
));
268 DEBUG((EFI_D_ERROR
,"FIQ Exception at 0x%X\n",LR
));
271 DEBUG((EFI_D_ERROR
,"Unknown Exception at 0x%X\n",LR
));