/** @file This is the driver that initializes the Intel System Agent. Copyright (c) 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "SaInitDxe.h" #include "SaInit.h" #include /// /// Global Variables /// GLOBAL_REMOVE_IF_UNREFERENCED SYSTEM_AGENT_GLOBAL_NVS_AREA_PROTOCOL mSaGlobalNvsAreaProtocol; GLOBAL_REMOVE_IF_UNREFERENCED SA_POLICY_PROTOCOL *mSaPolicy; /** Initialize System Agent SSDT ACPI tables @retval EFI_SUCCESS ACPI tables are initialized successfully @retval EFI_NOT_FOUND ACPI tables not found **/ EFI_STATUS InitializeSaSsdtAcpiTables ( VOID ) { EFI_STATUS Status; EFI_HANDLE *HandleBuffer; UINTN NumberOfHandles; EFI_FV_FILETYPE FileType; UINT32 FvStatus; EFI_FV_FILE_ATTRIBUTES Attributes; UINTN Size; UINTN i; EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; INTN Instance; EFI_ACPI_COMMON_HEADER *CurrentTable; UINTN AcpiTableKey; UINT8 *CurrPtr; UINT8 *EndPtr; UINT32 *Signature; EFI_ACPI_DESCRIPTION_HEADER *SaAcpiTable; EFI_ACPI_TABLE_PROTOCOL *AcpiTable; FwVol = NULL; SaAcpiTable = NULL; /// /// Locate ACPI Table protocol /// DEBUG ((DEBUG_INFO, "Init SA SSDT table\n")); Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable); if (Status != EFI_SUCCESS) { DEBUG ((DEBUG_WARN, "Fail to locate EfiAcpiTableProtocol.\n")); return EFI_NOT_FOUND; } /// /// Locate protocol. /// There is little chance we can't find an FV protocol /// Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NumberOfHandles, &HandleBuffer ); ASSERT_EFI_ERROR (Status); /// /// Looking for FV with ACPI storage file /// for (i = 0; i < NumberOfHandles; i++) { /// /// Get the protocol on this handle /// This should not fail because of LocateHandleBuffer /// Status = gBS->HandleProtocol ( HandleBuffer[i], &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &FwVol ); ASSERT_EFI_ERROR (Status); /// /// See if it has the ACPI storage file /// Size = 0; FvStatus = 0; Status = FwVol->ReadFile ( FwVol, &gSaSsdtAcpiTableStorageGuid, NULL, &Size, &FileType, &Attributes, &FvStatus ); /// /// If we found it, then we are done /// if (Status == EFI_SUCCESS) { break; } } /// /// Free any allocated buffers /// FreePool (HandleBuffer); /// /// Sanity check that we found our data file /// ASSERT (FwVol != NULL); if (FwVol == NULL) { DEBUG ((DEBUG_INFO, "SA Global NVS table not found\n")); return EFI_NOT_FOUND; } /// /// Our exit status is determined by the success of the previous operations /// If the protocol was found, Instance already points to it. /// Read tables from the storage file. /// Instance = 0; CurrentTable = NULL; while (Status == EFI_SUCCESS) { Status = FwVol->ReadSection ( FwVol, &gSaSsdtAcpiTableStorageGuid, EFI_SECTION_RAW, Instance, (VOID **) &CurrentTable, &Size, &FvStatus ); if (!EFI_ERROR (Status)) { /// /// Check the table ID to modify the table /// if (((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->OemTableId == SIGNATURE_64 ('S', 'a', 'S', 's', 'd', 't', ' ', 0)) { SaAcpiTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable; /// /// Locate the SSDT package /// CurrPtr = (UINT8 *) SaAcpiTable; EndPtr = CurrPtr + SaAcpiTable->Length; for (; CurrPtr <= EndPtr; CurrPtr++) { Signature = (UINT32 *) (CurrPtr + 3); if (*Signature == SIGNATURE_32 ('S', 'A', 'N', 'V')) { ASSERT (*(UINT32 *) (CurrPtr + 3 + sizeof (*Signature) + 2) == 0xFFFF0000); ASSERT (*(UINT16 *) (CurrPtr + 3 + sizeof (*Signature) + 2 + sizeof (UINT32) + 1) == 0xAA55); /// /// SA Global NVS Area address /// *(UINT32 *) (CurrPtr + 3 + sizeof (*Signature) + 2) = (UINT32) (UINTN) mSaGlobalNvsAreaProtocol.Area; /// /// SA Global NVS Area size /// *(UINT16 *) (CurrPtr + 3 + sizeof (*Signature) + 2 + sizeof (UINT32) + 1) = sizeof (SYSTEM_AGENT_GLOBAL_NVS_AREA); AcpiTableKey = 0; Status = AcpiTable->InstallAcpiTable ( AcpiTable, SaAcpiTable, SaAcpiTable->Length, &AcpiTableKey ); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; } } } /// /// Increment the instance /// Instance++; CurrentTable = NULL; } } return Status; } /** This function gets registered as a callback to perform Dmar Igd @param[in] Event - A pointer to the Event that triggered the callback. @param[in] Context - A pointer to private data registered with the callback function. **/ VOID EFIAPI SaAcpiEndOfDxeCallback ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; if (MmioRead16 (MmPciBase (SA_MC_BUS, 2, 0) + R_SA_IGD_VID) != 0xFFFF) { Status = GetVBiosVbtEndOfDxe (); if (EFI_SUCCESS != Status) { DEBUG ((DEBUG_WARN, "[SA] EndOfDxe Op Region Error, Status = %r \n", Status)); } } return; } /** SystemAgent Acpi Initialization. @param[in] ImageHandle Handle for the image of this driver @retval EFI_SUCCESS The function completed successfully @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate **/ EFI_STATUS EFIAPI SaAcpiInit ( IN EFI_HANDLE ImageHandle ) { EFI_STATUS Status; EFI_EVENT EndOfDxeEvent; /// /// Get the platform setup policy. /// Status = gBS->LocateProtocol (&gSaPolicyProtocolGuid, NULL, (VOID **) &mSaPolicy); ASSERT_EFI_ERROR (Status); /// /// Install System Agent Global NVS protocol /// DEBUG ((DEBUG_INFO, "Install SA GNVS protocol\n")); Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (SYSTEM_AGENT_GLOBAL_NVS_AREA), (VOID **) &mSaGlobalNvsAreaProtocol.Area); ASSERT_EFI_ERROR (Status); ZeroMem ((VOID *) mSaGlobalNvsAreaProtocol.Area, sizeof (SYSTEM_AGENT_GLOBAL_NVS_AREA)); mSaGlobalNvsAreaProtocol.Area->XPcieCfgBaseAddress = (UINT32) (MmPciBase (0, 0, 0)); Status = gBS->InstallMultipleProtocolInterfaces ( &ImageHandle, &gSaGlobalNvsAreaProtocolGuid, &mSaGlobalNvsAreaProtocol, NULL ); ASSERT_EFI_ERROR (Status); /// /// GtPostInit Initialization /// DEBUG ((DEBUG_INFO, "Initializing GT ACPI tables\n")); GraphicsInit (ImageHandle, mSaPolicy); /// /// Vtd Initialization /// DEBUG ((DEBUG_INFO, "Initializing VT-d ACPI tables\n")); VtdInit (mSaPolicy); /// /// IgdOpRegion Install Initialization /// DEBUG ((DEBUG_INFO, "Initializing IGD OpRegion\n")); IgdOpRegionInit (); /// /// Register an end of DXE event for SA ACPI to do tasks before invoking any UEFI drivers, /// applications, or connecting consoles,... /// Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, SaAcpiEndOfDxeCallback, NULL, &gEfiEndOfDxeEventGroupGuid, &EndOfDxeEvent ); /// /// Install System Agent Global NVS ACPI table /// Status = InitializeSaSsdtAcpiTables (); return EFI_SUCCESS; }