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