/** @file Copyright (c) 2021, Intel Corporation. All rights reserved.
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); 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; }