]> git.proxmox.com Git - mirror_edk2.git/blob - UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
UefiPayloadPkg: Fix the build failure
[mirror_edk2.git] / UefiPayloadPkg / UefiPayloadEntry / UniversalPayloadEntry.c
1 /** @file
2
3 Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5
6 **/
7
8 #include "UefiPayloadEntry.h"
9
10 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
11 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
12 EFI_RESOURCE_ATTRIBUTE_TESTED | \
13 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
14 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
15 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
16 EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
17 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
18 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
19 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
20 EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
21
22 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
23 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
24 EFI_RESOURCE_ATTRIBUTE_TESTED )
25
26 extern VOID *mHobList;
27
28 /**
29 Some bootloader may pass a pcd database, and UPL also contain a PCD database.
30 Dxe PCD driver has the assumption that the two PCD database can be catenated and
31 the local token number should be successive。
32 This function will fix up the UPL PCD database to meet that assumption.
33
34 @param[in] DxeFv The FV where to find the Universal PCD database.
35
36 @retval EFI_SUCCESS If it completed successfully.
37 @retval other Failed to fix up.
38 **/
39 EFI_STATUS
40 FixUpPcdDatabase (
41 IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv
42 )
43 {
44 EFI_STATUS Status;
45 EFI_FFS_FILE_HEADER *FileHeader;
46 VOID *PcdRawData;
47 PEI_PCD_DATABASE *PeiDatabase;
48 PEI_PCD_DATABASE *UplDatabase;
49 EFI_HOB_GUID_TYPE *GuidHob;
50 DYNAMICEX_MAPPING *ExMapTable;
51 UINTN Index;
52
53 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
54 if (GuidHob == NULL) {
55 //
56 // No fix-up is needed.
57 //
58 return EFI_SUCCESS;
59 }
60 PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);
61 DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token number is %d\n", PeiDatabase->LocalTokenCount));
62
63 Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr (PcdPcdDriverFile), &FileHeader);
64 ASSERT_EFI_ERROR (Status);
65 if (EFI_ERROR (Status)) {
66 return Status;
67 }
68 Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData);
69 ASSERT_EFI_ERROR (Status);
70 if (EFI_ERROR (Status)) {
71 return Status;
72 }
73
74 UplDatabase = (PEI_PCD_DATABASE *) PcdRawData;
75 ExMapTable = (DYNAMICEX_MAPPING *) (UINTN) ((UINTN) PcdRawData + UplDatabase->ExMapTableOffset);
76
77 for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) {
78 ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount;
79 }
80 DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n"));
81 return EFI_SUCCESS;
82 }
83
84 /**
85 Add HOB into HOB list
86
87 @param[in] Hob The HOB to be added into the HOB list.
88 **/
89 VOID
90 AddNewHob (
91 IN EFI_PEI_HOB_POINTERS *Hob
92 )
93 {
94 EFI_PEI_HOB_POINTERS NewHob;
95
96 if (Hob->Raw == NULL) {
97 return;
98 }
99 NewHob.Header = CreateHob (Hob->Header->HobType, Hob->Header->HobLength);
100
101 if (NewHob.Header != NULL) {
102 CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER));
103 }
104 }
105
106 /**
107 Found the Resource Descriptor HOB that contains a range
108
109 @param[in] Base Memory start address
110 @param[in] Top Memory Top.
111
112 @return The pointer to the Resource Descriptor HOB.
113 **/
114 EFI_HOB_RESOURCE_DESCRIPTOR *
115 FindResourceDescriptorByRange (
116 VOID *HobList,
117 EFI_PHYSICAL_ADDRESS Base,
118 EFI_PHYSICAL_ADDRESS Top
119 )
120 {
121 EFI_PEI_HOB_POINTERS Hob;
122 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
123
124 for (Hob.Raw = (UINT8 *) HobList; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
125 //
126 // Skip all HOBs except Resource Descriptor HOBs
127 //
128 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
129 continue;
130 }
131
132 //
133 // Skip Resource Descriptor HOBs that do not describe tested system memory
134 //
135 ResourceHob = Hob.ResourceDescriptor;
136 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
137 continue;
138 }
139 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
140 continue;
141 }
142
143 //
144 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
145 //
146 if (Base < ResourceHob->PhysicalStart) {
147 continue;
148 }
149 if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {
150 continue;
151 }
152 return ResourceHob;
153 }
154 return NULL;
155 }
156
157 /**
158 Find the highest below 4G memory resource descriptor, except the input Resource Descriptor.
159
160 @param[in] HobList Hob start address
161 @param[in] MinimalNeededSize Minimal needed size.
162 @param[in] ExceptResourceHob Ignore this Resource Descriptor.
163
164 @return The pointer to the Resource Descriptor HOB.
165 **/
166 EFI_HOB_RESOURCE_DESCRIPTOR *
167 FindAnotherHighestBelow4GResourceDescriptor (
168 IN VOID *HobList,
169 IN UINTN MinimalNeededSize,
170 IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob
171 )
172 {
173 EFI_PEI_HOB_POINTERS Hob;
174 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
175 EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob;
176 ReturnResourceHob = NULL;
177
178 for (Hob.Raw = (UINT8 *) HobList; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
179 //
180 // Skip all HOBs except Resource Descriptor HOBs
181 //
182 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
183 continue;
184 }
185
186 //
187 // Skip Resource Descriptor HOBs that do not describe tested system memory
188 //
189 ResourceHob = Hob.ResourceDescriptor;
190 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
191 continue;
192 }
193 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
194 continue;
195 }
196
197 //
198 // Skip if the Resource Descriptor HOB equals to ExceptResourceHob
199 //
200 if (ResourceHob == ExceptResourceHob) {
201 continue;
202 }
203 //
204 // Skip Resource Descriptor HOBs that are beyond 4G
205 //
206 if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > BASE_4GB) {
207 continue;
208 }
209 //
210 // Skip Resource Descriptor HOBs that are too small
211 //
212 if (ResourceHob->ResourceLength < MinimalNeededSize) {
213 continue;
214 }
215
216 //
217 // Return the topest Resource Descriptor
218 //
219 if (ReturnResourceHob == NULL) {
220 ReturnResourceHob = ResourceHob;
221 } else {
222 if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) {
223 ReturnResourceHob = ResourceHob;
224 }
225 }
226 }
227 return ReturnResourceHob;
228 }
229
230 /**
231 It will build HOBs based on information from bootloaders.
232
233 @retval EFI_SUCCESS If it completed successfully.
234 @retval Others If it failed to build required HOBs.
235 **/
236 EFI_STATUS
237 BuildHobs (
238 IN UINTN BootloaderParameter,
239 OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
240 )
241 {
242 EFI_PEI_HOB_POINTERS Hob;
243 UINTN MinimalNeededSize;
244 EFI_PHYSICAL_ADDRESS FreeMemoryBottom;
245 EFI_PHYSICAL_ADDRESS FreeMemoryTop;
246 EFI_PHYSICAL_ADDRESS MemoryBottom;
247 EFI_PHYSICAL_ADDRESS MemoryTop;
248 EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
249 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
250 UNIVERSAL_PAYLOAD_EXTRA_DATA *ExtraData;
251 UINT8 *GuidHob;
252 EFI_HOB_FIRMWARE_VOLUME *FvHob;
253
254 Hob.Raw = (UINT8 *) BootloaderParameter;
255 MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
256
257 ASSERT (Hob.Raw != NULL);
258 ASSERT ((UINTN) Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop);
259 ASSERT ((UINTN) Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop);
260 ASSERT ((UINTN) Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom);
261 ASSERT ((UINTN) Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom);
262
263
264 //
265 // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop
266 //
267 PhitResourceHob = FindResourceDescriptorByRange(Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop);
268 if (PhitResourceHob == NULL) {
269 //
270 // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob
271 //
272 ResourceHob = FindAnotherHighestBelow4GResourceDescriptor(Hob.Raw, MinimalNeededSize, NULL);
273 if (ResourceHob == NULL) {
274 return EFI_NOT_FOUND;
275 }
276
277 MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
278 FreeMemoryBottom = MemoryBottom;
279 FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
280 MemoryTop = FreeMemoryTop;
281 } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) {
282 //
283 // New availiable Memory range in new hob is right above memory top in old hob.
284 //
285 MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop;
286 FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop;
287 FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize;
288 MemoryTop = FreeMemoryTop;
289 } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) {
290 //
291 // New availiable Memory range in new hob is right below memory bottom in old hob.
292 //
293 MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize;
294 FreeMemoryBottom = MemoryBottom;
295 FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom;
296 MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop;
297 } else {
298 //
299 // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob
300 // Find another Resource Descriptor Hob
301 //
302 ResourceHob = FindAnotherHighestBelow4GResourceDescriptor(Hob.Raw, MinimalNeededSize, PhitResourceHob);
303 if (ResourceHob == NULL) {
304 return EFI_NOT_FOUND;
305 }
306
307 MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
308 FreeMemoryBottom = MemoryBottom;
309 FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
310 MemoryTop = FreeMemoryTop;
311 }
312 HobConstructor ((VOID *) (UINTN) MemoryBottom, (VOID *) (UINTN) MemoryTop, (VOID *) (UINTN) FreeMemoryBottom, (VOID *) (UINTN) FreeMemoryTop);
313 //
314 // From now on, mHobList will point to the new Hob range.
315 //
316
317 //
318 // Create an empty FvHob for the DXE FV that contains DXE core.
319 //
320 BuildFvHob ((EFI_PHYSICAL_ADDRESS) 0, 0);
321 //
322 // Since payload created new Hob, move all hobs except PHIT from boot loader hob list.
323 //
324 while (!END_OF_HOB_LIST (Hob)) {
325 if (Hob.Header->HobType != EFI_HOB_TYPE_HANDOFF) {
326 // Add this hob to payload HOB
327 AddNewHob (&Hob);
328 }
329 Hob.Raw = GET_NEXT_HOB (Hob);
330 }
331
332 //
333 // Get DXE FV location
334 //
335 GuidHob = GetFirstGuidHob(&gUniversalPayloadExtraDataGuid);
336 ASSERT (GuidHob != NULL);
337 ExtraData = (UNIVERSAL_PAYLOAD_EXTRA_DATA *) GET_GUID_HOB_DATA (GuidHob);
338 ASSERT (ExtraData->Count == 1);
339 ASSERT (AsciiStrCmp (ExtraData->Entry[0].Identifier, "uefi_fv") == 0);
340
341 *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) ExtraData->Entry[0].Base;
342 ASSERT ((*DxeFv)->FvLength == ExtraData->Entry[0].Size);
343
344 //
345 // Update DXE FV information to first fv hob in the hob list, which
346 // is the empty FvHob created before.
347 //
348 FvHob = GetFirstHob (EFI_HOB_TYPE_FV);
349 FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) *DxeFv;
350 FvHob->Length = (*DxeFv)->FvLength;
351 return EFI_SUCCESS;
352 }
353
354 /**
355 Entry point to the C language phase of UEFI payload.
356
357 @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
358 **/
359 EFI_STATUS
360 EFIAPI
361 _ModuleEntryPoint (
362 IN UINTN BootloaderParameter
363 )
364 {
365 EFI_STATUS Status;
366 PHYSICAL_ADDRESS DxeCoreEntryPoint;
367 EFI_PEI_HOB_POINTERS Hob;
368 EFI_FIRMWARE_VOLUME_HEADER *DxeFv;
369
370 mHobList = (VOID *) BootloaderParameter;
371 DxeFv = NULL;
372 // Call constructor for all libraries
373 ProcessLibraryConstructorList ();
374
375 DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));
376 DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof(UINTN)));
377
378 // Initialize floating point operating environment to be compliant with UEFI spec.
379 InitializeFloatingPointUnits ();
380
381 // Build HOB based on information from Bootloader
382 Status = BuildHobs (BootloaderParameter, &DxeFv);
383 ASSERT_EFI_ERROR (Status);
384
385 FixUpPcdDatabase (DxeFv);
386 Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint);
387 ASSERT_EFI_ERROR (Status);
388
389 //
390 // Mask off all legacy 8259 interrupt sources
391 //
392 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
393 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
394
395 Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *) GetFirstHob(EFI_HOB_TYPE_HANDOFF);
396 HandOffToDxeCore (DxeCoreEntryPoint, Hob);
397
398 // Should not get here
399 CpuDeadLoop ();
400 return EFI_SUCCESS;
401 }