Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: exoparg3 - AML execution - opcodes with 3 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("exoparg3")
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 /*******************************************************************************
0041  *
0042  * FUNCTION:    acpi_ex_opcode_3A_0T_0R
0043  *
0044  * PARAMETERS:  walk_state          - Current walk state
0045  *
0046  * RETURN:      Status
0047  *
0048  * DESCRIPTION: Execute Triadic operator (3 operands)
0049  *
0050  ******************************************************************************/
0051 acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
0052 {
0053     union acpi_operand_object **operand = &walk_state->operands[0];
0054     struct acpi_signal_fatal_info *fatal;
0055     acpi_status status = AE_OK;
0056 
0057     ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R,
0058                 acpi_ps_get_opcode_name(walk_state->opcode));
0059 
0060     switch (walk_state->opcode) {
0061     case AML_FATAL_OP:  /* Fatal (fatal_type fatal_code fatal_arg) */
0062 
0063         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0064                   "FatalOp: Type %X Code %X Arg %X "
0065                   "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
0066                   (u32)operand[0]->integer.value,
0067                   (u32)operand[1]->integer.value,
0068                   (u32)operand[2]->integer.value));
0069 
0070         fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
0071         if (fatal) {
0072             fatal->type = (u32) operand[0]->integer.value;
0073             fatal->code = (u32) operand[1]->integer.value;
0074             fatal->argument = (u32) operand[2]->integer.value;
0075         }
0076 
0077         /* Always signal the OS! */
0078 
0079         status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal);
0080 
0081         /* Might return while OS is shutting down, just continue */
0082 
0083         ACPI_FREE(fatal);
0084         goto cleanup;
0085 
0086     case AML_EXTERNAL_OP:
0087         /*
0088          * If the interpreter sees this opcode, just ignore it. The External
0089          * op is intended for use by disassemblers in order to properly
0090          * disassemble control method invocations. The opcode or group of
0091          * opcodes should be surrounded by an "if (0)" clause to ensure that
0092          * AML interpreters never see the opcode. Thus, something is
0093          * wrong if an external opcode ever gets here.
0094          */
0095         ACPI_ERROR((AE_INFO, "Executed External Op"));
0096         status = AE_OK;
0097         goto cleanup;
0098 
0099     default:
0100 
0101         ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0102                 walk_state->opcode));
0103 
0104         status = AE_AML_BAD_OPCODE;
0105         goto cleanup;
0106     }
0107 
0108 cleanup:
0109 
0110     return_ACPI_STATUS(status);
0111 }
0112 
0113 /*******************************************************************************
0114  *
0115  * FUNCTION:    acpi_ex_opcode_3A_1T_1R
0116  *
0117  * PARAMETERS:  walk_state          - Current walk state
0118  *
0119  * RETURN:      Status
0120  *
0121  * DESCRIPTION: Execute Triadic operator (3 operands)
0122  *
0123  ******************************************************************************/
0124 
0125 acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
0126 {
0127     union acpi_operand_object **operand = &walk_state->operands[0];
0128     union acpi_operand_object *return_desc = NULL;
0129     char *buffer = NULL;
0130     acpi_status status = AE_OK;
0131     u64 index;
0132     acpi_size length;
0133 
0134     ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R,
0135                 acpi_ps_get_opcode_name(walk_state->opcode));
0136 
0137     switch (walk_state->opcode) {
0138     case AML_MID_OP:    /* Mid (Source[0], Index[1], Length[2], Result[3]) */
0139         /*
0140          * Create the return object. The Source operand is guaranteed to be
0141          * either a String or a Buffer, so just use its type.
0142          */
0143         return_desc = acpi_ut_create_internal_object((operand[0])->
0144                                  common.type);
0145         if (!return_desc) {
0146             status = AE_NO_MEMORY;
0147             goto cleanup;
0148         }
0149 
0150         /* Get the Integer values from the objects */
0151 
0152         index = operand[1]->integer.value;
0153         length = (acpi_size)operand[2]->integer.value;
0154 
0155         /*
0156          * If the index is beyond the length of the String/Buffer, or if the
0157          * requested length is zero, return a zero-length String/Buffer
0158          */
0159         if (index >= operand[0]->string.length) {
0160             length = 0;
0161         }
0162 
0163         /* Truncate request if larger than the actual String/Buffer */
0164 
0165         else if ((index + length) > operand[0]->string.length) {
0166             length =
0167                 (acpi_size)operand[0]->string.length -
0168                 (acpi_size)index;
0169         }
0170 
0171         /* Strings always have a sub-pointer, not so for buffers */
0172 
0173         switch ((operand[0])->common.type) {
0174         case ACPI_TYPE_STRING:
0175 
0176             /* Always allocate a new buffer for the String */
0177 
0178             buffer = ACPI_ALLOCATE_ZEROED((acpi_size)length + 1);
0179             if (!buffer) {
0180                 status = AE_NO_MEMORY;
0181                 goto cleanup;
0182             }
0183             break;
0184 
0185         case ACPI_TYPE_BUFFER:
0186 
0187             /* If the requested length is zero, don't allocate a buffer */
0188 
0189             if (length > 0) {
0190 
0191                 /* Allocate a new buffer for the Buffer */
0192 
0193                 buffer = ACPI_ALLOCATE_ZEROED(length);
0194                 if (!buffer) {
0195                     status = AE_NO_MEMORY;
0196                     goto cleanup;
0197                 }
0198             }
0199             break;
0200 
0201         default:    /* Should not happen */
0202 
0203             status = AE_AML_OPERAND_TYPE;
0204             goto cleanup;
0205         }
0206 
0207         if (buffer) {
0208 
0209             /* We have a buffer, copy the portion requested */
0210 
0211             memcpy(buffer,
0212                    operand[0]->string.pointer + index, length);
0213         }
0214 
0215         /* Set the length of the new String/Buffer */
0216 
0217         return_desc->string.pointer = buffer;
0218         return_desc->string.length = (u32) length;
0219 
0220         /* Mark buffer initialized */
0221 
0222         return_desc->buffer.flags |= AOPOBJ_DATA_VALID;
0223         break;
0224 
0225     default:
0226 
0227         ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0228                 walk_state->opcode));
0229 
0230         status = AE_AML_BAD_OPCODE;
0231         goto cleanup;
0232     }
0233 
0234     /* Store the result in the target */
0235 
0236     status = acpi_ex_store(return_desc, operand[3], walk_state);
0237 
0238 cleanup:
0239 
0240     /* Delete return object on error */
0241 
0242     if (ACPI_FAILURE(status) || walk_state->result_obj) {
0243         acpi_ut_remove_reference(return_desc);
0244         walk_state->result_obj = NULL;
0245     } else {
0246         /* Set the return object and exit */
0247 
0248         walk_state->result_obj = return_desc;
0249     }
0250 
0251     return_ACPI_STATUS(status);
0252 }