/** @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 #include #include #include #include #include #include /** 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; }