/** @file ACPI Platform Driver Copyright (c) 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that 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 #include #include #include #include #include #include #include #include #include #include GLOBAL_REMOVE_IF_UNREFERENCED EFI_GLOBAL_NVS_AREA_PROTOCOL mGlobalNvsArea; /** @brief Global NVS initialize. @param[in] GlobalNvs - Pointer of Global NVS area @retval EFI_SUCCESS - Allocate Global NVS completed. @retval EFI_OUT_OF_RESOURCES - Failed to allocate required page for GNVS. **/ EFI_STATUS EFIAPI AcpiGnvsInit ( IN OUT VOID **GlobalNvs ); VOID UpdateDsdt ( IN VOID *Table ); // // Function implementations // /** Locate the first instance of a protocol. If the protocol requested is an FV protocol, then it will return the first FV that contains the ACPI table storage file. @param[in] Protocol The protocol to find. @param[in] Instance Return pointer to the first instance of the protocol. @param[in] Type TRUE if the desired protocol is a FV protocol. @retval EFI_SUCCESS The function completed successfully. @retval EFI_NOT_FOUND The protocol could not be located. @retval EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. **/ EFI_STATUS LocateSupportProtocol ( IN EFI_GUID *Protocol, IN EFI_GUID *gEfiAcpiMultiTableStorageGuid, OUT VOID **Instance, IN BOOLEAN Type ) { EFI_STATUS Status; EFI_HANDLE *HandleBuffer; UINTN NumberOfHandles; EFI_FV_FILETYPE FileType; UINT32 FvStatus; EFI_FV_FILE_ATTRIBUTES Attributes; UINTN Size; UINTN Index; // // Locate protocol. // Status = gBS->LocateHandleBuffer ( ByProtocol, Protocol, NULL, &NumberOfHandles, &HandleBuffer ); if (EFI_ERROR (Status)) { // // Defined errors at this time are not found and out of resources. // 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], Protocol, Instance ); ASSERT_EFI_ERROR (Status); if (!Type) { // // Not looking for the FV protocol, so find the first instance of the // protocol. There should not be any errors because our handle buffer // should always contain at least one or LocateHandleBuffer would have // returned not found. // break; } // // See if it has the ACPI storage file // Size = 0; FvStatus = 0; Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL *) (*Instance))->ReadFile ( *Instance, gEfiAcpiMultiTableStorageGuid, NULL, &Size, &FileType, &Attributes, &FvStatus ); // // If we found it, then we are done // if (Status == EFI_SUCCESS) { break; } } // // Our exit status is determined by the success of the previous operations // If the protocol was found, Instance already points to it. // // // Free any allocated buffers // FreePool (HandleBuffer); return Status; } EFI_STATUS PublishAcpiTablesFromFv ( IN EFI_GUID *gEfiAcpiMultiTableStorageGuid ) { EFI_STATUS Status; EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; EFI_ACPI_COMMON_HEADER *CurrentTable; UINT32 FvStatus; UINTN Size; EFI_ACPI_TABLE_VERSION Version; UINTN TableHandle; INTN Instance; EFI_ACPI_TABLE_PROTOCOL *AcpiTable; Instance = 0; TableHandle = 0; CurrentTable = NULL; FwVol = NULL; // // Find the AcpiSupport protocol // Status = LocateSupportProtocol ( &gEfiAcpiTableProtocolGuid, gEfiAcpiMultiTableStorageGuid, (VOID **) &AcpiTable, FALSE ); ASSERT_EFI_ERROR (Status); // // Locate the firmware volume protocol // Status = LocateSupportProtocol ( &gEfiFirmwareVolume2ProtocolGuid, gEfiAcpiMultiTableStorageGuid, (VOID **) &FwVol, TRUE ); // // Read tables from the storage file. // while (Status == EFI_SUCCESS) { Status = FwVol->ReadSection ( FwVol, gEfiAcpiMultiTableStorageGuid, EFI_SECTION_RAW, Instance, (VOID **) &CurrentTable, &Size, &FvStatus ); if (!EFI_ERROR (Status)) { // // Perform any table specific updates. // if (CurrentTable->Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) { UpdateDsdt (CurrentTable); } BoardUpdateAcpiTable (CurrentTable, &Version); // // Add the table // TableHandle = 0; if (Version != EFI_ACPI_TABLE_VERSION_NONE) { Status = AcpiTable->InstallAcpiTable ( AcpiTable, CurrentTable, CurrentTable->Length, &TableHandle ); } ASSERT_EFI_ERROR (Status); // // Increment the instance // Instance++; CurrentTable = NULL; } } // // Finished // return EFI_SUCCESS; } /** ACPI Platform driver installation function. @param[in] ImageHandle Handle for this drivers loaded image protocol. @param[in] SystemTable EFI system table. @retval EFI_SUCCESS The driver installed without error. @retval EFI_ABORTED The driver encountered an error and could not complete installation of the ACPI tables. **/ EFI_STATUS EFIAPI InstallAcpiBoard ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_HANDLE Handle; AcpiGnvsInit((VOID **) &mGlobalNvsArea.Area); // // This PCD set must be done before PublishAcpiTablesFromFv. // The PCD data will be used there. // PcdSet64S (PcdAcpiGnvsAddress, (UINT64)(UINTN)mGlobalNvsArea.Area); // // Platform ACPI Tables // PublishAcpiTablesFromFv (&gEfiCallerIdGuid); // // This protocol publish must be done after PublishAcpiTablesFromFv. // The NVS data is be updated there. // Handle = NULL; Status = gBS->InstallMultipleProtocolInterfaces ( &Handle, &gEfiGlobalNvsAreaProtocolGuid, &mGlobalNvsArea, NULL ); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }