3 Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
8 #include "UefiPayloadEntry.h"
10 STATIC UINT32 mTopOfLowerUsableDram
= 0;
13 Callback function to build resource descriptor HOB
15 This function build a HOB based on the memory map entry info.
16 It creates only EFI_RESOURCE_MEMORY_MAPPED_IO and EFI_RESOURCE_MEMORY_RESERVED
19 @param MemoryMapEntry Memory map entry info got from bootloader.
20 @param Params A pointer to ACPI_BOARD_INFO.
22 @retval EFI_SUCCESS Successfully build a HOB.
23 @retval EFI_INVALID_PARAMETER Invalid parameter provided.
27 IN MEMROY_MAP_ENTRY
*MemoryMapEntry
,
31 EFI_PHYSICAL_ADDRESS Base
;
32 EFI_RESOURCE_TYPE Type
;
34 EFI_RESOURCE_ATTRIBUTE_TYPE Attribue
;
35 ACPI_BOARD_INFO
*AcpiBoardInfo
;
37 AcpiBoardInfo
= (ACPI_BOARD_INFO
*)Params
;
38 if (AcpiBoardInfo
== NULL
) {
39 return EFI_INVALID_PARAMETER
;
43 // Skip types already handled in MemInfoCallback
45 if (MemoryMapEntry
->Type
== E820_RAM
|| MemoryMapEntry
->Type
== E820_ACPI
) {
49 if (MemoryMapEntry
->Base
== AcpiBoardInfo
->PcieBaseAddress
) {
51 // MMCONF is always MMIO
53 Type
= EFI_RESOURCE_MEMORY_MAPPED_IO
;
54 } else if (MemoryMapEntry
->Base
< mTopOfLowerUsableDram
) {
56 // It's in DRAM and thus must be reserved
58 Type
= EFI_RESOURCE_MEMORY_RESERVED
;
59 } else if ((MemoryMapEntry
->Base
< 0x100000000ULL
) && (MemoryMapEntry
->Base
>= mTopOfLowerUsableDram
)) {
61 // It's not in DRAM, must be MMIO
63 Type
= EFI_RESOURCE_MEMORY_MAPPED_IO
;
65 Type
= EFI_RESOURCE_MEMORY_RESERVED
;
68 Base
= MemoryMapEntry
->Base
;
69 Size
= MemoryMapEntry
->Size
;
71 Attribue
= EFI_RESOURCE_ATTRIBUTE_PRESENT
|
72 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
73 EFI_RESOURCE_ATTRIBUTE_TESTED
|
74 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
75 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
|
76 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
|
77 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
;
79 BuildResourceDescriptorHob (Type
, Attribue
, (EFI_PHYSICAL_ADDRESS
)Base
, Size
);
80 DEBUG ((DEBUG_INFO
, "buildhob: base = 0x%lx, size = 0x%lx, type = 0x%x\n", Base
, Size
, Type
));
82 if (MemoryMapEntry
->Type
== E820_UNUSABLE
||
83 MemoryMapEntry
->Type
== E820_DISABLED
) {
84 BuildMemoryAllocationHob (Base
, Size
, EfiUnusableMemory
);
85 } else if (MemoryMapEntry
->Type
== E820_PMEM
) {
86 BuildMemoryAllocationHob (Base
, Size
, EfiPersistentMemory
);
94 Callback function to find TOLUD (Top of Lower Usable DRAM)
96 Estimate where TOLUD (Top of Lower Usable DRAM) resides. The exact position
97 would require platform specific code.
99 @param MemoryMapEntry Memory map entry info got from bootloader.
100 @param Params Not used for now.
102 @retval EFI_SUCCESS Successfully updated mTopOfLowerUsableDram.
106 IN MEMROY_MAP_ENTRY
*MemoryMapEntry
,
111 // This code assumes that the memory map on this x86 machine below 4GiB is continous
112 // until TOLUD. In addition it assumes that the bootloader provided memory tables have
113 // no "holes" and thus the first memory range not covered by e820 marks the end of
114 // usable DRAM. In addition it's assumed that every reserved memory region touching
115 // usable RAM is also covering DRAM, everything else that is marked reserved thus must be
116 // MMIO not detectable by bootloader/OS
120 // Skip memory types not RAM or reserved
122 if ((MemoryMapEntry
->Type
== E820_UNUSABLE
) || (MemoryMapEntry
->Type
== E820_DISABLED
) ||
123 (MemoryMapEntry
->Type
== E820_PMEM
)) {
128 // Skip resources above 4GiB
130 if ((MemoryMapEntry
->Base
+ MemoryMapEntry
->Size
) > 0x100000000ULL
) {
134 if ((MemoryMapEntry
->Type
== E820_RAM
) || (MemoryMapEntry
->Type
== E820_ACPI
) ||
135 (MemoryMapEntry
->Type
== E820_NVS
)) {
137 // It's usable DRAM. Update TOLUD.
139 if (mTopOfLowerUsableDram
< (MemoryMapEntry
->Base
+ MemoryMapEntry
->Size
)) {
140 mTopOfLowerUsableDram
= (UINT32
)(MemoryMapEntry
->Base
+ MemoryMapEntry
->Size
);
144 // It might be 'reserved DRAM' or 'MMIO'.
146 // If it touches usable DRAM at Base assume it's DRAM as well,
147 // as it could be bootloader installed tables, TSEG, GTT, ...
149 if (mTopOfLowerUsableDram
== MemoryMapEntry
->Base
) {
150 mTopOfLowerUsableDram
= (UINT32
)(MemoryMapEntry
->Base
+ MemoryMapEntry
->Size
);
159 Callback function to build resource descriptor HOB
161 This function build a HOB based on the memory map entry info.
162 Only add EFI_RESOURCE_SYSTEM_MEMORY.
164 @param MemoryMapEntry Memory map entry info got from bootloader.
165 @param Params Not used for now.
167 @retval RETURN_SUCCESS Successfully build a HOB.
171 IN MEMROY_MAP_ENTRY
*MemoryMapEntry
,
175 EFI_PHYSICAL_ADDRESS Base
;
176 EFI_RESOURCE_TYPE Type
;
178 EFI_RESOURCE_ATTRIBUTE_TYPE Attribue
;
181 // Skip everything not known to be usable DRAM.
182 // It will be added later.
184 if ((MemoryMapEntry
->Type
!= E820_RAM
) && (MemoryMapEntry
->Type
!= E820_ACPI
) &&
185 (MemoryMapEntry
->Type
!= E820_NVS
)) {
186 return RETURN_SUCCESS
;
189 Type
= EFI_RESOURCE_SYSTEM_MEMORY
;
190 Base
= MemoryMapEntry
->Base
;
191 Size
= MemoryMapEntry
->Size
;
193 Attribue
= EFI_RESOURCE_ATTRIBUTE_PRESENT
|
194 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
195 EFI_RESOURCE_ATTRIBUTE_TESTED
|
196 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
197 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
|
198 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
|
199 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
;
201 BuildResourceDescriptorHob (Type
, Attribue
, (EFI_PHYSICAL_ADDRESS
)Base
, Size
);
202 DEBUG ((DEBUG_INFO
, "buildhob: base = 0x%lx, size = 0x%lx, type = 0x%x\n", Base
, Size
, Type
));
204 if (MemoryMapEntry
->Type
== E820_ACPI
) {
205 BuildMemoryAllocationHob (Base
, Size
, EfiACPIReclaimMemory
);
206 } else if (MemoryMapEntry
->Type
== E820_NVS
) {
207 BuildMemoryAllocationHob (Base
, Size
, EfiACPIMemoryNVS
);
210 return RETURN_SUCCESS
;
216 It will build HOBs based on information from bootloaders.
218 @retval EFI_SUCCESS If it completed successfully.
219 @retval Others If it failed to build required HOBs.
227 SYSTEM_TABLE_INFO SysTableInfo
;
228 SYSTEM_TABLE_INFO
*NewSysTableInfo
;
229 ACPI_BOARD_INFO
*AcpiBoardInfo
;
230 EFI_PEI_GRAPHICS_INFO_HOB GfxInfo
;
231 EFI_PEI_GRAPHICS_INFO_HOB
*NewGfxInfo
;
232 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB GfxDeviceInfo
;
233 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB
*NewGfxDeviceInfo
;
234 UNIVERSAL_PAYLOAD_SMBIOS_TABLE
*SmBiosTableHob
;
235 UNIVERSAL_PAYLOAD_ACPI_TABLE
*AcpiTableHob
;
240 DEBUG ((DEBUG_INFO
, "Guessing Top of Lower Usable DRAM:\n"));
241 Status
= ParseMemoryInfo (FindToludCallback
, NULL
);
242 if (EFI_ERROR(Status
)) {
245 DEBUG ((DEBUG_INFO
, "Assuming TOLUD = 0x%x\n", mTopOfLowerUsableDram
));
248 // Parse memory info and build memory HOBs for Usable RAM
250 DEBUG ((DEBUG_INFO
, "Building ResourceDescriptorHobs for usable memory:\n"));
251 Status
= ParseMemoryInfo (MemInfoCallback
, NULL
);
252 if (EFI_ERROR(Status
)) {
257 // Create guid hob for frame buffer information
259 Status
= ParseGfxInfo (&GfxInfo
);
260 if (!EFI_ERROR (Status
)) {
261 NewGfxInfo
= BuildGuidHob (&gEfiGraphicsInfoHobGuid
, sizeof (GfxInfo
));
262 ASSERT (NewGfxInfo
!= NULL
);
263 CopyMem (NewGfxInfo
, &GfxInfo
, sizeof (GfxInfo
));
264 DEBUG ((DEBUG_INFO
, "Created graphics info hob\n"));
268 Status
= ParseGfxDeviceInfo (&GfxDeviceInfo
);
269 if (!EFI_ERROR (Status
)) {
270 NewGfxDeviceInfo
= BuildGuidHob (&gEfiGraphicsDeviceInfoHobGuid
, sizeof (GfxDeviceInfo
));
271 ASSERT (NewGfxDeviceInfo
!= NULL
);
272 CopyMem (NewGfxDeviceInfo
, &GfxDeviceInfo
, sizeof (GfxDeviceInfo
));
273 DEBUG ((DEBUG_INFO
, "Created graphics device info hob\n"));
278 // Create guid hob for system tables like acpi table and smbios table
280 Status
= ParseSystemTable(&SysTableInfo
);
281 ASSERT_EFI_ERROR (Status
);
282 if (!EFI_ERROR (Status
)) {
283 NewSysTableInfo
= BuildGuidHob (&gUefiSystemTableInfoGuid
, sizeof (SYSTEM_TABLE_INFO
));
284 ASSERT (NewSysTableInfo
!= NULL
);
285 CopyMem (NewSysTableInfo
, &SysTableInfo
, sizeof (SYSTEM_TABLE_INFO
));
286 DEBUG ((DEBUG_INFO
, "Detected Acpi Table at 0x%lx, length 0x%x\n", SysTableInfo
.AcpiTableBase
, SysTableInfo
.AcpiTableSize
));
287 DEBUG ((DEBUG_INFO
, "Detected Smbios Table at 0x%lx, length 0x%x\n", SysTableInfo
.SmbiosTableBase
, SysTableInfo
.SmbiosTableSize
));
290 // Creat SmBios table Hob
292 SmBiosTableHob
= BuildGuidHob (&gUniversalPayloadSmbiosTableGuid
, sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE
));
293 ASSERT (SmBiosTableHob
!= NULL
);
294 SmBiosTableHob
->Header
.Revision
= UNIVERSAL_PAYLOAD_SMBIOS_TABLE_REVISION
;
295 SmBiosTableHob
->Header
.Length
= sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE
);
296 SmBiosTableHob
->SmBiosEntryPoint
= SysTableInfo
.SmbiosTableBase
;
297 DEBUG ((DEBUG_INFO
, "Create smbios table gUniversalPayloadSmbiosTableGuid guid hob\n"));
300 // Creat ACPI table Hob
302 AcpiTableHob
= BuildGuidHob (&gUniversalPayloadAcpiTableGuid
, sizeof (UNIVERSAL_PAYLOAD_ACPI_TABLE
));
303 ASSERT (AcpiTableHob
!= NULL
);
304 AcpiTableHob
->Header
.Revision
= UNIVERSAL_PAYLOAD_ACPI_TABLE_REVISION
;
305 AcpiTableHob
->Header
.Length
= sizeof (UNIVERSAL_PAYLOAD_ACPI_TABLE
);
306 AcpiTableHob
->Rsdp
= SysTableInfo
.AcpiTableBase
;
307 DEBUG ((DEBUG_INFO
, "Create smbios table gUniversalPayloadAcpiTableGuid guid hob\n"));
310 // Create guid hob for acpi board information
312 AcpiBoardInfo
= BuildHobFromAcpi (SysTableInfo
.AcpiTableBase
);
313 ASSERT (AcpiBoardInfo
!= NULL
);
316 // Parse memory info and build memory HOBs for reserved DRAM and MMIO
318 DEBUG ((DEBUG_INFO
, "Building ResourceDescriptorHobs for reserved memory:\n"));
319 Status
= ParseMemoryInfo (MemInfoCallbackMmio
, AcpiBoardInfo
);
320 if (EFI_ERROR(Status
)) {
325 // Parse the misc info provided by bootloader
327 Status
= ParseMiscInfo ();
328 if (EFI_ERROR (Status
)) {
329 DEBUG ((DEBUG_WARN
, "Error when parsing misc info, Status = %r\n", Status
));
333 // Parse platform specific information.
335 Status
= ParsePlatformInfo ();
336 if (EFI_ERROR (Status
)) {
337 DEBUG ((DEBUG_ERROR
, "Error when parsing platform info, Status = %r\n", Status
));
346 This function will build some generic HOBs that doesn't depend on information from bootloaders.
355 UINT8 PhysicalAddressBits
;
356 EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute
;
358 // The UEFI payload FV
359 BuildMemoryAllocationHob (PcdGet32 (PcdPayloadFdMemBase
), PcdGet32 (PcdPayloadFdMemSize
), EfiBootServicesData
);
362 // Build CPU memory space and IO space hob
364 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
365 if (RegEax
>= 0x80000008) {
366 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
367 PhysicalAddressBits
= (UINT8
) RegEax
;
369 PhysicalAddressBits
= 36;
372 BuildCpuHob (PhysicalAddressBits
, 16);
375 // Report Local APIC range, cause sbl HOB to be NULL, comment now
377 ResourceAttribute
= (
378 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
379 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
380 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
381 EFI_RESOURCE_ATTRIBUTE_TESTED
383 BuildResourceDescriptorHob (EFI_RESOURCE_MEMORY_MAPPED_IO
, ResourceAttribute
, 0xFEC80000, SIZE_512KB
);
384 BuildMemoryAllocationHob ( 0xFEC80000, SIZE_512KB
, EfiMemoryMappedIO
);
390 Entry point to the C language phase of UEFI payload.
392 @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
397 IN UINTN BootloaderParameter
401 PHYSICAL_ADDRESS DxeCoreEntryPoint
;
405 EFI_PEI_HOB_POINTERS Hob
;
406 SERIAL_PORT_INFO SerialPortInfo
;
407 UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO
*UniversalSerialPort
;
409 PcdSet64S (PcdBootloaderParameter
, BootloaderParameter
);
410 // Initialize floating point operating environment to be compliant with UEFI spec.
411 InitializeFloatingPointUnits ();
413 // HOB region is used for HOB and memory allocation for this module
414 MemBase
= PcdGet32 (PcdPayloadFdMemBase
);
415 HobMemBase
= ALIGN_VALUE (MemBase
+ PcdGet32 (PcdPayloadFdMemSize
), SIZE_1MB
);
416 HobMemTop
= HobMemBase
+ FixedPcdGet32 (PcdSystemMemoryUefiRegionSize
);
418 HobConstructor ((VOID
*)MemBase
, (VOID
*)HobMemTop
, (VOID
*)HobMemBase
, (VOID
*)HobMemTop
);
421 // Build serial port info
423 Status
= ParseSerialInfo (&SerialPortInfo
);
424 if (!EFI_ERROR (Status
)) {
425 UniversalSerialPort
= BuildGuidHob (&gUniversalPayloadSerialPortInfoGuid
, sizeof (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO
));
426 ASSERT (UniversalSerialPort
!= NULL
);
427 UniversalSerialPort
->Header
.Revision
= UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO_REVISION
;
428 UniversalSerialPort
->Header
.Length
= sizeof (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO
);
429 UniversalSerialPort
->UseMmio
= (SerialPortInfo
.Type
== 1)?FALSE
:TRUE
;
430 UniversalSerialPort
->RegisterBase
= SerialPortInfo
.BaseAddr
;
431 UniversalSerialPort
->BaudRate
= SerialPortInfo
.Baud
;
432 UniversalSerialPort
->RegisterStride
= (UINT8
)SerialPortInfo
.RegWidth
;
435 // The library constructors might depend on serial port, so call it after serial port hob
436 ProcessLibraryConstructorList ();
437 DEBUG ((DEBUG_INFO
, "sizeof(UINTN) = 0x%x\n", sizeof(UINTN
)));
439 // Build HOB based on information from Bootloader
440 Status
= BuildHobFromBl ();
441 if (EFI_ERROR (Status
)) {
442 DEBUG ((DEBUG_ERROR
, "BuildHobFromBl Status = %r\n", Status
));
446 // Build other HOBs required by DXE
450 Status
= LoadDxeCore (&DxeCoreEntryPoint
);
451 ASSERT_EFI_ERROR (Status
);
453 DEBUG ((DEBUG_INFO
, "DxeCoreEntryPoint = 0x%lx\n", DxeCoreEntryPoint
));
456 // Mask off all legacy 8259 interrupt sources
458 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, 0xFF);
459 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, 0xFF);
461 Hob
.HandoffInformationTable
= (EFI_HOB_HANDOFF_INFO_TABLE
*) GetFirstHob(EFI_HOB_TYPE_HANDOFF
);
462 HandOffToDxeCore (DxeCoreEntryPoint
, Hob
);
464 // Should not get here