316 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: uteval - Object evaluation5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acnamesp.h"13 14#define _COMPONENT ACPI_UTILITIES15ACPI_MODULE_NAME("uteval")16 17/*******************************************************************************18 *19 * FUNCTION: acpi_ut_evaluate_object20 *21 * PARAMETERS: prefix_node - Starting node22 * path - Path to object from starting node23 * expected_return_types - Bitmap of allowed return types24 * return_desc - Where a return value is stored25 *26 * RETURN: Status27 *28 * DESCRIPTION: Evaluates a namespace object and verifies the type of the29 * return object. Common code that simplifies accessing objects30 * that have required return objects of fixed types.31 *32 * NOTE: Internal function, no parameter validation33 *34 ******************************************************************************/35 36acpi_status37acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,38 const char *path,39 u32 expected_return_btypes,40 union acpi_operand_object **return_desc)41{42 struct acpi_evaluate_info *info;43 acpi_status status;44 u32 return_btype;45 46 ACPI_FUNCTION_TRACE(ut_evaluate_object);47 48 /* Allocate the evaluation information block */49 50 info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));51 if (!info) {52 return_ACPI_STATUS(AE_NO_MEMORY);53 }54 55 info->prefix_node = prefix_node;56 info->relative_pathname = path;57 58 /* Evaluate the object/method */59 60 status = acpi_ns_evaluate(info);61 if (ACPI_FAILURE(status)) {62 if (status == AE_NOT_FOUND) {63 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,64 "[%4.4s.%s] was not found\n",65 acpi_ut_get_node_name(prefix_node),66 path));67 } else {68 ACPI_ERROR_METHOD("Method execution failed",69 prefix_node, path, status);70 }71 72 goto cleanup;73 }74 75 /* Did we get a return object? */76 77 if (!info->return_object) {78 if (expected_return_btypes) {79 ACPI_ERROR_METHOD("No object was returned from",80 prefix_node, path, AE_NOT_EXIST);81 82 status = AE_NOT_EXIST;83 }84 85 goto cleanup;86 }87 88 /* Map the return object type to the bitmapped type */89 90 switch ((info->return_object)->common.type) {91 case ACPI_TYPE_INTEGER:92 93 return_btype = ACPI_BTYPE_INTEGER;94 break;95 96 case ACPI_TYPE_BUFFER:97 98 return_btype = ACPI_BTYPE_BUFFER;99 break;100 101 case ACPI_TYPE_STRING:102 103 return_btype = ACPI_BTYPE_STRING;104 break;105 106 case ACPI_TYPE_PACKAGE:107 108 return_btype = ACPI_BTYPE_PACKAGE;109 break;110 111 default:112 113 return_btype = 0;114 break;115 }116 117 if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) {118 /*119 * We received a return object, but one was not expected. This can120 * happen frequently if the "implicit return" feature is enabled.121 * Just delete the return object and return AE_OK.122 */123 acpi_ut_remove_reference(info->return_object);124 goto cleanup;125 }126 127 /* Is the return object one of the expected types? */128 129 if (!(expected_return_btypes & return_btype)) {130 ACPI_ERROR_METHOD("Return object type is incorrect",131 prefix_node, path, AE_TYPE);132 133 ACPI_ERROR((AE_INFO,134 "Type returned from %s was incorrect: %s, expected Btypes: 0x%X",135 path,136 acpi_ut_get_object_type_name(info->return_object),137 expected_return_btypes));138 139 /* On error exit, we must delete the return object */140 141 acpi_ut_remove_reference(info->return_object);142 status = AE_TYPE;143 goto cleanup;144 }145 146 /* Object type is OK, return it */147 148 *return_desc = info->return_object;149 150cleanup:151 ACPI_FREE(info);152 return_ACPI_STATUS(status);153}154 155/*******************************************************************************156 *157 * FUNCTION: acpi_ut_evaluate_numeric_object158 *159 * PARAMETERS: object_name - Object name to be evaluated160 * device_node - Node for the device161 * value - Where the value is returned162 *163 * RETURN: Status164 *165 * DESCRIPTION: Evaluates a numeric namespace object for a selected device166 * and stores result in *Value.167 *168 * NOTE: Internal function, no parameter validation169 *170 ******************************************************************************/171 172acpi_status173acpi_ut_evaluate_numeric_object(const char *object_name,174 struct acpi_namespace_node *device_node,175 u64 *value)176{177 union acpi_operand_object *obj_desc;178 acpi_status status;179 180 ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object);181 182 status = acpi_ut_evaluate_object(device_node, object_name,183 ACPI_BTYPE_INTEGER, &obj_desc);184 if (ACPI_FAILURE(status)) {185 return_ACPI_STATUS(status);186 }187 188 /* Get the returned Integer */189 190 *value = obj_desc->integer.value;191 192 /* On exit, we must delete the return object */193 194 acpi_ut_remove_reference(obj_desc);195 return_ACPI_STATUS(status);196}197 198/*******************************************************************************199 *200 * FUNCTION: acpi_ut_execute_STA201 *202 * PARAMETERS: device_node - Node for the device203 * flags - Where the status flags are returned204 *205 * RETURN: Status206 *207 * DESCRIPTION: Executes _STA for selected device and stores results in208 * *Flags. If _STA does not exist, then the device is assumed209 * to be present/functional/enabled (as per the ACPI spec).210 *211 * NOTE: Internal function, no parameter validation212 *213 ******************************************************************************/214 215acpi_status216acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)217{218 union acpi_operand_object *obj_desc;219 acpi_status status;220 221 ACPI_FUNCTION_TRACE(ut_execute_STA);222 223 status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA,224 ACPI_BTYPE_INTEGER, &obj_desc);225 if (ACPI_FAILURE(status)) {226 if (AE_NOT_FOUND == status) {227 /*228 * if _STA does not exist, then (as per the ACPI specification),229 * the returned flags will indicate that the device is present,230 * functional, and enabled.231 */232 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,233 "_STA on %4.4s was not found, assuming device is present\n",234 acpi_ut_get_node_name(device_node)));235 236 *flags = ACPI_UINT32_MAX;237 status = AE_OK;238 }239 240 return_ACPI_STATUS(status);241 }242 243 /* Extract the status flags */244 245 *flags = (u32) obj_desc->integer.value;246 247 /* On exit, we must delete the return object */248 249 acpi_ut_remove_reference(obj_desc);250 return_ACPI_STATUS(status);251}252 253/*******************************************************************************254 *255 * FUNCTION: acpi_ut_execute_power_methods256 *257 * PARAMETERS: device_node - Node for the device258 * method_names - Array of power method names259 * method_count - Number of methods to execute260 * out_values - Where the power method values are returned261 *262 * RETURN: Status, out_values263 *264 * DESCRIPTION: Executes the specified power methods for the device and returns265 * the result(s).266 *267 * NOTE: Internal function, no parameter validation268 *269******************************************************************************/270 271acpi_status272acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,273 const char **method_names,274 u8 method_count, u8 *out_values)275{276 union acpi_operand_object *obj_desc;277 acpi_status status;278 acpi_status final_status = AE_NOT_FOUND;279 u32 i;280 281 ACPI_FUNCTION_TRACE(ut_execute_power_methods);282 283 for (i = 0; i < method_count; i++) {284 /*285 * Execute the power method (_sx_d or _sx_w). The only allowable286 * return type is an Integer.287 */288 status = acpi_ut_evaluate_object(device_node,289 ACPI_CAST_PTR(char,290 method_names[i]),291 ACPI_BTYPE_INTEGER, &obj_desc);292 if (ACPI_SUCCESS(status)) {293 out_values[i] = (u8)obj_desc->integer.value;294 295 /* Delete the return object */296 297 acpi_ut_remove_reference(obj_desc);298 final_status = AE_OK; /* At least one value is valid */299 continue;300 }301 302 out_values[i] = ACPI_UINT8_MAX;303 if (status == AE_NOT_FOUND) {304 continue; /* Ignore if not found */305 }306 307 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,308 "Failed %s on Device %4.4s, %s\n",309 ACPI_CAST_PTR(char, method_names[i]),310 acpi_ut_get_node_name(device_node),311 acpi_format_exception(status)));312 }313 314 return_ACPI_STATUS(final_status);315}316