]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/PrePi/PrePi.c
ArmPlatformPkg/PrePeiCore: seed temporary stack before entering PEI core
[mirror_edk2.git] / ArmPlatformPkg / PrePi / PrePi.c
1 /** @file
2 *
3 * Copyright (c) 2011-2017, 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 <Ppi/SecPerformance.h>
28 #include <Guid/LzmaDecompress.h>
29
30 #include "PrePi.h"
31 #include "LzmaDecompress.h"
32
33 #define IS_XIP() (((UINT64)FixedPcdGet64 (PcdFdBaseAddress) > mSystemMemoryEnd) || \
34 ((FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) < FixedPcdGet64 (PcdSystemMemoryBase)))
35
36 UINT64 mSystemMemoryEnd = FixedPcdGet64(PcdSystemMemoryBase) +
37 FixedPcdGet64(PcdSystemMemorySize) - 1;
38
39 EFI_STATUS
40 EFIAPI
41 ExtractGuidedSectionLibConstructor (
42 VOID
43 );
44
45 EFI_STATUS
46 EFIAPI
47 LzmaDecompressLibConstructor (
48 VOID
49 );
50
51 EFI_STATUS
52 GetPlatformPpi (
53 IN EFI_GUID *PpiGuid,
54 OUT VOID **Ppi
55 )
56 {
57 UINTN PpiListSize;
58 UINTN PpiListCount;
59 EFI_PEI_PPI_DESCRIPTOR *PpiList;
60 UINTN Index;
61
62 PpiListSize = 0;
63 ArmPlatformGetPlatformPpiList (&PpiListSize, &PpiList);
64 PpiListCount = PpiListSize / sizeof(EFI_PEI_PPI_DESCRIPTOR);
65 for (Index = 0; Index < PpiListCount; Index++, PpiList++) {
66 if (CompareGuid (PpiList->Guid, PpiGuid) == TRUE) {
67 *Ppi = PpiList->Ppi;
68 return EFI_SUCCESS;
69 }
70 }
71
72 return EFI_NOT_FOUND;
73 }
74
75 VOID
76 PrePiMain (
77 IN UINTN UefiMemoryBase,
78 IN UINTN StacksBase,
79 IN UINT64 StartTimeStamp
80 )
81 {
82 EFI_HOB_HANDOFF_INFO_TABLE* HobList;
83 ARM_MP_CORE_INFO_PPI* ArmMpCoreInfoPpi;
84 UINTN ArmCoreCount;
85 ARM_CORE_INFO* ArmCoreInfoTable;
86 EFI_STATUS Status;
87 CHAR8 Buffer[100];
88 UINTN CharCount;
89 UINTN StacksSize;
90 FIRMWARE_SEC_PERFORMANCE Performance;
91
92 // If ensure the FD is either part of the System Memory or totally outside of the System Memory (XIP)
93 ASSERT (IS_XIP() ||
94 ((FixedPcdGet64 (PcdFdBaseAddress) >= FixedPcdGet64 (PcdSystemMemoryBase)) &&
95 ((UINT64)(FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= (UINT64)mSystemMemoryEnd)));
96
97 // Initialize the architecture specific bits
98 ArchInitialize ();
99
100 // Initialize the Serial Port
101 SerialPortInitialize ();
102 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"UEFI firmware (version %s built at %a on %a)\n\r",
103 (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__);
104 SerialPortWrite ((UINT8 *) Buffer, CharCount);
105
106 // Initialize the Debug Agent for Source Level Debugging
107 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
108 SaveAndSetDebugTimerInterrupt (TRUE);
109
110 // Declare the PI/UEFI memory region
111 HobList = HobConstructor (
112 (VOID*)UefiMemoryBase,
113 FixedPcdGet32 (PcdSystemMemoryUefiRegionSize),
114 (VOID*)UefiMemoryBase,
115 (VOID*)StacksBase // The top of the UEFI Memory is reserved for the stacks
116 );
117 PrePeiSetHobList (HobList);
118
119 // Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
120 Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
121 ASSERT_EFI_ERROR (Status);
122
123 // Create the Stacks HOB (reserve the memory for all stacks)
124 if (ArmIsMpCore ()) {
125 StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize) +
126 ((FixedPcdGet32 (PcdCoreCount) - 1) * FixedPcdGet32 (PcdCPUCoreSecondaryStackSize));
127 } else {
128 StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize);
129 }
130 BuildStackHob (StacksBase, StacksSize);
131
132 //TODO: Call CpuPei as a library
133 BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize));
134
135 if (ArmIsMpCore ()) {
136 // Only MP Core platform need to produce gArmMpCoreInfoPpiGuid
137 Status = GetPlatformPpi (&gArmMpCoreInfoPpiGuid, (VOID**)&ArmMpCoreInfoPpi);
138
139 // On MP Core Platform we must implement the ARM MP Core Info PPI (gArmMpCoreInfoPpiGuid)
140 ASSERT_EFI_ERROR (Status);
141
142 // Build the MP Core Info Table
143 ArmCoreCount = 0;
144 Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable);
145 if (!EFI_ERROR(Status) && (ArmCoreCount > 0)) {
146 // Build MPCore Info HOB
147 BuildGuidDataHob (&gArmMpCoreInfoGuid, ArmCoreInfoTable, sizeof (ARM_CORE_INFO) * ArmCoreCount);
148 }
149 }
150
151 // Store timer value logged at the beginning of firmware image execution
152 Performance.ResetEnd = GetTimeInNanoSecond (StartTimeStamp);
153
154 // Build SEC Performance Data Hob
155 BuildGuidDataHob (&gEfiFirmwarePerformanceGuid, &Performance, sizeof (Performance));
156
157 // Set the Boot Mode
158 SetBootMode (ArmPlatformGetBootMode ());
159
160 // Initialize Platform HOBs (CpuHob and FvHob)
161 Status = PlatformPeim ();
162 ASSERT_EFI_ERROR (Status);
163
164 // Now, the HOB List has been initialized, we can register performance information
165 PERF_START (NULL, "PEI", NULL, StartTimeStamp);
166
167 // SEC phase needs to run library constructors by hand.
168 ExtractGuidedSectionLibConstructor ();
169 LzmaDecompressLibConstructor ();
170
171 // Build HOBs to pass up our version of stuff the DXE Core needs to save space
172 BuildPeCoffLoaderHob ();
173 BuildExtractSectionHob (
174 &gLzmaCustomDecompressGuid,
175 LzmaGuidedSectionGetInfo,
176 LzmaGuidedSectionExtraction
177 );
178
179 // Assume the FV that contains the SEC (our code) also contains a compressed FV.
180 Status = DecompressFirstFv ();
181 ASSERT_EFI_ERROR (Status);
182
183 // Load the DXE Core and transfer control to it
184 Status = LoadDxeCoreFromFv (NULL, 0);
185 ASSERT_EFI_ERROR (Status);
186 }
187
188 VOID
189 CEntryPoint (
190 IN UINTN MpId,
191 IN UINTN UefiMemoryBase,
192 IN UINTN StacksBase
193 )
194 {
195 UINT64 StartTimeStamp;
196
197 // Initialize the platform specific controllers
198 ArmPlatformInitialize (MpId);
199
200 if (ArmPlatformIsPrimaryCore (MpId) && PerformanceMeasurementEnabled ()) {
201 // Initialize the Timer Library to setup the Timer HW controller
202 TimerConstructor ();
203 // We cannot call yet the PerformanceLib because the HOB List has not been initialized
204 StartTimeStamp = GetPerformanceCounter ();
205 } else {
206 StartTimeStamp = 0;
207 }
208
209 // Data Cache enabled on Primary core when MMU is enabled.
210 ArmDisableDataCache ();
211 // Invalidate Data cache
212 ArmInvalidateDataCache ();
213 // Invalidate instruction cache
214 ArmInvalidateInstructionCache ();
215 // Enable Instruction Caches on all cores.
216 ArmEnableInstructionCache ();
217
218 // Define the Global Variable region when we are not running in XIP
219 if (!IS_XIP()) {
220 if (ArmPlatformIsPrimaryCore (MpId)) {
221 if (ArmIsMpCore()) {
222 // Signal the Global Variable Region is defined (event: ARM_CPU_EVENT_DEFAULT)
223 ArmCallSEV ();
224 }
225 } else {
226 // Wait the Primay core has defined the address of the Global Variable region (event: ARM_CPU_EVENT_DEFAULT)
227 ArmCallWFE ();
228 }
229 }
230
231 // If not primary Jump to Secondary Main
232 if (ArmPlatformIsPrimaryCore (MpId)) {
233 // Goto primary Main.
234 PrimaryMain (UefiMemoryBase, StacksBase, StartTimeStamp);
235 } else {
236 SecondaryMain (MpId);
237 }
238
239 // DXE Core should always load and never return
240 ASSERT (FALSE);
241 }
242