162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: uteval - Object evaluation 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <acpi/acpi.h> 1162306a36Sopenharmony_ci#include "accommon.h" 1262306a36Sopenharmony_ci#include "acnamesp.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define _COMPONENT ACPI_UTILITIES 1562306a36Sopenharmony_ciACPI_MODULE_NAME("uteval") 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/******************************************************************************* 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * FUNCTION: acpi_ut_evaluate_object 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * PARAMETERS: prefix_node - Starting node 2262306a36Sopenharmony_ci * path - Path to object from starting node 2362306a36Sopenharmony_ci * expected_return_types - Bitmap of allowed return types 2462306a36Sopenharmony_ci * return_desc - Where a return value is stored 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * RETURN: Status 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * DESCRIPTION: Evaluates a namespace object and verifies the type of the 2962306a36Sopenharmony_ci * return object. Common code that simplifies accessing objects 3062306a36Sopenharmony_ci * that have required return objects of fixed types. 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * NOTE: Internal function, no parameter validation 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci ******************************************************************************/ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciacpi_status 3762306a36Sopenharmony_ciacpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, 3862306a36Sopenharmony_ci const char *path, 3962306a36Sopenharmony_ci u32 expected_return_btypes, 4062306a36Sopenharmony_ci union acpi_operand_object **return_desc) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci struct acpi_evaluate_info *info; 4362306a36Sopenharmony_ci acpi_status status; 4462306a36Sopenharmony_ci u32 return_btype; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ut_evaluate_object); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci /* Allocate the evaluation information block */ 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); 5162306a36Sopenharmony_ci if (!info) { 5262306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci info->prefix_node = prefix_node; 5662306a36Sopenharmony_ci info->relative_pathname = path; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci /* Evaluate the object/method */ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci status = acpi_ns_evaluate(info); 6162306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 6262306a36Sopenharmony_ci if (status == AE_NOT_FOUND) { 6362306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 6462306a36Sopenharmony_ci "[%4.4s.%s] was not found\n", 6562306a36Sopenharmony_ci acpi_ut_get_node_name(prefix_node), 6662306a36Sopenharmony_ci path)); 6762306a36Sopenharmony_ci } else { 6862306a36Sopenharmony_ci ACPI_ERROR_METHOD("Method execution failed", 6962306a36Sopenharmony_ci prefix_node, path, status); 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci goto cleanup; 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci /* Did we get a return object? */ 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci if (!info->return_object) { 7862306a36Sopenharmony_ci if (expected_return_btypes) { 7962306a36Sopenharmony_ci ACPI_ERROR_METHOD("No object was returned from", 8062306a36Sopenharmony_ci prefix_node, path, AE_NOT_EXIST); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci status = AE_NOT_EXIST; 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci goto cleanup; 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* Map the return object type to the bitmapped type */ 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci switch ((info->return_object)->common.type) { 9162306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci return_btype = ACPI_BTYPE_INTEGER; 9462306a36Sopenharmony_ci break; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci case ACPI_TYPE_BUFFER: 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci return_btype = ACPI_BTYPE_BUFFER; 9962306a36Sopenharmony_ci break; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci case ACPI_TYPE_STRING: 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci return_btype = ACPI_BTYPE_STRING; 10462306a36Sopenharmony_ci break; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci case ACPI_TYPE_PACKAGE: 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci return_btype = ACPI_BTYPE_PACKAGE; 10962306a36Sopenharmony_ci break; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci default: 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci return_btype = 0; 11462306a36Sopenharmony_ci break; 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) { 11862306a36Sopenharmony_ci /* 11962306a36Sopenharmony_ci * We received a return object, but one was not expected. This can 12062306a36Sopenharmony_ci * happen frequently if the "implicit return" feature is enabled. 12162306a36Sopenharmony_ci * Just delete the return object and return AE_OK. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ci acpi_ut_remove_reference(info->return_object); 12462306a36Sopenharmony_ci goto cleanup; 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci /* Is the return object one of the expected types? */ 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci if (!(expected_return_btypes & return_btype)) { 13062306a36Sopenharmony_ci ACPI_ERROR_METHOD("Return object type is incorrect", 13162306a36Sopenharmony_ci prefix_node, path, AE_TYPE); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 13462306a36Sopenharmony_ci "Type returned from %s was incorrect: %s, expected Btypes: 0x%X", 13562306a36Sopenharmony_ci path, 13662306a36Sopenharmony_ci acpi_ut_get_object_type_name(info->return_object), 13762306a36Sopenharmony_ci expected_return_btypes)); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci /* On error exit, we must delete the return object */ 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci acpi_ut_remove_reference(info->return_object); 14262306a36Sopenharmony_ci status = AE_TYPE; 14362306a36Sopenharmony_ci goto cleanup; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* Object type is OK, return it */ 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci *return_desc = info->return_object; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cicleanup: 15162306a36Sopenharmony_ci ACPI_FREE(info); 15262306a36Sopenharmony_ci return_ACPI_STATUS(status); 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci/******************************************************************************* 15662306a36Sopenharmony_ci * 15762306a36Sopenharmony_ci * FUNCTION: acpi_ut_evaluate_numeric_object 15862306a36Sopenharmony_ci * 15962306a36Sopenharmony_ci * PARAMETERS: object_name - Object name to be evaluated 16062306a36Sopenharmony_ci * device_node - Node for the device 16162306a36Sopenharmony_ci * value - Where the value is returned 16262306a36Sopenharmony_ci * 16362306a36Sopenharmony_ci * RETURN: Status 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * DESCRIPTION: Evaluates a numeric namespace object for a selected device 16662306a36Sopenharmony_ci * and stores result in *Value. 16762306a36Sopenharmony_ci * 16862306a36Sopenharmony_ci * NOTE: Internal function, no parameter validation 16962306a36Sopenharmony_ci * 17062306a36Sopenharmony_ci ******************************************************************************/ 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ciacpi_status 17362306a36Sopenharmony_ciacpi_ut_evaluate_numeric_object(const char *object_name, 17462306a36Sopenharmony_ci struct acpi_namespace_node *device_node, 17562306a36Sopenharmony_ci u64 *value) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci union acpi_operand_object *obj_desc; 17862306a36Sopenharmony_ci acpi_status status; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci status = acpi_ut_evaluate_object(device_node, object_name, 18362306a36Sopenharmony_ci ACPI_BTYPE_INTEGER, &obj_desc); 18462306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 18562306a36Sopenharmony_ci return_ACPI_STATUS(status); 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* Get the returned Integer */ 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci *value = obj_desc->integer.value; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci /* On exit, we must delete the return object */ 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci acpi_ut_remove_reference(obj_desc); 19562306a36Sopenharmony_ci return_ACPI_STATUS(status); 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci/******************************************************************************* 19962306a36Sopenharmony_ci * 20062306a36Sopenharmony_ci * FUNCTION: acpi_ut_execute_STA 20162306a36Sopenharmony_ci * 20262306a36Sopenharmony_ci * PARAMETERS: device_node - Node for the device 20362306a36Sopenharmony_ci * flags - Where the status flags are returned 20462306a36Sopenharmony_ci * 20562306a36Sopenharmony_ci * RETURN: Status 20662306a36Sopenharmony_ci * 20762306a36Sopenharmony_ci * DESCRIPTION: Executes _STA for selected device and stores results in 20862306a36Sopenharmony_ci * *Flags. If _STA does not exist, then the device is assumed 20962306a36Sopenharmony_ci * to be present/functional/enabled (as per the ACPI spec). 21062306a36Sopenharmony_ci * 21162306a36Sopenharmony_ci * NOTE: Internal function, no parameter validation 21262306a36Sopenharmony_ci * 21362306a36Sopenharmony_ci ******************************************************************************/ 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ciacpi_status 21662306a36Sopenharmony_ciacpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci union acpi_operand_object *obj_desc; 21962306a36Sopenharmony_ci acpi_status status; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ut_execute_STA); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA, 22462306a36Sopenharmony_ci ACPI_BTYPE_INTEGER, &obj_desc); 22562306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 22662306a36Sopenharmony_ci if (AE_NOT_FOUND == status) { 22762306a36Sopenharmony_ci /* 22862306a36Sopenharmony_ci * if _STA does not exist, then (as per the ACPI specification), 22962306a36Sopenharmony_ci * the returned flags will indicate that the device is present, 23062306a36Sopenharmony_ci * functional, and enabled. 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 23362306a36Sopenharmony_ci "_STA on %4.4s was not found, assuming device is present\n", 23462306a36Sopenharmony_ci acpi_ut_get_node_name(device_node))); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci *flags = ACPI_UINT32_MAX; 23762306a36Sopenharmony_ci status = AE_OK; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci return_ACPI_STATUS(status); 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* Extract the status flags */ 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci *flags = (u32) obj_desc->integer.value; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* On exit, we must delete the return object */ 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci acpi_ut_remove_reference(obj_desc); 25062306a36Sopenharmony_ci return_ACPI_STATUS(status); 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci/******************************************************************************* 25462306a36Sopenharmony_ci * 25562306a36Sopenharmony_ci * FUNCTION: acpi_ut_execute_power_methods 25662306a36Sopenharmony_ci * 25762306a36Sopenharmony_ci * PARAMETERS: device_node - Node for the device 25862306a36Sopenharmony_ci * method_names - Array of power method names 25962306a36Sopenharmony_ci * method_count - Number of methods to execute 26062306a36Sopenharmony_ci * out_values - Where the power method values are returned 26162306a36Sopenharmony_ci * 26262306a36Sopenharmony_ci * RETURN: Status, out_values 26362306a36Sopenharmony_ci * 26462306a36Sopenharmony_ci * DESCRIPTION: Executes the specified power methods for the device and returns 26562306a36Sopenharmony_ci * the result(s). 26662306a36Sopenharmony_ci * 26762306a36Sopenharmony_ci * NOTE: Internal function, no parameter validation 26862306a36Sopenharmony_ci * 26962306a36Sopenharmony_ci******************************************************************************/ 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ciacpi_status 27262306a36Sopenharmony_ciacpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, 27362306a36Sopenharmony_ci const char **method_names, 27462306a36Sopenharmony_ci u8 method_count, u8 *out_values) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci union acpi_operand_object *obj_desc; 27762306a36Sopenharmony_ci acpi_status status; 27862306a36Sopenharmony_ci acpi_status final_status = AE_NOT_FOUND; 27962306a36Sopenharmony_ci u32 i; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ut_execute_power_methods); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci for (i = 0; i < method_count; i++) { 28462306a36Sopenharmony_ci /* 28562306a36Sopenharmony_ci * Execute the power method (_sx_d or _sx_w). The only allowable 28662306a36Sopenharmony_ci * return type is an Integer. 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_ci status = acpi_ut_evaluate_object(device_node, 28962306a36Sopenharmony_ci ACPI_CAST_PTR(char, 29062306a36Sopenharmony_ci method_names[i]), 29162306a36Sopenharmony_ci ACPI_BTYPE_INTEGER, &obj_desc); 29262306a36Sopenharmony_ci if (ACPI_SUCCESS(status)) { 29362306a36Sopenharmony_ci out_values[i] = (u8)obj_desc->integer.value; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* Delete the return object */ 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci acpi_ut_remove_reference(obj_desc); 29862306a36Sopenharmony_ci final_status = AE_OK; /* At least one value is valid */ 29962306a36Sopenharmony_ci continue; 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci out_values[i] = ACPI_UINT8_MAX; 30362306a36Sopenharmony_ci if (status == AE_NOT_FOUND) { 30462306a36Sopenharmony_ci continue; /* Ignore if not found */ 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 30862306a36Sopenharmony_ci "Failed %s on Device %4.4s, %s\n", 30962306a36Sopenharmony_ci ACPI_CAST_PTR(char, method_names[i]), 31062306a36Sopenharmony_ci acpi_ut_get_node_name(device_node), 31162306a36Sopenharmony_ci acpi_format_exception(status))); 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci return_ACPI_STATUS(final_status); 31562306a36Sopenharmony_ci} 316