Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acparser.h"
0013 #include "acinterp.h"
0014 #include "acevents.h"
0015 #include "amlcode.h"
0016 
0017 #define _COMPONENT          ACPI_EXECUTER
0018 ACPI_MODULE_NAME("exoparg2")
0019 
0020 /*!
0021  * Naming convention for AML interpreter execution routines.
0022  *
0023  * The routines that begin execution of AML opcodes are named with a common
0024  * convention based upon the number of arguments, the number of target operands,
0025  * and whether or not a value is returned:
0026  *
0027  *      AcpiExOpcode_xA_yT_zR
0028  *
0029  * Where:
0030  *
0031  * xA - ARGUMENTS:    The number of arguments (input operands) that are
0032  *                    required for this opcode type (1 through 6 args).
0033  * yT - TARGETS:      The number of targets (output operands) that are required
0034  *                    for this opcode type (0, 1, or 2 targets).
0035  * zR - RETURN VALUE: Indicates whether this opcode type returns a value
0036  *                    as the function return (0 or 1).
0037  *
0038  * The AcpiExOpcode* functions are called via the Dispatcher component with
0039  * fully resolved operands.
0040 !*/
0041 /*******************************************************************************
0042  *
0043  * FUNCTION:    acpi_ex_opcode_2A_0T_0R
0044  *
0045  * PARAMETERS:  walk_state          - Current walk state
0046  *
0047  * RETURN:      Status
0048  *
0049  * DESCRIPTION: Execute opcode with two arguments, no target, and no return
0050  *              value.
0051  *
0052  * ALLOCATION:  Deletes both operands
0053  *
0054  ******************************************************************************/
0055 acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
0056 {
0057     union acpi_operand_object **operand = &walk_state->operands[0];
0058     struct acpi_namespace_node *node;
0059     u32 value;
0060     acpi_status status = AE_OK;
0061 
0062     ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R,
0063                 acpi_ps_get_opcode_name(walk_state->opcode));
0064 
0065     /* Examine the opcode */
0066 
0067     switch (walk_state->opcode) {
0068     case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */
0069 
0070         /* The first operand is a namespace node */
0071 
0072         node = (struct acpi_namespace_node *)operand[0];
0073 
0074         /* Second value is the notify value */
0075 
0076         value = (u32) operand[1]->integer.value;
0077 
0078         /* Are notifies allowed on this object? */
0079 
0080         if (!acpi_ev_is_notify_object(node)) {
0081             ACPI_ERROR((AE_INFO,
0082                     "Unexpected notify object type [%s]",
0083                     acpi_ut_get_type_name(node->type)));
0084 
0085             status = AE_AML_OPERAND_TYPE;
0086             break;
0087         }
0088 
0089         /*
0090          * Dispatch the notify to the appropriate handler
0091          * NOTE: the request is queued for execution after this method
0092          * completes. The notify handlers are NOT invoked synchronously
0093          * from this thread -- because handlers may in turn run other
0094          * control methods.
0095          */
0096         status = acpi_ev_queue_notify_request(node, value);
0097         break;
0098 
0099     default:
0100 
0101         ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0102                 walk_state->opcode));
0103         status = AE_AML_BAD_OPCODE;
0104     }
0105 
0106     return_ACPI_STATUS(status);
0107 }
0108 
0109 /*******************************************************************************
0110  *
0111  * FUNCTION:    acpi_ex_opcode_2A_2T_1R
0112  *
0113  * PARAMETERS:  walk_state          - Current walk state
0114  *
0115  * RETURN:      Status
0116  *
0117  * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
0118  *              and one implicit return value.
0119  *
0120  ******************************************************************************/
0121 
0122 acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
0123 {
0124     union acpi_operand_object **operand = &walk_state->operands[0];
0125     union acpi_operand_object *return_desc1 = NULL;
0126     union acpi_operand_object *return_desc2 = NULL;
0127     acpi_status status;
0128 
0129     ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R,
0130                 acpi_ps_get_opcode_name(walk_state->opcode));
0131 
0132     /* Execute the opcode */
0133 
0134     switch (walk_state->opcode) {
0135     case AML_DIVIDE_OP:
0136 
0137         /* Divide (Dividend, Divisor, remainder_result quotient_result) */
0138 
0139         return_desc1 =
0140             acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
0141         if (!return_desc1) {
0142             status = AE_NO_MEMORY;
0143             goto cleanup;
0144         }
0145 
0146         return_desc2 =
0147             acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
0148         if (!return_desc2) {
0149             status = AE_NO_MEMORY;
0150             goto cleanup;
0151         }
0152 
0153         /* Quotient to return_desc1, remainder to return_desc2 */
0154 
0155         status = acpi_ut_divide(operand[0]->integer.value,
0156                     operand[1]->integer.value,
0157                     &return_desc1->integer.value,
0158                     &return_desc2->integer.value);
0159         if (ACPI_FAILURE(status)) {
0160             goto cleanup;
0161         }
0162         break;
0163 
0164     default:
0165 
0166         ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0167                 walk_state->opcode));
0168 
0169         status = AE_AML_BAD_OPCODE;
0170         goto cleanup;
0171     }
0172 
0173     /* Store the results to the target reference operands */
0174 
0175     status = acpi_ex_store(return_desc2, operand[2], walk_state);
0176     if (ACPI_FAILURE(status)) {
0177         goto cleanup;
0178     }
0179 
0180     status = acpi_ex_store(return_desc1, operand[3], walk_state);
0181     if (ACPI_FAILURE(status)) {
0182         goto cleanup;
0183     }
0184 
0185 cleanup:
0186     /*
0187      * Since the remainder is not returned indirectly, remove a reference to
0188      * it. Only the quotient is returned indirectly.
0189      */
0190     acpi_ut_remove_reference(return_desc2);
0191 
0192     if (ACPI_FAILURE(status)) {
0193 
0194         /* Delete the return object */
0195 
0196         acpi_ut_remove_reference(return_desc1);
0197     }
0198 
0199     /* Save return object (the remainder) on success */
0200 
0201     else {
0202         walk_state->result_obj = return_desc1;
0203     }
0204 
0205     return_ACPI_STATUS(status);
0206 }
0207 
0208 /*******************************************************************************
0209  *
0210  * FUNCTION:    acpi_ex_opcode_2A_1T_1R
0211  *
0212  * PARAMETERS:  walk_state          - Current walk state
0213  *
0214  * RETURN:      Status
0215  *
0216  * DESCRIPTION: Execute opcode with two arguments, one target, and a return
0217  *              value.
0218  *
0219  ******************************************************************************/
0220 
0221 acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
0222 {
0223     union acpi_operand_object **operand = &walk_state->operands[0];
0224     union acpi_operand_object *return_desc = NULL;
0225     u64 index;
0226     acpi_status status = AE_OK;
0227     acpi_size length = 0;
0228 
0229     ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R,
0230                 acpi_ps_get_opcode_name(walk_state->opcode));
0231 
0232     /* Execute the opcode */
0233 
0234     if (walk_state->op_info->flags & AML_MATH) {
0235 
0236         /* All simple math opcodes (add, etc.) */
0237 
0238         return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
0239         if (!return_desc) {
0240             status = AE_NO_MEMORY;
0241             goto cleanup;
0242         }
0243 
0244         return_desc->integer.value =
0245             acpi_ex_do_math_op(walk_state->opcode,
0246                        operand[0]->integer.value,
0247                        operand[1]->integer.value);
0248         goto store_result_to_target;
0249     }
0250 
0251     switch (walk_state->opcode) {
0252     case AML_MOD_OP:    /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
0253 
0254         return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
0255         if (!return_desc) {
0256             status = AE_NO_MEMORY;
0257             goto cleanup;
0258         }
0259 
0260         /* return_desc will contain the remainder */
0261 
0262         status = acpi_ut_divide(operand[0]->integer.value,
0263                     operand[1]->integer.value,
0264                     NULL, &return_desc->integer.value);
0265         break;
0266 
0267     case AML_CONCATENATE_OP:    /* Concatenate (Data1, Data2, Result) */
0268 
0269         status =
0270             acpi_ex_do_concatenate(operand[0], operand[1], &return_desc,
0271                        walk_state);
0272         break;
0273 
0274     case AML_TO_STRING_OP:  /* to_string (Buffer, Length, Result) (ACPI 2.0) */
0275         /*
0276          * Input object is guaranteed to be a buffer at this point (it may have
0277          * been converted.)  Copy the raw buffer data to a new object of
0278          * type String.
0279          */
0280 
0281         /*
0282          * Get the length of the new string. It is the smallest of:
0283          * 1) Length of the input buffer
0284          * 2) Max length as specified in the to_string operator
0285          * 3) Length of input buffer up to a zero byte (null terminator)
0286          *
0287          * NOTE: A length of zero is ok, and will create a zero-length, null
0288          *       terminated string.
0289          */
0290         while ((length < operand[0]->buffer.length) &&  /* Length of input buffer */
0291                (length < operand[1]->integer.value) &&  /* Length operand */
0292                (operand[0]->buffer.pointer[length])) {  /* Null terminator */
0293             length++;
0294         }
0295 
0296         /* Allocate a new string object */
0297 
0298         return_desc = acpi_ut_create_string_object(length);
0299         if (!return_desc) {
0300             status = AE_NO_MEMORY;
0301             goto cleanup;
0302         }
0303 
0304         /*
0305          * Copy the raw buffer data with no transform.
0306          * (NULL terminated already)
0307          */
0308         memcpy(return_desc->string.pointer,
0309                operand[0]->buffer.pointer, length);
0310         break;
0311 
0312     case AML_CONCATENATE_TEMPLATE_OP:
0313 
0314         /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
0315 
0316         status =
0317             acpi_ex_concat_template(operand[0], operand[1],
0318                         &return_desc, walk_state);
0319         break;
0320 
0321     case AML_INDEX_OP:  /* Index (Source Index Result) */
0322 
0323         /* Create the internal return object */
0324 
0325         return_desc =
0326             acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
0327         if (!return_desc) {
0328             status = AE_NO_MEMORY;
0329             goto cleanup;
0330         }
0331 
0332         /* Initialize the Index reference object */
0333 
0334         index = operand[1]->integer.value;
0335         return_desc->reference.value = (u32) index;
0336         return_desc->reference.class = ACPI_REFCLASS_INDEX;
0337 
0338         /*
0339          * At this point, the Source operand is a String, Buffer, or Package.
0340          * Verify that the index is within range.
0341          */
0342         switch ((operand[0])->common.type) {
0343         case ACPI_TYPE_STRING:
0344 
0345             if (index >= operand[0]->string.length) {
0346                 length = operand[0]->string.length;
0347                 status = AE_AML_STRING_LIMIT;
0348             }
0349 
0350             return_desc->reference.target_type =
0351                 ACPI_TYPE_BUFFER_FIELD;
0352             return_desc->reference.index_pointer =
0353                 &(operand[0]->buffer.pointer[index]);
0354             break;
0355 
0356         case ACPI_TYPE_BUFFER:
0357 
0358             if (index >= operand[0]->buffer.length) {
0359                 length = operand[0]->buffer.length;
0360                 status = AE_AML_BUFFER_LIMIT;
0361             }
0362 
0363             return_desc->reference.target_type =
0364                 ACPI_TYPE_BUFFER_FIELD;
0365             return_desc->reference.index_pointer =
0366                 &(operand[0]->buffer.pointer[index]);
0367             break;
0368 
0369         case ACPI_TYPE_PACKAGE:
0370 
0371             if (index >= operand[0]->package.count) {
0372                 length = operand[0]->package.count;
0373                 status = AE_AML_PACKAGE_LIMIT;
0374             }
0375 
0376             return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
0377             return_desc->reference.where =
0378                 &operand[0]->package.elements[index];
0379             break;
0380 
0381         default:
0382 
0383             ACPI_ERROR((AE_INFO,
0384                     "Invalid object type: %X",
0385                     (operand[0])->common.type));
0386             status = AE_AML_INTERNAL;
0387             goto cleanup;
0388         }
0389 
0390         /* Failure means that the Index was beyond the end of the object */
0391 
0392         if (ACPI_FAILURE(status)) {
0393             ACPI_BIOS_EXCEPTION((AE_INFO, status,
0394                          "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
0395                          ACPI_FORMAT_UINT64(index),
0396                          (u32)length));
0397             goto cleanup;
0398         }
0399 
0400         /*
0401          * Save the target object and add a reference to it for the life
0402          * of the index
0403          */
0404         return_desc->reference.object = operand[0];
0405         acpi_ut_add_reference(operand[0]);
0406 
0407         /* Store the reference to the Target */
0408 
0409         status = acpi_ex_store(return_desc, operand[2], walk_state);
0410 
0411         /* Return the reference */
0412 
0413         walk_state->result_obj = return_desc;
0414         goto cleanup;
0415 
0416     default:
0417 
0418         ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0419                 walk_state->opcode));
0420         status = AE_AML_BAD_OPCODE;
0421         break;
0422     }
0423 
0424 store_result_to_target:
0425 
0426     if (ACPI_SUCCESS(status)) {
0427         /*
0428          * Store the result of the operation (which is now in return_desc) into
0429          * the Target descriptor.
0430          */
0431         status = acpi_ex_store(return_desc, operand[2], walk_state);
0432         if (ACPI_FAILURE(status)) {
0433             goto cleanup;
0434         }
0435 
0436         if (!walk_state->result_obj) {
0437             walk_state->result_obj = return_desc;
0438         }
0439     }
0440 
0441 cleanup:
0442 
0443     /* Delete return object on error */
0444 
0445     if (ACPI_FAILURE(status)) {
0446         acpi_ut_remove_reference(return_desc);
0447         walk_state->result_obj = NULL;
0448     }
0449 
0450     return_ACPI_STATUS(status);
0451 }
0452 
0453 /*******************************************************************************
0454  *
0455  * FUNCTION:    acpi_ex_opcode_2A_0T_1R
0456  *
0457  * PARAMETERS:  walk_state          - Current walk state
0458  *
0459  * RETURN:      Status
0460  *
0461  * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
0462  *
0463  ******************************************************************************/
0464 
0465 acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
0466 {
0467     union acpi_operand_object **operand = &walk_state->operands[0];
0468     union acpi_operand_object *return_desc = NULL;
0469     acpi_status status = AE_OK;
0470     u8 logical_result = FALSE;
0471 
0472     ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R,
0473                 acpi_ps_get_opcode_name(walk_state->opcode));
0474 
0475     /* Create the internal return object */
0476 
0477     return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
0478     if (!return_desc) {
0479         status = AE_NO_MEMORY;
0480         goto cleanup;
0481     }
0482 
0483     /* Execute the Opcode */
0484 
0485     if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
0486 
0487         /* logical_op (Operand0, Operand1) */
0488 
0489         status = acpi_ex_do_logical_numeric_op(walk_state->opcode,
0490                                operand[0]->integer.
0491                                value,
0492                                operand[1]->integer.
0493                                value, &logical_result);
0494         goto store_logical_result;
0495     } else if (walk_state->op_info->flags & AML_LOGICAL) {
0496 
0497         /* logical_op (Operand0, Operand1) */
0498 
0499         status = acpi_ex_do_logical_op(walk_state->opcode, operand[0],
0500                            operand[1], &logical_result);
0501         goto store_logical_result;
0502     }
0503 
0504     switch (walk_state->opcode) {
0505     case AML_ACQUIRE_OP:    /* Acquire (mutex_object, Timeout) */
0506 
0507         status =
0508             acpi_ex_acquire_mutex(operand[1], operand[0], walk_state);
0509         if (status == AE_TIME) {
0510             logical_result = TRUE;  /* TRUE = Acquire timed out */
0511             status = AE_OK;
0512         }
0513         break;
0514 
0515     case AML_WAIT_OP:   /* Wait (event_object, Timeout) */
0516 
0517         status = acpi_ex_system_wait_event(operand[1], operand[0]);
0518         if (status == AE_TIME) {
0519             logical_result = TRUE;  /* TRUE, Wait timed out */
0520             status = AE_OK;
0521         }
0522         break;
0523 
0524     default:
0525 
0526         ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0527                 walk_state->opcode));
0528 
0529         status = AE_AML_BAD_OPCODE;
0530         goto cleanup;
0531     }
0532 
0533 store_logical_result:
0534     /*
0535      * Set return value to according to logical_result. logical TRUE (all ones)
0536      * Default is FALSE (zero)
0537      */
0538     if (logical_result) {
0539         return_desc->integer.value = ACPI_UINT64_MAX;
0540     }
0541 
0542 cleanup:
0543 
0544     /* Delete return object on error */
0545 
0546     if (ACPI_FAILURE(status)) {
0547         acpi_ut_remove_reference(return_desc);
0548     }
0549 
0550     /* Save return object on success */
0551 
0552     else {
0553         walk_state->result_obj = return_desc;
0554     }
0555 
0556     return_ACPI_STATUS(status);
0557 }