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