3 Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
8 #include "UefiPayloadEntry.h"
11 Callback function to build resource descriptor HOB
13 This function build a HOB based on the memory map entry info.
15 @param MemoryMapEntry Memory map entry info got from bootloader.
16 @param Params Not used for now.
18 @retval RETURN_SUCCESS Successfully build a HOB.
22 IN MEMROY_MAP_ENTRY
*MemoryMapEntry
,
26 EFI_PHYSICAL_ADDRESS Base
;
27 EFI_RESOURCE_TYPE Type
;
29 EFI_RESOURCE_ATTRIBUTE_TYPE Attribue
;
31 Type
= (MemoryMapEntry
->Type
== 1) ? EFI_RESOURCE_SYSTEM_MEMORY
: EFI_RESOURCE_MEMORY_RESERVED
;
32 Base
= MemoryMapEntry
->Base
;
33 Size
= MemoryMapEntry
->Size
;
35 Attribue
= EFI_RESOURCE_ATTRIBUTE_PRESENT
|
36 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
37 EFI_RESOURCE_ATTRIBUTE_TESTED
|
38 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
39 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
|
40 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
|
41 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
;
43 if (Base
>= BASE_4GB
) {
44 // Remove tested attribute to avoid DXE core to dispatch driver to memory above 4GB
45 Attribue
&= ~EFI_RESOURCE_ATTRIBUTE_TESTED
;
48 BuildResourceDescriptorHob (Type
, Attribue
, (EFI_PHYSICAL_ADDRESS
)Base
, Size
);
49 DEBUG ((DEBUG_INFO
, "buildhob: base = 0x%lx, size = 0x%lx, type = 0x%x\n", Base
, Size
, Type
));
51 return RETURN_SUCCESS
;
57 Find the board related info from ACPI table
59 @param AcpiTableBase ACPI table start address in memory
60 @param AcpiBoardInfo Pointer to the acpi board info strucutre
62 @retval RETURN_SUCCESS Successfully find out all the required information.
63 @retval RETURN_NOT_FOUND Failed to find the required info.
68 IN UINT64 AcpiTableBase
,
69 OUT ACPI_BOARD_INFO
*AcpiBoardInfo
72 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*Rsdp
;
73 EFI_ACPI_DESCRIPTION_HEADER
*Rsdt
;
76 EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt
;
77 EFI_ACPI_DESCRIPTION_HEADER
*Xsdt
;
82 EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER
*MmCfgHdr
;
83 EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE
*MmCfgBase
;
85 Rsdp
= (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)(UINTN
)AcpiTableBase
;
86 DEBUG ((DEBUG_INFO
, "Rsdp at 0x%p\n", Rsdp
));
87 DEBUG ((DEBUG_INFO
, "Rsdt at 0x%x, Xsdt at 0x%lx\n", Rsdp
->RsdtAddress
, Rsdp
->XsdtAddress
));
94 Rsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*)(UINTN
)(Rsdp
->RsdtAddress
);
96 Entry32
= (UINT32
*)(Rsdt
+ 1);
97 Entry32Num
= (Rsdt
->Length
- sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) >> 2;
98 for (Idx
= 0; Idx
< Entry32Num
; Idx
++) {
99 Signature
= (UINT32
*)(UINTN
)Entry32
[Idx
];
100 if (*Signature
== EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
) {
101 Fadt
= (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*)Signature
;
102 DEBUG ((DEBUG_INFO
, "Found Fadt in Rsdt\n"));
105 if (*Signature
== EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
) {
106 MmCfgHdr
= (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER
*)Signature
;
107 DEBUG ((DEBUG_INFO
, "Found MM config address in Rsdt\n"));
110 if ((Fadt
!= NULL
) && (MmCfgHdr
!= NULL
)) {
117 // Search Xsdt Second
119 Xsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*)(UINTN
)(Rsdp
->XsdtAddress
);
121 Entry64
= (UINT64
*)(Xsdt
+ 1);
122 Entry64Num
= (Xsdt
->Length
- sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) >> 3;
123 for (Idx
= 0; Idx
< Entry64Num
; Idx
++) {
124 Signature
= (UINT32
*)(UINTN
)Entry64
[Idx
];
125 if (*Signature
== EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
) {
126 Fadt
= (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*)Signature
;
127 DEBUG ((DEBUG_INFO
, "Found Fadt in Xsdt\n"));
130 if (*Signature
== EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
) {
131 MmCfgHdr
= (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER
*)Signature
;
132 DEBUG ((DEBUG_INFO
, "Found MM config address in Xsdt\n"));
135 if ((Fadt
!= NULL
) && (MmCfgHdr
!= NULL
)) {
142 return RETURN_NOT_FOUND
;
147 AcpiBoardInfo
->PmCtrlRegBase
= Fadt
->Pm1aCntBlk
;
148 AcpiBoardInfo
->PmTimerRegBase
= Fadt
->PmTmrBlk
;
149 AcpiBoardInfo
->ResetRegAddress
= Fadt
->ResetReg
.Address
;
150 AcpiBoardInfo
->ResetValue
= Fadt
->ResetValue
;
151 AcpiBoardInfo
->PmEvtBase
= Fadt
->Pm1aEvtBlk
;
152 AcpiBoardInfo
->PmGpeEnBase
= Fadt
->Gpe0Blk
+ Fadt
->Gpe0BlkLen
/ 2;
154 if (MmCfgHdr
!= NULL
) {
155 MmCfgBase
= (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE
*)((UINT8
*) MmCfgHdr
+ sizeof (*MmCfgHdr
));
156 AcpiBoardInfo
->PcieBaseAddress
= MmCfgBase
->BaseAddress
;
157 AcpiBoardInfo
->PcieBaseSize
= (MmCfgBase
->EndBusNumber
+ 1 - MmCfgBase
->StartBusNumber
) * 4096 * 32 * 8;
159 AcpiBoardInfo
->PcieBaseAddress
= 0;
160 AcpiBoardInfo
->PcieBaseSize
= 0;
162 DEBUG ((DEBUG_INFO
, "PmCtrl Reg 0x%lx\n", AcpiBoardInfo
->PmCtrlRegBase
));
163 DEBUG ((DEBUG_INFO
, "PmTimer Reg 0x%lx\n", AcpiBoardInfo
->PmTimerRegBase
));
164 DEBUG ((DEBUG_INFO
, "Reset Reg 0x%lx\n", AcpiBoardInfo
->ResetRegAddress
));
165 DEBUG ((DEBUG_INFO
, "Reset Value 0x%x\n", AcpiBoardInfo
->ResetValue
));
166 DEBUG ((DEBUG_INFO
, "PmEvt Reg 0x%lx\n", AcpiBoardInfo
->PmEvtBase
));
167 DEBUG ((DEBUG_INFO
, "PmGpeEn Reg 0x%lx\n", AcpiBoardInfo
->PmGpeEnBase
));
168 DEBUG ((DEBUG_INFO
, "PcieBaseAddr 0x%lx\n", AcpiBoardInfo
->PcieBaseAddress
));
169 DEBUG ((DEBUG_INFO
, "PcieBaseSize 0x%lx\n", AcpiBoardInfo
->PcieBaseSize
));
172 // Verify values for proper operation
174 ASSERT(Fadt
->Pm1aCntBlk
!= 0);
175 ASSERT(Fadt
->PmTmrBlk
!= 0);
176 ASSERT(Fadt
->ResetReg
.Address
!= 0);
177 ASSERT(Fadt
->Pm1aEvtBlk
!= 0);
178 ASSERT(Fadt
->Gpe0Blk
!= 0);
184 // Check the consistency of SCI enabling
190 if (Fadt
->Pm1CntLen
== 4) {
191 SciEnabled
= (IoRead32 (Fadt
->Pm1aCntBlk
) & BIT0
)? TRUE
: FALSE
;
194 // if (Pm1CntLen == 2), use 16 bit IO read;
195 // if (Pm1CntLen != 2 && Pm1CntLen != 4), use 16 bit IO read as a fallback
197 SciEnabled
= (IoRead16 (Fadt
->Pm1aCntBlk
) & BIT0
)? TRUE
: FALSE
;
200 if (!(Fadt
->Flags
& EFI_ACPI_5_0_HW_REDUCED_ACPI
) &&
201 (Fadt
->SmiCmd
== 0) &&
204 // The ACPI enabling status is inconsistent: SCI is not enabled but ACPI
205 // table does not provide a means to enable it through FADT->SmiCmd
207 DEBUG ((DEBUG_ERROR
, "ERROR: The ACPI enabling status is inconsistent: SCI is not"
208 " enabled but the ACPI table does not provide a means to enable it through FADT->SmiCmd."
209 " This may cause issues in OS.\n"));
213 return RETURN_SUCCESS
;
218 It will build HOBs based on information from bootloaders.
220 @retval EFI_SUCCESS If it completed successfully.
221 @retval Others If it failed to build required HOBs.
229 SYSTEM_TABLE_INFO SysTableInfo
;
230 SYSTEM_TABLE_INFO
*NewSysTableInfo
;
231 ACPI_BOARD_INFO AcpiBoardInfo
;
232 ACPI_BOARD_INFO
*NewAcpiBoardInfo
;
233 EFI_PEI_GRAPHICS_INFO_HOB GfxInfo
;
234 EFI_PEI_GRAPHICS_INFO_HOB
*NewGfxInfo
;
235 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB GfxDeviceInfo
;
236 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB
*NewGfxDeviceInfo
;
237 UNIVERSAL_PAYLOAD_SMBIOS_TABLE
*SmBiosTableHob
;
240 // Parse memory info and build memory HOBs
242 Status
= ParseMemoryInfo (MemInfoCallback
, NULL
);
243 if (EFI_ERROR(Status
)) {
248 // Create guid hob for frame buffer information
250 Status
= ParseGfxInfo (&GfxInfo
);
251 if (!EFI_ERROR (Status
)) {
252 NewGfxInfo
= BuildGuidHob (&gEfiGraphicsInfoHobGuid
, sizeof (GfxInfo
));
253 ASSERT (NewGfxInfo
!= NULL
);
254 CopyMem (NewGfxInfo
, &GfxInfo
, sizeof (GfxInfo
));
255 DEBUG ((DEBUG_INFO
, "Created graphics info hob\n"));
259 Status
= ParseGfxDeviceInfo (&GfxDeviceInfo
);
260 if (!EFI_ERROR (Status
)) {
261 NewGfxDeviceInfo
= BuildGuidHob (&gEfiGraphicsDeviceInfoHobGuid
, sizeof (GfxDeviceInfo
));
262 ASSERT (NewGfxDeviceInfo
!= NULL
);
263 CopyMem (NewGfxDeviceInfo
, &GfxDeviceInfo
, sizeof (GfxDeviceInfo
));
264 DEBUG ((DEBUG_INFO
, "Created graphics device info hob\n"));
269 // Create guid hob for system tables like acpi table and smbios table
271 Status
= ParseSystemTable(&SysTableInfo
);
272 ASSERT_EFI_ERROR (Status
);
273 if (!EFI_ERROR (Status
)) {
274 NewSysTableInfo
= BuildGuidHob (&gUefiSystemTableInfoGuid
, sizeof (SYSTEM_TABLE_INFO
));
275 ASSERT (NewSysTableInfo
!= NULL
);
276 CopyMem (NewSysTableInfo
, &SysTableInfo
, sizeof (SYSTEM_TABLE_INFO
));
277 DEBUG ((DEBUG_INFO
, "Detected Acpi Table at 0x%lx, length 0x%x\n", SysTableInfo
.AcpiTableBase
, SysTableInfo
.AcpiTableSize
));
278 DEBUG ((DEBUG_INFO
, "Detected Smbios Table at 0x%lx, length 0x%x\n", SysTableInfo
.SmbiosTableBase
, SysTableInfo
.SmbiosTableSize
));
281 // Creat SmBios table Hob
283 SmBiosTableHob
= BuildGuidHob (&gUniversalPayloadSmbiosTableGuid
, sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE
));
284 ASSERT (SmBiosTableHob
!= NULL
);
285 SmBiosTableHob
->Header
.Revision
= UNIVERSAL_PAYLOAD_SMBIOS_TABLE_REVISION
;
286 SmBiosTableHob
->Header
.Length
= sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE
);
287 SmBiosTableHob
->SmBiosEntryPoint
= SysTableInfo
.SmbiosTableBase
;
288 DEBUG ((DEBUG_INFO
, "Create smbios table gUniversalPayloadSmbiosTableGuid guid hob\n"));
291 // Create guid hob for acpi board information
293 Status
= ParseAcpiInfo (SysTableInfo
.AcpiTableBase
, &AcpiBoardInfo
);
294 ASSERT_EFI_ERROR (Status
);
295 if (!EFI_ERROR (Status
)) {
296 NewAcpiBoardInfo
= BuildGuidHob (&gUefiAcpiBoardInfoGuid
, sizeof (ACPI_BOARD_INFO
));
297 ASSERT (NewAcpiBoardInfo
!= NULL
);
298 CopyMem (NewAcpiBoardInfo
, &AcpiBoardInfo
, sizeof (ACPI_BOARD_INFO
));
299 DEBUG ((DEBUG_INFO
, "Create acpi board info guid hob\n"));
303 // Parse platform specific information.
305 Status
= ParsePlatformInfo ();
306 if (EFI_ERROR (Status
)) {
307 DEBUG ((DEBUG_ERROR
, "Error when parsing platform info, Status = %r\n", Status
));
316 This function will build some generic HOBs that doesn't depend on information from bootloaders.
325 UINT8 PhysicalAddressBits
;
326 EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute
;
328 // The UEFI payload FV
329 BuildMemoryAllocationHob (PcdGet32 (PcdPayloadFdMemBase
), PcdGet32 (PcdPayloadFdMemSize
), EfiBootServicesData
);
332 // Build CPU memory space and IO space hob
334 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
335 if (RegEax
>= 0x80000008) {
336 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
337 PhysicalAddressBits
= (UINT8
) RegEax
;
339 PhysicalAddressBits
= 36;
342 BuildCpuHob (PhysicalAddressBits
, 16);
345 // Report Local APIC range, cause sbl HOB to be NULL, comment now
347 ResourceAttribute
= (
348 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
349 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
350 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
351 EFI_RESOURCE_ATTRIBUTE_TESTED
353 BuildResourceDescriptorHob (EFI_RESOURCE_MEMORY_MAPPED_IO
, ResourceAttribute
, 0xFEC80000, SIZE_512KB
);
354 BuildMemoryAllocationHob ( 0xFEC80000, SIZE_512KB
, EfiMemoryMappedIO
);
360 Entry point to the C language phase of UEFI payload.
362 @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
367 IN UINTN BootloaderParameter
371 PHYSICAL_ADDRESS DxeCoreEntryPoint
;
372 EFI_HOB_HANDOFF_INFO_TABLE
*HandoffHobTable
;
377 EFI_PEI_HOB_POINTERS Hob
;
379 // Call constructor for all libraries
380 ProcessLibraryConstructorList ();
382 DEBUG ((DEBUG_INFO
, "GET_BOOTLOADER_PARAMETER() = 0x%lx\n", GET_BOOTLOADER_PARAMETER()));
383 DEBUG ((DEBUG_INFO
, "sizeof(UINTN) = 0x%x\n", sizeof(UINTN
)));
385 // Initialize floating point operating environment to be compliant with UEFI spec.
386 InitializeFloatingPointUnits ();
388 // HOB region is used for HOB and memory allocation for this module
389 MemBase
= PcdGet32 (PcdPayloadFdMemBase
);
390 HobMemBase
= ALIGN_VALUE (MemBase
+ PcdGet32 (PcdPayloadFdMemSize
), SIZE_1MB
);
391 HobMemTop
= HobMemBase
+ FixedPcdGet32 (PcdSystemMemoryUefiRegionSize
);
393 // DXE core assumes the memory below HOB region could be used, so include the FV region memory into HOB range.
394 MemSize
= HobMemTop
- MemBase
;
395 HandoffHobTable
= HobConstructor ((VOID
*)MemBase
, MemSize
, (VOID
*)HobMemBase
, (VOID
*)HobMemTop
);
397 // Build HOB based on information from Bootloader
398 Status
= BuildHobFromBl ();
399 if (EFI_ERROR (Status
)) {
400 DEBUG ((DEBUG_ERROR
, "BuildHobFromBl Status = %r\n", Status
));
404 // Build other HOBs required by DXE
408 Status
= LoadDxeCore (&DxeCoreEntryPoint
);
409 ASSERT_EFI_ERROR (Status
);
411 DEBUG ((DEBUG_INFO
, "DxeCoreEntryPoint = 0x%lx\n", DxeCoreEntryPoint
));
414 // Mask off all legacy 8259 interrupt sources
416 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, 0xFF);
417 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, 0xFF);
419 Hob
.HandoffInformationTable
= HandoffHobTable
;
420 HandOffToDxeCore (DxeCoreEntryPoint
, Hob
);
422 // Should not get here