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