259 lines
8.0 KiB
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;
|
|
}
|