/** @file
|
This is the driver that initializes the Intel System Agent.
|
|
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
#include "SaInitDxe.h"
|
#include "SaInit.h"
|
#include <Protocol/SaGlobalNvsArea.h>
|
|
///
|
/// 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;
|
}
|
|