Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: exoparg6 - AML execution - opcodes with 6 arguments
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acinterp.h"
0013 #include "acparser.h"
0014 #include "amlcode.h"
0015 
0016 #define _COMPONENT          ACPI_EXECUTER
0017 ACPI_MODULE_NAME("exoparg6")
0018 
0019 /*!
0020  * Naming convention for AML interpreter execution routines.
0021  *
0022  * The routines that begin execution of AML opcodes are named with a common
0023  * convention based upon the number of arguments, the number of target operands,
0024  * and whether or not a value is returned:
0025  *
0026  *      AcpiExOpcode_xA_yT_zR
0027  *
0028  * Where:
0029  *
0030  * xA - ARGUMENTS:    The number of arguments (input operands) that are
0031  *                    required for this opcode type (1 through 6 args).
0032  * yT - TARGETS:      The number of targets (output operands) that are required
0033  *                    for this opcode type (0, 1, or 2 targets).
0034  * zR - RETURN VALUE: Indicates whether this opcode type returns a value
0035  *                    as the function return (0 or 1).
0036  *
0037  * The AcpiExOpcode* functions are called via the Dispatcher component with
0038  * fully resolved operands.
0039 !*/
0040 /* Local prototypes */
0041 static u8
0042 acpi_ex_do_match(u32 match_op,
0043          union acpi_operand_object *package_obj,
0044          union acpi_operand_object *match_obj);
0045 
0046 /*******************************************************************************
0047  *
0048  * FUNCTION:    acpi_ex_do_match
0049  *
0050  * PARAMETERS:  match_op        - The AML match operand
0051  *              package_obj     - Object from the target package
0052  *              match_obj       - Object to be matched
0053  *
0054  * RETURN:      TRUE if the match is successful, FALSE otherwise
0055  *
0056  * DESCRIPTION: Implements the low-level match for the ASL Match operator.
0057  *              Package elements will be implicitly converted to the type of
0058  *              the match object (Integer/Buffer/String).
0059  *
0060  ******************************************************************************/
0061 
0062 static u8
0063 acpi_ex_do_match(u32 match_op,
0064          union acpi_operand_object *package_obj,
0065          union acpi_operand_object *match_obj)
0066 {
0067     u8 logical_result = TRUE;
0068     acpi_status status;
0069 
0070     /*
0071      * Note: Since the package_obj/match_obj ordering is opposite to that of
0072      * the standard logical operators, we have to reverse them when we call
0073      * do_logical_op in order to make the implicit conversion rules work
0074      * correctly. However, this means we have to flip the entire equation
0075      * also. A bit ugly perhaps, but overall, better than fussing the
0076      * parameters around at runtime, over and over again.
0077      *
0078      * Below, P[i] refers to the package element, M refers to the Match object.
0079      */
0080     switch (match_op) {
0081     case MATCH_MTR:
0082 
0083         /* Always true */
0084 
0085         break;
0086 
0087     case MATCH_MEQ:
0088         /*
0089          * True if equal: (P[i] == M)
0090          * Change to:     (M == P[i])
0091          */
0092         status =
0093             acpi_ex_do_logical_op(AML_LOGICAL_EQUAL_OP, match_obj,
0094                       package_obj, &logical_result);
0095         if (ACPI_FAILURE(status)) {
0096             return (FALSE);
0097         }
0098         break;
0099 
0100     case MATCH_MLE:
0101         /*
0102          * True if less than or equal: (P[i] <= M) (P[i] not_greater than M)
0103          * Change to:                  (M >= P[i]) (M not_less than P[i])
0104          */
0105         status =
0106             acpi_ex_do_logical_op(AML_LOGICAL_LESS_OP, match_obj,
0107                       package_obj, &logical_result);
0108         if (ACPI_FAILURE(status)) {
0109             return (FALSE);
0110         }
0111         logical_result = (u8) ! logical_result;
0112         break;
0113 
0114     case MATCH_MLT:
0115         /*
0116          * True if less than: (P[i] < M)
0117          * Change to:         (M > P[i])
0118          */
0119         status =
0120             acpi_ex_do_logical_op(AML_LOGICAL_GREATER_OP, match_obj,
0121                       package_obj, &logical_result);
0122         if (ACPI_FAILURE(status)) {
0123             return (FALSE);
0124         }
0125         break;
0126 
0127     case MATCH_MGE:
0128         /*
0129          * True if greater than or equal: (P[i] >= M) (P[i] not_less than M)
0130          * Change to:                     (M <= P[i]) (M not_greater than P[i])
0131          */
0132         status =
0133             acpi_ex_do_logical_op(AML_LOGICAL_GREATER_OP, match_obj,
0134                       package_obj, &logical_result);
0135         if (ACPI_FAILURE(status)) {
0136             return (FALSE);
0137         }
0138         logical_result = (u8) ! logical_result;
0139         break;
0140 
0141     case MATCH_MGT:
0142         /*
0143          * True if greater than: (P[i] > M)
0144          * Change to:            (M < P[i])
0145          */
0146         status =
0147             acpi_ex_do_logical_op(AML_LOGICAL_LESS_OP, match_obj,
0148                       package_obj, &logical_result);
0149         if (ACPI_FAILURE(status)) {
0150             return (FALSE);
0151         }
0152         break;
0153 
0154     default:
0155 
0156         /* Undefined */
0157 
0158         return (FALSE);
0159     }
0160 
0161     return (logical_result);
0162 }
0163 
0164 /*******************************************************************************
0165  *
0166  * FUNCTION:    acpi_ex_opcode_6A_0T_1R
0167  *
0168  * PARAMETERS:  walk_state          - Current walk state
0169  *
0170  * RETURN:      Status
0171  *
0172  * DESCRIPTION: Execute opcode with 6 arguments, no target, and a return value
0173  *
0174  ******************************************************************************/
0175 
0176 acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state *walk_state)
0177 {
0178     union acpi_operand_object **operand = &walk_state->operands[0];
0179     union acpi_operand_object *return_desc = NULL;
0180     acpi_status status = AE_OK;
0181     u64 index;
0182     union acpi_operand_object *this_element;
0183 
0184     ACPI_FUNCTION_TRACE_STR(ex_opcode_6A_0T_1R,
0185                 acpi_ps_get_opcode_name(walk_state->opcode));
0186 
0187     switch (walk_state->opcode) {
0188     case AML_MATCH_OP:
0189         /*
0190          * Match (search_pkg[0], match_op1[1], match_obj1[2],
0191          *                      match_op2[3], match_obj2[4], start_index[5])
0192          */
0193 
0194         /* Validate both Match Term Operators (MTR, MEQ, etc.) */
0195 
0196         if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
0197             (operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
0198             ACPI_ERROR((AE_INFO, "Match operator out of range"));
0199             status = AE_AML_OPERAND_VALUE;
0200             goto cleanup;
0201         }
0202 
0203         /* Get the package start_index, validate against the package length */
0204 
0205         index = operand[5]->integer.value;
0206         if (index >= operand[0]->package.count) {
0207             ACPI_ERROR((AE_INFO,
0208                     "Index (0x%8.8X%8.8X) beyond package end (0x%X)",
0209                     ACPI_FORMAT_UINT64(index),
0210                     operand[0]->package.count));
0211             status = AE_AML_PACKAGE_LIMIT;
0212             goto cleanup;
0213         }
0214 
0215         /* Create an integer for the return value */
0216         /* Default return value is ACPI_UINT64_MAX if no match found */
0217 
0218         return_desc = acpi_ut_create_integer_object(ACPI_UINT64_MAX);
0219         if (!return_desc) {
0220             status = AE_NO_MEMORY;
0221             goto cleanup;
0222 
0223         }
0224 
0225         /*
0226          * Examine each element until a match is found. Both match conditions
0227          * must be satisfied for a match to occur. Within the loop,
0228          * "continue" signifies that the current element does not match
0229          * and the next should be examined.
0230          *
0231          * Upon finding a match, the loop will terminate via "break" at
0232          * the bottom. If it terminates "normally", match_value will be
0233          * ACPI_UINT64_MAX (Ones) (its initial value) indicating that no
0234          * match was found.
0235          */
0236         for (; index < operand[0]->package.count; index++) {
0237 
0238             /* Get the current package element */
0239 
0240             this_element = operand[0]->package.elements[index];
0241 
0242             /* Treat any uninitialized (NULL) elements as non-matching */
0243 
0244             if (!this_element) {
0245                 continue;
0246             }
0247 
0248             /*
0249              * Both match conditions must be satisfied. Execution of a continue
0250              * (proceed to next iteration of enclosing for loop) signifies a
0251              * non-match.
0252              */
0253             if (!acpi_ex_do_match((u32) operand[1]->integer.value,
0254                           this_element, operand[2])) {
0255                 continue;
0256             }
0257 
0258             if (!acpi_ex_do_match((u32) operand[3]->integer.value,
0259                           this_element, operand[4])) {
0260                 continue;
0261             }
0262 
0263             /* Match found: Index is the return value */
0264 
0265             return_desc->integer.value = index;
0266             break;
0267         }
0268         break;
0269 
0270     case AML_LOAD_TABLE_OP:
0271 
0272         status = acpi_ex_load_table_op(walk_state, &return_desc);
0273         break;
0274 
0275     default:
0276 
0277         ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0278                 walk_state->opcode));
0279 
0280         status = AE_AML_BAD_OPCODE;
0281         goto cleanup;
0282     }
0283 
0284 cleanup:
0285 
0286     /* Delete return object on error */
0287 
0288     if (ACPI_FAILURE(status)) {
0289         acpi_ut_remove_reference(return_desc);
0290     }
0291 
0292     /* Save return object on success */
0293 
0294     else {
0295         walk_state->result_obj = return_desc;
0296     }
0297 
0298     return_ACPI_STATUS(status);
0299 }