]> git.proxmox.com Git - mirror_edk2.git/blob - UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c
UefiPayloadPkg: Add PCI root bridge info hob support for SBL
[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 MEMROY_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 MEMROY_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 MEMROY_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 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;
236
237 //
238 // First find TOLUD
239 //
240 DEBUG ((DEBUG_INFO , "Guessing Top of Lower Usable DRAM:\n"));
241 Status = ParseMemoryInfo (FindToludCallback, NULL);
242 if (EFI_ERROR(Status)) {
243 return Status;
244 }
245 DEBUG ((DEBUG_INFO , "Assuming TOLUD = 0x%x\n", mTopOfLowerUsableDram));
246
247 //
248 // Parse memory info and build memory HOBs for Usable RAM
249 //
250 DEBUG ((DEBUG_INFO , "Building ResourceDescriptorHobs for usable memory:\n"));
251 Status = ParseMemoryInfo (MemInfoCallback, NULL);
252 if (EFI_ERROR(Status)) {
253 return Status;
254 }
255
256 //
257 // Create guid hob for frame buffer information
258 //
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"));
265 }
266
267
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"));
274 }
275
276
277 //
278 // Create guid hob for system tables like acpi table and smbios table
279 //
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));
288 }
289 //
290 // Creat SmBios table Hob
291 //
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"));
298
299 //
300 // Creat ACPI table Hob
301 //
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"));
308
309 //
310 // Create guid hob for acpi board information
311 //
312 AcpiBoardInfo = BuildHobFromAcpi (SysTableInfo.AcpiTableBase);
313 ASSERT (AcpiBoardInfo != NULL);
314
315 //
316 // Parse memory info and build memory HOBs for reserved DRAM and MMIO
317 //
318 DEBUG ((DEBUG_INFO , "Building ResourceDescriptorHobs for reserved memory:\n"));
319 Status = ParseMemoryInfo (MemInfoCallbackMmio, AcpiBoardInfo);
320 if (EFI_ERROR(Status)) {
321 return Status;
322 }
323
324 //
325 // Parse the misc info provided by bootloader
326 //
327 Status = ParseMiscInfo ();
328 if (EFI_ERROR (Status)) {
329 DEBUG ((DEBUG_WARN, "Error when parsing misc info, Status = %r\n", Status));
330 }
331
332 //
333 // Parse platform specific information.
334 //
335 Status = ParsePlatformInfo ();
336 if (EFI_ERROR (Status)) {
337 DEBUG ((DEBUG_ERROR, "Error when parsing platform info, Status = %r\n", Status));
338 return Status;
339 }
340
341 return EFI_SUCCESS;
342 }
343
344
345 /**
346 This function will build some generic HOBs that doesn't depend on information from bootloaders.
347
348 **/
349 VOID
350 BuildGenericHob (
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
389 /**
390 Entry point to the C language phase of UEFI payload.
391
392 @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
393 **/
394 EFI_STATUS
395 EFIAPI
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 PcdSet64S (PcdBootloaderParameter, BootloaderParameter);
410 // Initialize floating point operating environment to be compliant with UEFI spec.
411 InitializeFloatingPointUnits ();
412
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);
417
418 HobConstructor ((VOID *)MemBase, (VOID *)HobMemTop, (VOID *)HobMemBase, (VOID *)HobMemTop);
419
420 //
421 // Build serial port info
422 //
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;
433 }
434
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)));
438
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));
443 return Status;
444 }
445
446 // Build other HOBs required by DXE
447 BuildGenericHob ();
448
449 // Load the DXE Core
450 Status = LoadDxeCore (&DxeCoreEntryPoint);
451 ASSERT_EFI_ERROR (Status);
452
453 DEBUG ((DEBUG_INFO, "DxeCoreEntryPoint = 0x%lx\n", DxeCoreEntryPoint));
454
455 //
456 // Mask off all legacy 8259 interrupt sources
457 //
458 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
459 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
460
461 Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *) GetFirstHob(EFI_HOB_TYPE_HANDOFF);
462 HandOffToDxeCore (DxeCoreEntryPoint, Hob);
463
464 // Should not get here
465 CpuDeadLoop ();
466 return EFI_SUCCESS;
467 }