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