alder_lake_bios/Intel/AlderLake/AlderLakeChipsetPkg/UpdateDsdtByAcpiSdtDxe/UpdateDsdtByAcpiSdt.c

259 lines
8.0 KiB
C

/** @file
//;******************************************************************************
//;* Copyright (c) 2014, Insyde Software Corporation. All Rights Reserved.
//;*
//;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
//;* transmit, broadcast, present, recite, release, license or otherwise exploit
//;* any part of this publication in any form, by any means, without the prior
//;* written permission of Insyde Software Corporation.
//;*
//;******************************************************************************
*/
#include <Uefi.h>
#include <Protocol/AcpiSystemDescriptionTable.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <IndustryStandard/Acpi.h>
#include <ChipsetSetupConfig.h>
#include <Library/DxeInsydeChipsetLib.h>
#include <Library/MemoryAllocationLib.h>
/**
To find out the target OperationRegion handle by the input Name.
@param [in] AcpiSdtProtocol A pointer of EFI_ACPI_SDT_PROTOCOL.
@param [in] Name The name of the target OperationRegion.
@param [in] ParentHandle The parent ACPI handle of the handles which will be searched.
@param [out] HandlePtr The pointer to target ACPI handle on return.
@retval EFI_SUCCESS: The target ACPI handle is found
@retval EFI_INVALID_PARAMETER: ParentHandle is NULL
@retval EFI_NOT_FOUND: Could not find the target ACPI handle
**/
EFI_STATUS
FindOpRegionByName (
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol,
IN UINT32 Name,
IN EFI_ACPI_HANDLE ParentHandle,
OUT EFI_ACPI_HANDLE *HandlePtr
)
{
EFI_STATUS Status;
EFI_STATUS GetOptionStatus;
EFI_STATUS GetChildStatus;
EFI_ACPI_DATA_TYPE DataType;
UINT8 Data;
UINT8 *DataPtr;
UINTN DataSize;
EFI_ACPI_HANDLE ChildHandle;
EFI_ACPI_HANDLE UnusedHandle;
if (ParentHandle == NULL) {
return EFI_INVALID_PARAMETER;
}
*HandlePtr = NULL;
ChildHandle = NULL;
GetChildStatus = EFI_SUCCESS;
while (!EFI_ERROR(GetChildStatus)) {
UnusedHandle = ChildHandle;
GetChildStatus = AcpiSdtProtocol->GetChild (ParentHandle, &ChildHandle);
if (UnusedHandle != NULL) {
//
// Close the handle which will not be used
//
Status = AcpiSdtProtocol->Close (UnusedHandle);
}
if (EFI_ERROR(GetChildStatus) || (ChildHandle == NULL)) {
//
// Get child handle failed, or there is no child handle
//
*HandlePtr = NULL;
return EFI_NOT_FOUND;
}
//
// Got the child handle, to check it is the target handle or not
//
DataPtr = &Data;
GetOptionStatus = AcpiSdtProtocol->GetOption (ChildHandle, 0, &DataType, &DataPtr, &DataSize);
if (!EFI_ERROR(GetOptionStatus) && (DataType != 0)) {
//
//Get the OpCode successful, and the DataType is not EFI_ACPI_DATA_TYPE_NONE
//
if ((*DataPtr == 0x08)) {
//
// The OpCpde is AML_NAME_OP(0x08)
//
GetOptionStatus = AcpiSdtProtocol->GetOption (ChildHandle, 1, &DataType, &DataPtr, &DataSize);
if (!EFI_ERROR(GetOptionStatus)) {
if (CompareMem (DataPtr, &Name, sizeof (Name)) == 0) {
//
// The name is matched.
// Got the target handle.
//
*HandlePtr = ChildHandle;
return EFI_SUCCESS;
}
}
}
}
}
return EFI_NOT_FOUND;
}
/**
This function is called when an ACPI table is installed by the ACPI Table Protocol.
Update object when DSDT table is installed.
@param [in] Table A pointer to the ACPI table header.
@param [in] Version The ACPI table's version.
@param [in] TableKey The table key for the ACPI table. This is identical
to the table key used in the EFI_ACPI_TABLE_PROTOCOL.
@retval EFI_SUCCESS: Update Object to DSDT table successfully
@retval EFI_LOAD_ERROR: Failed to update
@retval EFI_OUT_OF_RESOURCES: Could not allocate needed resources
**/
EFI_STATUS
UpdateDsdt (
IN EFI_ACPI_SDT_HEADER *Table,
IN EFI_ACPI_TABLE_VERSION Version,
IN UINTN TableKey
)
{
EFI_STATUS Status;
EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol;
EFI_ACPI_HANDLE RootHandle;
EFI_ACPI_HANDLE Handle;
EFI_ACPI_DATA_TYPE DataType;
UINT8 Data;
UINT8 *DataPtr;
UINTN DataSize;
CHIPSET_CONFIGURATION *SetupVariable;
SetupVariable = NULL;
SetupVariable = AllocateZeroPool (sizeof (CHIPSET_CONFIGURATION));
if (SetupVariable == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = GetChipsetSetupVariableDxe (SetupVariable, sizeof (CHIPSET_CONFIGURATION));
if (EFI_ERROR (Status)) {
FreePool (SetupVariable);
ASSERT_EFI_ERROR (Status);
return Status;
}
Status = EFI_SUCCESS;
if (Table->Signature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
//
// The installed table is DSDT Table.
// Locate ACPI SDT Protocol.
//
Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&AcpiSdtProtocol);
if (EFI_ERROR(Status)) {
if (SetupVariable != NULL) {
FreePool (SetupVariable);
}
return Status;
}
Status = AcpiSdtProtocol->OpenSdt (TableKey, &RootHandle);
if (EFI_ERROR(Status)) {
if (SetupVariable != NULL) {
FreePool (SetupVariable);
}
return Status;
}
Handle = NULL;
DataPtr = &Data;
//
// Call FindOpRegionByName() to find out the Object in DSDT
//
Status = FindOpRegionByName (AcpiSdtProtocol, SIGNATURE_32 ('S', 'S', '1', '_'), RootHandle, &Handle);
if (!EFI_ERROR(Status) && (Handle != NULL)) {
//
// The SS1_ name object is found
// Set the SS1_ value to the term 2 of SS1_ name object
//
Status = AcpiSdtProtocol->GetOption (Handle, 2, &DataType, &DataPtr, &DataSize);
if (EFI_ERROR(Status)) {
if (SetupVariable != NULL) {
FreePool (SetupVariable);
}
return Status;
}
*DataPtr = SetupVariable->DisableAcpiS1;
Status = AcpiSdtProtocol->SetOption (Handle, 2, DataPtr, DataSize);
if (EFI_ERROR(Status)) {
if (SetupVariable != NULL) {
FreePool (SetupVariable);
}
return Status;
}
Status = AcpiSdtProtocol->Close (Handle);
}
Status = AcpiSdtProtocol->Close (RootHandle);
//
// Update is done, unregister the callback function.
//
Status = AcpiSdtProtocol->RegisterNotify (FALSE, UpdateDsdt);
}
if (SetupVariable != NULL) {
FreePool (SetupVariable);
}
return Status;
}
/**
Entry point of the UpdateDsdtByAcpiSdt Driver.
Register the callback function - UpdateDsdt, which will be called when
an ACPI table is installed by the ACPI Table Protocol.
@param [in] ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver
@param [in] SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table
@retval EFI_SUCCESS: Driver initialized successfully
@retval EFI_LOAD_ERROR: Failed to Initialize or has been loaded
@retval EFI_OUT_OF_RESOURCES: Could not allocate needed resources
**/
EFI_STATUS
EFIAPI
UpdateDsdtByAcpiSdtEntry (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol;
Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&AcpiSdtProtocol);
if (EFI_ERROR(Status)) {
return Status;
}
Status = AcpiSdtProtocol->RegisterNotify (TRUE, UpdateDsdt);
return Status;
}