746 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: dswload2 - Dispatcher second 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#include "acevents.h"18#ifdef ACPI_EXEC_APP19#include "aecommon.h"20#endif21 22#define _COMPONENT ACPI_DISPATCHER23ACPI_MODULE_NAME("dswload2")24 25/*******************************************************************************26 *27 * FUNCTION: acpi_ds_load2_begin_op28 *29 * PARAMETERS: walk_state - Current state of the parse tree walk30 * out_op - Where to return op if a new one is created31 *32 * RETURN: Status33 *34 * DESCRIPTION: Descending callback used during the loading of ACPI tables.35 *36 ******************************************************************************/37acpi_status38acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,39 union acpi_parse_object **out_op)40{41 union acpi_parse_object *op;42 struct acpi_namespace_node *node;43 acpi_status status;44 acpi_object_type object_type;45 char *buffer_ptr;46 u32 flags;47 48 ACPI_FUNCTION_TRACE(ds_load2_begin_op);49 50 op = walk_state->op;51 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,52 walk_state));53 54 if (op) {55 if ((walk_state->control_state) &&56 (walk_state->control_state->common.state ==57 ACPI_CONTROL_CONDITIONAL_EXECUTING)) {58 59 /* We are executing a while loop outside of a method */60 61 status = acpi_ds_exec_begin_op(walk_state, out_op);62 return_ACPI_STATUS(status);63 }64 65 /* We only care about Namespace opcodes here */66 67 if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&68 (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||69 (!(walk_state->op_info->flags & AML_NAMED))) {70 return_ACPI_STATUS(AE_OK);71 }72 73 /* Get the name we are going to enter or lookup in the namespace */74 75 if (walk_state->opcode == AML_INT_NAMEPATH_OP) {76 77 /* For Namepath op, get the path string */78 79 buffer_ptr = op->common.value.string;80 if (!buffer_ptr) {81 82 /* No name, just exit */83 84 return_ACPI_STATUS(AE_OK);85 }86 } else {87 /* Get name from the op */88 89 buffer_ptr = ACPI_CAST_PTR(char, &op->named.name);90 }91 } else {92 /* Get the namestring from the raw AML */93 94 buffer_ptr =95 acpi_ps_get_next_namestring(&walk_state->parser_state);96 }97 98 /* Map the opcode into an internal object type */99 100 object_type = walk_state->op_info->object_type;101 102 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,103 "State=%p Op=%p Type=%X\n", walk_state, op,104 object_type));105 106 switch (walk_state->opcode) {107 case AML_FIELD_OP:108 case AML_BANK_FIELD_OP:109 case AML_INDEX_FIELD_OP:110 111 node = NULL;112 status = AE_OK;113 break;114 115 case AML_INT_NAMEPATH_OP:116 /*117 * The name_path is an object reference to an existing object.118 * Don't enter the name into the namespace, but look it up119 * for use later.120 */121 status =122 acpi_ns_lookup(walk_state->scope_info, buffer_ptr,123 object_type, ACPI_IMODE_EXECUTE,124 ACPI_NS_SEARCH_PARENT, walk_state, &(node));125 break;126 127 case AML_SCOPE_OP:128 129 /* Special case for Scope(\) -> refers to the Root node */130 131 if (op && (op->named.node == acpi_gbl_root_node)) {132 node = op->named.node;133 134 status =135 acpi_ds_scope_stack_push(node, object_type,136 walk_state);137 if (ACPI_FAILURE(status)) {138 return_ACPI_STATUS(status);139 }140 } else {141 /*142 * The Path is an object reference to an existing object.143 * Don't enter the name into the namespace, but look it up144 * for use later.145 */146 status =147 acpi_ns_lookup(walk_state->scope_info, buffer_ptr,148 object_type, ACPI_IMODE_EXECUTE,149 ACPI_NS_SEARCH_PARENT, walk_state,150 &(node));151 if (ACPI_FAILURE(status)) {152#ifdef ACPI_ASL_COMPILER153 if (status == AE_NOT_FOUND) {154 status = AE_OK;155 } else {156 ACPI_ERROR_NAMESPACE(walk_state->157 scope_info,158 buffer_ptr,159 status);160 }161#else162 ACPI_ERROR_NAMESPACE(walk_state->scope_info,163 buffer_ptr, status);164#endif165 return_ACPI_STATUS(status);166 }167 }168 169 /*170 * We must check to make sure that the target is171 * one of the opcodes that actually opens a scope172 */173 switch (node->type) {174 case ACPI_TYPE_ANY:175 case ACPI_TYPE_LOCAL_SCOPE: /* Scope */176 case ACPI_TYPE_DEVICE:177 case ACPI_TYPE_POWER:178 case ACPI_TYPE_PROCESSOR:179 case ACPI_TYPE_THERMAL:180 181 /* These are acceptable types */182 break;183 184 case ACPI_TYPE_INTEGER:185 case ACPI_TYPE_STRING:186 case ACPI_TYPE_BUFFER:187 188 /*189 * These types we will allow, but we will change the type.190 * This enables some existing code of the form:191 *192 * Name (DEB, 0)193 * Scope (DEB) { ... }194 */195 ACPI_WARNING((AE_INFO,196 "Type override - [%4.4s] had invalid type (%s) "197 "for Scope operator, changed to type ANY",198 acpi_ut_get_node_name(node),199 acpi_ut_get_type_name(node->type)));200 201 node->type = ACPI_TYPE_ANY;202 walk_state->scope_info->common.value = ACPI_TYPE_ANY;203 break;204 205 case ACPI_TYPE_METHOD:206 207 /*208 * Allow scope change to root during execution of module-level209 * code. Root is typed METHOD during this time.210 */211 if ((node == acpi_gbl_root_node) &&212 (walk_state->213 parse_flags & ACPI_PARSE_MODULE_LEVEL)) {214 break;215 }216 217 ACPI_FALLTHROUGH;218 219 default:220 221 /* All other types are an error */222 223 ACPI_ERROR((AE_INFO,224 "Invalid type (%s) for target of "225 "Scope operator [%4.4s] (Cannot override)",226 acpi_ut_get_type_name(node->type),227 acpi_ut_get_node_name(node)));228 229 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);230 }231 break;232 233 default:234 235 /* All other opcodes */236 237 if (op && op->common.node) {238 239 /* This op/node was previously entered into the namespace */240 241 node = op->common.node;242 243 if (acpi_ns_opens_scope(object_type)) {244 status =245 acpi_ds_scope_stack_push(node, object_type,246 walk_state);247 if (ACPI_FAILURE(status)) {248 return_ACPI_STATUS(status);249 }250 }251 252 return_ACPI_STATUS(AE_OK);253 }254 255 /*256 * Enter the named type into the internal namespace. We enter the name257 * as we go downward in the parse tree. Any necessary subobjects that258 * involve arguments to the opcode must be created as we go back up the259 * parse tree later.260 *261 * Note: Name may already exist if we are executing a deferred opcode.262 */263 if (walk_state->deferred_node) {264 265 /* This name is already in the namespace, get the node */266 267 node = walk_state->deferred_node;268 status = AE_OK;269 break;270 }271 272 flags = ACPI_NS_NO_UPSEARCH;273 if (walk_state->pass_number == ACPI_IMODE_EXECUTE) {274 275 /* Execution mode, node cannot already exist, node is temporary */276 277 flags |= ACPI_NS_ERROR_IF_FOUND;278 279 if (!280 (walk_state->281 parse_flags & ACPI_PARSE_MODULE_LEVEL)) {282 flags |= ACPI_NS_TEMPORARY;283 }284 }285#ifdef ACPI_ASL_COMPILER286 287 /*288 * Do not open a scope for AML_EXTERNAL_OP289 * acpi_ns_lookup can open a new scope based on the object type290 * of this op. AML_EXTERNAL_OP is a declaration rather than a291 * definition. In the case that this external is a method object,292 * acpi_ns_lookup will open a new scope. However, an AML_EXTERNAL_OP293 * associated with the ACPI_TYPE_METHOD is a declaration, rather than294 * a definition. Flags is set to avoid opening a scope for any295 * AML_EXTERNAL_OP.296 */297 if (walk_state->opcode == AML_EXTERNAL_OP) {298 flags |= ACPI_NS_DONT_OPEN_SCOPE;299 }300#endif301 302 /*303 * For name creation opcodes, the full namepath prefix must304 * exist, except for the final (new) nameseg.305 */306 if (walk_state->op_info->flags & AML_NAMED) {307 flags |= ACPI_NS_PREFIX_MUST_EXIST;308 }309 310 /* Add new entry or lookup existing entry */311 312 status =313 acpi_ns_lookup(walk_state->scope_info, buffer_ptr,314 object_type, ACPI_IMODE_LOAD_PASS2, flags,315 walk_state, &node);316 317 if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) {318 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,319 "***New Node [%4.4s] %p is temporary\n",320 acpi_ut_get_node_name(node), node));321 }322 break;323 }324 325 if (ACPI_FAILURE(status)) {326 ACPI_ERROR_NAMESPACE(walk_state->scope_info,327 buffer_ptr, status);328 return_ACPI_STATUS(status);329 }330 331 if (!op) {332 333 /* Create a new op */334 335 op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml);336 if (!op) {337 return_ACPI_STATUS(AE_NO_MEMORY);338 }339 340 /* Initialize the new op */341 342 if (node) {343 op->named.name = node->name.integer;344 }345 *out_op = op;346 }347 348 /*349 * Put the Node in the "op" object that the parser uses, so we350 * can get it again quickly when this scope is closed351 */352 op->common.node = node;353 return_ACPI_STATUS(status);354}355 356/*******************************************************************************357 *358 * FUNCTION: acpi_ds_load2_end_op359 *360 * PARAMETERS: walk_state - Current state of the parse tree walk361 *362 * RETURN: Status363 *364 * DESCRIPTION: Ascending callback used during the loading of the namespace,365 * both control methods and everything else.366 *367 ******************************************************************************/368 369acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)370{371 union acpi_parse_object *op;372 acpi_status status = AE_OK;373 acpi_object_type object_type;374 struct acpi_namespace_node *node;375 union acpi_parse_object *arg;376 struct acpi_namespace_node *new_node;377 u32 i;378 u8 region_space;379#ifdef ACPI_EXEC_APP380 union acpi_operand_object *obj_desc;381 char *namepath;382#endif383 384 ACPI_FUNCTION_TRACE(ds_load2_end_op);385 386 op = walk_state->op;387 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",388 walk_state->op_info->name, op, walk_state));389 390 /* Check if opcode had an associated namespace object */391 392 if (!(walk_state->op_info->flags & AML_NSOBJECT)) {393 return_ACPI_STATUS(AE_OK);394 }395 396 if (op->common.aml_opcode == AML_SCOPE_OP) {397 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,398 "Ending scope Op=%p State=%p\n", op,399 walk_state));400 }401 402 object_type = walk_state->op_info->object_type;403 404 /*405 * Get the Node/name from the earlier lookup406 * (It was saved in the *op structure)407 */408 node = op->common.node;409 410 /*411 * Put the Node on the object stack (Contains the ACPI Name of412 * this object)413 */414 walk_state->operands[0] = (void *)node;415 walk_state->num_operands = 1;416 417 /* Pop the scope stack */418 419 if (acpi_ns_opens_scope(object_type) &&420 (op->common.aml_opcode != AML_INT_METHODCALL_OP)) {421 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,422 "(%s) Popping scope for Op %p\n",423 acpi_ut_get_type_name(object_type), op));424 425 status = acpi_ds_scope_stack_pop(walk_state);426 if (ACPI_FAILURE(status)) {427 goto cleanup;428 }429 }430 431 /*432 * Named operations are as follows:433 *434 * AML_ALIAS435 * AML_BANKFIELD436 * AML_CREATEBITFIELD437 * AML_CREATEBYTEFIELD438 * AML_CREATEDWORDFIELD439 * AML_CREATEFIELD440 * AML_CREATEQWORDFIELD441 * AML_CREATEWORDFIELD442 * AML_DATA_REGION443 * AML_DEVICE444 * AML_EVENT445 * AML_FIELD446 * AML_INDEXFIELD447 * AML_METHOD448 * AML_METHODCALL449 * AML_MUTEX450 * AML_NAME451 * AML_NAMEDFIELD452 * AML_OPREGION453 * AML_POWERRES454 * AML_PROCESSOR455 * AML_SCOPE456 * AML_THERMALZONE457 */458 459 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,460 "Create-Load [%s] State=%p Op=%p NamedObj=%p\n",461 acpi_ps_get_opcode_name(op->common.aml_opcode),462 walk_state, op, node));463 464 /* Decode the opcode */465 466 arg = op->common.value.arg;467 468 switch (walk_state->op_info->type) {469 470 case AML_TYPE_CREATE_FIELD:471 /*472 * Create the field object, but the field buffer and index must473 * be evaluated later during the execution phase474 */475 status = acpi_ds_create_buffer_field(op, walk_state);476 if (ACPI_FAILURE(status)) {477 ACPI_EXCEPTION((AE_INFO, status,478 "CreateBufferField failure"));479 goto cleanup;480 }481 break;482 483 case AML_TYPE_NAMED_FIELD:484 /*485 * If we are executing a method, initialize the field486 */487 if (walk_state->method_node) {488 status = acpi_ds_init_field_objects(op, walk_state);489 }490 491 switch (op->common.aml_opcode) {492 case AML_INDEX_FIELD_OP:493 494 status =495 acpi_ds_create_index_field(op,496 (acpi_handle)arg->common.497 node, walk_state);498 break;499 500 case AML_BANK_FIELD_OP:501 502 status =503 acpi_ds_create_bank_field(op, arg->common.node,504 walk_state);505 break;506 507 case AML_FIELD_OP:508 509 status =510 acpi_ds_create_field(op, arg->common.node,511 walk_state);512 break;513 514 default:515 516 /* All NAMED_FIELD opcodes must be handled above */517 break;518 }519 break;520 521 case AML_TYPE_NAMED_SIMPLE:522 523 status = acpi_ds_create_operands(walk_state, arg);524 if (ACPI_FAILURE(status)) {525 goto cleanup;526 }527 528 switch (op->common.aml_opcode) {529 case AML_PROCESSOR_OP:530 531 status = acpi_ex_create_processor(walk_state);532 break;533 534 case AML_POWER_RESOURCE_OP:535 536 status = acpi_ex_create_power_resource(walk_state);537 break;538 539 case AML_MUTEX_OP:540 541 status = acpi_ex_create_mutex(walk_state);542 break;543 544 case AML_EVENT_OP:545 546 status = acpi_ex_create_event(walk_state);547 break;548 549 case AML_ALIAS_OP:550 551 status = acpi_ex_create_alias(walk_state);552 break;553 554 default:555 556 /* Unknown opcode */557 558 status = AE_OK;559 goto cleanup;560 }561 562 /* Delete operands */563 564 for (i = 1; i < walk_state->num_operands; i++) {565 acpi_ut_remove_reference(walk_state->operands[i]);566 walk_state->operands[i] = NULL;567 }568 569 break;570 571 case AML_TYPE_NAMED_COMPLEX:572 573 switch (op->common.aml_opcode) {574 case AML_REGION_OP:575 case AML_DATA_REGION_OP:576 577 if (op->common.aml_opcode == AML_REGION_OP) {578 region_space = (acpi_adr_space_type)579 ((op->common.value.arg)->common.value.580 integer);581 } else {582 region_space = ACPI_ADR_SPACE_DATA_TABLE;583 }584 585 /*586 * The op_region is not fully parsed at this time. The only valid587 * argument is the space_id. (We must save the address of the588 * AML of the address and length operands)589 *590 * If we have a valid region, initialize it. The namespace is591 * unlocked at this point.592 *593 * Need to unlock interpreter if it is locked (if we are running594 * a control method), in order to allow _REG methods to be run595 * during acpi_ev_initialize_region.596 */597 if (walk_state->method_node) {598 /*599 * Executing a method: initialize the region and unlock600 * the interpreter601 */602 status = acpi_ex_create_region(op->named.data,603 op->named.length,604 region_space,605 walk_state);606 if (ACPI_FAILURE(status)) {607 return_ACPI_STATUS(status);608 }609 }610 611 status =612 acpi_ev_initialize_region613 (acpi_ns_get_attached_object(node));614 break;615 616 case AML_NAME_OP:617 618 status = acpi_ds_create_node(walk_state, node, op);619 if (ACPI_FAILURE(status)) {620 goto cleanup;621 }622#ifdef ACPI_EXEC_APP623 /*624 * acpi_exec support for namespace initialization file (initialize625 * Name opcodes in this code.)626 */627 namepath = acpi_ns_get_external_pathname(node);628 status = ae_lookup_init_file_entry(namepath, &obj_desc);629 if (ACPI_SUCCESS(status)) {630 631 /* Detach any existing object, attach new object */632 633 if (node->object) {634 acpi_ns_detach_object(node);635 }636 acpi_ns_attach_object(node, obj_desc,637 obj_desc->common.type);638 }639 ACPI_FREE(namepath);640 status = AE_OK;641#endif642 break;643 644 case AML_METHOD_OP:645 /*646 * method_op pkg_length name_string method_flags term_list647 *648 * Note: We must create the method node/object pair as soon as we649 * see the method declaration. This allows later pass1 parsing650 * of invocations of the method (need to know the number of651 * arguments.)652 */653 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,654 "LOADING-Method: State=%p Op=%p NamedObj=%p\n",655 walk_state, op, op->named.node));656 657 if (!acpi_ns_get_attached_object(op->named.node)) {658 walk_state->operands[0] =659 ACPI_CAST_PTR(void, op->named.node);660 walk_state->num_operands = 1;661 662 status =663 acpi_ds_create_operands(walk_state,664 op->common.value.665 arg);666 if (ACPI_SUCCESS(status)) {667 status =668 acpi_ex_create_method(op->named.669 data,670 op->named.671 length,672 walk_state);673 }674 675 walk_state->operands[0] = NULL;676 walk_state->num_operands = 0;677 678 if (ACPI_FAILURE(status)) {679 return_ACPI_STATUS(status);680 }681 }682 break;683 684 default:685 686 /* All NAMED_COMPLEX opcodes must be handled above */687 break;688 }689 break;690 691 case AML_CLASS_INTERNAL:692 693 /* case AML_INT_NAMEPATH_OP: */694 break;695 696 case AML_CLASS_METHOD_CALL:697 698 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,699 "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n",700 walk_state, op, node));701 702 /*703 * Lookup the method name and save the Node704 */705 status =706 acpi_ns_lookup(walk_state->scope_info,707 arg->common.value.string, ACPI_TYPE_ANY,708 ACPI_IMODE_LOAD_PASS2,709 ACPI_NS_SEARCH_PARENT |710 ACPI_NS_DONT_OPEN_SCOPE, walk_state,711 &(new_node));712 if (ACPI_SUCCESS(status)) {713 /*714 * Make sure that what we found is indeed a method715 * We didn't search for a method on purpose, to see if the name716 * would resolve717 */718 if (new_node->type != ACPI_TYPE_METHOD) {719 status = AE_AML_OPERAND_TYPE;720 }721 722 /* We could put the returned object (Node) on the object stack for723 * later, but for now, we will put it in the "op" object that the724 * parser uses, so we can get it again at the end of this scope725 */726 op->common.node = new_node;727 } else {728 ACPI_ERROR_NAMESPACE(walk_state->scope_info,729 arg->common.value.string, status);730 }731 break;732 733 default:734 735 break;736 }737 738cleanup:739 740 /* Remove the Node pushed at the very beginning */741 742 walk_state->operands[0] = NULL;743 walk_state->num_operands = 0;744 return_ACPI_STATUS(status);745}746