597 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: dswload - Dispatcher first pass namespace load callbacks5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acparser.h"13#include "amlcode.h"14#include "acdispat.h"15#include "acinterp.h"16#include "acnamesp.h"17#ifdef ACPI_ASL_COMPILER18#include "acdisasm.h"19#endif20 21#define _COMPONENT ACPI_DISPATCHER22ACPI_MODULE_NAME("dswload")23 24/*******************************************************************************25 *26 * FUNCTION: acpi_ds_init_callbacks27 *28 * PARAMETERS: walk_state - Current state of the parse tree walk29 * pass_number - 1, 2, or 330 *31 * RETURN: Status32 *33 * DESCRIPTION: Init walk state callbacks34 *35 ******************************************************************************/36acpi_status37acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number)38{39 40 switch (pass_number) {41 case 0:42 43 /* Parse only - caller will setup callbacks */44 45 walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |46 ACPI_PARSE_DELETE_TREE | ACPI_PARSE_DISASSEMBLE;47 walk_state->descending_callback = NULL;48 walk_state->ascending_callback = NULL;49 break;50 51 case 1:52 53 /* Load pass 1 */54 55 walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |56 ACPI_PARSE_DELETE_TREE;57 walk_state->descending_callback = acpi_ds_load1_begin_op;58 walk_state->ascending_callback = acpi_ds_load1_end_op;59 break;60 61 case 2:62 63 /* Load pass 2 */64 65 walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |66 ACPI_PARSE_DELETE_TREE;67 walk_state->descending_callback = acpi_ds_load2_begin_op;68 walk_state->ascending_callback = acpi_ds_load2_end_op;69 break;70 71 case 3:72 73 /* Execution pass */74 75 walk_state->parse_flags |= ACPI_PARSE_EXECUTE |76 ACPI_PARSE_DELETE_TREE;77 walk_state->descending_callback = acpi_ds_exec_begin_op;78 walk_state->ascending_callback = acpi_ds_exec_end_op;79 break;80 81 default:82 83 return (AE_BAD_PARAMETER);84 }85 86 return (AE_OK);87}88 89/*******************************************************************************90 *91 * FUNCTION: acpi_ds_load1_begin_op92 *93 * PARAMETERS: walk_state - Current state of the parse tree walk94 * out_op - Where to return op if a new one is created95 *96 * RETURN: Status97 *98 * DESCRIPTION: Descending callback used during the loading of ACPI tables.99 *100 ******************************************************************************/101 102acpi_status103acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state,104 union acpi_parse_object **out_op)105{106 union acpi_parse_object *op;107 struct acpi_namespace_node *node;108 acpi_status status;109 acpi_object_type object_type;110 char *path;111 u32 flags;112 113 ACPI_FUNCTION_TRACE_PTR(ds_load1_begin_op, walk_state->op);114 115 op = walk_state->op;116 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,117 walk_state));118 119 /* We are only interested in opcodes that have an associated name */120 121 if (op) {122 if (!(walk_state->op_info->flags & AML_NAMED)) {123 *out_op = op;124 return_ACPI_STATUS(AE_OK);125 }126 127 /* Check if this object has already been installed in the namespace */128 129 if (op->common.node) {130 *out_op = op;131 return_ACPI_STATUS(AE_OK);132 }133 }134 135 path = acpi_ps_get_next_namestring(&walk_state->parser_state);136 137 /* Map the raw opcode into an internal object type */138 139 object_type = walk_state->op_info->object_type;140 141 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,142 "State=%p Op=%p [%s]\n", walk_state, op,143 acpi_ut_get_type_name(object_type)));144 145 switch (walk_state->opcode) {146 case AML_SCOPE_OP:147 /*148 * The target name of the Scope() operator must exist at this point so149 * that we can actually open the scope to enter new names underneath it.150 * Allow search-to-root for single namesegs.151 */152 status =153 acpi_ns_lookup(walk_state->scope_info, path, object_type,154 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,155 walk_state, &(node));156#ifdef ACPI_ASL_COMPILER157 if (status == AE_NOT_FOUND) {158 /*159 * Table disassembly:160 * Target of Scope() not found. Generate an External for it, and161 * insert the name into the namespace.162 */163 acpi_dm_add_op_to_external_list(op, path,164 ACPI_TYPE_DEVICE, 0, 0);165 status =166 acpi_ns_lookup(walk_state->scope_info, path,167 object_type, ACPI_IMODE_LOAD_PASS1,168 ACPI_NS_SEARCH_PARENT, walk_state,169 &node);170 }171#endif172 if (ACPI_FAILURE(status)) {173 ACPI_ERROR_NAMESPACE(walk_state->scope_info, path,174 status);175 return_ACPI_STATUS(status);176 }177 178 /*179 * Check to make sure that the target is180 * one of the opcodes that actually opens a scope181 */182 switch (node->type) {183 case ACPI_TYPE_ANY:184 case ACPI_TYPE_LOCAL_SCOPE: /* Scope */185 case ACPI_TYPE_DEVICE:186 case ACPI_TYPE_POWER:187 case ACPI_TYPE_PROCESSOR:188 case ACPI_TYPE_THERMAL:189 190 /* These are acceptable types */191 break;192 193 case ACPI_TYPE_INTEGER:194 case ACPI_TYPE_STRING:195 case ACPI_TYPE_BUFFER:196 /*197 * These types we will allow, but we will change the type.198 * This enables some existing code of the form:199 *200 * Name (DEB, 0)201 * Scope (DEB) { ... }202 *203 * Note: silently change the type here. On the second pass,204 * we will report a warning205 */206 ACPI_DEBUG_PRINT((ACPI_DB_INFO,207 "Type override - [%4.4s] had invalid type (%s) "208 "for Scope operator, changed to type ANY\n",209 acpi_ut_get_node_name(node),210 acpi_ut_get_type_name(node->type)));211 212 node->type = ACPI_TYPE_ANY;213 walk_state->scope_info->common.value = ACPI_TYPE_ANY;214 break;215 216 case ACPI_TYPE_METHOD:217 /*218 * Allow scope change to root during execution of module-level219 * code. Root is typed METHOD during this time.220 */221 if ((node == acpi_gbl_root_node) &&222 (walk_state->223 parse_flags & ACPI_PARSE_MODULE_LEVEL)) {224 break;225 }226 227 ACPI_FALLTHROUGH;228 229 default:230 231 /* All other types are an error */232 233 ACPI_ERROR((AE_INFO,234 "Invalid type (%s) for target of "235 "Scope operator [%4.4s] (Cannot override)",236 acpi_ut_get_type_name(node->type),237 acpi_ut_get_node_name(node)));238 239 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);240 }241 break;242 243 default:244 /*245 * For all other named opcodes, we will enter the name into246 * the namespace.247 *248 * Setup the search flags.249 * Since we are entering a name into the namespace, we do not want to250 * enable the search-to-root upsearch.251 *252 * There are only two conditions where it is acceptable that the name253 * already exists:254 * 1) the Scope() operator can reopen a scoping object that was255 * previously defined (Scope, Method, Device, etc.)256 * 2) Whenever we are parsing a deferred opcode (op_region, Buffer,257 * buffer_field, or Package), the name of the object is already258 * in the namespace.259 */260 if (walk_state->deferred_node) {261 262 /* This name is already in the namespace, get the node */263 264 node = walk_state->deferred_node;265 status = AE_OK;266 break;267 }268 269 /*270 * If we are executing a method, do not create any namespace objects271 * during the load phase, only during execution.272 */273 if (walk_state->method_node) {274 node = NULL;275 status = AE_OK;276 break;277 }278 279 flags = ACPI_NS_NO_UPSEARCH;280 if ((walk_state->opcode != AML_SCOPE_OP) &&281 (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {282 if (walk_state->namespace_override) {283 flags |= ACPI_NS_OVERRIDE_IF_FOUND;284 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,285 "[%s] Override allowed\n",286 acpi_ut_get_type_name287 (object_type)));288 } else {289 flags |= ACPI_NS_ERROR_IF_FOUND;290 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,291 "[%s] Cannot already exist\n",292 acpi_ut_get_type_name293 (object_type)));294 }295 } else {296 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,297 "[%s] Both Find or Create allowed\n",298 acpi_ut_get_type_name(object_type)));299 }300 301 /*302 * Enter the named type into the internal namespace. We enter the name303 * as we go downward in the parse tree. Any necessary subobjects that304 * involve arguments to the opcode must be created as we go back up the305 * parse tree later.306 */307 status =308 acpi_ns_lookup(walk_state->scope_info, path, object_type,309 ACPI_IMODE_LOAD_PASS1, flags, walk_state,310 &node);311 if (ACPI_FAILURE(status)) {312 if (status == AE_ALREADY_EXISTS) {313 314 /* The name already exists in this scope */315 316 if (node->flags & ANOBJ_IS_EXTERNAL) {317 /*318 * Allow one create on an object or segment that was319 * previously declared External320 */321 node->flags &= ~ANOBJ_IS_EXTERNAL;322 node->type = (u8) object_type;323 324 /* Just retyped a node, probably will need to open a scope */325 326 if (acpi_ns_opens_scope(object_type)) {327 status =328 acpi_ds_scope_stack_push329 (node, object_type,330 walk_state);331 if (ACPI_FAILURE(status)) {332 return_ACPI_STATUS333 (status);334 }335 }336 337 status = AE_OK;338 }339 }340 341 if (ACPI_FAILURE(status)) {342 ACPI_ERROR_NAMESPACE(walk_state->scope_info,343 path, status);344 return_ACPI_STATUS(status);345 }346 }347 break;348 }349 350 /* Common exit */351 352 if (!op) {353 354 /* Create a new op */355 356 op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml);357 if (!op) {358 return_ACPI_STATUS(AE_NO_MEMORY);359 }360 }361 362 /* Initialize the op */363 364#ifdef ACPI_CONSTANT_EVAL_ONLY365 op->named.path = path;366#endif367 368 if (node) {369 /*370 * Put the Node in the "op" object that the parser uses, so we371 * can get it again quickly when this scope is closed372 */373 op->common.node = node;374 op->named.name = node->name.integer;375 }376 377 acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),378 op);379 *out_op = op;380 return_ACPI_STATUS(status);381}382 383/*******************************************************************************384 *385 * FUNCTION: acpi_ds_load1_end_op386 *387 * PARAMETERS: walk_state - Current state of the parse tree walk388 *389 * RETURN: Status390 *391 * DESCRIPTION: Ascending callback used during the loading of the namespace,392 * both control methods and everything else.393 *394 ******************************************************************************/395 396acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)397{398 union acpi_parse_object *op;399 acpi_object_type object_type;400 acpi_status status = AE_OK;401#ifdef ACPI_ASL_COMPILER402 u8 param_count;403#endif404 405 ACPI_FUNCTION_TRACE(ds_load1_end_op);406 407 op = walk_state->op;408 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,409 walk_state));410 411 /*412 * Disassembler: handle create field operators here.413 *414 * create_buffer_field is a deferred op that is typically processed in load415 * pass 2. However, disassembly of control method contents walk the parse416 * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed417 * in a later walk. This is a problem when there is a control method that418 * has the same name as the AML_CREATE object. In this case, any use of the419 * name segment will be detected as a method call rather than a reference420 * to a buffer field.421 *422 * This earlier creation during disassembly solves this issue by inserting423 * the named object in the ACPI namespace so that references to this name424 * would be a name string rather than a method call.425 */426 if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) &&427 (walk_state->op_info->flags & AML_CREATE)) {428 status = acpi_ds_create_buffer_field(op, walk_state);429 return_ACPI_STATUS(status);430 }431 432 /* We are only interested in opcodes that have an associated name */433 434 if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {435 return_ACPI_STATUS(AE_OK);436 }437 438 /* Get the object type to determine if we should pop the scope */439 440 object_type = walk_state->op_info->object_type;441 442 if (walk_state->op_info->flags & AML_FIELD) {443 /*444 * If we are executing a method, do not create any namespace objects445 * during the load phase, only during execution.446 */447 if (!walk_state->method_node) {448 if (walk_state->opcode == AML_FIELD_OP ||449 walk_state->opcode == AML_BANK_FIELD_OP ||450 walk_state->opcode == AML_INDEX_FIELD_OP) {451 status =452 acpi_ds_init_field_objects(op, walk_state);453 }454 }455 return_ACPI_STATUS(status);456 }457 458 /*459 * If we are executing a method, do not create any namespace objects460 * during the load phase, only during execution.461 */462 if (!walk_state->method_node) {463 if (op->common.aml_opcode == AML_REGION_OP) {464 status =465 acpi_ex_create_region(op->named.data,466 op->named.length,467 (acpi_adr_space_type)468 ((op->common.value.arg)->469 common.value.integer),470 walk_state);471 if (ACPI_FAILURE(status)) {472 return_ACPI_STATUS(status);473 }474 } else if (op->common.aml_opcode == AML_DATA_REGION_OP) {475 status =476 acpi_ex_create_region(op->named.data,477 op->named.length,478 ACPI_ADR_SPACE_DATA_TABLE,479 walk_state);480 if (ACPI_FAILURE(status)) {481 return_ACPI_STATUS(status);482 }483 }484 }485 486 if (op->common.aml_opcode == AML_NAME_OP) {487 488 /* For Name opcode, get the object type from the argument */489 490 if (op->common.value.arg) {491 object_type = (acpi_ps_get_opcode_info((op->common.492 value.arg)->493 common.494 aml_opcode))->495 object_type;496 497 /* Set node type if we have a namespace node */498 499 if (op->common.node) {500 op->common.node->type = (u8) object_type;501 }502 }503 }504#ifdef ACPI_ASL_COMPILER505 /*506 * For external opcode, get the object type from the argument and507 * get the parameter count from the argument's next.508 */509 if (acpi_gbl_disasm_flag &&510 op->common.node && op->common.aml_opcode == AML_EXTERNAL_OP) {511 /*512 * Note, if this external is not a method513 * Op->Common.Value.Arg->Common.Next->Common.Value.Integer == 0514 * Therefore, param_count will be 0.515 */516 param_count =517 (u8)op->common.value.arg->common.next->common.value.integer;518 object_type = (u8)op->common.value.arg->common.value.integer;519 op->common.node->flags |= ANOBJ_IS_EXTERNAL;520 op->common.node->type = (u8)object_type;521 522 acpi_dm_create_subobject_for_external((u8)object_type,523 &op->common.node,524 param_count);525 526 /*527 * Add the external to the external list because we may be528 * emitting code based off of the items within the external list.529 */530 acpi_dm_add_op_to_external_list(op, op->named.path,531 (u8)object_type, param_count,532 ACPI_EXT_ORIGIN_FROM_OPCODE |533 ACPI_EXT_RESOLVED_REFERENCE);534 }535#endif536 537 /*538 * If we are executing a method, do not create any namespace objects539 * during the load phase, only during execution.540 */541 if (!walk_state->method_node) {542 if (op->common.aml_opcode == AML_METHOD_OP) {543 /*544 * method_op pkg_length name_string method_flags term_list545 *546 * Note: We must create the method node/object pair as soon as we547 * see the method declaration. This allows later pass1 parsing548 * of invocations of the method (need to know the number of549 * arguments.)550 */551 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,552 "LOADING-Method: State=%p Op=%p NamedObj=%p\n",553 walk_state, op, op->named.node));554 555 if (!acpi_ns_get_attached_object(op->named.node)) {556 walk_state->operands[0] =557 ACPI_CAST_PTR(void, op->named.node);558 walk_state->num_operands = 1;559 560 status =561 acpi_ds_create_operands(walk_state,562 op->common.value.563 arg);564 if (ACPI_SUCCESS(status)) {565 status =566 acpi_ex_create_method(op->named.567 data,568 op->named.569 length,570 walk_state);571 }572 573 walk_state->operands[0] = NULL;574 walk_state->num_operands = 0;575 576 if (ACPI_FAILURE(status)) {577 return_ACPI_STATUS(status);578 }579 }580 }581 }582 583 /* Pop the scope stack (only if loading a table) */584 585 if (!walk_state->method_node &&586 op->common.aml_opcode != AML_EXTERNAL_OP &&587 acpi_ns_opens_scope(object_type)) {588 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,589 "(%s): Popping scope for Op %p\n",590 acpi_ut_get_type_name(object_type), op));591 592 status = acpi_ds_scope_stack_pop(walk_state);593 }594 595 return_ACPI_STATUS(status);596}597