| /** @file | |
| Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "UefiPayloadEntry.h" | |
| /** | |
| Find the board related info from ACPI table | |
| @param AcpiTableBase ACPI table start address in memory | |
| @param AcpiBoardInfo Pointer to the acpi board info strucutre | |
| @retval RETURN_SUCCESS Successfully find out all the required information. | |
| @retval RETURN_NOT_FOUND Failed to find the required info. | |
| **/ | |
| RETURN_STATUS | |
| ParseAcpiInfo ( | |
| IN UINT64 AcpiTableBase, | |
| OUT ACPI_BOARD_INFO *AcpiBoardInfo | |
| ) | |
| { | |
| EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; | |
| EFI_ACPI_DESCRIPTION_HEADER *Rsdt; | |
| UINT32 *Entry32; | |
| UINTN Entry32Num; | |
| EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt; | |
| EFI_ACPI_DESCRIPTION_HEADER *Xsdt; | |
| UINT64 *Entry64; | |
| UINTN Entry64Num; | |
| UINTN Idx; | |
| UINT32 *Signature; | |
| EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *MmCfgHdr; | |
| EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *MmCfgBase; | |
| Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)AcpiTableBase; | |
| DEBUG ((DEBUG_INFO, "Rsdp at 0x%p\n", Rsdp)); | |
| DEBUG ((DEBUG_INFO, "Rsdt at 0x%x, Xsdt at 0x%lx\n", Rsdp->RsdtAddress, Rsdp->XsdtAddress)); | |
| // | |
| // Search Rsdt First | |
| // | |
| Fadt = NULL; | |
| MmCfgHdr = NULL; | |
| Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->RsdtAddress); | |
| if (Rsdt != NULL) { | |
| Entry32 = (UINT32 *)(Rsdt + 1); | |
| Entry32Num = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 2; | |
| for (Idx = 0; Idx < Entry32Num; Idx++) { | |
| Signature = (UINT32 *)(UINTN)Entry32[Idx]; | |
| if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { | |
| Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; | |
| DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n")); | |
| } | |
| if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) { | |
| MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature; | |
| DEBUG ((DEBUG_INFO, "Found MM config address in Rsdt\n")); | |
| } | |
| if ((Fadt != NULL) && (MmCfgHdr != NULL)) { | |
| goto Done; | |
| } | |
| } | |
| } | |
| // | |
| // Search Xsdt Second | |
| // | |
| Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->XsdtAddress); | |
| if (Xsdt != NULL) { | |
| Entry64 = (UINT64 *)(Xsdt + 1); | |
| Entry64Num = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 3; | |
| for (Idx = 0; Idx < Entry64Num; Idx++) { | |
| Signature = (UINT32 *)(UINTN)Entry64[Idx]; | |
| if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { | |
| Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; | |
| DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n")); | |
| } | |
| if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) { | |
| MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature; | |
| DEBUG ((DEBUG_INFO, "Found MM config address in Xsdt\n")); | |
| } | |
| if ((Fadt != NULL) && (MmCfgHdr != NULL)) { | |
| goto Done; | |
| } | |
| } | |
| } | |
| if (Fadt == NULL) { | |
| return RETURN_NOT_FOUND; | |
| } | |
| Done: | |
| AcpiBoardInfo->PmCtrlRegBase = Fadt->Pm1aCntBlk; | |
| AcpiBoardInfo->PmTimerRegBase = Fadt->PmTmrBlk; | |
| AcpiBoardInfo->ResetRegAddress = Fadt->ResetReg.Address; | |
| AcpiBoardInfo->ResetValue = Fadt->ResetValue; | |
| AcpiBoardInfo->PmEvtBase = Fadt->Pm1aEvtBlk; | |
| AcpiBoardInfo->PmGpeEnBase = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2; | |
| if (MmCfgHdr != NULL) { | |
| MmCfgBase = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)((UINT8 *)MmCfgHdr + sizeof (*MmCfgHdr)); | |
| AcpiBoardInfo->PcieBaseAddress = MmCfgBase->BaseAddress; | |
| AcpiBoardInfo->PcieBaseSize = (MmCfgBase->EndBusNumber + 1 - MmCfgBase->StartBusNumber) * 4096 * 32 * 8; | |
| } else { | |
| AcpiBoardInfo->PcieBaseAddress = 0; | |
| AcpiBoardInfo->PcieBaseSize = 0; | |
| } | |
| DEBUG ((DEBUG_INFO, "PmCtrl Reg 0x%lx\n", AcpiBoardInfo->PmCtrlRegBase)); | |
| DEBUG ((DEBUG_INFO, "PmTimer Reg 0x%lx\n", AcpiBoardInfo->PmTimerRegBase)); | |
| DEBUG ((DEBUG_INFO, "Reset Reg 0x%lx\n", AcpiBoardInfo->ResetRegAddress)); | |
| DEBUG ((DEBUG_INFO, "Reset Value 0x%x\n", AcpiBoardInfo->ResetValue)); | |
| DEBUG ((DEBUG_INFO, "PmEvt Reg 0x%lx\n", AcpiBoardInfo->PmEvtBase)); | |
| DEBUG ((DEBUG_INFO, "PmGpeEn Reg 0x%lx\n", AcpiBoardInfo->PmGpeEnBase)); | |
| DEBUG ((DEBUG_INFO, "PcieBaseAddr 0x%lx\n", AcpiBoardInfo->PcieBaseAddress)); | |
| DEBUG ((DEBUG_INFO, "PcieBaseSize 0x%lx\n", AcpiBoardInfo->PcieBaseSize)); | |
| // | |
| // Verify values for proper operation | |
| // | |
| ASSERT (Fadt->Pm1aCntBlk != 0); | |
| ASSERT (Fadt->PmTmrBlk != 0); | |
| ASSERT (Fadt->ResetReg.Address != 0); | |
| ASSERT (Fadt->Pm1aEvtBlk != 0); | |
| ASSERT (Fadt->Gpe0Blk != 0); | |
| DEBUG_CODE_BEGIN (); | |
| BOOLEAN SciEnabled; | |
| // | |
| // Check the consistency of SCI enabling | |
| // | |
| // | |
| // Get SCI_EN value | |
| // | |
| if (Fadt->Pm1CntLen == 4) { | |
| SciEnabled = (IoRead32 (Fadt->Pm1aCntBlk) & BIT0) ? TRUE : FALSE; | |
| } else { | |
| // | |
| // if (Pm1CntLen == 2), use 16 bit IO read; | |
| // if (Pm1CntLen != 2 && Pm1CntLen != 4), use 16 bit IO read as a fallback | |
| // | |
| SciEnabled = (IoRead16 (Fadt->Pm1aCntBlk) & BIT0) ? TRUE : FALSE; | |
| } | |
| if (!(Fadt->Flags & EFI_ACPI_5_0_HW_REDUCED_ACPI) && | |
| (Fadt->SmiCmd == 0) && | |
| !SciEnabled) | |
| { | |
| // | |
| // The ACPI enabling status is inconsistent: SCI is not enabled but ACPI | |
| // table does not provide a means to enable it through FADT->SmiCmd | |
| // | |
| DEBUG (( | |
| DEBUG_ERROR, | |
| "ERROR: The ACPI enabling status is inconsistent: SCI is not" | |
| " enabled but the ACPI table does not provide a means to enable it through FADT->SmiCmd." | |
| " This may cause issues in OS.\n" | |
| )); | |
| } | |
| DEBUG_CODE_END (); | |
| return RETURN_SUCCESS; | |
| } | |
| /** | |
| Build ACPI board info HOB using infomation from ACPI table | |
| @param AcpiTableBase ACPI table start address in memory | |
| @retval A pointer to ACPI board HOB ACPI_BOARD_INFO. Null if build HOB failure. | |
| **/ | |
| ACPI_BOARD_INFO * | |
| BuildHobFromAcpi ( | |
| IN UINT64 AcpiTableBase | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| ACPI_BOARD_INFO AcpiBoardInfo; | |
| ACPI_BOARD_INFO *NewAcpiBoardInfo; | |
| NewAcpiBoardInfo = NULL; | |
| Status = ParseAcpiInfo (AcpiTableBase, &AcpiBoardInfo); | |
| ASSERT_EFI_ERROR (Status); | |
| if (!EFI_ERROR (Status)) { | |
| NewAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO)); | |
| ASSERT (NewAcpiBoardInfo != NULL); | |
| CopyMem (NewAcpiBoardInfo, &AcpiBoardInfo, sizeof (ACPI_BOARD_INFO)); | |
| DEBUG ((DEBUG_INFO, "Create acpi board info guid hob\n")); | |
| } | |
| return NewAcpiBoardInfo; | |
| } |