Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: uteval - Object evaluation
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acnamesp.h"
0013 
0014 #define _COMPONENT          ACPI_UTILITIES
0015 ACPI_MODULE_NAME("uteval")
0016 
0017 /*******************************************************************************
0018  *
0019  * FUNCTION:    acpi_ut_evaluate_object
0020  *
0021  * PARAMETERS:  prefix_node         - Starting node
0022  *              path                - Path to object from starting node
0023  *              expected_return_types - Bitmap of allowed return types
0024  *              return_desc         - Where a return value is stored
0025  *
0026  * RETURN:      Status
0027  *
0028  * DESCRIPTION: Evaluates a namespace object and verifies the type of the
0029  *              return object. Common code that simplifies accessing objects
0030  *              that have required return objects of fixed types.
0031  *
0032  *              NOTE: Internal function, no parameter validation
0033  *
0034  ******************************************************************************/
0035 
0036 acpi_status
0037 acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
0038             const char *path,
0039             u32 expected_return_btypes,
0040             union acpi_operand_object **return_desc)
0041 {
0042     struct acpi_evaluate_info *info;
0043     acpi_status status;
0044     u32 return_btype;
0045 
0046     ACPI_FUNCTION_TRACE(ut_evaluate_object);
0047 
0048     /* Allocate the evaluation information block */
0049 
0050     info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
0051     if (!info) {
0052         return_ACPI_STATUS(AE_NO_MEMORY);
0053     }
0054 
0055     info->prefix_node = prefix_node;
0056     info->relative_pathname = path;
0057 
0058     /* Evaluate the object/method */
0059 
0060     status = acpi_ns_evaluate(info);
0061     if (ACPI_FAILURE(status)) {
0062         if (status == AE_NOT_FOUND) {
0063             ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0064                       "[%4.4s.%s] was not found\n",
0065                       acpi_ut_get_node_name(prefix_node),
0066                       path));
0067         } else {
0068             ACPI_ERROR_METHOD("Method execution failed",
0069                       prefix_node, path, status);
0070         }
0071 
0072         goto cleanup;
0073     }
0074 
0075     /* Did we get a return object? */
0076 
0077     if (!info->return_object) {
0078         if (expected_return_btypes) {
0079             ACPI_ERROR_METHOD("No object was returned from",
0080                       prefix_node, path, AE_NOT_EXIST);
0081 
0082             status = AE_NOT_EXIST;
0083         }
0084 
0085         goto cleanup;
0086     }
0087 
0088     /* Map the return object type to the bitmapped type */
0089 
0090     switch ((info->return_object)->common.type) {
0091     case ACPI_TYPE_INTEGER:
0092 
0093         return_btype = ACPI_BTYPE_INTEGER;
0094         break;
0095 
0096     case ACPI_TYPE_BUFFER:
0097 
0098         return_btype = ACPI_BTYPE_BUFFER;
0099         break;
0100 
0101     case ACPI_TYPE_STRING:
0102 
0103         return_btype = ACPI_BTYPE_STRING;
0104         break;
0105 
0106     case ACPI_TYPE_PACKAGE:
0107 
0108         return_btype = ACPI_BTYPE_PACKAGE;
0109         break;
0110 
0111     default:
0112 
0113         return_btype = 0;
0114         break;
0115     }
0116 
0117     if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) {
0118         /*
0119          * We received a return object, but one was not expected. This can
0120          * happen frequently if the "implicit return" feature is enabled.
0121          * Just delete the return object and return AE_OK.
0122          */
0123         acpi_ut_remove_reference(info->return_object);
0124         goto cleanup;
0125     }
0126 
0127     /* Is the return object one of the expected types? */
0128 
0129     if (!(expected_return_btypes & return_btype)) {
0130         ACPI_ERROR_METHOD("Return object type is incorrect",
0131                   prefix_node, path, AE_TYPE);
0132 
0133         ACPI_ERROR((AE_INFO,
0134                 "Type returned from %s was incorrect: %s, expected Btypes: 0x%X",
0135                 path,
0136                 acpi_ut_get_object_type_name(info->return_object),
0137                 expected_return_btypes));
0138 
0139         /* On error exit, we must delete the return object */
0140 
0141         acpi_ut_remove_reference(info->return_object);
0142         status = AE_TYPE;
0143         goto cleanup;
0144     }
0145 
0146     /* Object type is OK, return it */
0147 
0148     *return_desc = info->return_object;
0149 
0150 cleanup:
0151     ACPI_FREE(info);
0152     return_ACPI_STATUS(status);
0153 }
0154 
0155 /*******************************************************************************
0156  *
0157  * FUNCTION:    acpi_ut_evaluate_numeric_object
0158  *
0159  * PARAMETERS:  object_name         - Object name to be evaluated
0160  *              device_node         - Node for the device
0161  *              value               - Where the value is returned
0162  *
0163  * RETURN:      Status
0164  *
0165  * DESCRIPTION: Evaluates a numeric namespace object for a selected device
0166  *              and stores result in *Value.
0167  *
0168  *              NOTE: Internal function, no parameter validation
0169  *
0170  ******************************************************************************/
0171 
0172 acpi_status
0173 acpi_ut_evaluate_numeric_object(const char *object_name,
0174                 struct acpi_namespace_node *device_node,
0175                 u64 *value)
0176 {
0177     union acpi_operand_object *obj_desc;
0178     acpi_status status;
0179 
0180     ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object);
0181 
0182     status = acpi_ut_evaluate_object(device_node, object_name,
0183                      ACPI_BTYPE_INTEGER, &obj_desc);
0184     if (ACPI_FAILURE(status)) {
0185         return_ACPI_STATUS(status);
0186     }
0187 
0188     /* Get the returned Integer */
0189 
0190     *value = obj_desc->integer.value;
0191 
0192     /* On exit, we must delete the return object */
0193 
0194     acpi_ut_remove_reference(obj_desc);
0195     return_ACPI_STATUS(status);
0196 }
0197 
0198 /*******************************************************************************
0199  *
0200  * FUNCTION:    acpi_ut_execute_STA
0201  *
0202  * PARAMETERS:  device_node         - Node for the device
0203  *              flags               - Where the status flags are returned
0204  *
0205  * RETURN:      Status
0206  *
0207  * DESCRIPTION: Executes _STA for selected device and stores results in
0208  *              *Flags. If _STA does not exist, then the device is assumed
0209  *              to be present/functional/enabled (as per the ACPI spec).
0210  *
0211  *              NOTE: Internal function, no parameter validation
0212  *
0213  ******************************************************************************/
0214 
0215 acpi_status
0216 acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)
0217 {
0218     union acpi_operand_object *obj_desc;
0219     acpi_status status;
0220 
0221     ACPI_FUNCTION_TRACE(ut_execute_STA);
0222 
0223     status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA,
0224                      ACPI_BTYPE_INTEGER, &obj_desc);
0225     if (ACPI_FAILURE(status)) {
0226         if (AE_NOT_FOUND == status) {
0227             /*
0228              * if _STA does not exist, then (as per the ACPI specification),
0229              * the returned flags will indicate that the device is present,
0230              * functional, and enabled.
0231              */
0232             ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0233                       "_STA on %4.4s was not found, assuming device is present\n",
0234                       acpi_ut_get_node_name(device_node)));
0235 
0236             *flags = ACPI_UINT32_MAX;
0237             status = AE_OK;
0238         }
0239 
0240         return_ACPI_STATUS(status);
0241     }
0242 
0243     /* Extract the status flags */
0244 
0245     *flags = (u32) obj_desc->integer.value;
0246 
0247     /* On exit, we must delete the return object */
0248 
0249     acpi_ut_remove_reference(obj_desc);
0250     return_ACPI_STATUS(status);
0251 }
0252 
0253 /*******************************************************************************
0254  *
0255  * FUNCTION:    acpi_ut_execute_power_methods
0256  *
0257  * PARAMETERS:  device_node         - Node for the device
0258  *              method_names        - Array of power method names
0259  *              method_count        - Number of methods to execute
0260  *              out_values          - Where the power method values are returned
0261  *
0262  * RETURN:      Status, out_values
0263  *
0264  * DESCRIPTION: Executes the specified power methods for the device and returns
0265  *              the result(s).
0266  *
0267  *              NOTE: Internal function, no parameter validation
0268  *
0269 ******************************************************************************/
0270 
0271 acpi_status
0272 acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,
0273                   const char **method_names,
0274                   u8 method_count, u8 *out_values)
0275 {
0276     union acpi_operand_object *obj_desc;
0277     acpi_status status;
0278     acpi_status final_status = AE_NOT_FOUND;
0279     u32 i;
0280 
0281     ACPI_FUNCTION_TRACE(ut_execute_power_methods);
0282 
0283     for (i = 0; i < method_count; i++) {
0284         /*
0285          * Execute the power method (_sx_d or _sx_w). The only allowable
0286          * return type is an Integer.
0287          */
0288         status = acpi_ut_evaluate_object(device_node,
0289                          ACPI_CAST_PTR(char,
0290                                    method_names[i]),
0291                          ACPI_BTYPE_INTEGER, &obj_desc);
0292         if (ACPI_SUCCESS(status)) {
0293             out_values[i] = (u8)obj_desc->integer.value;
0294 
0295             /* Delete the return object */
0296 
0297             acpi_ut_remove_reference(obj_desc);
0298             final_status = AE_OK;   /* At least one value is valid */
0299             continue;
0300         }
0301 
0302         out_values[i] = ACPI_UINT8_MAX;
0303         if (status == AE_NOT_FOUND) {
0304             continue;   /* Ignore if not found */
0305         }
0306 
0307         ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0308                   "Failed %s on Device %4.4s, %s\n",
0309                   ACPI_CAST_PTR(char, method_names[i]),
0310                   acpi_ut_get_node_name(device_node),
0311                   acpi_format_exception(status)));
0312     }
0313 
0314     return_ACPI_STATUS(final_status);
0315 }