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