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