]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/PrePi/PrePi.c
ArmPlatformPkg/PrePi: Declared the ARM MP Core Info
[mirror_edk2.git] / ArmPlatformPkg / PrePi / PrePi.c
1 /** @file
2 *
3 * Copyright (c) 2011-2012, ARM Limited. All rights reserved.
4 *
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
9 *
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 *
13 **/
14
15 #include <PiPei.h>
16
17 #include <Library/DebugAgentLib.h>
18 #include <Library/PrePiLib.h>
19 #include <Library/PrintLib.h>
20 #include <Library/PeCoffGetEntryPointLib.h>
21 #include <Library/PrePiHobListPointerLib.h>
22 #include <Library/TimerLib.h>
23 #include <Library/PerformanceLib.h>
24
25 #include <Ppi/GuidedSectionExtraction.h>
26 #include <Ppi/ArmMpCoreInfo.h>
27 #include <Guid/LzmaDecompress.h>
28 #include <Guid/ArmGlobalVariableHob.h>
29
30 #include "PrePi.h"
31 #include "LzmaDecompress.h"
32
33 #define IS_XIP() (((UINT32)FixedPcdGet32 (PcdFdBaseAddress) > (UINT32)(FixedPcdGet32 (PcdSystemMemoryBase) + FixedPcdGet32 (PcdSystemMemorySize))) || \
34 ((FixedPcdGet32 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) < FixedPcdGet32 (PcdSystemMemoryBase)))
35
36 // Not used when PrePi in run in XIP mode
37 UINTN mGlobalVariableBase = 0;
38
39 VOID
40 PrePiCommonExceptionEntry (
41 IN UINT32 Entry,
42 IN UINT32 LR
43 );
44
45 EFI_STATUS
46 EFIAPI
47 ExtractGuidedSectionLibConstructor (
48 VOID
49 );
50
51 EFI_STATUS
52 EFIAPI
53 LzmaDecompressLibConstructor (
54 VOID
55 );
56
57 VOID
58 EFIAPI
59 BuildGlobalVariableHob (
60 IN EFI_PHYSICAL_ADDRESS GlobalVariableBase,
61 IN UINT32 GlobalVariableSize
62 )
63 {
64 ARM_HOB_GLOBAL_VARIABLE *Hob;
65
66 Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, sizeof (ARM_HOB_GLOBAL_VARIABLE));
67 ASSERT(Hob != NULL);
68
69 CopyGuid (&(Hob->Header.Name), &gArmGlobalVariableGuid);
70 Hob->GlobalVariableBase = GlobalVariableBase;
71 Hob->GlobalVariableSize = GlobalVariableSize;
72 }
73
74 EFI_STATUS
75 GetPlatformPpi (
76 IN EFI_GUID *PpiGuid,
77 OUT VOID **Ppi
78 )
79 {
80 UINTN PpiListSize;
81 UINTN PpiListCount;
82 EFI_PEI_PPI_DESCRIPTOR *PpiList;
83 UINTN Index;
84
85 PpiListSize = 0;
86 ArmPlatformGetPlatformPpiList (&PpiListSize, &PpiList);
87 PpiListCount = PpiListSize / sizeof(EFI_PEI_PPI_DESCRIPTOR);
88 for (Index = 0; Index < PpiListCount; Index++, PpiList++) {
89 if (CompareGuid (PpiList->Guid, PpiGuid) == TRUE) {
90 *Ppi = PpiList->Ppi;
91 return EFI_SUCCESS;
92 }
93 }
94
95 return EFI_NOT_FOUND;
96 }
97
98 VOID
99 PrePiMain (
100 IN UINTN UefiMemoryBase,
101 IN UINTN StacksBase,
102 IN UINTN GlobalVariableBase,
103 IN UINT64 StartTimeStamp
104 )
105 {
106 EFI_HOB_HANDOFF_INFO_TABLE* HobList;
107 ARM_MP_CORE_INFO_PPI* ArmMpCoreInfoPpi;
108 UINTN ArmCoreCount;
109 ARM_CORE_INFO* ArmCoreInfoTable;
110 EFI_STATUS Status;
111 CHAR8 Buffer[100];
112 UINTN CharCount;
113 UINTN StacksSize;
114
115 // If ensure the FD is either part of the System Memory or totally outside of the System Memory (XIP)
116 ASSERT (IS_XIP() ||
117 ((FixedPcdGet32 (PcdFdBaseAddress) >= FixedPcdGet32 (PcdSystemMemoryBase)) &&
118 ((UINT32)(FixedPcdGet32 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= (UINT32)(FixedPcdGet32 (PcdSystemMemoryBase) + FixedPcdGet32 (PcdSystemMemorySize)))));
119
120 // Enable program flow prediction, if supported.
121 ArmEnableBranchPrediction ();
122
123 if (FixedPcdGet32(PcdVFPEnabled)) {
124 ArmEnableVFP();
125 }
126
127 // Initialize the Serial Port
128 SerialPortInitialize ();
129 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"UEFI firmware (version %s built at %a on %a)\n\r",
130 (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__);
131 SerialPortWrite ((UINT8 *) Buffer, CharCount);
132
133 // Initialize the Debug Agent for Source Level Debugging
134 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
135 SaveAndSetDebugTimerInterrupt (TRUE);
136
137 // Declare the PI/UEFI memory region
138 HobList = HobConstructor (
139 (VOID*)UefiMemoryBase,
140 FixedPcdGet32 (PcdSystemMemoryUefiRegionSize),
141 (VOID*)UefiMemoryBase,
142 (VOID*)StacksBase // The top of the UEFI Memory is reserved for the stacks
143 );
144 PrePeiSetHobList (HobList);
145
146 // Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
147 Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
148 ASSERT_EFI_ERROR (Status);
149
150 // Create the Stacks HOB (reserve the memory for all stacks)
151 if (ArmIsMpCore ()) {
152 StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize) + (FixedPcdGet32(PcdClusterCount) * 4 * FixedPcdGet32(PcdCPUCoreSecondaryStackSize));
153 } else {
154 StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize);
155 }
156 BuildStackHob (StacksBase, StacksSize);
157
158 // Declare the Global Variable HOB
159 BuildGlobalVariableHob (GlobalVariableBase, FixedPcdGet32 (PcdPeiGlobalVariableSize));
160
161 //TODO: Call CpuPei as a library
162 BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize));
163
164 if (ArmIsMpCore ()) {
165 // Only MP Core platform need to produce gArmMpCoreInfoPpiGuid
166 Status = GetPlatformPpi (&gArmMpCoreInfoPpiGuid, (VOID**)&ArmMpCoreInfoPpi);
167
168 // On MP Core Platform we must implement the ARM MP Core Info PPI (gArmMpCoreInfoPpiGuid)
169 ASSERT_EFI_ERROR (Status);
170
171 // Build the MP Core Info Table
172 ArmCoreCount = 0;
173 Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable);
174 if (!EFI_ERROR(Status) && (ArmCoreCount > 0)) {
175 // Build MPCore Info HOB
176 BuildGuidDataHob (&gArmMpCoreInfoGuid, ArmCoreInfoTable, sizeof (ARM_CORE_INFO) * ArmCoreCount);
177 }
178 }
179
180 // Set the Boot Mode
181 SetBootMode (ArmPlatformGetBootMode ());
182
183 // Initialize Platform HOBs (CpuHob and FvHob)
184 Status = PlatformPeim ();
185 ASSERT_EFI_ERROR (Status);
186
187 // Now, the HOB List has been initialized, we can register performance information
188 PERF_START (NULL, "PEI", NULL, StartTimeStamp);
189
190 // SEC phase needs to run library constructors by hand.
191 ExtractGuidedSectionLibConstructor ();
192 LzmaDecompressLibConstructor ();
193
194 // Build HOBs to pass up our version of stuff the DXE Core needs to save space
195 BuildPeCoffLoaderHob ();
196 BuildExtractSectionHob (
197 &gLzmaCustomDecompressGuid,
198 LzmaGuidedSectionGetInfo,
199 LzmaGuidedSectionExtraction
200 );
201
202 // Assume the FV that contains the SEC (our code) also contains a compressed FV.
203 Status = DecompressFirstFv ();
204 ASSERT_EFI_ERROR (Status);
205
206 // Load the DXE Core and transfer control to it
207 Status = LoadDxeCoreFromFv (NULL, 0);
208 ASSERT_EFI_ERROR (Status);
209 }
210
211 VOID
212 CEntryPoint (
213 IN UINTN MpId,
214 IN UINTN UefiMemoryBase,
215 IN UINTN StacksBase,
216 IN UINTN GlobalVariableBase
217 )
218 {
219 UINT64 StartTimeStamp;
220
221 // Initialize the platform specific controllers
222 ArmPlatformInitialize (MpId);
223
224 if (IS_PRIMARY_CORE(MpId) && PerformanceMeasurementEnabled ()) {
225 // Initialize the Timer Library to setup the Timer HW controller
226 TimerConstructor ();
227 // We cannot call yet the PerformanceLib because the HOB List has not been initialized
228 StartTimeStamp = GetPerformanceCounter ();
229 } else {
230 StartTimeStamp = 0;
231 }
232
233 // Clean Data cache
234 ArmCleanInvalidateDataCache ();
235
236 // Invalidate instruction cache
237 ArmInvalidateInstructionCache ();
238
239 //TODO:Drain Write Buffer
240
241 // Enable Instruction & Data caches
242 ArmEnableDataCache ();
243 ArmEnableInstructionCache ();
244
245 // Define the Global Variable region when we are not running in XIP
246 if (!IS_XIP()) {
247 if (IS_PRIMARY_CORE(MpId)) {
248 mGlobalVariableBase = GlobalVariableBase;
249 if (ArmIsMpCore()) {
250 // Signal the Global Variable Region is defined (event: ARM_CPU_EVENT_DEFAULT)
251 ArmCallSEV ();
252 }
253 } else {
254 // Wait the Primay core has defined the address of the Global Variable region (event: ARM_CPU_EVENT_DEFAULT)
255 ArmCallWFE ();
256 }
257 }
258
259 // Write VBAR - The Vector table must be 32-byte aligned
260 ASSERT (((UINT32)PrePiVectorTable & ((1 << 5)-1)) == 0);
261 ArmWriteVBar ((UINT32)PrePiVectorTable);
262
263 // If not primary Jump to Secondary Main
264 if (IS_PRIMARY_CORE(MpId)) {
265 // Goto primary Main.
266 PrimaryMain (UefiMemoryBase, StacksBase, GlobalVariableBase, StartTimeStamp);
267 } else {
268 SecondaryMain (MpId);
269 }
270
271 // DXE Core should always load and never return
272 ASSERT (FALSE);
273 }
274
275 VOID
276 PrePiCommonExceptionEntry (
277 IN UINT32 Entry,
278 IN UINT32 LR
279 )
280 {
281 CHAR8 Buffer[100];
282 UINTN CharCount;
283
284 switch (Entry) {
285 case 0:
286 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Reset Exception at 0x%X\n\r",LR);
287 break;
288 case 1:
289 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Undefined Exception at 0x%X\n\r",LR);
290 break;
291 case 2:
292 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"SWI Exception at 0x%X\n\r",LR);
293 break;
294 case 3:
295 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"PrefetchAbort Exception at 0x%X\n\r",LR);
296 break;
297 case 4:
298 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"DataAbort Exception at 0x%X\n\r",LR);
299 break;
300 case 5:
301 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Reserved Exception at 0x%X\n\r",LR);
302 break;
303 case 6:
304 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"IRQ Exception at 0x%X\n\r",LR);
305 break;
306 case 7:
307 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"FIQ Exception at 0x%X\n\r",LR);
308 break;
309 default:
310 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Unknown Exception at 0x%X\n\r",LR);
311 break;
312 }
313 SerialPortWrite ((UINT8 *) Buffer, CharCount);
314 while(1);
315 }