2 * Main file supporting the SEC Phase on ARM Platforms
4 * Copyright (c) 2011-2014, 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/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>
24 #include "SecInternal.h"
26 #define SerialPrint(txt) SerialPortWrite ((UINT8*)txt, AsciiStrLen(txt)+1);
38 // Invalidate the data cache. Doesn't have to do the Data cache clean.
39 ArmInvalidateDataCache ();
41 // Invalidate Instruction Cache
42 ArmInvalidateInstructionCache ();
44 // Invalidate I & D TLBs
47 // CPU specific settings
50 // Enable Floating Point Coprocessor if supported by the platform
51 if (FixedPcdGet32 (PcdVFPEnabled
)) {
55 // Initialize peripherals that must be done at the early stage
56 // Example: Some L2 controller, interconnect, clock, DMC, etc
57 ArmPlatformSecInitialize (MpId
);
59 // Primary CPU clears out the SCU tag RAMs, secondaries wait
60 if (ArmPlatformIsPrimaryCore (MpId
) && (SecBootMode
== ARM_SEC_COLD_BOOT
)) {
62 // Signal for the initial memory is configured (event: BOOT_MEM_INIT)
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 ();
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__
);
75 CharCount
= AsciiSPrint (Buffer
,sizeof (Buffer
),"Boot firmware (version %s built at %a on %a)\n\r",
76 (CHAR16
*)PcdGetPtr(PcdFirmwareVersionString
), __TIME__
, __DATE__
);
78 SerialPortWrite ((UINT8
*) Buffer
, CharCount
);
80 // Initialize the Debug Agent for Source Level Debugging
81 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC
, NULL
, NULL
);
82 SaveAndSetDebugTimerInterrupt (TRUE
);
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
));
90 // Enable the GIC CPU Interface
91 ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase
));
94 // Enable Full Access to CoProcessors
95 ArmWriteCpacr (CPACR_CP_FULL_ACCESS
);
97 // Test if Trustzone is supported on this platform
98 if (FixedPcdGetBool (PcdTrustzoneSupport
)) {
100 // Setup SMP in Non Secure world
101 ArmCpuSetupSmpNonSecure (GET_CORE_ID(MpId
));
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)));
109 // Enter Monitor Mode
111 (UINTN
)TrustedWorldInitialization
, MpId
, SecBootMode
,
112 (VOID
*) (PcdGet32 (PcdCPUCoresSecMonStackBase
) +
113 (PcdGet32 (PcdCPUCoreSecMonStackSize
) * (ArmPlatformGetCorePosition (MpId
) + 1)))
116 if (ArmPlatformIsPrimaryCore (MpId
)) {
117 SerialPrint ("Trust Zone Configuration is disabled\n\r");
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 ();
125 // Call the Platform specific function to execute additional actions if required
126 JumpAddress
= PcdGet64 (PcdFvBaseAddress
);
127 ArmPlatformSecExtraAction (MpId
, &JumpAddress
);
129 NonTrustedWorldTransition (MpId
, JumpAddress
);
131 ASSERT (0); // We must never return from the above function
135 TrustedWorldInitialization (
142 //-------------------- Monitor Mode ---------------------
144 // Set up Monitor World (Vector Table, etc)
145 ArmSecureMonitorWorldInitialize ();
147 // Transfer the interrupt to Non-secure World
148 ArmGicSetupNonSecure (MpId
, PcdGet32(PcdGicDistributorBase
), PcdGet32(PcdGicInterruptInterfaceBase
));
150 // Initialize platform specific security policy
151 ArmPlatformSecTrustzoneInit (MpId
);
153 // Setup the Trustzone Chipsets
154 if (SecBootMode
== ARM_SEC_COLD_BOOT
) {
155 if (ArmPlatformIsPrimaryCore (MpId
)) {
157 // Signal the secondary core the Security settings is done (event: EVENT_SECURE_INIT)
161 // The secondary cores need to wait until the Trustzone chipsets configuration is done
162 // before switching to Non Secure World
164 // Wait for the Primary Core to finish the initialization of the Secure World (event: EVENT_SECURE_INIT)
169 // Call the Platform specific function to execute additional actions if required
170 JumpAddress
= PcdGet64 (PcdFvBaseAddress
);
171 ArmPlatformSecExtraAction (MpId
, &JumpAddress
);
173 // Initialize architecture specific security policy
174 ArmSecArchTrustzoneInit ();
176 // CP15 Secure Configuration Register
177 ArmWriteScr (PcdGet32 (PcdArmScr
));
179 NonTrustedWorldTransition (MpId
, JumpAddress
);
183 NonTrustedWorldTransition (
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
));
194 return_from_exception (JumpAddress
);
195 //-------------------- Non Secure Mode ---------------------
197 // PEI Core should always load and never return