3 Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
8 #include "UefiPayloadEntry.h"
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 )
22 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
23 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
24 EFI_RESOURCE_ATTRIBUTE_TESTED )
26 extern VOID
*mHobList
;
29 Print all HOBs info from the HOB list.
31 @return The pointer to the HOB list.
35 IN CONST VOID
*HobStart
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.
44 @param[in] DxeFv The FV where to find the Universal PCD database.
46 @retval EFI_SUCCESS If it completed successfully.
47 @retval other Failed to fix up.
51 IN EFI_FIRMWARE_VOLUME_HEADER
*DxeFv
55 EFI_FFS_FILE_HEADER
*FileHeader
;
57 PEI_PCD_DATABASE
*PeiDatabase
;
58 PEI_PCD_DATABASE
*UplDatabase
;
59 EFI_HOB_GUID_TYPE
*GuidHob
;
60 DYNAMICEX_MAPPING
*ExMapTable
;
63 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
64 if (GuidHob
== NULL
) {
66 // No fix-up is needed.
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
));
73 Status
= FvFindFileByTypeGuid (DxeFv
, EFI_FV_FILETYPE_DRIVER
, PcdGetPtr (PcdPcdDriverFile
), &FileHeader
);
74 ASSERT_EFI_ERROR (Status
);
75 if (EFI_ERROR (Status
)) {
78 Status
= FileFindSection (FileHeader
, EFI_SECTION_RAW
, &PcdRawData
);
79 ASSERT_EFI_ERROR (Status
);
80 if (EFI_ERROR (Status
)) {
84 UplDatabase
= (PEI_PCD_DATABASE
*) PcdRawData
;
85 ExMapTable
= (DYNAMICEX_MAPPING
*) (UINTN
) ((UINTN
) PcdRawData
+ UplDatabase
->ExMapTableOffset
);
87 for (Index
= 0; Index
< UplDatabase
->ExTokenCount
; Index
++) {
88 ExMapTable
[Index
].TokenNumber
+= PeiDatabase
->LocalTokenCount
;
90 DEBUG ((DEBUG_INFO
, "Fix up UPL PCD database successfully\n"));
97 @param[in] Hob The HOB to be added into the HOB list.
101 IN EFI_PEI_HOB_POINTERS
*Hob
104 EFI_PEI_HOB_POINTERS NewHob
;
106 if (Hob
->Raw
== NULL
) {
109 NewHob
.Header
= CreateHob (Hob
->Header
->HobType
, Hob
->Header
->HobLength
);
111 if (NewHob
.Header
!= NULL
) {
112 CopyMem (NewHob
.Header
+ 1, Hob
->Header
+ 1, Hob
->Header
->HobLength
- sizeof (EFI_HOB_GENERIC_HEADER
));
117 Found the Resource Descriptor HOB that contains a range (Base, Top)
119 @param[in] HobList Hob start address
120 @param[in] Base Memory start address
121 @param[in] Top Memory end address.
123 @retval The pointer to the Resource Descriptor HOB.
125 EFI_HOB_RESOURCE_DESCRIPTOR
*
126 FindResourceDescriptorByRange (
128 IN EFI_PHYSICAL_ADDRESS Base
,
129 IN EFI_PHYSICAL_ADDRESS Top
132 EFI_PEI_HOB_POINTERS Hob
;
133 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
135 for (Hob
.Raw
= (UINT8
*) HobList
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
137 // Skip all HOBs except Resource Descriptor HOBs
139 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
144 // Skip Resource Descriptor HOBs that do not describe tested system memory
146 ResourceHob
= Hob
.ResourceDescriptor
;
147 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
150 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
155 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
157 if (Base
< ResourceHob
->PhysicalStart
) {
160 if (Top
> (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
)) {
169 Find the highest below 4G memory resource descriptor, except the input Resource Descriptor.
171 @param[in] HobList Hob start address
172 @param[in] MinimalNeededSize Minimal needed size.
173 @param[in] ExceptResourceHob Ignore this Resource Descriptor.
175 @retval The pointer to the Resource Descriptor HOB.
177 EFI_HOB_RESOURCE_DESCRIPTOR
*
178 FindAnotherHighestBelow4GResourceDescriptor (
180 IN UINTN MinimalNeededSize
,
181 IN EFI_HOB_RESOURCE_DESCRIPTOR
*ExceptResourceHob
184 EFI_PEI_HOB_POINTERS Hob
;
185 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
186 EFI_HOB_RESOURCE_DESCRIPTOR
*ReturnResourceHob
;
187 ReturnResourceHob
= NULL
;
189 for (Hob
.Raw
= (UINT8
*) HobList
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
191 // Skip all HOBs except Resource Descriptor HOBs
193 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
198 // Skip Resource Descriptor HOBs that do not describe tested system memory
200 ResourceHob
= Hob
.ResourceDescriptor
;
201 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
204 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
209 // Skip if the Resource Descriptor HOB equals to ExceptResourceHob
211 if (ResourceHob
== ExceptResourceHob
) {
215 // Skip Resource Descriptor HOBs that are beyond 4G
217 if ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) > BASE_4GB
) {
221 // Skip Resource Descriptor HOBs that are too small
223 if (ResourceHob
->ResourceLength
< MinimalNeededSize
) {
228 // Return the topest Resource Descriptor
230 if (ReturnResourceHob
== NULL
) {
231 ReturnResourceHob
= ResourceHob
;
233 if (ReturnResourceHob
->PhysicalStart
< ResourceHob
->PhysicalStart
) {
234 ReturnResourceHob
= ResourceHob
;
238 return ReturnResourceHob
;
242 It will build HOBs based on information from bootloaders.
244 @param[in] BootloaderParameter The starting memory address of bootloader parameter block.
245 @param[out] DxeFv The pointer to the DXE FV in memory.
247 @retval EFI_SUCCESS If it completed successfully.
248 @retval Others If it failed to build required HOBs.
252 IN UINTN BootloaderParameter
,
253 OUT EFI_FIRMWARE_VOLUME_HEADER
**DxeFv
256 EFI_PEI_HOB_POINTERS Hob
;
257 UINTN MinimalNeededSize
;
258 EFI_PHYSICAL_ADDRESS FreeMemoryBottom
;
259 EFI_PHYSICAL_ADDRESS FreeMemoryTop
;
260 EFI_PHYSICAL_ADDRESS MemoryBottom
;
261 EFI_PHYSICAL_ADDRESS MemoryTop
;
262 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
263 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
264 UNIVERSAL_PAYLOAD_EXTRA_DATA
*ExtraData
;
266 EFI_HOB_FIRMWARE_VOLUME
*FvHob
;
267 UNIVERSAL_PAYLOAD_ACPI_TABLE
*AcpiTable
;
268 ACPI_BOARD_INFO
*AcpiBoardInfo
;
270 Hob
.Raw
= (UINT8
*) BootloaderParameter
;
271 MinimalNeededSize
= FixedPcdGet32 (PcdSystemMemoryUefiRegionSize
);
273 ASSERT (Hob
.Raw
!= NULL
);
274 ASSERT ((UINTN
) Hob
.HandoffInformationTable
->EfiFreeMemoryTop
== Hob
.HandoffInformationTable
->EfiFreeMemoryTop
);
275 ASSERT ((UINTN
) Hob
.HandoffInformationTable
->EfiMemoryTop
== Hob
.HandoffInformationTable
->EfiMemoryTop
);
276 ASSERT ((UINTN
) Hob
.HandoffInformationTable
->EfiFreeMemoryBottom
== Hob
.HandoffInformationTable
->EfiFreeMemoryBottom
);
277 ASSERT ((UINTN
) Hob
.HandoffInformationTable
->EfiMemoryBottom
== Hob
.HandoffInformationTable
->EfiMemoryBottom
);
281 // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop
283 PhitResourceHob
= FindResourceDescriptorByRange(Hob
.Raw
, Hob
.HandoffInformationTable
->EfiMemoryBottom
, Hob
.HandoffInformationTable
->EfiMemoryTop
);
284 if (PhitResourceHob
== NULL
) {
286 // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob
288 ResourceHob
= FindAnotherHighestBelow4GResourceDescriptor(Hob
.Raw
, MinimalNeededSize
, NULL
);
289 if (ResourceHob
== NULL
) {
290 return EFI_NOT_FOUND
;
293 MemoryBottom
= ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- MinimalNeededSize
;
294 FreeMemoryBottom
= MemoryBottom
;
295 FreeMemoryTop
= ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
;
296 MemoryTop
= FreeMemoryTop
;
297 } else if (PhitResourceHob
->PhysicalStart
+ PhitResourceHob
->ResourceLength
- Hob
.HandoffInformationTable
->EfiMemoryTop
>= MinimalNeededSize
) {
299 // New availiable Memory range in new hob is right above memory top in old hob.
301 MemoryBottom
= Hob
.HandoffInformationTable
->EfiFreeMemoryTop
;
302 FreeMemoryBottom
= Hob
.HandoffInformationTable
->EfiMemoryTop
;
303 FreeMemoryTop
= FreeMemoryBottom
+ MinimalNeededSize
;
304 MemoryTop
= FreeMemoryTop
;
305 } else if (Hob
.HandoffInformationTable
->EfiMemoryBottom
- PhitResourceHob
->PhysicalStart
>= MinimalNeededSize
) {
307 // New availiable Memory range in new hob is right below memory bottom in old hob.
309 MemoryBottom
= Hob
.HandoffInformationTable
->EfiMemoryBottom
- MinimalNeededSize
;
310 FreeMemoryBottom
= MemoryBottom
;
311 FreeMemoryTop
= Hob
.HandoffInformationTable
->EfiMemoryBottom
;
312 MemoryTop
= Hob
.HandoffInformationTable
->EfiMemoryTop
;
315 // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob
316 // Find another Resource Descriptor Hob
318 ResourceHob
= FindAnotherHighestBelow4GResourceDescriptor(Hob
.Raw
, MinimalNeededSize
, PhitResourceHob
);
319 if (ResourceHob
== NULL
) {
320 return EFI_NOT_FOUND
;
323 MemoryBottom
= ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- MinimalNeededSize
;
324 FreeMemoryBottom
= MemoryBottom
;
325 FreeMemoryTop
= ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
;
326 MemoryTop
= FreeMemoryTop
;
328 HobConstructor ((VOID
*) (UINTN
) MemoryBottom
, (VOID
*) (UINTN
) MemoryTop
, (VOID
*) (UINTN
) FreeMemoryBottom
, (VOID
*) (UINTN
) FreeMemoryTop
);
330 // From now on, mHobList will point to the new Hob range.
334 // Create an empty FvHob for the DXE FV that contains DXE core.
336 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) 0, 0);
338 // Since payload created new Hob, move all hobs except PHIT from boot loader hob list.
340 while (!END_OF_HOB_LIST (Hob
)) {
341 if (Hob
.Header
->HobType
!= EFI_HOB_TYPE_HANDOFF
) {
342 // Add this hob to payload HOB
345 Hob
.Raw
= GET_NEXT_HOB (Hob
);
349 // Get DXE FV location
351 GuidHob
= GetFirstGuidHob(&gUniversalPayloadExtraDataGuid
);
352 ASSERT (GuidHob
!= NULL
);
353 ExtraData
= (UNIVERSAL_PAYLOAD_EXTRA_DATA
*) GET_GUID_HOB_DATA (GuidHob
);
354 ASSERT (ExtraData
->Count
== 1);
355 ASSERT (AsciiStrCmp (ExtraData
->Entry
[0].Identifier
, "uefi_fv") == 0);
357 *DxeFv
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) ExtraData
->Entry
[0].Base
;
358 ASSERT ((*DxeFv
)->FvLength
== ExtraData
->Entry
[0].Size
);
361 // Create guid hob for acpi board information
363 GuidHob
= GetFirstGuidHob(&gUniversalPayloadAcpiTableGuid
);
364 if (GuidHob
!= NULL
) {
365 AcpiTable
= (UNIVERSAL_PAYLOAD_ACPI_TABLE
*) GET_GUID_HOB_DATA (GuidHob
);
366 AcpiBoardInfo
= BuildHobFromAcpi ((UINT64
)AcpiTable
->Rsdp
);
367 ASSERT (AcpiBoardInfo
!= NULL
);
371 // Update DXE FV information to first fv hob in the hob list, which
372 // is the empty FvHob created before.
374 FvHob
= GetFirstHob (EFI_HOB_TYPE_FV
);
375 FvHob
->BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) *DxeFv
;
376 FvHob
->Length
= (*DxeFv
)->FvLength
;
381 Entry point to the C language phase of UEFI payload.
383 @param[in] BootloaderParameter The starting address of bootloader parameter block.
385 @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
390 IN UINTN BootloaderParameter
394 PHYSICAL_ADDRESS DxeCoreEntryPoint
;
395 EFI_PEI_HOB_POINTERS Hob
;
396 EFI_FIRMWARE_VOLUME_HEADER
*DxeFv
;
398 mHobList
= (VOID
*) BootloaderParameter
;
400 // Call constructor for all libraries
401 ProcessLibraryConstructorList ();
403 DEBUG ((DEBUG_INFO
, "Entering Universal Payload...\n"));
404 DEBUG ((DEBUG_INFO
, "sizeof(UINTN) = 0x%x\n", sizeof(UINTN
)));
408 // Dump the Hobs from boot loader
413 // Initialize floating point operating environment to be compliant with UEFI spec.
414 InitializeFloatingPointUnits ();
416 // Build HOB based on information from Bootloader
417 Status
= BuildHobs (BootloaderParameter
, &DxeFv
);
418 ASSERT_EFI_ERROR (Status
);
420 FixUpPcdDatabase (DxeFv
);
421 Status
= UniversalLoadDxeCore (DxeFv
, &DxeCoreEntryPoint
);
422 ASSERT_EFI_ERROR (Status
);
425 // Mask off all legacy 8259 interrupt sources
427 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, 0xFF);
428 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, 0xFF);
430 Hob
.HandoffInformationTable
= (EFI_HOB_HANDOFF_INFO_TABLE
*) GetFirstHob(EFI_HOB_TYPE_HANDOFF
);
431 HandOffToDxeCore (DxeCoreEntryPoint
, Hob
);
433 // Should not get here