diff --git a/EmbeddedPkg/EmbeddedPkg.dsc b/EmbeddedPkg/EmbeddedPkg.dsc index b13693c5e2..a3a136da32 100644 --- a/EmbeddedPkg/EmbeddedPkg.dsc +++ b/EmbeddedPkg/EmbeddedPkg.dsc @@ -98,6 +98,7 @@ EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf + AcpiLib|EmbeddedPkg/Library/AcpiLib/AcpiLib.inf FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf # Networking Requirements diff --git a/EmbeddedPkg/Include/Library/AcpiLib.h b/EmbeddedPkg/Include/Library/AcpiLib.h new file mode 100644 index 0000000000..3eaa1d558e --- /dev/null +++ b/EmbeddedPkg/Include/Library/AcpiLib.h @@ -0,0 +1,62 @@ +/** @file + Helper Library for ACPI + + Copyright (c) 2014, ARM Ltd. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ACPI_LIB_H__ +#define __ACPI_LIB_H__ + +#include <Uefi.h> + +// +// Macros for the Generic Address Space +// +#define NULL_GAS { EFI_ACPI_5_0_SYSTEM_MEMORY, 0, 0, EFI_ACPI_5_0_UNDEFINED, 0L } +#define ARM_GAS8(Address) { EFI_ACPI_5_0_SYSTEM_MEMORY, 8, 0, EFI_ACPI_5_0_BYTE, Address } +#define ARM_GAS16(Address) { EFI_ACPI_5_0_SYSTEM_MEMORY, 16, 0, EFI_ACPI_5_0_WORD, Address } +#define ARM_GAS32(Address) { EFI_ACPI_5_0_SYSTEM_MEMORY, 32, 0, EFI_ACPI_5_0_DWORD, Address } +#define ARM_GASN(Address) { EFI_ACPI_5_0_SYSTEM_MEMORY, 0, 0, EFI_ACPI_5_0_DWORD, Address } + +// +// Macros for the Multiple APIC Description Table (MADT) +// +#define EFI_ACPI_5_0_GIC_DISTRIBUTOR_INIT(GicDistHwId, GicDistBase, GicDistVector) \ + { \ + EFI_ACPI_5_0_GICD, sizeof (EFI_ACPI_5_0_GIC_DISTRIBUTOR_STRUCTURE), EFI_ACPI_RESERVED_WORD, \ + GicDistHwId, GicDistBase, GicDistVector, EFI_ACPI_RESERVED_DWORD \ + } + +// Note the parking protocol is configured by UEFI if required +#define EFI_ACPI_5_0_GIC_STRUCTURE_INIT(GicId, AcpiCpuId, Flags, PmuIrq, GicBase) \ + { \ + EFI_ACPI_5_0_GIC, sizeof (EFI_ACPI_5_0_GIC_STRUCTURE), EFI_ACPI_RESERVED_WORD, \ + GicId, AcpiCpuId, Flags, 0, PmuIrq, 0, GicBase \ + } + + +/** + Locate and Install the ACPI tables from the Firmware Volume + + @param AcpiFile Guid of the ACPI file into the Firmware Volume + + @return EFI_SUCCESS The function completed successfully. + @return EFI_NOT_FOUND The protocol could not be located. + @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. + +**/ +EFI_STATUS +LocateAndInstallAcpiFromFv ( + IN CONST EFI_GUID* AcpiFile + ); + +#endif // __ACPI_LIB_H__ diff --git a/EmbeddedPkg/Library/AcpiLib/AcpiLib.c b/EmbeddedPkg/Library/AcpiLib/AcpiLib.c new file mode 100644 index 0000000000..4090055928 --- /dev/null +++ b/EmbeddedPkg/Library/AcpiLib/AcpiLib.c @@ -0,0 +1,146 @@ +/** @file +* +* Copyright (c) 2014, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include <Uefi.h> + +#include <Library/AcpiLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include <Protocol/AcpiTable.h> +#include <Protocol/FirmwareVolume2.h> + +#include <IndustryStandard/Acpi.h> + +/** + Locate and Install the ACPI tables from the Firmware Volume + + @param AcpiFile Guid of the ACPI file into the Firmware Volume + + @return EFI_SUCCESS The function completed successfully. + @return EFI_NOT_FOUND The protocol could not be located. + @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. + +**/ +EFI_STATUS +LocateAndInstallAcpiFromFv ( + IN CONST EFI_GUID* AcpiFile + ) +{ + EFI_STATUS Status; + EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + UINT32 FvStatus; + UINTN Index; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; + INTN SectionInstance; + UINTN SectionSize; + EFI_ACPI_COMMON_HEADER *AcpiTable; + UINTN AcpiTableSize; + UINTN AcpiTableKey; + + // Ensure the ACPI Table is present + Status = gBS->LocateProtocol ( + &gEfiAcpiTableProtocolGuid, + NULL, + (VOID**)&AcpiProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + FvStatus = 0; + SectionInstance = 0; + + // Locate all the Firmware Volume protocols. + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Looking for FV with ACPI storage file + for (Index = 0; Index < NumberOfHandles; Index++) { + // + // Get the protocol on this handle + // This should not fail because of LocateHandleBuffer + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID**) &FvInstance + ); + if (EFI_ERROR (Status)) { + goto FREE_HANDLE_BUFFER; + } + + while (Status == EFI_SUCCESS) { + // AcpiTable must be allocated by ReadSection (ie: AcpiTable == NULL) + AcpiTable = NULL; + + // See if it has the ACPI storage file + Status = FvInstance->ReadSection ( + FvInstance, + AcpiFile, + EFI_SECTION_RAW, + SectionInstance, + (VOID**) &AcpiTable, + &SectionSize, + &FvStatus + ); + if (!EFI_ERROR (Status)) { + AcpiTableKey = 0; + AcpiTableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Length; + ASSERT (SectionSize >= AcpiTableSize); + + DEBUG ((EFI_D_ERROR, "- Found '%c%c%c%c' ACPI Table\n", + (((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature & 0xFF), + ((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 8) & 0xFF), + ((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 16) & 0xFF), + ((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 24) & 0xFF))); + + // Install the ACPI Table + Status = AcpiProtocol->InstallAcpiTable ( + AcpiProtocol, + AcpiTable, + AcpiTableSize, + &AcpiTableKey + ); + // Free memory allocated by ReadSection + gBS->FreePool (AcpiTable); + + if (EFI_ERROR (Status)) { + break; + } + + // Increment the section instance + SectionInstance++; + } + } + } + +FREE_HANDLE_BUFFER: + // + // Free any allocated buffers + // + gBS->FreePool (HandleBuffer); + + return EFI_SUCCESS; +} diff --git a/EmbeddedPkg/Library/AcpiLib/AcpiLib.inf b/EmbeddedPkg/Library/AcpiLib/AcpiLib.inf new file mode 100644 index 0000000000..5080c50756 --- /dev/null +++ b/EmbeddedPkg/Library/AcpiLib/AcpiLib.inf @@ -0,0 +1,36 @@ +#/** @file +# +# Copyright (c) 2014, ARM Ltd. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiLib + FILE_GUID = 24b9d62c-5a36-417b-94b6-38dbaea90dcf + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = AcpiLib + +[Sources.common] + AcpiLib.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + DebugLib + UefiBootServicesTableLib + +[Protocols] + gEfiAcpiTableProtocolGuid + gEfiFirmwareVolume2ProtocolGuid