/** @file ACPI Platform Driver Copyright (c) 2020, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #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 ); // // 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; 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)) { // // Add the table // TableHandle = 0; 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; }