VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 15.7 KB
Line 
1/** @file
2
3 Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5
6**/
7
8#include <Guid/MemoryTypeInformation.h>
9#include "UefiPayloadEntry.h"
10
11STATIC UINT32 mTopOfLowerUsableDram = 0;
12
13EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
14 { EfiACPIReclaimMemory, FixedPcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory) },
15 { EfiACPIMemoryNVS, FixedPcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS) },
16 { EfiReservedMemoryType, FixedPcdGet32 (PcdMemoryTypeEfiReservedMemoryType) },
17 { EfiRuntimeServicesData, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesData) },
18 { EfiRuntimeServicesCode, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode) },
19 { EfiMaxMemoryType, 0 }
20};
21
22/**
23 Callback function to build resource descriptor HOB
24
25 This function build a HOB based on the memory map entry info.
26 It creates only EFI_RESOURCE_MEMORY_MAPPED_IO and EFI_RESOURCE_MEMORY_RESERVED
27 resources.
28
29 @param MemoryMapEntry Memory map entry info got from bootloader.
30 @param Params A pointer to ACPI_BOARD_INFO.
31
32 @retval EFI_SUCCESS Successfully build a HOB.
33 @retval EFI_INVALID_PARAMETER Invalid parameter provided.
34**/
35EFI_STATUS
36MemInfoCallbackMmio (
37 IN MEMORY_MAP_ENTRY *MemoryMapEntry,
38 IN VOID *Params
39 )
40{
41 EFI_PHYSICAL_ADDRESS Base;
42 EFI_RESOURCE_TYPE Type;
43 UINT64 Size;
44 EFI_RESOURCE_ATTRIBUTE_TYPE Attribue;
45 ACPI_BOARD_INFO *AcpiBoardInfo;
46
47 AcpiBoardInfo = (ACPI_BOARD_INFO *)Params;
48 if (AcpiBoardInfo == NULL) {
49 return EFI_INVALID_PARAMETER;
50 }
51
52 //
53 // Skip types already handled in MemInfoCallback
54 //
55 if ((MemoryMapEntry->Type == E820_RAM) || (MemoryMapEntry->Type == E820_ACPI)) {
56 return EFI_SUCCESS;
57 }
58
59 if (MemoryMapEntry->Base == AcpiBoardInfo->PcieBaseAddress) {
60 //
61 // MMCONF is always MMIO
62 //
63 Type = EFI_RESOURCE_MEMORY_MAPPED_IO;
64 } else if (MemoryMapEntry->Base < mTopOfLowerUsableDram) {
65 //
66 // It's in DRAM and thus must be reserved
67 //
68 Type = EFI_RESOURCE_MEMORY_RESERVED;
69 } else if ((MemoryMapEntry->Base < 0x100000000ULL) && (MemoryMapEntry->Base >= mTopOfLowerUsableDram)) {
70 //
71 // It's not in DRAM, must be MMIO
72 //
73 Type = EFI_RESOURCE_MEMORY_MAPPED_IO;
74 } else {
75 Type = EFI_RESOURCE_MEMORY_RESERVED;
76 }
77
78 Base = MemoryMapEntry->Base;
79 Size = MemoryMapEntry->Size;
80
81 Attribue = EFI_RESOURCE_ATTRIBUTE_PRESENT |
82 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
83 EFI_RESOURCE_ATTRIBUTE_TESTED |
84 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
85 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
86 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
87 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;
88
89 BuildResourceDescriptorHob (Type, Attribue, (EFI_PHYSICAL_ADDRESS)Base, Size);
90 DEBUG ((DEBUG_INFO, "buildhob: base = 0x%lx, size = 0x%lx, type = 0x%x\n", Base, Size, Type));
91
92 if ((MemoryMapEntry->Type == E820_UNUSABLE) ||
93 (MemoryMapEntry->Type == E820_DISABLED))
94 {
95 BuildMemoryAllocationHob (Base, Size, EfiUnusableMemory);
96 } else if (MemoryMapEntry->Type == E820_PMEM) {
97 BuildMemoryAllocationHob (Base, Size, EfiPersistentMemory);
98 }
99
100 return EFI_SUCCESS;
101}
102
103/**
104 Callback function to find TOLUD (Top of Lower Usable DRAM)
105
106 Estimate where TOLUD (Top of Lower Usable DRAM) resides. The exact position
107 would require platform specific code.
108
109 @param MemoryMapEntry Memory map entry info got from bootloader.
110 @param Params Not used for now.
111
112 @retval EFI_SUCCESS Successfully updated mTopOfLowerUsableDram.
113**/
114EFI_STATUS
115FindToludCallback (
116 IN MEMORY_MAP_ENTRY *MemoryMapEntry,
117 IN VOID *Params
118 )
119{
120 //
121 // This code assumes that the memory map on this x86 machine below 4GiB is continous
122 // until TOLUD. In addition it assumes that the bootloader provided memory tables have
123 // no "holes" and thus the first memory range not covered by e820 marks the end of
124 // usable DRAM. In addition it's assumed that every reserved memory region touching
125 // usable RAM is also covering DRAM, everything else that is marked reserved thus must be
126 // MMIO not detectable by bootloader/OS
127 //
128
129 //
130 // Skip memory types not RAM or reserved
131 //
132 if ((MemoryMapEntry->Type == E820_UNUSABLE) || (MemoryMapEntry->Type == E820_DISABLED) ||
133 (MemoryMapEntry->Type == E820_PMEM))
134 {
135 return EFI_SUCCESS;
136 }
137
138 //
139 // Skip resources above 4GiB
140 //
141 if ((MemoryMapEntry->Base + MemoryMapEntry->Size) > 0x100000000ULL) {
142 return EFI_SUCCESS;
143 }
144
145 if ((MemoryMapEntry->Type == E820_RAM) || (MemoryMapEntry->Type == E820_ACPI) ||
146 (MemoryMapEntry->Type == E820_NVS))
147 {
148 //
149 // It's usable DRAM. Update TOLUD.
150 //
151 if (mTopOfLowerUsableDram < (MemoryMapEntry->Base + MemoryMapEntry->Size)) {
152 mTopOfLowerUsableDram = (UINT32)(MemoryMapEntry->Base + MemoryMapEntry->Size);
153 }
154 } else {
155 //
156 // It might be 'reserved DRAM' or 'MMIO'.
157 //
158 // If it touches usable DRAM at Base assume it's DRAM as well,
159 // as it could be bootloader installed tables, TSEG, GTT, ...
160 //
161 if (mTopOfLowerUsableDram == MemoryMapEntry->Base) {
162 mTopOfLowerUsableDram = (UINT32)(MemoryMapEntry->Base + MemoryMapEntry->Size);
163 }
164 }
165
166 return EFI_SUCCESS;
167}
168
169/**
170 Callback function to build resource descriptor HOB
171
172 This function build a HOB based on the memory map entry info.
173 Only add EFI_RESOURCE_SYSTEM_MEMORY.
174
175 @param MemoryMapEntry Memory map entry info got from bootloader.
176 @param Params Not used for now.
177
178 @retval RETURN_SUCCESS Successfully build a HOB.
179**/
180EFI_STATUS
181MemInfoCallback (
182 IN MEMORY_MAP_ENTRY *MemoryMapEntry,
183 IN VOID *Params
184 )
185{
186 EFI_PHYSICAL_ADDRESS Base;
187 EFI_RESOURCE_TYPE Type;
188 UINT64 Size;
189 EFI_RESOURCE_ATTRIBUTE_TYPE Attribue;
190
191 //
192 // Skip everything not known to be usable DRAM.
193 // It will be added later.
194 //
195 if ((MemoryMapEntry->Type != E820_RAM) && (MemoryMapEntry->Type != E820_ACPI) &&
196 (MemoryMapEntry->Type != E820_NVS))
197 {
198 return RETURN_SUCCESS;
199 }
200
201 Type = EFI_RESOURCE_SYSTEM_MEMORY;
202 Base = MemoryMapEntry->Base;
203 Size = MemoryMapEntry->Size;
204
205 Attribue = EFI_RESOURCE_ATTRIBUTE_PRESENT |
206 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
207 EFI_RESOURCE_ATTRIBUTE_TESTED |
208 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
209 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
210 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
211 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;
212
213 BuildResourceDescriptorHob (Type, Attribue, (EFI_PHYSICAL_ADDRESS)Base, Size);
214 DEBUG ((DEBUG_INFO, "buildhob: base = 0x%lx, size = 0x%lx, type = 0x%x\n", Base, Size, Type));
215
216 if (MemoryMapEntry->Type == E820_ACPI) {
217 BuildMemoryAllocationHob (Base, Size, EfiACPIReclaimMemory);
218 } else if (MemoryMapEntry->Type == E820_NVS) {
219 BuildMemoryAllocationHob (Base, Size, EfiACPIMemoryNVS);
220 }
221
222 return RETURN_SUCCESS;
223}
224
225/**
226 It will build HOBs based on information from bootloaders.
227
228 @retval EFI_SUCCESS If it completed successfully.
229 @retval Others If it failed to build required HOBs.
230**/
231EFI_STATUS
232BuildHobFromBl (
233 VOID
234 )
235{
236 EFI_STATUS Status;
237 ACPI_BOARD_INFO *AcpiBoardInfo;
238 EFI_PEI_GRAPHICS_INFO_HOB GfxInfo;
239 EFI_PEI_GRAPHICS_INFO_HOB *NewGfxInfo;
240 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB GfxDeviceInfo;
241 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *NewGfxDeviceInfo;
242 UNIVERSAL_PAYLOAD_SMBIOS_TABLE *SmBiosTableHob;
243 UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTableHob;
244
245 //
246 // First find TOLUD
247 //
248 DEBUG ((DEBUG_INFO, "Guessing Top of Lower Usable DRAM:\n"));
249 Status = ParseMemoryInfo (FindToludCallback, NULL);
250 if (EFI_ERROR (Status)) {
251 return Status;
252 }
253
254 DEBUG ((DEBUG_INFO, "Assuming TOLUD = 0x%x\n", mTopOfLowerUsableDram));
255
256 //
257 // Parse memory info and build memory HOBs for Usable RAM
258 //
259 DEBUG ((DEBUG_INFO, "Building ResourceDescriptorHobs for usable memory:\n"));
260 Status = ParseMemoryInfo (MemInfoCallback, NULL);
261 if (EFI_ERROR (Status)) {
262 return Status;
263 }
264
265 //
266 // Create guid hob for frame buffer information
267 //
268 Status = ParseGfxInfo (&GfxInfo);
269 if (!EFI_ERROR (Status)) {
270 NewGfxInfo = BuildGuidHob (&gEfiGraphicsInfoHobGuid, sizeof (GfxInfo));
271 ASSERT (NewGfxInfo != NULL);
272 CopyMem (NewGfxInfo, &GfxInfo, sizeof (GfxInfo));
273 DEBUG ((DEBUG_INFO, "Created graphics info hob\n"));
274 }
275
276 Status = ParseGfxDeviceInfo (&GfxDeviceInfo);
277 if (!EFI_ERROR (Status)) {
278 NewGfxDeviceInfo = BuildGuidHob (&gEfiGraphicsDeviceInfoHobGuid, sizeof (GfxDeviceInfo));
279 ASSERT (NewGfxDeviceInfo != NULL);
280 CopyMem (NewGfxDeviceInfo, &GfxDeviceInfo, sizeof (GfxDeviceInfo));
281 DEBUG ((DEBUG_INFO, "Created graphics device info hob\n"));
282 }
283
284 //
285 // Creat SmBios table Hob
286 //
287 SmBiosTableHob = BuildGuidHob (&gUniversalPayloadSmbiosTableGuid, sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE));
288 ASSERT (SmBiosTableHob != NULL);
289 SmBiosTableHob->Header.Revision = UNIVERSAL_PAYLOAD_SMBIOS_TABLE_REVISION;
290 SmBiosTableHob->Header.Length = sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE);
291 DEBUG ((DEBUG_INFO, "Create smbios table gUniversalPayloadSmbiosTableGuid guid hob\n"));
292 Status = ParseSmbiosTable (SmBiosTableHob);
293 if (!EFI_ERROR (Status)) {
294 DEBUG ((DEBUG_INFO, "Detected Smbios Table at 0x%lx\n", SmBiosTableHob->SmBiosEntryPoint));
295 }
296
297 //
298 // Creat ACPI table Hob
299 //
300 AcpiTableHob = BuildGuidHob (&gUniversalPayloadAcpiTableGuid, sizeof (UNIVERSAL_PAYLOAD_ACPI_TABLE));
301 ASSERT (AcpiTableHob != NULL);
302 AcpiTableHob->Header.Revision = UNIVERSAL_PAYLOAD_ACPI_TABLE_REVISION;
303 AcpiTableHob->Header.Length = sizeof (UNIVERSAL_PAYLOAD_ACPI_TABLE);
304 DEBUG ((DEBUG_INFO, "Create ACPI table gUniversalPayloadAcpiTableGuid guid hob\n"));
305 Status = ParseAcpiTableInfo (AcpiTableHob);
306 if (!EFI_ERROR (Status)) {
307 DEBUG ((DEBUG_INFO, "Detected ACPI Table at 0x%lx\n", AcpiTableHob->Rsdp));
308 }
309
310 //
311 // Create guid hob for acpi board information
312 //
313 AcpiBoardInfo = BuildHobFromAcpi (AcpiTableHob->Rsdp);
314 ASSERT (AcpiBoardInfo != NULL);
315
316 //
317 // Parse memory info and build memory HOBs for reserved DRAM and MMIO
318 //
319 DEBUG ((DEBUG_INFO, "Building ResourceDescriptorHobs for reserved memory:\n"));
320 Status = ParseMemoryInfo (MemInfoCallbackMmio, AcpiBoardInfo);
321 if (EFI_ERROR (Status)) {
322 return Status;
323 }
324
325 //
326 // Parse the misc info provided by bootloader
327 //
328 Status = ParseMiscInfo ();
329 if (EFI_ERROR (Status)) {
330 DEBUG ((DEBUG_WARN, "Error when parsing misc info, Status = %r\n", Status));
331 }
332
333 //
334 // Parse platform specific information.
335 //
336 Status = ParsePlatformInfo ();
337 if (EFI_ERROR (Status)) {
338 DEBUG ((DEBUG_ERROR, "Error when parsing platform info, Status = %r\n", Status));
339 return Status;
340 }
341
342 return EFI_SUCCESS;
343}
344
345/**
346 This function will build some generic HOBs that doesn't depend on information from bootloaders.
347
348**/
349VOID
350BuildGenericHob (
351 VOID
352 )
353{
354 UINT32 RegEax;
355 UINT8 PhysicalAddressBits;
356 EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute;
357
358 // The UEFI payload FV
359 BuildMemoryAllocationHob (PcdGet32 (PcdPayloadFdMemBase), PcdGet32 (PcdPayloadFdMemSize), EfiBootServicesData);
360
361 //
362 // Build CPU memory space and IO space hob
363 //
364 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
365 if (RegEax >= 0x80000008) {
366 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
367 PhysicalAddressBits = (UINT8)RegEax;
368 } else {
369 PhysicalAddressBits = 36;
370 }
371
372 BuildCpuHob (PhysicalAddressBits, 16);
373
374 //
375 // Report Local APIC range, cause sbl HOB to be NULL, comment now
376 //
377 ResourceAttribute = (
378 EFI_RESOURCE_ATTRIBUTE_PRESENT |
379 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
380 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
381 EFI_RESOURCE_ATTRIBUTE_TESTED
382 );
383 BuildResourceDescriptorHob (EFI_RESOURCE_MEMORY_MAPPED_IO, ResourceAttribute, 0xFEC80000, SIZE_512KB);
384 BuildMemoryAllocationHob (0xFEC80000, SIZE_512KB, EfiMemoryMappedIO);
385}
386
387/**
388 Entry point to the C language phase of UEFI payload.
389
390 @param[in] BootloaderParameter The starting address of bootloader parameter block.
391
392 @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
393**/
394EFI_STATUS
395EFIAPI
396_ModuleEntryPoint (
397 IN UINTN BootloaderParameter
398 )
399{
400 EFI_STATUS Status;
401 PHYSICAL_ADDRESS DxeCoreEntryPoint;
402 UINTN MemBase;
403 UINTN HobMemBase;
404 UINTN HobMemTop;
405 EFI_PEI_HOB_POINTERS Hob;
406 SERIAL_PORT_INFO SerialPortInfo;
407 UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *UniversalSerialPort;
408
409 Status = PcdSet64S (PcdBootloaderParameter, BootloaderParameter);
410 ASSERT_EFI_ERROR (Status);
411
412 // Initialize floating point operating environment to be compliant with UEFI spec.
413 InitializeFloatingPointUnits ();
414
415 // HOB region is used for HOB and memory allocation for this module
416 MemBase = PcdGet32 (PcdPayloadFdMemBase);
417 HobMemBase = ALIGN_VALUE (MemBase + PcdGet32 (PcdPayloadFdMemSize), SIZE_1MB);
418 HobMemTop = HobMemBase + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
419
420 HobConstructor ((VOID *)MemBase, (VOID *)HobMemTop, (VOID *)HobMemBase, (VOID *)HobMemTop);
421
422 //
423 // Build serial port info
424 //
425 Status = ParseSerialInfo (&SerialPortInfo);
426 if (!EFI_ERROR (Status)) {
427 UniversalSerialPort = BuildGuidHob (&gUniversalPayloadSerialPortInfoGuid, sizeof (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO));
428 ASSERT (UniversalSerialPort != NULL);
429 UniversalSerialPort->Header.Revision = UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO_REVISION;
430 UniversalSerialPort->Header.Length = sizeof (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO);
431 UniversalSerialPort->UseMmio = (SerialPortInfo.Type == 1) ? FALSE : TRUE;
432 UniversalSerialPort->RegisterBase = SerialPortInfo.BaseAddr;
433 UniversalSerialPort->BaudRate = SerialPortInfo.Baud;
434 UniversalSerialPort->RegisterStride = (UINT8)SerialPortInfo.RegWidth;
435 // Set PCD here (vs in PlatformHookLib.c) to avoid adding a new field to UniversalSerialPort struct
436 if (SerialPortInfo.InputHertz > 0) {
437 Status = PcdSet32S (PcdSerialClockRate, SerialPortInfo.InputHertz);
438 if (RETURN_ERROR (Status)) {
439 DEBUG ((DEBUG_ERROR, "Failed to set PcdSerialClockRate; Status = %r\n", Status));
440 return Status;
441 }
442 }
443 }
444
445 // The library constructors might depend on serial port, so call it after serial port hob
446 ProcessLibraryConstructorList ();
447 DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
448
449 // Build HOB based on information from Bootloader
450 Status = BuildHobFromBl ();
451 if (EFI_ERROR (Status)) {
452 DEBUG ((DEBUG_ERROR, "BuildHobFromBl Status = %r\n", Status));
453 return Status;
454 }
455
456 // Build other HOBs required by DXE
457 BuildGenericHob ();
458
459 //
460 // Create Memory Type Information HOB
461 //
462 BuildGuidDataHob (
463 &gEfiMemoryTypeInformationGuid,
464 mDefaultMemoryTypeInformation,
465 sizeof (mDefaultMemoryTypeInformation)
466 );
467
468 // Load the DXE Core
469 Status = LoadDxeCore (&DxeCoreEntryPoint);
470 ASSERT_EFI_ERROR (Status);
471
472 DEBUG ((DEBUG_INFO, "DxeCoreEntryPoint = 0x%lx\n", DxeCoreEntryPoint));
473
474 //
475 // Mask off all legacy 8259 interrupt sources
476 //
477 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
478 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
479
480 Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF);
481 HandOffToDxeCore (DxeCoreEntryPoint, Hob);
482
483 // Should not get here
484 CpuDeadLoop ();
485 return EFI_SUCCESS;
486}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette