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