]> git.proxmox.com Git - mirror_edk2.git/blob - UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c
UefiPayloadPkg: Create gUniversalPayloadSmbiosTableGuid Hob
[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 /**
11 Callback function to build resource descriptor HOB
12
13 This function build a HOB based on the memory map entry info.
14
15 @param MemoryMapEntry Memory map entry info got from bootloader.
16 @param Params Not used for now.
17
18 @retval RETURN_SUCCESS Successfully build a HOB.
19 **/
20 EFI_STATUS
21 MemInfoCallback (
22 IN MEMROY_MAP_ENTRY *MemoryMapEntry,
23 IN VOID *Params
24 )
25 {
26 EFI_PHYSICAL_ADDRESS Base;
27 EFI_RESOURCE_TYPE Type;
28 UINT64 Size;
29 EFI_RESOURCE_ATTRIBUTE_TYPE Attribue;
30
31 Type = (MemoryMapEntry->Type == 1) ? EFI_RESOURCE_SYSTEM_MEMORY : EFI_RESOURCE_MEMORY_RESERVED;
32 Base = MemoryMapEntry->Base;
33 Size = MemoryMapEntry->Size;
34
35 Attribue = EFI_RESOURCE_ATTRIBUTE_PRESENT |
36 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
37 EFI_RESOURCE_ATTRIBUTE_TESTED |
38 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
39 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
40 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
41 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;
42
43 if (Base >= BASE_4GB ) {
44 // Remove tested attribute to avoid DXE core to dispatch driver to memory above 4GB
45 Attribue &= ~EFI_RESOURCE_ATTRIBUTE_TESTED;
46 }
47
48 BuildResourceDescriptorHob (Type, Attribue, (EFI_PHYSICAL_ADDRESS)Base, Size);
49 DEBUG ((DEBUG_INFO , "buildhob: base = 0x%lx, size = 0x%lx, type = 0x%x\n", Base, Size, Type));
50
51 return RETURN_SUCCESS;
52 }
53
54
55
56 /**
57 Find the board related info from ACPI table
58
59 @param AcpiTableBase ACPI table start address in memory
60 @param AcpiBoardInfo Pointer to the acpi board info strucutre
61
62 @retval RETURN_SUCCESS Successfully find out all the required information.
63 @retval RETURN_NOT_FOUND Failed to find the required info.
64
65 **/
66 RETURN_STATUS
67 ParseAcpiInfo (
68 IN UINT64 AcpiTableBase,
69 OUT ACPI_BOARD_INFO *AcpiBoardInfo
70 )
71 {
72 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
73 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
74 UINT32 *Entry32;
75 UINTN Entry32Num;
76 EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
77 EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
78 UINT64 *Entry64;
79 UINTN Entry64Num;
80 UINTN Idx;
81 UINT32 *Signature;
82 EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *MmCfgHdr;
83 EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *MmCfgBase;
84
85 Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)AcpiTableBase;
86 DEBUG ((DEBUG_INFO, "Rsdp at 0x%p\n", Rsdp));
87 DEBUG ((DEBUG_INFO, "Rsdt at 0x%x, Xsdt at 0x%lx\n", Rsdp->RsdtAddress, Rsdp->XsdtAddress));
88
89 //
90 // Search Rsdt First
91 //
92 Fadt = NULL;
93 MmCfgHdr = NULL;
94 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->RsdtAddress);
95 if (Rsdt != NULL) {
96 Entry32 = (UINT32 *)(Rsdt + 1);
97 Entry32Num = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 2;
98 for (Idx = 0; Idx < Entry32Num; Idx++) {
99 Signature = (UINT32 *)(UINTN)Entry32[Idx];
100 if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
101 Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;
102 DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n"));
103 }
104
105 if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) {
106 MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature;
107 DEBUG ((DEBUG_INFO, "Found MM config address in Rsdt\n"));
108 }
109
110 if ((Fadt != NULL) && (MmCfgHdr != NULL)) {
111 goto Done;
112 }
113 }
114 }
115
116 //
117 // Search Xsdt Second
118 //
119 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->XsdtAddress);
120 if (Xsdt != NULL) {
121 Entry64 = (UINT64 *)(Xsdt + 1);
122 Entry64Num = (Xsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 3;
123 for (Idx = 0; Idx < Entry64Num; Idx++) {
124 Signature = (UINT32 *)(UINTN)Entry64[Idx];
125 if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
126 Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;
127 DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n"));
128 }
129
130 if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) {
131 MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature;
132 DEBUG ((DEBUG_INFO, "Found MM config address in Xsdt\n"));
133 }
134
135 if ((Fadt != NULL) && (MmCfgHdr != NULL)) {
136 goto Done;
137 }
138 }
139 }
140
141 if (Fadt == NULL) {
142 return RETURN_NOT_FOUND;
143 }
144
145 Done:
146
147 AcpiBoardInfo->PmCtrlRegBase = Fadt->Pm1aCntBlk;
148 AcpiBoardInfo->PmTimerRegBase = Fadt->PmTmrBlk;
149 AcpiBoardInfo->ResetRegAddress = Fadt->ResetReg.Address;
150 AcpiBoardInfo->ResetValue = Fadt->ResetValue;
151 AcpiBoardInfo->PmEvtBase = Fadt->Pm1aEvtBlk;
152 AcpiBoardInfo->PmGpeEnBase = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2;
153
154 if (MmCfgHdr != NULL) {
155 MmCfgBase = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)((UINT8*) MmCfgHdr + sizeof (*MmCfgHdr));
156 AcpiBoardInfo->PcieBaseAddress = MmCfgBase->BaseAddress;
157 AcpiBoardInfo->PcieBaseSize = (MmCfgBase->EndBusNumber + 1 - MmCfgBase->StartBusNumber) * 4096 * 32 * 8;
158 } else {
159 AcpiBoardInfo->PcieBaseAddress = 0;
160 AcpiBoardInfo->PcieBaseSize = 0;
161 }
162 DEBUG ((DEBUG_INFO, "PmCtrl Reg 0x%lx\n", AcpiBoardInfo->PmCtrlRegBase));
163 DEBUG ((DEBUG_INFO, "PmTimer Reg 0x%lx\n", AcpiBoardInfo->PmTimerRegBase));
164 DEBUG ((DEBUG_INFO, "Reset Reg 0x%lx\n", AcpiBoardInfo->ResetRegAddress));
165 DEBUG ((DEBUG_INFO, "Reset Value 0x%x\n", AcpiBoardInfo->ResetValue));
166 DEBUG ((DEBUG_INFO, "PmEvt Reg 0x%lx\n", AcpiBoardInfo->PmEvtBase));
167 DEBUG ((DEBUG_INFO, "PmGpeEn Reg 0x%lx\n", AcpiBoardInfo->PmGpeEnBase));
168 DEBUG ((DEBUG_INFO, "PcieBaseAddr 0x%lx\n", AcpiBoardInfo->PcieBaseAddress));
169 DEBUG ((DEBUG_INFO, "PcieBaseSize 0x%lx\n", AcpiBoardInfo->PcieBaseSize));
170
171 //
172 // Verify values for proper operation
173 //
174 ASSERT(Fadt->Pm1aCntBlk != 0);
175 ASSERT(Fadt->PmTmrBlk != 0);
176 ASSERT(Fadt->ResetReg.Address != 0);
177 ASSERT(Fadt->Pm1aEvtBlk != 0);
178 ASSERT(Fadt->Gpe0Blk != 0);
179
180 DEBUG_CODE_BEGIN ();
181 BOOLEAN SciEnabled;
182
183 //
184 // Check the consistency of SCI enabling
185 //
186
187 //
188 // Get SCI_EN value
189 //
190 if (Fadt->Pm1CntLen == 4) {
191 SciEnabled = (IoRead32 (Fadt->Pm1aCntBlk) & BIT0)? TRUE : FALSE;
192 } else {
193 //
194 // if (Pm1CntLen == 2), use 16 bit IO read;
195 // if (Pm1CntLen != 2 && Pm1CntLen != 4), use 16 bit IO read as a fallback
196 //
197 SciEnabled = (IoRead16 (Fadt->Pm1aCntBlk) & BIT0)? TRUE : FALSE;
198 }
199
200 if (!(Fadt->Flags & EFI_ACPI_5_0_HW_REDUCED_ACPI) &&
201 (Fadt->SmiCmd == 0) &&
202 !SciEnabled) {
203 //
204 // The ACPI enabling status is inconsistent: SCI is not enabled but ACPI
205 // table does not provide a means to enable it through FADT->SmiCmd
206 //
207 DEBUG ((DEBUG_ERROR, "ERROR: The ACPI enabling status is inconsistent: SCI is not"
208 " enabled but the ACPI table does not provide a means to enable it through FADT->SmiCmd."
209 " This may cause issues in OS.\n"));
210 }
211 DEBUG_CODE_END ();
212
213 return RETURN_SUCCESS;
214 }
215
216
217 /**
218 It will build HOBs based on information from bootloaders.
219
220 @retval EFI_SUCCESS If it completed successfully.
221 @retval Others If it failed to build required HOBs.
222 **/
223 EFI_STATUS
224 BuildHobFromBl (
225 VOID
226 )
227 {
228 EFI_STATUS Status;
229 SYSTEM_TABLE_INFO SysTableInfo;
230 SYSTEM_TABLE_INFO *NewSysTableInfo;
231 ACPI_BOARD_INFO AcpiBoardInfo;
232 ACPI_BOARD_INFO *NewAcpiBoardInfo;
233 EFI_PEI_GRAPHICS_INFO_HOB GfxInfo;
234 EFI_PEI_GRAPHICS_INFO_HOB *NewGfxInfo;
235 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB GfxDeviceInfo;
236 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *NewGfxDeviceInfo;
237 UNIVERSAL_PAYLOAD_SMBIOS_TABLE *SmBiosTableHob;
238
239 //
240 // Parse memory info and build memory HOBs
241 //
242 Status = ParseMemoryInfo (MemInfoCallback, NULL);
243 if (EFI_ERROR(Status)) {
244 return Status;
245 }
246
247 //
248 // Create guid hob for frame buffer information
249 //
250 Status = ParseGfxInfo (&GfxInfo);
251 if (!EFI_ERROR (Status)) {
252 NewGfxInfo = BuildGuidHob (&gEfiGraphicsInfoHobGuid, sizeof (GfxInfo));
253 ASSERT (NewGfxInfo != NULL);
254 CopyMem (NewGfxInfo, &GfxInfo, sizeof (GfxInfo));
255 DEBUG ((DEBUG_INFO, "Created graphics info hob\n"));
256 }
257
258
259 Status = ParseGfxDeviceInfo (&GfxDeviceInfo);
260 if (!EFI_ERROR (Status)) {
261 NewGfxDeviceInfo = BuildGuidHob (&gEfiGraphicsDeviceInfoHobGuid, sizeof (GfxDeviceInfo));
262 ASSERT (NewGfxDeviceInfo != NULL);
263 CopyMem (NewGfxDeviceInfo, &GfxDeviceInfo, sizeof (GfxDeviceInfo));
264 DEBUG ((DEBUG_INFO, "Created graphics device info hob\n"));
265 }
266
267
268 //
269 // Create guid hob for system tables like acpi table and smbios table
270 //
271 Status = ParseSystemTable(&SysTableInfo);
272 ASSERT_EFI_ERROR (Status);
273 if (!EFI_ERROR (Status)) {
274 NewSysTableInfo = BuildGuidHob (&gUefiSystemTableInfoGuid, sizeof (SYSTEM_TABLE_INFO));
275 ASSERT (NewSysTableInfo != NULL);
276 CopyMem (NewSysTableInfo, &SysTableInfo, sizeof (SYSTEM_TABLE_INFO));
277 DEBUG ((DEBUG_INFO, "Detected Acpi Table at 0x%lx, length 0x%x\n", SysTableInfo.AcpiTableBase, SysTableInfo.AcpiTableSize));
278 DEBUG ((DEBUG_INFO, "Detected Smbios Table at 0x%lx, length 0x%x\n", SysTableInfo.SmbiosTableBase, SysTableInfo.SmbiosTableSize));
279 }
280 //
281 // Creat SmBios table Hob
282 //
283 SmBiosTableHob = BuildGuidHob (&gUniversalPayloadSmbiosTableGuid, sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE));
284 ASSERT (SmBiosTableHob != NULL);
285 SmBiosTableHob->Header.Revision = UNIVERSAL_PAYLOAD_SMBIOS_TABLE_REVISION;
286 SmBiosTableHob->Header.Length = sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE);
287 SmBiosTableHob->SmBiosEntryPoint = SysTableInfo.SmbiosTableBase;
288 DEBUG ((DEBUG_INFO, "Create smbios table gUniversalPayloadSmbiosTableGuid guid hob\n"));
289
290 //
291 // Create guid hob for acpi board information
292 //
293 Status = ParseAcpiInfo (SysTableInfo.AcpiTableBase, &AcpiBoardInfo);
294 ASSERT_EFI_ERROR (Status);
295 if (!EFI_ERROR (Status)) {
296 NewAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO));
297 ASSERT (NewAcpiBoardInfo != NULL);
298 CopyMem (NewAcpiBoardInfo, &AcpiBoardInfo, sizeof (ACPI_BOARD_INFO));
299 DEBUG ((DEBUG_INFO, "Create acpi board info guid hob\n"));
300 }
301
302 //
303 // Parse platform specific information.
304 //
305 Status = ParsePlatformInfo ();
306 if (EFI_ERROR (Status)) {
307 DEBUG ((DEBUG_ERROR, "Error when parsing platform info, Status = %r\n", Status));
308 return Status;
309 }
310
311 return EFI_SUCCESS;
312 }
313
314
315 /**
316 This function will build some generic HOBs that doesn't depend on information from bootloaders.
317
318 **/
319 VOID
320 BuildGenericHob (
321 VOID
322 )
323 {
324 UINT32 RegEax;
325 UINT8 PhysicalAddressBits;
326 EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute;
327
328 // The UEFI payload FV
329 BuildMemoryAllocationHob (PcdGet32 (PcdPayloadFdMemBase), PcdGet32 (PcdPayloadFdMemSize), EfiBootServicesData);
330
331 //
332 // Build CPU memory space and IO space hob
333 //
334 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
335 if (RegEax >= 0x80000008) {
336 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
337 PhysicalAddressBits = (UINT8) RegEax;
338 } else {
339 PhysicalAddressBits = 36;
340 }
341
342 BuildCpuHob (PhysicalAddressBits, 16);
343
344 //
345 // Report Local APIC range, cause sbl HOB to be NULL, comment now
346 //
347 ResourceAttribute = (
348 EFI_RESOURCE_ATTRIBUTE_PRESENT |
349 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
350 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
351 EFI_RESOURCE_ATTRIBUTE_TESTED
352 );
353 BuildResourceDescriptorHob (EFI_RESOURCE_MEMORY_MAPPED_IO, ResourceAttribute, 0xFEC80000, SIZE_512KB);
354 BuildMemoryAllocationHob ( 0xFEC80000, SIZE_512KB, EfiMemoryMappedIO);
355
356 }
357
358
359 /**
360 Entry point to the C language phase of UEFI payload.
361
362 @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
363 **/
364 EFI_STATUS
365 EFIAPI
366 PayloadEntry (
367 IN UINTN BootloaderParameter
368 )
369 {
370 EFI_STATUS Status;
371 PHYSICAL_ADDRESS DxeCoreEntryPoint;
372 EFI_HOB_HANDOFF_INFO_TABLE *HandoffHobTable;
373 UINTN MemBase;
374 UINTN MemSize;
375 UINTN HobMemBase;
376 UINTN HobMemTop;
377 EFI_PEI_HOB_POINTERS Hob;
378
379 // Call constructor for all libraries
380 ProcessLibraryConstructorList ();
381
382 DEBUG ((DEBUG_INFO, "GET_BOOTLOADER_PARAMETER() = 0x%lx\n", GET_BOOTLOADER_PARAMETER()));
383 DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof(UINTN)));
384
385 // Initialize floating point operating environment to be compliant with UEFI spec.
386 InitializeFloatingPointUnits ();
387
388 // HOB region is used for HOB and memory allocation for this module
389 MemBase = PcdGet32 (PcdPayloadFdMemBase);
390 HobMemBase = ALIGN_VALUE (MemBase + PcdGet32 (PcdPayloadFdMemSize), SIZE_1MB);
391 HobMemTop = HobMemBase + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
392
393 // DXE core assumes the memory below HOB region could be used, so include the FV region memory into HOB range.
394 MemSize = HobMemTop - MemBase;
395 HandoffHobTable = HobConstructor ((VOID *)MemBase, MemSize, (VOID *)HobMemBase, (VOID *)HobMemTop);
396
397 // Build HOB based on information from Bootloader
398 Status = BuildHobFromBl ();
399 if (EFI_ERROR (Status)) {
400 DEBUG ((DEBUG_ERROR, "BuildHobFromBl Status = %r\n", Status));
401 return Status;
402 }
403
404 // Build other HOBs required by DXE
405 BuildGenericHob ();
406
407 // Load the DXE Core
408 Status = LoadDxeCore (&DxeCoreEntryPoint);
409 ASSERT_EFI_ERROR (Status);
410
411 DEBUG ((DEBUG_INFO, "DxeCoreEntryPoint = 0x%lx\n", DxeCoreEntryPoint));
412
413 //
414 // Mask off all legacy 8259 interrupt sources
415 //
416 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
417 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
418
419 Hob.HandoffInformationTable = HandoffHobTable;
420 HandOffToDxeCore (DxeCoreEntryPoint, Hob);
421
422 // Should not get here
423 CpuDeadLoop ();
424 return EFI_SUCCESS;
425 }