Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: dswload - Dispatcher first pass namespace load callbacks
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 "amlcode.h"
0014 #include "acdispat.h"
0015 #include "acinterp.h"
0016 #include "acnamesp.h"
0017 #ifdef ACPI_ASL_COMPILER
0018 #include "acdisasm.h"
0019 #endif
0020 
0021 #define _COMPONENT          ACPI_DISPATCHER
0022 ACPI_MODULE_NAME("dswload")
0023 
0024 /*******************************************************************************
0025  *
0026  * FUNCTION:    acpi_ds_init_callbacks
0027  *
0028  * PARAMETERS:  walk_state      - Current state of the parse tree walk
0029  *              pass_number     - 1, 2, or 3
0030  *
0031  * RETURN:      Status
0032  *
0033  * DESCRIPTION: Init walk state callbacks
0034  *
0035  ******************************************************************************/
0036 acpi_status
0037 acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number)
0038 {
0039 
0040     switch (pass_number) {
0041     case 0:
0042 
0043         /* Parse only - caller will setup callbacks */
0044 
0045         walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
0046             ACPI_PARSE_DELETE_TREE | ACPI_PARSE_DISASSEMBLE;
0047         walk_state->descending_callback = NULL;
0048         walk_state->ascending_callback = NULL;
0049         break;
0050 
0051     case 1:
0052 
0053         /* Load pass 1 */
0054 
0055         walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
0056             ACPI_PARSE_DELETE_TREE;
0057         walk_state->descending_callback = acpi_ds_load1_begin_op;
0058         walk_state->ascending_callback = acpi_ds_load1_end_op;
0059         break;
0060 
0061     case 2:
0062 
0063         /* Load pass 2 */
0064 
0065         walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
0066             ACPI_PARSE_DELETE_TREE;
0067         walk_state->descending_callback = acpi_ds_load2_begin_op;
0068         walk_state->ascending_callback = acpi_ds_load2_end_op;
0069         break;
0070 
0071     case 3:
0072 
0073         /* Execution pass */
0074 
0075         walk_state->parse_flags |= ACPI_PARSE_EXECUTE |
0076             ACPI_PARSE_DELETE_TREE;
0077         walk_state->descending_callback = acpi_ds_exec_begin_op;
0078         walk_state->ascending_callback = acpi_ds_exec_end_op;
0079         break;
0080 
0081     default:
0082 
0083         return (AE_BAD_PARAMETER);
0084     }
0085 
0086     return (AE_OK);
0087 }
0088 
0089 /*******************************************************************************
0090  *
0091  * FUNCTION:    acpi_ds_load1_begin_op
0092  *
0093  * PARAMETERS:  walk_state      - Current state of the parse tree walk
0094  *              out_op          - Where to return op if a new one is created
0095  *
0096  * RETURN:      Status
0097  *
0098  * DESCRIPTION: Descending callback used during the loading of ACPI tables.
0099  *
0100  ******************************************************************************/
0101 
0102 acpi_status
0103 acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state,
0104                union acpi_parse_object **out_op)
0105 {
0106     union acpi_parse_object *op;
0107     struct acpi_namespace_node *node;
0108     acpi_status status;
0109     acpi_object_type object_type;
0110     char *path;
0111     u32 flags;
0112 
0113     ACPI_FUNCTION_TRACE_PTR(ds_load1_begin_op, walk_state->op);
0114 
0115     op = walk_state->op;
0116     ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
0117               walk_state));
0118 
0119     /* We are only interested in opcodes that have an associated name */
0120 
0121     if (op) {
0122         if (!(walk_state->op_info->flags & AML_NAMED)) {
0123             *out_op = op;
0124             return_ACPI_STATUS(AE_OK);
0125         }
0126 
0127         /* Check if this object has already been installed in the namespace */
0128 
0129         if (op->common.node) {
0130             *out_op = op;
0131             return_ACPI_STATUS(AE_OK);
0132         }
0133     }
0134 
0135     path = acpi_ps_get_next_namestring(&walk_state->parser_state);
0136 
0137     /* Map the raw opcode into an internal object type */
0138 
0139     object_type = walk_state->op_info->object_type;
0140 
0141     ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0142               "State=%p Op=%p [%s]\n", walk_state, op,
0143               acpi_ut_get_type_name(object_type)));
0144 
0145     switch (walk_state->opcode) {
0146     case AML_SCOPE_OP:
0147         /*
0148          * The target name of the Scope() operator must exist at this point so
0149          * that we can actually open the scope to enter new names underneath it.
0150          * Allow search-to-root for single namesegs.
0151          */
0152         status =
0153             acpi_ns_lookup(walk_state->scope_info, path, object_type,
0154                    ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
0155                    walk_state, &(node));
0156 #ifdef ACPI_ASL_COMPILER
0157         if (status == AE_NOT_FOUND) {
0158             /*
0159              * Table disassembly:
0160              * Target of Scope() not found. Generate an External for it, and
0161              * insert the name into the namespace.
0162              */
0163             acpi_dm_add_op_to_external_list(op, path,
0164                             ACPI_TYPE_DEVICE, 0, 0);
0165             status =
0166                 acpi_ns_lookup(walk_state->scope_info, path,
0167                        object_type, ACPI_IMODE_LOAD_PASS1,
0168                        ACPI_NS_SEARCH_PARENT, walk_state,
0169                        &node);
0170         }
0171 #endif
0172         if (ACPI_FAILURE(status)) {
0173             ACPI_ERROR_NAMESPACE(walk_state->scope_info, path,
0174                          status);
0175             return_ACPI_STATUS(status);
0176         }
0177 
0178         /*
0179          * Check to make sure that the target is
0180          * one of the opcodes that actually opens a scope
0181          */
0182         switch (node->type) {
0183         case ACPI_TYPE_ANY:
0184         case ACPI_TYPE_LOCAL_SCOPE: /* Scope  */
0185         case ACPI_TYPE_DEVICE:
0186         case ACPI_TYPE_POWER:
0187         case ACPI_TYPE_PROCESSOR:
0188         case ACPI_TYPE_THERMAL:
0189 
0190             /* These are acceptable types */
0191             break;
0192 
0193         case ACPI_TYPE_INTEGER:
0194         case ACPI_TYPE_STRING:
0195         case ACPI_TYPE_BUFFER:
0196             /*
0197              * These types we will allow, but we will change the type.
0198              * This enables some existing code of the form:
0199              *
0200              *  Name (DEB, 0)
0201              *  Scope (DEB) { ... }
0202              *
0203              * Note: silently change the type here. On the second pass,
0204              * we will report a warning
0205              */
0206             ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0207                       "Type override - [%4.4s] had invalid type (%s) "
0208                       "for Scope operator, changed to type ANY\n",
0209                       acpi_ut_get_node_name(node),
0210                       acpi_ut_get_type_name(node->type)));
0211 
0212             node->type = ACPI_TYPE_ANY;
0213             walk_state->scope_info->common.value = ACPI_TYPE_ANY;
0214             break;
0215 
0216         case ACPI_TYPE_METHOD:
0217             /*
0218              * Allow scope change to root during execution of module-level
0219              * code. Root is typed METHOD during this time.
0220              */
0221             if ((node == acpi_gbl_root_node) &&
0222                 (walk_state->
0223                  parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
0224                 break;
0225             }
0226 
0227             ACPI_FALLTHROUGH;
0228 
0229         default:
0230 
0231             /* All other types are an error */
0232 
0233             ACPI_ERROR((AE_INFO,
0234                     "Invalid type (%s) for target of "
0235                     "Scope operator [%4.4s] (Cannot override)",
0236                     acpi_ut_get_type_name(node->type),
0237                     acpi_ut_get_node_name(node)));
0238 
0239             return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0240         }
0241         break;
0242 
0243     default:
0244         /*
0245          * For all other named opcodes, we will enter the name into
0246          * the namespace.
0247          *
0248          * Setup the search flags.
0249          * Since we are entering a name into the namespace, we do not want to
0250          * enable the search-to-root upsearch.
0251          *
0252          * There are only two conditions where it is acceptable that the name
0253          * already exists:
0254          *    1) the Scope() operator can reopen a scoping object that was
0255          *       previously defined (Scope, Method, Device, etc.)
0256          *    2) Whenever we are parsing a deferred opcode (op_region, Buffer,
0257          *       buffer_field, or Package), the name of the object is already
0258          *       in the namespace.
0259          */
0260         if (walk_state->deferred_node) {
0261 
0262             /* This name is already in the namespace, get the node */
0263 
0264             node = walk_state->deferred_node;
0265             status = AE_OK;
0266             break;
0267         }
0268 
0269         /*
0270          * If we are executing a method, do not create any namespace objects
0271          * during the load phase, only during execution.
0272          */
0273         if (walk_state->method_node) {
0274             node = NULL;
0275             status = AE_OK;
0276             break;
0277         }
0278 
0279         flags = ACPI_NS_NO_UPSEARCH;
0280         if ((walk_state->opcode != AML_SCOPE_OP) &&
0281             (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
0282             if (walk_state->namespace_override) {
0283                 flags |= ACPI_NS_OVERRIDE_IF_FOUND;
0284                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0285                           "[%s] Override allowed\n",
0286                           acpi_ut_get_type_name
0287                           (object_type)));
0288             } else {
0289                 flags |= ACPI_NS_ERROR_IF_FOUND;
0290                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0291                           "[%s] Cannot already exist\n",
0292                           acpi_ut_get_type_name
0293                           (object_type)));
0294             }
0295         } else {
0296             ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0297                       "[%s] Both Find or Create allowed\n",
0298                       acpi_ut_get_type_name(object_type)));
0299         }
0300 
0301         /*
0302          * Enter the named type into the internal namespace. We enter the name
0303          * as we go downward in the parse tree. Any necessary subobjects that
0304          * involve arguments to the opcode must be created as we go back up the
0305          * parse tree later.
0306          */
0307         status =
0308             acpi_ns_lookup(walk_state->scope_info, path, object_type,
0309                    ACPI_IMODE_LOAD_PASS1, flags, walk_state,
0310                    &node);
0311         if (ACPI_FAILURE(status)) {
0312             if (status == AE_ALREADY_EXISTS) {
0313 
0314                 /* The name already exists in this scope */
0315 
0316                 if (node->flags & ANOBJ_IS_EXTERNAL) {
0317                     /*
0318                      * Allow one create on an object or segment that was
0319                      * previously declared External
0320                      */
0321                     node->flags &= ~ANOBJ_IS_EXTERNAL;
0322                     node->type = (u8) object_type;
0323 
0324                     /* Just retyped a node, probably will need to open a scope */
0325 
0326                     if (acpi_ns_opens_scope(object_type)) {
0327                         status =
0328                             acpi_ds_scope_stack_push
0329                             (node, object_type,
0330                              walk_state);
0331                         if (ACPI_FAILURE(status)) {
0332                             return_ACPI_STATUS
0333                                 (status);
0334                         }
0335                     }
0336 
0337                     status = AE_OK;
0338                 }
0339             }
0340 
0341             if (ACPI_FAILURE(status)) {
0342                 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
0343                              path, status);
0344                 return_ACPI_STATUS(status);
0345             }
0346         }
0347         break;
0348     }
0349 
0350     /* Common exit */
0351 
0352     if (!op) {
0353 
0354         /* Create a new op */
0355 
0356         op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml);
0357         if (!op) {
0358             return_ACPI_STATUS(AE_NO_MEMORY);
0359         }
0360     }
0361 
0362     /* Initialize the op */
0363 
0364 #ifdef ACPI_CONSTANT_EVAL_ONLY
0365     op->named.path = path;
0366 #endif
0367 
0368     if (node) {
0369         /*
0370          * Put the Node in the "op" object that the parser uses, so we
0371          * can get it again quickly when this scope is closed
0372          */
0373         op->common.node = node;
0374         op->named.name = node->name.integer;
0375     }
0376 
0377     acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),
0378                op);
0379     *out_op = op;
0380     return_ACPI_STATUS(status);
0381 }
0382 
0383 /*******************************************************************************
0384  *
0385  * FUNCTION:    acpi_ds_load1_end_op
0386  *
0387  * PARAMETERS:  walk_state      - Current state of the parse tree walk
0388  *
0389  * RETURN:      Status
0390  *
0391  * DESCRIPTION: Ascending callback used during the loading of the namespace,
0392  *              both control methods and everything else.
0393  *
0394  ******************************************************************************/
0395 
0396 acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
0397 {
0398     union acpi_parse_object *op;
0399     acpi_object_type object_type;
0400     acpi_status status = AE_OK;
0401 #ifdef ACPI_ASL_COMPILER
0402     u8 param_count;
0403 #endif
0404 
0405     ACPI_FUNCTION_TRACE(ds_load1_end_op);
0406 
0407     op = walk_state->op;
0408     ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
0409               walk_state));
0410 
0411     /*
0412      * Disassembler: handle create field operators here.
0413      *
0414      * create_buffer_field is a deferred op that is typically processed in load
0415      * pass 2. However, disassembly of control method contents walk the parse
0416      * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed
0417      * in a later walk. This is a problem when there is a control method that
0418      * has the same name as the AML_CREATE object. In this case, any use of the
0419      * name segment will be detected as a method call rather than a reference
0420      * to a buffer field.
0421      *
0422      * This earlier creation during disassembly solves this issue by inserting
0423      * the named object in the ACPI namespace so that references to this name
0424      * would be a name string rather than a method call.
0425      */
0426     if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) &&
0427         (walk_state->op_info->flags & AML_CREATE)) {
0428         status = acpi_ds_create_buffer_field(op, walk_state);
0429         return_ACPI_STATUS(status);
0430     }
0431 
0432     /* We are only interested in opcodes that have an associated name */
0433 
0434     if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {
0435         return_ACPI_STATUS(AE_OK);
0436     }
0437 
0438     /* Get the object type to determine if we should pop the scope */
0439 
0440     object_type = walk_state->op_info->object_type;
0441 
0442     if (walk_state->op_info->flags & AML_FIELD) {
0443         /*
0444          * If we are executing a method, do not create any namespace objects
0445          * during the load phase, only during execution.
0446          */
0447         if (!walk_state->method_node) {
0448             if (walk_state->opcode == AML_FIELD_OP ||
0449                 walk_state->opcode == AML_BANK_FIELD_OP ||
0450                 walk_state->opcode == AML_INDEX_FIELD_OP) {
0451                 status =
0452                     acpi_ds_init_field_objects(op, walk_state);
0453             }
0454         }
0455         return_ACPI_STATUS(status);
0456     }
0457 
0458     /*
0459      * If we are executing a method, do not create any namespace objects
0460      * during the load phase, only during execution.
0461      */
0462     if (!walk_state->method_node) {
0463         if (op->common.aml_opcode == AML_REGION_OP) {
0464             status =
0465                 acpi_ex_create_region(op->named.data,
0466                           op->named.length,
0467                           (acpi_adr_space_type)
0468                           ((op->common.value.arg)->
0469                            common.value.integer),
0470                           walk_state);
0471             if (ACPI_FAILURE(status)) {
0472                 return_ACPI_STATUS(status);
0473             }
0474         } else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
0475             status =
0476                 acpi_ex_create_region(op->named.data,
0477                           op->named.length,
0478                           ACPI_ADR_SPACE_DATA_TABLE,
0479                           walk_state);
0480             if (ACPI_FAILURE(status)) {
0481                 return_ACPI_STATUS(status);
0482             }
0483         }
0484     }
0485 
0486     if (op->common.aml_opcode == AML_NAME_OP) {
0487 
0488         /* For Name opcode, get the object type from the argument */
0489 
0490         if (op->common.value.arg) {
0491             object_type = (acpi_ps_get_opcode_info((op->common.
0492                                 value.arg)->
0493                                    common.
0494                                    aml_opcode))->
0495                 object_type;
0496 
0497             /* Set node type if we have a namespace node */
0498 
0499             if (op->common.node) {
0500                 op->common.node->type = (u8) object_type;
0501             }
0502         }
0503     }
0504 #ifdef ACPI_ASL_COMPILER
0505     /*
0506      * For external opcode, get the object type from the argument and
0507      * get the parameter count from the argument's next.
0508      */
0509     if (acpi_gbl_disasm_flag &&
0510         op->common.node && op->common.aml_opcode == AML_EXTERNAL_OP) {
0511         /*
0512          * Note, if this external is not a method
0513          * Op->Common.Value.Arg->Common.Next->Common.Value.Integer == 0
0514          * Therefore, param_count will be 0.
0515          */
0516         param_count =
0517             (u8)op->common.value.arg->common.next->common.value.integer;
0518         object_type = (u8)op->common.value.arg->common.value.integer;
0519         op->common.node->flags |= ANOBJ_IS_EXTERNAL;
0520         op->common.node->type = (u8)object_type;
0521 
0522         acpi_dm_create_subobject_for_external((u8)object_type,
0523                               &op->common.node,
0524                               param_count);
0525 
0526         /*
0527          * Add the external to the external list because we may be
0528          * emitting code based off of the items within the external list.
0529          */
0530         acpi_dm_add_op_to_external_list(op, op->named.path,
0531                         (u8)object_type, param_count,
0532                         ACPI_EXT_ORIGIN_FROM_OPCODE |
0533                         ACPI_EXT_RESOLVED_REFERENCE);
0534     }
0535 #endif
0536 
0537     /*
0538      * If we are executing a method, do not create any namespace objects
0539      * during the load phase, only during execution.
0540      */
0541     if (!walk_state->method_node) {
0542         if (op->common.aml_opcode == AML_METHOD_OP) {
0543             /*
0544              * method_op pkg_length name_string method_flags term_list
0545              *
0546              * Note: We must create the method node/object pair as soon as we
0547              * see the method declaration. This allows later pass1 parsing
0548              * of invocations of the method (need to know the number of
0549              * arguments.)
0550              */
0551             ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0552                       "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
0553                       walk_state, op, op->named.node));
0554 
0555             if (!acpi_ns_get_attached_object(op->named.node)) {
0556                 walk_state->operands[0] =
0557                     ACPI_CAST_PTR(void, op->named.node);
0558                 walk_state->num_operands = 1;
0559 
0560                 status =
0561                     acpi_ds_create_operands(walk_state,
0562                                 op->common.value.
0563                                 arg);
0564                 if (ACPI_SUCCESS(status)) {
0565                     status =
0566                         acpi_ex_create_method(op->named.
0567                                   data,
0568                                   op->named.
0569                                   length,
0570                                   walk_state);
0571                 }
0572 
0573                 walk_state->operands[0] = NULL;
0574                 walk_state->num_operands = 0;
0575 
0576                 if (ACPI_FAILURE(status)) {
0577                     return_ACPI_STATUS(status);
0578                 }
0579             }
0580         }
0581     }
0582 
0583     /* Pop the scope stack (only if loading a table) */
0584 
0585     if (!walk_state->method_node &&
0586         op->common.aml_opcode != AML_EXTERNAL_OP &&
0587         acpi_ns_opens_scope(object_type)) {
0588         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0589                   "(%s): Popping scope for Op %p\n",
0590                   acpi_ut_get_type_name(object_type), op));
0591 
0592         status = acpi_ds_scope_stack_pop(walk_state);
0593     }
0594 
0595     return_ACPI_STATUS(status);
0596 }