- Added support to create MADT table at runtime. - Dropped the Madt.aslc from compilation since we are creating a new one at runtime.
Signed-off-by: Tanmay Jagdale tanmay.jagdale@linaro.org --- .../Qemu/SbsaQemu/AcpiTables/AcpiTables.inf | 1 - .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c | 158 ++++++++++++++++++ .../SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf | 17 +- 3 files changed, 174 insertions(+), 2 deletions(-)
diff --git a/Silicon/Qemu/SbsaQemu/AcpiTables/AcpiTables.inf b/Silicon/Qemu/SbsaQemu/AcpiTables/AcpiTables.inf index 9f8ced9db0..571b57c21a 100644 --- a/Silicon/Qemu/SbsaQemu/AcpiTables/AcpiTables.inf +++ b/Silicon/Qemu/SbsaQemu/AcpiTables/AcpiTables.inf @@ -20,7 +20,6 @@ AcpiTables.h Dsdt.asl Fadt.aslc - Madt.aslc Gtdt.aslc Spcr.aslc Mcfg.aslc diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c index 87f2c1aaec..b6acb12f8c 100644 --- a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c +++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c @@ -6,14 +6,23 @@ * SPDX-License-Identifier: BSD-2-Clause-Patent * **/ +#include <IndustryStandard/Acpi.h> +#include <IndustryStandard/Acpi10.h> +#include <IndustryStandard/Acpi60.h> +#include <Library/AcpiLib.h> +#include <Library/BaseMemoryLib.h> #include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> #include <Library/PcdLib.h> #include <Library/UefiBootServicesTableLib.h> #include <Library/UefiDriverEntryPoint.h> #include <Library/UefiLib.h> +#include <Protocol/AcpiTable.h> #include <Protocol/FdtClient.h> #include <libfdt.h>
+#include "../../AcpiTables/AcpiTables.h" + /* * A function that walks through the Device Tree created * by Qemu and counts the number of CPUs present in it. @@ -58,6 +67,136 @@ SbsaQemuCountCpusFromFdt( ASSERT_RETURN_ERROR (PcdStatus); }
+/* + * A Function to Compute the ACPI Table Checksum + */ +VOID +AcpiPlatformChecksum ( + IN UINT8 *Buffer, + IN UINTN Size + ) +{ + UINTN ChecksumOffset; + + ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum); + + // Set checksum to 0 first + Buffer[ChecksumOffset] = 0; + + // Update checksum value + Buffer[ChecksumOffset] = CalculateCheckSum8(Buffer, Size); +} + +/* + * A function that add the MADT ACPI table. + IN EFI_ACPI_COMMON_HEADER *CurrentTable + */ +EFI_STATUS +AddMadtTable ( + IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable + ) +{ + EFI_STATUS Status; + UINTN TableHandle; + UINT32 TableSize; + EFI_PHYSICAL_ADDRESS PageAddress; + UINT8 *New; + UINT32 NumCores; + EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header = { + __ACPI_HEADER (EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, + EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER, + EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION), + 0, 0 }; + + EFI_ACPI_6_0_GIC_STRUCTURE Gicc = EFI_ACPI_6_0_GICC_STRUCTURE_INIT( + 0, /* GicID */ + 0, /* AcpiCpuUid */ + 0, /* Mpidr */ + EFI_ACPI_6_0_GIC_ENABLED, /* Flags */ + 23, /* PmuIrq */ + 0, /* GicBase */ + 0x2c020000, /* GicVbase */ + 0x2c010000, /* GicHBase */ + 25, /* GsivId */ + 0 /* GicRBase */, + 0 /* Efficiency */); + Gicc.PhysicalBaseAddress = FixedPcdGet32 (PcdGicDistributorBase); + + EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE Gicd = EFI_ACPI_6_0_GIC_DISTRIBUTOR_INIT(0, 0, 0, 3); + Gicd.PhysicalBaseAddress = FixedPcdGet32 (PcdGicDistributorBase); + + EFI_ACPI_6_0_GICR_STRUCTURE Gicr = EFI_ACPI_6_0_GIC_REDISTRIBUTOR_INIT(0, 0x300000); + Gicr.DiscoveryRangeBaseAddress = FixedPcdGet32 (PcdGicRedistributorsBase); + + EFI_ACPI_6_0_GIC_ITS_STRUCTURE GicIts = EFI_ACPI_6_0_GIC_ITS_FRAME_INIT(0, 0x30020000); + + NumCores = PcdGet32 (PcdCoreCount); + + // Count the new table size based on the number of cores + TableSize = sizeof (EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER) + + (sizeof (EFI_ACPI_6_0_GIC_STRUCTURE) * NumCores) + + sizeof (EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE) + + sizeof (EFI_ACPI_6_0_GICR_STRUCTURE) + + sizeof (EFI_ACPI_6_0_GIC_ITS_STRUCTURE); + + PageAddress = 0xFFFFFFFFUL; + Status = gBS->AllocatePages ( + AllocateAnyPages, + EfiACPIReclaimMemory, + EFI_SIZE_TO_PAGES (TableSize), + &PageAddress + ); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Failed to allocate pages for MADT table\n")); + return EFI_OUT_OF_RESOURCES; + } + + New = (UINT8 *)(UINTN) PageAddress; + ZeroMem (New, TableSize); + + // Add the ACPI Description table header + CopyMem(New, &Header, sizeof (EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER)); + ((EFI_ACPI_DESCRIPTION_HEADER*) New)->Length = TableSize; + New += sizeof (EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER); + + // Add new GICC structures for the Cores + for (NumCores = 0; NumCores < PcdGet32 (PcdCoreCount); NumCores++) { + EFI_ACPI_6_0_GIC_STRUCTURE *GiccPtr; + + CopyMem (New, &Gicc, sizeof (EFI_ACPI_6_0_GIC_STRUCTURE)); + GiccPtr = (EFI_ACPI_6_0_GIC_STRUCTURE *) New; + GiccPtr->AcpiProcessorUid = NumCores; + GiccPtr->MPIDR = NumCores; + New += sizeof (EFI_ACPI_6_0_GIC_STRUCTURE); + } + + // GIC Distributor Structure + CopyMem(New, &Gicd, sizeof (EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE)); + New += sizeof (EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE); + + // GIC ReDistributor Structure + CopyMem(New, &Gicr, sizeof (EFI_ACPI_6_0_GICR_STRUCTURE)); + New += sizeof (EFI_ACPI_6_0_GICR_STRUCTURE); + + // Finally the GIC ITS Structure + CopyMem(New, &GicIts, sizeof (EFI_ACPI_6_0_GIC_ITS_STRUCTURE)); + New += sizeof (EFI_ACPI_6_0_GIC_ITS_STRUCTURE); + + AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize); + + Status = AcpiTable->InstallAcpiTable ( + AcpiTable, + (EFI_ACPI_COMMON_HEADER *)PageAddress, + TableSize, + &TableHandle + ); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Failed to install MADT table\n")); + } + + return Status; +} + EFI_STATUS EFIAPI InitializeSbsaQemuAcpiDxe ( @@ -65,8 +204,27 @@ InitializeSbsaQemuAcpiDxe ( IN EFI_SYSTEM_TABLE *SystemTable ) { + EFI_STATUS Status; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + // Parse the device tree and get the number of CPUs SbsaQemuCountCpusFromFdt();
+ // Check if ACPI Table Protocol has been installed + Status = gBS->LocateProtocol ( + &gEfiAcpiTableProtocolGuid, + NULL, + (VOID **)&AcpiTable + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Failed to locate ACPI Table Protocol\n")); + return Status; + } + + Status = AddMadtTable (AcpiTable); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Failed to add MADT table\n")); + } + return EFI_SUCCESS; } diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf index efc4d295bf..fc1d25e7fe 100644 --- a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf +++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf @@ -41,9 +41,24 @@ UefiRuntimeServicesTableLib
[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdCoreCount gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdClusterCount gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdDeviceTreeBaseAddress
[Depex] - TRUE + gEfiAcpiTableProtocolGuid ## CONSUMES + +[Guids] + gEdkiiPlatformHasAcpiGuid + +[Protocols] + gEfiAcpiTableProtocolGuid ## CONSUMES + +[FixedPcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision + gArmTokenSpaceGuid.PcdGicDistributorBase + gArmTokenSpaceGuid.PcdGicRedistributorsBase + + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision