]> git.proxmox.com Git - mirror_edk2.git/blob - UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c
0fed1e36918aa6d58499a246a4b212a59833aa3d
[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 {
85 BuildMemoryAllocationHob (Base, Size, EfiUnusableMemory);
86 } else if (MemoryMapEntry->Type == E820_PMEM) {
87 BuildMemoryAllocationHob (Base, Size, EfiPersistentMemory);
88 }
89
90 return EFI_SUCCESS;
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 {
125 return EFI_SUCCESS;
126 }
127
128 //
129 // Skip resources above 4GiB
130 //
131 if ((MemoryMapEntry->Base + MemoryMapEntry->Size) > 0x100000000ULL) {
132 return EFI_SUCCESS;
133 }
134
135 if ((MemoryMapEntry->Type == E820_RAM) || (MemoryMapEntry->Type == E820_ACPI) ||
136 (MemoryMapEntry->Type == E820_NVS))
137 {
138 //
139 // It's usable DRAM. Update TOLUD.
140 //
141 if (mTopOfLowerUsableDram < (MemoryMapEntry->Base + MemoryMapEntry->Size)) {
142 mTopOfLowerUsableDram = (UINT32)(MemoryMapEntry->Base + MemoryMapEntry->Size);
143 }
144 } else {
145 //
146 // It might be 'reserved DRAM' or 'MMIO'.
147 //
148 // If it touches usable DRAM at Base assume it's DRAM as well,
149 // as it could be bootloader installed tables, TSEG, GTT, ...
150 //
151 if (mTopOfLowerUsableDram == MemoryMapEntry->Base) {
152 mTopOfLowerUsableDram = (UINT32)(MemoryMapEntry->Base + MemoryMapEntry->Size);
153 }
154 }
155
156 return EFI_SUCCESS;
157 }
158
159 /**
160 Callback function to build resource descriptor HOB
161
162 This function build a HOB based on the memory map entry info.
163 Only add EFI_RESOURCE_SYSTEM_MEMORY.
164
165 @param MemoryMapEntry Memory map entry info got from bootloader.
166 @param Params Not used for now.
167
168 @retval RETURN_SUCCESS Successfully build a HOB.
169 **/
170 EFI_STATUS
171 MemInfoCallback (
172 IN MEMORY_MAP_ENTRY *MemoryMapEntry,
173 IN VOID *Params
174 )
175 {
176 EFI_PHYSICAL_ADDRESS Base;
177 EFI_RESOURCE_TYPE Type;
178 UINT64 Size;
179 EFI_RESOURCE_ATTRIBUTE_TYPE Attribue;
180
181 //
182 // Skip everything not known to be usable DRAM.
183 // It will be added later.
184 //
185 if ((MemoryMapEntry->Type != E820_RAM) && (MemoryMapEntry->Type != E820_ACPI) &&
186 (MemoryMapEntry->Type != E820_NVS))
187 {
188 return RETURN_SUCCESS;
189 }
190
191 Type = EFI_RESOURCE_SYSTEM_MEMORY;
192 Base = MemoryMapEntry->Base;
193 Size = MemoryMapEntry->Size;
194
195 Attribue = EFI_RESOURCE_ATTRIBUTE_PRESENT |
196 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
197 EFI_RESOURCE_ATTRIBUTE_TESTED |
198 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
199 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
200 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
201 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;
202
203 BuildResourceDescriptorHob (Type, Attribue, (EFI_PHYSICAL_ADDRESS)Base, Size);
204 DEBUG ((DEBUG_INFO, "buildhob: base = 0x%lx, size = 0x%lx, type = 0x%x\n", Base, Size, Type));
205
206 if (MemoryMapEntry->Type == E820_ACPI) {
207 BuildMemoryAllocationHob (Base, Size, EfiACPIReclaimMemory);
208 } else if (MemoryMapEntry->Type == E820_NVS) {
209 BuildMemoryAllocationHob (Base, Size, EfiACPIMemoryNVS);
210 }
211
212 return RETURN_SUCCESS;
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
244 DEBUG ((DEBUG_INFO, "Assuming TOLUD = 0x%x\n", mTopOfLowerUsableDram));
245
246 //
247 // Parse memory info and build memory HOBs for Usable RAM
248 //
249 DEBUG ((DEBUG_INFO, "Building ResourceDescriptorHobs for usable memory:\n"));
250 Status = ParseMemoryInfo (MemInfoCallback, NULL);
251 if (EFI_ERROR (Status)) {
252 return Status;
253 }
254
255 //
256 // Create guid hob for frame buffer information
257 //
258 Status = ParseGfxInfo (&GfxInfo);
259 if (!EFI_ERROR (Status)) {
260 NewGfxInfo = BuildGuidHob (&gEfiGraphicsInfoHobGuid, sizeof (GfxInfo));
261 ASSERT (NewGfxInfo != NULL);
262 CopyMem (NewGfxInfo, &GfxInfo, sizeof (GfxInfo));
263 DEBUG ((DEBUG_INFO, "Created graphics info hob\n"));
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 // Creat SmBios table Hob
276 //
277 SmBiosTableHob = BuildGuidHob (&gUniversalPayloadSmbiosTableGuid, sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE));
278 ASSERT (SmBiosTableHob != NULL);
279 SmBiosTableHob->Header.Revision = UNIVERSAL_PAYLOAD_SMBIOS_TABLE_REVISION;
280 SmBiosTableHob->Header.Length = sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE);
281 DEBUG ((DEBUG_INFO, "Create smbios table gUniversalPayloadSmbiosTableGuid guid hob\n"));
282 Status = ParseSmbiosTable (SmBiosTableHob);
283 if (!EFI_ERROR (Status)) {
284 DEBUG ((DEBUG_INFO, "Detected Smbios Table at 0x%lx\n", SmBiosTableHob->SmBiosEntryPoint));
285 }
286
287 //
288 // Creat ACPI table Hob
289 //
290 AcpiTableHob = BuildGuidHob (&gUniversalPayloadAcpiTableGuid, sizeof (UNIVERSAL_PAYLOAD_ACPI_TABLE));
291 ASSERT (AcpiTableHob != NULL);
292 AcpiTableHob->Header.Revision = UNIVERSAL_PAYLOAD_ACPI_TABLE_REVISION;
293 AcpiTableHob->Header.Length = sizeof (UNIVERSAL_PAYLOAD_ACPI_TABLE);
294 DEBUG ((DEBUG_INFO, "Create ACPI table gUniversalPayloadAcpiTableGuid guid hob\n"));
295 Status = ParseAcpiTableInfo (AcpiTableHob);
296 if (!EFI_ERROR (Status)) {
297 DEBUG ((DEBUG_INFO, "Detected ACPI Table at 0x%lx\n", AcpiTableHob->Rsdp));
298 }
299
300 //
301 // Create guid hob for acpi board information
302 //
303 AcpiBoardInfo = BuildHobFromAcpi (AcpiTableHob->Rsdp);
304 ASSERT (AcpiBoardInfo != NULL);
305
306 //
307 // Parse memory info and build memory HOBs for reserved DRAM and MMIO
308 //
309 DEBUG ((DEBUG_INFO, "Building ResourceDescriptorHobs for reserved memory:\n"));
310 Status = ParseMemoryInfo (MemInfoCallbackMmio, AcpiBoardInfo);
311 if (EFI_ERROR (Status)) {
312 return Status;
313 }
314
315 //
316 // Parse the misc info provided by bootloader
317 //
318 Status = ParseMiscInfo ();
319 if (EFI_ERROR (Status)) {
320 DEBUG ((DEBUG_WARN, "Error when parsing misc info, Status = %r\n", Status));
321 }
322
323 //
324 // Parse platform specific information.
325 //
326 Status = ParsePlatformInfo ();
327 if (EFI_ERROR (Status)) {
328 DEBUG ((DEBUG_ERROR, "Error when parsing platform info, Status = %r\n", Status));
329 return Status;
330 }
331
332 return EFI_SUCCESS;
333 }
334
335 /**
336 This function will build some generic HOBs that doesn't depend on information from bootloaders.
337
338 **/
339 VOID
340 BuildGenericHob (
341 VOID
342 )
343 {
344 UINT32 RegEax;
345 UINT8 PhysicalAddressBits;
346 EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute;
347
348 // The UEFI payload FV
349 BuildMemoryAllocationHob (PcdGet32 (PcdPayloadFdMemBase), PcdGet32 (PcdPayloadFdMemSize), EfiBootServicesData);
350
351 //
352 // Build CPU memory space and IO space hob
353 //
354 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
355 if (RegEax >= 0x80000008) {
356 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
357 PhysicalAddressBits = (UINT8)RegEax;
358 } else {
359 PhysicalAddressBits = 36;
360 }
361
362 BuildCpuHob (PhysicalAddressBits, 16);
363
364 //
365 // Report Local APIC range, cause sbl HOB to be NULL, comment now
366 //
367 ResourceAttribute = (
368 EFI_RESOURCE_ATTRIBUTE_PRESENT |
369 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
370 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
371 EFI_RESOURCE_ATTRIBUTE_TESTED
372 );
373 BuildResourceDescriptorHob (EFI_RESOURCE_MEMORY_MAPPED_IO, ResourceAttribute, 0xFEC80000, SIZE_512KB);
374 BuildMemoryAllocationHob (0xFEC80000, SIZE_512KB, EfiMemoryMappedIO);
375 }
376
377 /**
378 Entry point to the C language phase of UEFI payload.
379
380 @param[in] BootloaderParameter The starting address of bootloader parameter block.
381
382 @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
383 **/
384 EFI_STATUS
385 EFIAPI
386 _ModuleEntryPoint (
387 IN UINTN BootloaderParameter
388 )
389 {
390 EFI_STATUS Status;
391 PHYSICAL_ADDRESS DxeCoreEntryPoint;
392 UINTN MemBase;
393 UINTN HobMemBase;
394 UINTN HobMemTop;
395 EFI_PEI_HOB_POINTERS Hob;
396 SERIAL_PORT_INFO SerialPortInfo;
397 UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *UniversalSerialPort;
398
399 Status = PcdSet64S (PcdBootloaderParameter, BootloaderParameter);
400 ASSERT_EFI_ERROR (Status);
401
402 // Initialize floating point operating environment to be compliant with UEFI spec.
403 InitializeFloatingPointUnits ();
404
405 // HOB region is used for HOB and memory allocation for this module
406 MemBase = PcdGet32 (PcdPayloadFdMemBase);
407 HobMemBase = ALIGN_VALUE (MemBase + PcdGet32 (PcdPayloadFdMemSize), SIZE_1MB);
408 HobMemTop = HobMemBase + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
409
410 HobConstructor ((VOID *)MemBase, (VOID *)HobMemTop, (VOID *)HobMemBase, (VOID *)HobMemTop);
411
412 //
413 // Build serial port info
414 //
415 Status = ParseSerialInfo (&SerialPortInfo);
416 if (!EFI_ERROR (Status)) {
417 UniversalSerialPort = BuildGuidHob (&gUniversalPayloadSerialPortInfoGuid, sizeof (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO));
418 ASSERT (UniversalSerialPort != NULL);
419 UniversalSerialPort->Header.Revision = UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO_REVISION;
420 UniversalSerialPort->Header.Length = sizeof (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO);
421 UniversalSerialPort->UseMmio = (SerialPortInfo.Type == 1) ? FALSE : TRUE;
422 UniversalSerialPort->RegisterBase = SerialPortInfo.BaseAddr;
423 UniversalSerialPort->BaudRate = SerialPortInfo.Baud;
424 UniversalSerialPort->RegisterStride = (UINT8)SerialPortInfo.RegWidth;
425 }
426
427 // The library constructors might depend on serial port, so call it after serial port hob
428 ProcessLibraryConstructorList ();
429 DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
430
431 // Build HOB based on information from Bootloader
432 Status = BuildHobFromBl ();
433 if (EFI_ERROR (Status)) {
434 DEBUG ((DEBUG_ERROR, "BuildHobFromBl Status = %r\n", Status));
435 return Status;
436 }
437
438 // Build other HOBs required by DXE
439 BuildGenericHob ();
440
441 // Load the DXE Core
442 Status = LoadDxeCore (&DxeCoreEntryPoint);
443 ASSERT_EFI_ERROR (Status);
444
445 DEBUG ((DEBUG_INFO, "DxeCoreEntryPoint = 0x%lx\n", DxeCoreEntryPoint));
446
447 //
448 // Mask off all legacy 8259 interrupt sources
449 //
450 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
451 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
452
453 Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF);
454 HandOffToDxeCore (DxeCoreEntryPoint, Hob);
455
456 // Should not get here
457 CpuDeadLoop ();
458 return EFI_SUCCESS;
459 }