LCOV - code coverage report
Current view: top level - drivers/acpi/acpica - dsutils.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 171 220 77.7 %
Date: 2022-04-01 13:59:58 Functions: 9 9 100.0 %
Branches: 78 135 57.8 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
       2                 :            : /*******************************************************************************
       3                 :            :  *
       4                 :            :  * Module Name: dsutils - Dispatcher utilities
       5                 :            :  *
       6                 :            :  ******************************************************************************/
       7                 :            : 
       8                 :            : #include <acpi/acpi.h>
       9                 :            : #include "accommon.h"
      10                 :            : #include "acparser.h"
      11                 :            : #include "amlcode.h"
      12                 :            : #include "acdispat.h"
      13                 :            : #include "acinterp.h"
      14                 :            : #include "acnamesp.h"
      15                 :            : #include "acdebug.h"
      16                 :            : 
      17                 :            : #define _COMPONENT          ACPI_DISPATCHER
      18                 :            : ACPI_MODULE_NAME("dsutils")
      19                 :            : 
      20                 :            : /*******************************************************************************
      21                 :            :  *
      22                 :            :  * FUNCTION:    acpi_ds_clear_implicit_return
      23                 :            :  *
      24                 :            :  * PARAMETERS:  walk_state          - Current State
      25                 :            :  *
      26                 :            :  * RETURN:      None.
      27                 :            :  *
      28                 :            :  * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
      29                 :            :  *              to delete "stale" return values (if enabled, the return value
      30                 :            :  *              from every operator is saved at least momentarily, in case the
      31                 :            :  *              parent method exits.)
      32                 :            :  *
      33                 :            :  ******************************************************************************/
      34                 :     323454 : void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
      35                 :            : {
      36                 :     323454 :         ACPI_FUNCTION_NAME(ds_clear_implicit_return);
      37                 :            : 
      38                 :            :         /*
      39                 :            :          * Slack must be enabled for this feature
      40                 :            :          */
      41         [ +  - ]:     323454 :         if (!acpi_gbl_enable_interpreter_slack) {
      42                 :            :                 return;
      43                 :            :         }
      44                 :            : 
      45         [ +  + ]:     323454 :         if (walk_state->implicit_return_obj) {
      46                 :            :                 /*
      47                 :            :                  * Delete any "stale" implicit return. However, in
      48                 :            :                  * complex statements, the implicit return value can be
      49                 :            :                  * bubbled up several levels.
      50                 :            :                  */
      51                 :            :                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
      52                 :            :                                   "Removing reference on stale implicit return obj %p\n",
      53                 :     321270 :                                   walk_state->implicit_return_obj));
      54                 :            : 
      55                 :     321270 :                 acpi_ut_remove_reference(walk_state->implicit_return_obj);
      56                 :     321270 :                 walk_state->implicit_return_obj = NULL;
      57                 :            :         }
      58                 :            : }
      59                 :            : 
      60                 :            : /*******************************************************************************
      61                 :            :  *
      62                 :            :  * FUNCTION:    acpi_ds_do_implicit_return
      63                 :            :  *
      64                 :            :  * PARAMETERS:  return_desc         - The return value
      65                 :            :  *              walk_state          - Current State
      66                 :            :  *              add_reference       - True if a reference should be added to the
      67                 :            :  *                                    return object
      68                 :            :  *
      69                 :            :  * RETURN:      TRUE if implicit return enabled, FALSE otherwise
      70                 :            :  *
      71                 :            :  * DESCRIPTION: Implements the optional "implicit return".  We save the result
      72                 :            :  *              of every ASL operator and control method invocation in case the
      73                 :            :  *              parent method exit. Before storing a new return value, we
      74                 :            :  *              delete the previous return value.
      75                 :            :  *
      76                 :            :  ******************************************************************************/
      77                 :            : 
      78                 :            : u8
      79                 :     367332 : acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
      80                 :            :                            struct acpi_walk_state *walk_state, u8 add_reference)
      81                 :            : {
      82                 :     367332 :         ACPI_FUNCTION_NAME(ds_do_implicit_return);
      83                 :            : 
      84                 :            :         /*
      85                 :            :          * Slack must be enabled for this feature, and we must
      86                 :            :          * have a valid return object
      87                 :            :          */
      88   [ +  -  +  + ]:     367332 :         if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) {
      89                 :            :                 return (FALSE);
      90                 :            :         }
      91                 :            : 
      92                 :            :         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
      93                 :            :                           "Result %p will be implicitly returned; Prev=%p\n",
      94                 :     365148 :                           return_desc, walk_state->implicit_return_obj));
      95                 :            : 
      96                 :            :         /*
      97                 :            :          * Delete any "stale" implicit return value first. However, in
      98                 :            :          * complex statements, the implicit return value can be
      99                 :            :          * bubbled up several levels, so we don't clear the value if it
     100                 :            :          * is the same as the return_desc.
     101                 :            :          */
     102         [ +  + ]:     365148 :         if (walk_state->implicit_return_obj) {
     103         [ +  + ]:     362964 :                 if (walk_state->implicit_return_obj == return_desc) {
     104                 :            :                         return (TRUE);
     105                 :            :                 }
     106                 :     313971 :                 acpi_ds_clear_implicit_return(walk_state);
     107                 :            :         }
     108                 :            : 
     109                 :            :         /* Save the implicit return value, add a reference if requested */
     110                 :            : 
     111                 :     316155 :         walk_state->implicit_return_obj = return_desc;
     112         [ +  - ]:     316155 :         if (add_reference) {
     113                 :     316155 :                 acpi_ut_add_reference(return_desc);
     114                 :            :         }
     115                 :            : 
     116                 :            :         return (TRUE);
     117                 :            : }
     118                 :            : 
     119                 :            : /*******************************************************************************
     120                 :            :  *
     121                 :            :  * FUNCTION:    acpi_ds_is_result_used
     122                 :            :  *
     123                 :            :  * PARAMETERS:  op                  - Current Op
     124                 :            :  *              walk_state          - Current State
     125                 :            :  *
     126                 :            :  * RETURN:      TRUE if result is used, FALSE otherwise
     127                 :            :  *
     128                 :            :  * DESCRIPTION: Check if a result object will be used by the parent
     129                 :            :  *
     130                 :            :  ******************************************************************************/
     131                 :            : 
     132                 :            : u8
     133                 :     280809 : acpi_ds_is_result_used(union acpi_parse_object * op,
     134                 :            :                        struct acpi_walk_state * walk_state)
     135                 :            : {
     136                 :     280809 :         const struct acpi_opcode_info *parent_info;
     137                 :            : 
     138                 :     280809 :         ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op);
     139                 :            : 
     140                 :            :         /* Must have both an Op and a Result Object */
     141                 :            : 
     142         [ -  + ]:     280809 :         if (!op) {
     143                 :          0 :                 ACPI_ERROR((AE_INFO, "Null Op"));
     144                 :          0 :                 return_UINT8(TRUE);
     145                 :            :         }
     146                 :            : 
     147                 :            :         /*
     148                 :            :          * We know that this operator is not a
     149                 :            :          * Return() operator (would not come here.) The following code is the
     150                 :            :          * optional support for a so-called "implicit return". Some AML code
     151                 :            :          * assumes that the last value of the method is "implicitly" returned
     152                 :            :          * to the caller. Just save the last result as the return value.
     153                 :            :          * NOTE: this is optional because the ASL language does not actually
     154                 :            :          * support this behavior.
     155                 :            :          */
     156                 :     280809 :         (void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state,
     157                 :            :                                          TRUE);
     158                 :            : 
     159                 :            :         /*
     160                 :            :          * Now determine if the parent will use the result
     161                 :            :          *
     162                 :            :          * If there is no parent, or the parent is a scope_op, we are executing
     163                 :            :          * at the method level. An executing method typically has no parent,
     164                 :            :          * since each method is parsed separately. A method invoked externally
     165                 :            :          * via execute_control_method has a scope_op as the parent.
     166                 :            :          */
     167         [ +  + ]:     280809 :         if ((!op->common.parent) ||
     168         [ +  + ]:     280341 :             (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
     169                 :            : 
     170                 :            :                 /* No parent, the return value cannot possibly be used */
     171                 :            : 
     172                 :            :                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
     173                 :            :                                   "At Method level, result of [%s] not used\n",
     174                 :            :                                   acpi_ps_get_opcode_name(op->common.
     175                 :            :                                                           aml_opcode)));
     176                 :            :                 return_UINT8(FALSE);
     177                 :            :         }
     178                 :            : 
     179                 :            :         /* Get info on the parent. The root_op is AML_SCOPE */
     180                 :            : 
     181                 :     277755 :         parent_info =
     182                 :     277755 :             acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
     183         [ -  + ]:     277755 :         if (parent_info->class == AML_CLASS_UNKNOWN) {
     184                 :          0 :                 ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op));
     185                 :          0 :                 return_UINT8(FALSE);
     186                 :            :         }
     187                 :            : 
     188                 :            :         /*
     189                 :            :          * Decide what to do with the result based on the parent. If
     190                 :            :          * the parent opcode will not use the result, delete the object.
     191                 :            :          * Otherwise leave it as is, it will be deleted when it is used
     192                 :            :          * as an operand later.
     193                 :            :          */
     194   [ +  +  -  + ]:     277755 :         switch (parent_info->class) {
     195                 :     114108 :         case AML_CLASS_CONTROL:
     196                 :            : 
     197      [ +  +  + ]:     114108 :                 switch (op->common.parent->common.aml_opcode) {
     198                 :       3042 :                 case AML_RETURN_OP:
     199                 :            : 
     200                 :            :                         /* Never delete the return value associated with a return opcode */
     201                 :            : 
     202                 :       3042 :                         goto result_used;
     203                 :            : 
     204                 :     107253 :                 case AML_IF_OP:
     205                 :            :                 case AML_WHILE_OP:
     206                 :            :                         /*
     207                 :            :                          * If we are executing the predicate AND this is the predicate op,
     208                 :            :                          * we will use the return value
     209                 :            :                          */
     210         [ -  + ]:     107253 :                         if ((walk_state->control_state->common.state ==
     211                 :          0 :                              ACPI_CONTROL_PREDICATE_EXECUTING) &&
     212         [ #  # ]:          0 :                             (walk_state->control_state->control.predicate_op ==
     213                 :            :                              op)) {
     214                 :          0 :                                 goto result_used;
     215                 :            :                         }
     216                 :            :                         break;
     217                 :            : 
     218                 :            :                 default:
     219                 :            : 
     220                 :            :                         /* Ignore other control opcodes */
     221                 :            : 
     222                 :            :                         break;
     223                 :            :                 }
     224                 :            : 
     225                 :            :                 /* The general control opcode returns no result */
     226                 :            : 
     227                 :     111066 :                 goto result_not_used;
     228                 :            : 
     229                 :        702 :         case AML_CLASS_CREATE:
     230                 :            :                 /*
     231                 :            :                  * These opcodes allow term_arg(s) as operands and therefore
     232                 :            :                  * the operands can be method calls. The result is used.
     233                 :            :                  */
     234                 :        702 :                 goto result_used;
     235                 :            : 
     236                 :          0 :         case AML_CLASS_NAMED_OBJECT:
     237                 :            : 
     238         [ #  # ]:          0 :                 if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
     239                 :            :                     (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP)
     240         [ #  # ]:          0 :                     || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)
     241         [ #  # ]:          0 :                     || (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
     242         [ #  # ]:          0 :                     || (op->common.parent->common.aml_opcode ==
     243                 :            :                         AML_VARIABLE_PACKAGE_OP)
     244         [ #  # ]:          0 :                     || (op->common.parent->common.aml_opcode ==
     245                 :            :                         AML_INT_EVAL_SUBTREE_OP)
     246         [ #  # ]:          0 :                     || (op->common.parent->common.aml_opcode ==
     247                 :            :                         AML_BANK_FIELD_OP)) {
     248                 :            :                         /*
     249                 :            :                          * These opcodes allow term_arg(s) as operands and therefore
     250                 :            :                          * the operands can be method calls. The result is used.
     251                 :            :                          */
     252                 :          0 :                         goto result_used;
     253                 :            :                 }
     254                 :            : 
     255                 :          0 :                 goto result_not_used;
     256                 :            : 
     257                 :     162945 :         default:
     258                 :            :                 /*
     259                 :            :                  * In all other cases. the parent will actually use the return
     260                 :            :                  * object, so keep it.
     261                 :            :                  */
     262                 :     162945 :                 goto result_used;
     263                 :            :         }
     264                 :            : 
     265                 :     280809 : result_used:
     266                 :            :         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
     267                 :            :                           "Result of [%s] used by Parent [%s] Op=%p\n",
     268                 :            :                           acpi_ps_get_opcode_name(op->common.aml_opcode),
     269                 :            :                           acpi_ps_get_opcode_name(op->common.parent->common.
     270                 :            :                                                   aml_opcode), op));
     271                 :            : 
     272                 :            :         return_UINT8(TRUE);
     273                 :            : 
     274                 :     280809 : result_not_used:
     275                 :            :         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
     276                 :            :                           "Result of [%s] not used by Parent [%s] Op=%p\n",
     277                 :            :                           acpi_ps_get_opcode_name(op->common.aml_opcode),
     278                 :            :                           acpi_ps_get_opcode_name(op->common.parent->common.
     279                 :            :                                                   aml_opcode), op));
     280                 :            : 
     281                 :            :         return_UINT8(FALSE);
     282                 :            : }
     283                 :            : 
     284                 :            : /*******************************************************************************
     285                 :            :  *
     286                 :            :  * FUNCTION:    acpi_ds_delete_result_if_not_used
     287                 :            :  *
     288                 :            :  * PARAMETERS:  op              - Current parse Op
     289                 :            :  *              result_obj      - Result of the operation
     290                 :            :  *              walk_state      - Current state
     291                 :            :  *
     292                 :            :  * RETURN:      Status
     293                 :            :  *
     294                 :            :  * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
     295                 :            :  *              result descriptor, check if the parent opcode will actually use
     296                 :            :  *              this result. If not, delete the result now so that it will
     297                 :            :  *              not become orphaned.
     298                 :            :  *
     299                 :            :  ******************************************************************************/
     300                 :            : 
     301                 :            : void
     302                 :     278625 : acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
     303                 :            :                                   union acpi_operand_object *result_obj,
     304                 :            :                                   struct acpi_walk_state *walk_state)
     305                 :            : {
     306                 :     278625 :         union acpi_operand_object *obj_desc;
     307                 :     278625 :         acpi_status status;
     308                 :            : 
     309                 :     278625 :         ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj);
     310                 :            : 
     311         [ -  + ]:     278625 :         if (!op) {
     312                 :          0 :                 ACPI_ERROR((AE_INFO, "Null Op"));
     313                 :          0 :                 return_VOID;
     314                 :            :         }
     315                 :            : 
     316         [ +  - ]:     278625 :         if (!result_obj) {
     317                 :            :                 return_VOID;
     318                 :            :         }
     319                 :            : 
     320         [ +  + ]:     278625 :         if (!acpi_ds_is_result_used(op, walk_state)) {
     321                 :            : 
     322                 :            :                 /* Must pop the result stack (obj_desc should be equal to result_obj) */
     323                 :            : 
     324                 :     114120 :                 status = acpi_ds_result_pop(&obj_desc, walk_state);
     325         [ +  - ]:     114120 :                 if (ACPI_SUCCESS(status)) {
     326                 :     114120 :                         acpi_ut_remove_reference(result_obj);
     327                 :            :                 }
     328                 :            :         }
     329                 :            : 
     330                 :            :         return_VOID;
     331                 :            : }
     332                 :            : 
     333                 :            : /*******************************************************************************
     334                 :            :  *
     335                 :            :  * FUNCTION:    acpi_ds_resolve_operands
     336                 :            :  *
     337                 :            :  * PARAMETERS:  walk_state          - Current walk state with operands on stack
     338                 :            :  *
     339                 :            :  * RETURN:      Status
     340                 :            :  *
     341                 :            :  * DESCRIPTION: Resolve all operands to their values. Used to prepare
     342                 :            :  *              arguments to a control method invocation (a call from one
     343                 :            :  *              method to another.)
     344                 :            :  *
     345                 :            :  ******************************************************************************/
     346                 :            : 
     347                 :       2184 : acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
     348                 :            : {
     349                 :       2184 :         u32 i;
     350                 :       2184 :         acpi_status status = AE_OK;
     351                 :            : 
     352                 :       2184 :         ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state);
     353                 :            : 
     354                 :            :         /*
     355                 :            :          * Attempt to resolve each of the valid operands
     356                 :            :          * Method arguments are passed by reference, not by value. This means
     357                 :            :          * that the actual objects are passed, not copies of the objects.
     358                 :            :          */
     359         [ +  + ]:       4368 :         for (i = 0; i < walk_state->num_operands; i++) {
     360                 :       2184 :                 status =
     361                 :       2184 :                     acpi_ex_resolve_to_value(&walk_state->operands[i],
     362                 :            :                                              walk_state);
     363         [ +  - ]:       2184 :                 if (ACPI_FAILURE(status)) {
     364                 :            :                         break;
     365                 :            :                 }
     366                 :            :         }
     367                 :            : 
     368                 :       2184 :         return_ACPI_STATUS(status);
     369                 :            : }
     370                 :            : 
     371                 :            : /*******************************************************************************
     372                 :            :  *
     373                 :            :  * FUNCTION:    acpi_ds_clear_operands
     374                 :            :  *
     375                 :            :  * PARAMETERS:  walk_state          - Current walk state with operands on stack
     376                 :            :  *
     377                 :            :  * RETURN:      None
     378                 :            :  *
     379                 :            :  * DESCRIPTION: Clear all operands on the current walk state operand stack.
     380                 :            :  *
     381                 :            :  ******************************************************************************/
     382                 :            : 
     383                 :     343743 : void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
     384                 :            : {
     385                 :     343743 :         u32 i;
     386                 :            : 
     387                 :     343743 :         ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state);
     388                 :            : 
     389                 :            :         /* Remove a reference on each operand on the stack */
     390                 :            : 
     391         [ +  + ]:    1158975 :         for (i = 0; i < walk_state->num_operands; i++) {
     392                 :            :                 /*
     393                 :            :                  * Remove a reference to all operands, including both
     394                 :            :                  * "Arguments" and "Targets".
     395                 :            :                  */
     396                 :     815232 :                 acpi_ut_remove_reference(walk_state->operands[i]);
     397                 :     815232 :                 walk_state->operands[i] = NULL;
     398                 :            :         }
     399                 :            : 
     400                 :     343743 :         walk_state->num_operands = 0;
     401                 :     343743 :         return_VOID;
     402                 :            : }
     403                 :            : 
     404                 :            : /*******************************************************************************
     405                 :            :  *
     406                 :            :  * FUNCTION:    acpi_ds_create_operand
     407                 :            :  *
     408                 :            :  * PARAMETERS:  walk_state      - Current walk state
     409                 :            :  *              arg             - Parse object for the argument
     410                 :            :  *              arg_index       - Which argument (zero based)
     411                 :            :  *
     412                 :            :  * RETURN:      Status
     413                 :            :  *
     414                 :            :  * DESCRIPTION: Translate a parse tree object that is an argument to an AML
     415                 :            :  *              opcode to the equivalent interpreter object. This may include
     416                 :            :  *              looking up a name or entering a new name into the internal
     417                 :            :  *              namespace.
     418                 :            :  *
     419                 :            :  ******************************************************************************/
     420                 :            : 
     421                 :            : acpi_status
     422                 :     856572 : acpi_ds_create_operand(struct acpi_walk_state *walk_state,
     423                 :            :                        union acpi_parse_object *arg, u32 arg_index)
     424                 :            : {
     425                 :     856572 :         acpi_status status = AE_OK;
     426                 :     856572 :         char *name_string;
     427                 :     856572 :         u32 name_length;
     428                 :     856572 :         union acpi_operand_object *obj_desc;
     429                 :     856572 :         union acpi_parse_object *parent_op;
     430                 :     856572 :         u16 opcode;
     431                 :     856572 :         acpi_interpreter_mode interpreter_mode;
     432                 :     856572 :         const struct acpi_opcode_info *op_info;
     433                 :            : 
     434                 :     856572 :         ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg);
     435                 :            : 
     436                 :            :         /* A valid name must be looked up in the namespace */
     437                 :            : 
     438         [ +  + ]:     856572 :         if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
     439         [ +  + ]:     156828 :             (arg->common.value.string) &&
     440         [ +  + ]:      13806 :             !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
     441                 :            :                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
     442                 :       8112 :                                   arg));
     443                 :            : 
     444                 :            :                 /* Get the entire name string from the AML stream */
     445                 :            : 
     446                 :       8112 :                 status = acpi_ex_get_name_string(ACPI_TYPE_ANY,
     447                 :            :                                                  arg->common.value.buffer,
     448                 :            :                                                  &name_string, &name_length);
     449                 :            : 
     450         [ +  - ]:       8112 :                 if (ACPI_FAILURE(status)) {
     451                 :            :                         return_ACPI_STATUS(status);
     452                 :            :                 }
     453                 :            : 
     454                 :            :                 /* All prefixes have been handled, and the name is in name_string */
     455                 :            : 
     456                 :            :                 /*
     457                 :            :                  * Special handling for buffer_field declarations. This is a deferred
     458                 :            :                  * opcode that unfortunately defines the field name as the last
     459                 :            :                  * parameter instead of the first. We get here when we are performing
     460                 :            :                  * the deferred execution, so the actual name of the field is already
     461                 :            :                  * in the namespace. We don't want to attempt to look it up again
     462                 :            :                  * because we may be executing in a different scope than where the
     463                 :            :                  * actual opcode exists.
     464                 :            :                  */
     465         [ -  + ]:       8112 :                 if ((walk_state->deferred_node) &&
     466         [ #  # ]:          0 :                     (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
     467         [ #  # ]:          0 :                     && (arg_index == (u32)
     468         [ #  # ]:          0 :                         ((walk_state->opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) {
     469                 :          0 :                         obj_desc =
     470                 :            :                             ACPI_CAST_PTR(union acpi_operand_object,
     471                 :            :                                           walk_state->deferred_node);
     472                 :          0 :                         status = AE_OK;
     473                 :            :                 } else {        /* All other opcodes */
     474                 :            : 
     475                 :            :                         /*
     476                 :            :                          * Differentiate between a namespace "create" operation
     477                 :            :                          * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
     478                 :            :                          * IMODE_EXECUTE) in order to support the creation of
     479                 :            :                          * namespace objects during the execution of control methods.
     480                 :            :                          */
     481                 :       8112 :                         parent_op = arg->common.parent;
     482                 :       8112 :                         op_info =
     483                 :       8112 :                             acpi_ps_get_opcode_info(parent_op->common.
     484                 :            :                                                     aml_opcode);
     485                 :            : 
     486         [ +  + ]:       8112 :                         if ((op_info->flags & AML_NSNODE) &&
     487         [ +  + ]:       3510 :                             (parent_op->common.aml_opcode !=
     488                 :            :                              AML_INT_METHODCALL_OP)
     489         [ +  - ]:       1482 :                             && (parent_op->common.aml_opcode != AML_REGION_OP)
     490         [ -  + ]:       1482 :                             && (parent_op->common.aml_opcode !=
     491                 :            :                                 AML_INT_NAMEPATH_OP)) {
     492                 :            : 
     493                 :            :                                 /* Enter name into namespace if not found */
     494                 :            : 
     495                 :            :                                 interpreter_mode = ACPI_IMODE_LOAD_PASS2;
     496                 :            :                         } else {
     497                 :            :                                 /* Return a failure if name not found */
     498                 :            : 
     499                 :       6630 :                                 interpreter_mode = ACPI_IMODE_EXECUTE;
     500                 :            :                         }
     501                 :            : 
     502                 :       8112 :                         status =
     503                 :       8112 :                             acpi_ns_lookup(walk_state->scope_info, name_string,
     504                 :            :                                            ACPI_TYPE_ANY, interpreter_mode,
     505                 :            :                                            ACPI_NS_SEARCH_PARENT |
     506                 :            :                                            ACPI_NS_DONT_OPEN_SCOPE, walk_state,
     507                 :            :                                            ACPI_CAST_INDIRECT_PTR(struct
     508                 :            :                                                                   acpi_namespace_node,
     509                 :            :                                                                   &obj_desc));
     510                 :            :                         /*
     511                 :            :                          * The only case where we pass through (ignore) a NOT_FOUND
     512                 :            :                          * error is for the cond_ref_of opcode.
     513                 :            :                          */
     514         [ -  + ]:       8112 :                         if (status == AE_NOT_FOUND) {
     515         [ #  # ]:          0 :                                 if (parent_op->common.aml_opcode ==
     516                 :            :                                     AML_CONDITIONAL_REF_OF_OP) {
     517                 :            :                                         /*
     518                 :            :                                          * For the Conditional Reference op, it's OK if
     519                 :            :                                          * the name is not found;  We just need a way to
     520                 :            :                                          * indicate this to the interpreter, set the
     521                 :            :                                          * object to the root
     522                 :            :                                          */
     523                 :          0 :                                         obj_desc =
     524                 :            :                                             ACPI_CAST_PTR(union
     525                 :            :                                                                  acpi_operand_object,
     526                 :            :                                                                  acpi_gbl_root_node);
     527                 :          0 :                                         status = AE_OK;
     528         [ #  # ]:          0 :                                 } else if (parent_op->common.aml_opcode ==
     529                 :            :                                            AML_EXTERNAL_OP) {
     530                 :            :                                         /*
     531                 :            :                                          * This opcode should never appear here. It is used only
     532                 :            :                                          * by AML disassemblers and is surrounded by an If(0)
     533                 :            :                                          * by the ASL compiler.
     534                 :            :                                          *
     535                 :            :                                          * Therefore, if we see it here, it is a serious error.
     536                 :            :                                          */
     537                 :            :                                         status = AE_AML_BAD_OPCODE;
     538                 :            :                                 } else {
     539                 :            :                                         /*
     540                 :            :                                          * We just plain didn't find it -- which is a
     541                 :            :                                          * very serious error at this point
     542                 :            :                                          */
     543                 :            :                                         status = AE_AML_NAME_NOT_FOUND;
     544                 :            :                                 }
     545                 :            :                         }
     546                 :            : 
     547         [ -  + ]:       8112 :                         if (ACPI_FAILURE(status)) {
     548                 :          0 :                                 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
     549                 :       8112 :                                                      name_string, status);
     550                 :            :                         }
     551                 :            :                 }
     552                 :            : 
     553                 :            :                 /* Free the namestring created above */
     554                 :            : 
     555                 :       8112 :                 ACPI_FREE(name_string);
     556                 :            : 
     557                 :            :                 /* Check status from the lookup */
     558                 :            : 
     559         [ +  - ]:       8112 :                 if (ACPI_FAILURE(status)) {
     560                 :            :                         return_ACPI_STATUS(status);
     561                 :            :                 }
     562                 :            : 
     563                 :            :                 /* Put the resulting object onto the current object stack */
     564                 :            : 
     565                 :       8112 :                 status = acpi_ds_obj_stack_push(obj_desc, walk_state);
     566                 :       8112 :                 if (ACPI_FAILURE(status)) {
     567                 :            :                         return_ACPI_STATUS(status);
     568                 :            :                 }
     569                 :            : 
     570                 :            :                 acpi_db_display_argument_object(obj_desc, walk_state);
     571                 :            :         } else {
     572                 :            :                 /* Check for null name case */
     573                 :            : 
     574         [ +  + ]:     848460 :                 if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
     575         [ +  + ]:     148716 :                     !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
     576                 :            :                         /*
     577                 :            :                          * If the name is null, this means that this is an
     578                 :            :                          * optional result parameter that was not specified
     579                 :            :                          * in the original ASL. Create a Zero Constant for a
     580                 :            :                          * placeholder. (Store to a constant is a Noop.)
     581                 :            :                          */
     582                 :            :                         opcode = AML_ZERO_OP;   /* Has no arguments! */
     583                 :            : 
     584                 :            :                         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
     585                 :            :                                           "Null namepath: Arg=%p\n", arg));
     586                 :            :                 } else {
     587                 :     705438 :                         opcode = arg->common.aml_opcode;
     588                 :            :                 }
     589                 :            : 
     590                 :            :                 /* Get the object type of the argument */
     591                 :            : 
     592                 :     848460 :                 op_info = acpi_ps_get_opcode_info(opcode);
     593         [ +  - ]:     848460 :                 if (op_info->object_type == ACPI_TYPE_INVALID) {
     594                 :            :                         return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
     595                 :            :                 }
     596                 :            : 
     597         [ +  + ]:     848460 :                 if ((op_info->flags & AML_HAS_RETVAL) ||
     598         [ +  + ]:     689649 :                     (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
     599                 :            :                         /*
     600                 :            :                          * Use value that was already previously returned
     601                 :            :                          * by the evaluation of this argument
     602                 :            :                          */
     603                 :     164505 :                         status = acpi_ds_result_pop(&obj_desc, walk_state);
     604         [ -  + ]:     164505 :                         if (ACPI_FAILURE(status)) {
     605                 :            :                                 /*
     606                 :            :                                  * Only error is underflow, and this indicates
     607                 :            :                                  * a missing or null operand!
     608                 :            :                                  */
     609                 :          0 :                                 ACPI_EXCEPTION((AE_INFO, status,
     610                 :            :                                                 "Missing or null operand"));
     611                 :          0 :                                 return_ACPI_STATUS(status);
     612                 :            :                         }
     613                 :            :                 } else {
     614                 :            :                         /* Create an ACPI_INTERNAL_OBJECT for the argument */
     615                 :            : 
     616                 :    1367910 :                         obj_desc =
     617                 :     683955 :                             acpi_ut_create_internal_object(op_info->
     618                 :            :                                                            object_type);
     619         [ +  - ]:     683955 :                         if (!obj_desc) {
     620                 :            :                                 return_ACPI_STATUS(AE_NO_MEMORY);
     621                 :            :                         }
     622                 :            : 
     623                 :            :                         /* Initialize the new object */
     624                 :            : 
     625                 :     683955 :                         status =
     626                 :     683955 :                             acpi_ds_init_object_from_op(walk_state, arg, opcode,
     627                 :            :                                                         &obj_desc);
     628         [ -  + ]:     683955 :                         if (ACPI_FAILURE(status)) {
     629                 :          0 :                                 acpi_ut_delete_object_desc(obj_desc);
     630                 :          0 :                                 return_ACPI_STATUS(status);
     631                 :            :                         }
     632                 :            :                 }
     633                 :            : 
     634                 :            :                 /* Put the operand object on the object stack */
     635                 :            : 
     636                 :     848460 :                 status = acpi_ds_obj_stack_push(obj_desc, walk_state);
     637                 :     848460 :                 if (ACPI_FAILURE(status)) {
     638                 :            :                         return_ACPI_STATUS(status);
     639                 :            :                 }
     640                 :            : 
     641                 :            :                 acpi_db_display_argument_object(obj_desc, walk_state);
     642                 :            :         }
     643                 :            : 
     644                 :            :         return_ACPI_STATUS(AE_OK);
     645                 :            : }
     646                 :            : 
     647                 :            : /*******************************************************************************
     648                 :            :  *
     649                 :            :  * FUNCTION:    acpi_ds_create_operands
     650                 :            :  *
     651                 :            :  * PARAMETERS:  walk_state          - Current state
     652                 :            :  *              first_arg           - First argument of a parser argument tree
     653                 :            :  *
     654                 :            :  * RETURN:      Status
     655                 :            :  *
     656                 :            :  * DESCRIPTION: Convert an operator's arguments from a parse tree format to
     657                 :            :  *              namespace objects and place those argument object on the object
     658                 :            :  *              stack in preparation for evaluation by the interpreter.
     659                 :            :  *
     660                 :            :  ******************************************************************************/
     661                 :            : 
     662                 :            : acpi_status
     663                 :     358608 : acpi_ds_create_operands(struct acpi_walk_state *walk_state,
     664                 :            :                         union acpi_parse_object *first_arg)
     665                 :            : {
     666                 :     358608 :         acpi_status status = AE_OK;
     667                 :     358608 :         union acpi_parse_object *arg;
     668                 :     358608 :         union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
     669                 :     358608 :         u32 arg_count = 0;
     670                 :     358608 :         u32 index = walk_state->num_operands;
     671                 :     358608 :         u32 i;
     672                 :            : 
     673                 :     358608 :         ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
     674                 :            : 
     675                 :            :         /* Get all arguments in the list */
     676                 :            : 
     677                 :     358608 :         arg = first_arg;
     678         [ +  + ]:    1191045 :         while (arg) {
     679         [ +  - ]:     832437 :                 if (index >= ACPI_OBJ_NUM_OPERANDS) {
     680                 :            :                         return_ACPI_STATUS(AE_BAD_DATA);
     681                 :            :                 }
     682                 :            : 
     683                 :     832437 :                 arguments[index] = arg;
     684                 :     832437 :                 walk_state->operands[index] = NULL;
     685                 :            : 
     686                 :            :                 /* Move on to next argument, if any */
     687                 :            : 
     688                 :     832437 :                 arg = arg->common.next;
     689                 :     832437 :                 arg_count++;
     690                 :     832437 :                 index++;
     691                 :            :         }
     692                 :            : 
     693                 :            :         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
     694                 :            :                           "NumOperands %d, ArgCount %d, Index %d\n",
     695                 :     358608 :                           walk_state->num_operands, arg_count, index));
     696                 :            : 
     697                 :            :         /* Create the interpreter arguments, in reverse order */
     698                 :            : 
     699                 :     358608 :         index--;
     700         [ +  + ]:    1191045 :         for (i = 0; i < arg_count; i++) {
     701                 :     832437 :                 arg = arguments[index];
     702                 :     832437 :                 walk_state->operand_index = (u8)index;
     703                 :            : 
     704                 :     832437 :                 status = acpi_ds_create_operand(walk_state, arg, index);
     705         [ -  + ]:     832437 :                 if (ACPI_FAILURE(status)) {
     706                 :          0 :                         goto cleanup;
     707                 :            :                 }
     708                 :            : 
     709                 :            :                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
     710                 :            :                                   "Created Arg #%u (%p) %u args total\n",
     711                 :     832437 :                                   index, arg, arg_count));
     712                 :     832437 :                 index--;
     713                 :            :         }
     714                 :            : 
     715                 :            :         return_ACPI_STATUS(status);
     716                 :            : 
     717                 :            : cleanup:
     718                 :            :         /*
     719                 :            :          * We must undo everything done above; meaning that we must
     720                 :            :          * pop everything off of the operand stack and delete those
     721                 :            :          * objects
     722                 :            :          */
     723                 :          0 :         acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
     724                 :            : 
     725                 :          0 :         ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %u", index));
     726                 :          0 :         return_ACPI_STATUS(status);
     727                 :            : }
     728                 :            : 
     729                 :            : /*****************************************************************************
     730                 :            :  *
     731                 :            :  * FUNCTION:    acpi_ds_evaluate_name_path
     732                 :            :  *
     733                 :            :  * PARAMETERS:  walk_state      - Current state of the parse tree walk,
     734                 :            :  *                                the opcode of current operation should be
     735                 :            :  *                                AML_INT_NAMEPATH_OP
     736                 :            :  *
     737                 :            :  * RETURN:      Status
     738                 :            :  *
     739                 :            :  * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent
     740                 :            :  *              interpreter object, convert it to value, if needed, duplicate
     741                 :            :  *              it, if needed, and push it onto the current result stack.
     742                 :            :  *
     743                 :            :  ****************************************************************************/
     744                 :            : 
     745                 :      21438 : acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
     746                 :            : {
     747                 :      21438 :         acpi_status status = AE_OK;
     748                 :      21438 :         union acpi_parse_object *op = walk_state->op;
     749                 :      21438 :         union acpi_operand_object **operand = &walk_state->operands[0];
     750                 :      21438 :         union acpi_operand_object *new_obj_desc;
     751                 :      21438 :         u8 type;
     752                 :            : 
     753                 :      21438 :         ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state);
     754                 :            : 
     755         [ -  + ]:      21438 :         if (!op->common.parent) {
     756                 :            : 
     757                 :            :                 /* This happens after certain exception processing */
     758                 :            : 
     759                 :          0 :                 goto exit;
     760                 :            :         }
     761                 :            : 
     762                 :      21438 :         if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
     763         [ +  + ]:      21438 :             (op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP) ||
     764                 :            :             (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) {
     765                 :            : 
     766                 :            :                 /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */
     767                 :            : 
     768                 :      15744 :                 goto exit;
     769                 :            :         }
     770                 :            : 
     771                 :       5694 :         status = acpi_ds_create_operand(walk_state, op, 0);
     772         [ -  + ]:       5694 :         if (ACPI_FAILURE(status)) {
     773                 :          0 :                 goto exit;
     774                 :            :         }
     775                 :            : 
     776         [ -  + ]:       5694 :         if (op->common.flags & ACPI_PARSEOP_TARGET) {
     777                 :          0 :                 new_obj_desc = *operand;
     778                 :          0 :                 goto push_result;
     779                 :            :         }
     780                 :            : 
     781                 :       5694 :         type = (*operand)->common.type;
     782                 :            : 
     783                 :       5694 :         status = acpi_ex_resolve_to_value(operand, walk_state);
     784         [ -  + ]:       5694 :         if (ACPI_FAILURE(status)) {
     785                 :          0 :                 goto exit;
     786                 :            :         }
     787                 :            : 
     788         [ -  + ]:       5694 :         if (type == ACPI_TYPE_INTEGER) {
     789                 :            : 
     790                 :            :                 /* It was incremented by acpi_ex_resolve_to_value */
     791                 :            : 
     792                 :          0 :                 acpi_ut_remove_reference(*operand);
     793                 :            : 
     794                 :          0 :                 status =
     795                 :          0 :                     acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc,
     796                 :            :                                                     walk_state);
     797         [ #  # ]:          0 :                 if (ACPI_FAILURE(status)) {
     798                 :          0 :                         goto exit;
     799                 :            :                 }
     800                 :            :         } else {
     801                 :            :                 /*
     802                 :            :                  * The object either was anew created or is
     803                 :            :                  * a Namespace node - don't decrement it.
     804                 :            :                  */
     805                 :       5694 :                 new_obj_desc = *operand;
     806                 :            :         }
     807                 :            : 
     808                 :            :         /* Cleanup for name-path operand */
     809                 :            : 
     810                 :       5694 :         status = acpi_ds_obj_stack_pop(1, walk_state);
     811         [ -  + ]:       5694 :         if (ACPI_FAILURE(status)) {
     812                 :          0 :                 walk_state->result_obj = new_obj_desc;
     813                 :          0 :                 goto exit;
     814                 :            :         }
     815                 :            : 
     816                 :       5694 : push_result:
     817                 :            : 
     818                 :       5694 :         walk_state->result_obj = new_obj_desc;
     819                 :            : 
     820                 :       5694 :         status = acpi_ds_result_push(walk_state->result_obj, walk_state);
     821         [ -  + ]:       5694 :         if (ACPI_SUCCESS(status)) {
     822                 :            : 
     823                 :            :                 /* Force to take it from stack */
     824                 :            : 
     825                 :       5694 :                 op->common.flags |= ACPI_PARSEOP_IN_STACK;
     826                 :            :         }
     827                 :            : 
     828                 :          0 : exit:
     829                 :            : 
     830                 :      21438 :         return_ACPI_STATUS(status);
     831                 :            : }

Generated by: LCOV version 1.14