162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: dswload - Dispatcher first pass namespace load callbacks 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <acpi/acpi.h> 1162306a36Sopenharmony_ci#include "accommon.h" 1262306a36Sopenharmony_ci#include "acparser.h" 1362306a36Sopenharmony_ci#include "amlcode.h" 1462306a36Sopenharmony_ci#include "acdispat.h" 1562306a36Sopenharmony_ci#include "acinterp.h" 1662306a36Sopenharmony_ci#include "acnamesp.h" 1762306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 1862306a36Sopenharmony_ci#include "acdisasm.h" 1962306a36Sopenharmony_ci#endif 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define _COMPONENT ACPI_DISPATCHER 2262306a36Sopenharmony_ciACPI_MODULE_NAME("dswload") 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/******************************************************************************* 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * FUNCTION: acpi_ds_init_callbacks 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * PARAMETERS: walk_state - Current state of the parse tree walk 2962306a36Sopenharmony_ci * pass_number - 1, 2, or 3 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * RETURN: Status 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci * DESCRIPTION: Init walk state callbacks 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci ******************************************************************************/ 3662306a36Sopenharmony_ciacpi_status 3762306a36Sopenharmony_ciacpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci switch (pass_number) { 4162306a36Sopenharmony_ci case 0: 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci /* Parse only - caller will setup callbacks */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | 4662306a36Sopenharmony_ci ACPI_PARSE_DELETE_TREE | ACPI_PARSE_DISASSEMBLE; 4762306a36Sopenharmony_ci walk_state->descending_callback = NULL; 4862306a36Sopenharmony_ci walk_state->ascending_callback = NULL; 4962306a36Sopenharmony_ci break; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci case 1: 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci /* Load pass 1 */ 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | 5662306a36Sopenharmony_ci ACPI_PARSE_DELETE_TREE; 5762306a36Sopenharmony_ci walk_state->descending_callback = acpi_ds_load1_begin_op; 5862306a36Sopenharmony_ci walk_state->ascending_callback = acpi_ds_load1_end_op; 5962306a36Sopenharmony_ci break; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci case 2: 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci /* Load pass 2 */ 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | 6662306a36Sopenharmony_ci ACPI_PARSE_DELETE_TREE; 6762306a36Sopenharmony_ci walk_state->descending_callback = acpi_ds_load2_begin_op; 6862306a36Sopenharmony_ci walk_state->ascending_callback = acpi_ds_load2_end_op; 6962306a36Sopenharmony_ci break; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci case 3: 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci /* Execution pass */ 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci walk_state->parse_flags |= ACPI_PARSE_EXECUTE | 7662306a36Sopenharmony_ci ACPI_PARSE_DELETE_TREE; 7762306a36Sopenharmony_ci walk_state->descending_callback = acpi_ds_exec_begin_op; 7862306a36Sopenharmony_ci walk_state->ascending_callback = acpi_ds_exec_end_op; 7962306a36Sopenharmony_ci break; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci default: 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci return (AE_BAD_PARAMETER); 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci return (AE_OK); 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/******************************************************************************* 9062306a36Sopenharmony_ci * 9162306a36Sopenharmony_ci * FUNCTION: acpi_ds_load1_begin_op 9262306a36Sopenharmony_ci * 9362306a36Sopenharmony_ci * PARAMETERS: walk_state - Current state of the parse tree walk 9462306a36Sopenharmony_ci * out_op - Where to return op if a new one is created 9562306a36Sopenharmony_ci * 9662306a36Sopenharmony_ci * RETURN: Status 9762306a36Sopenharmony_ci * 9862306a36Sopenharmony_ci * DESCRIPTION: Descending callback used during the loading of ACPI tables. 9962306a36Sopenharmony_ci * 10062306a36Sopenharmony_ci ******************************************************************************/ 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ciacpi_status 10362306a36Sopenharmony_ciacpi_ds_load1_begin_op(struct acpi_walk_state *walk_state, 10462306a36Sopenharmony_ci union acpi_parse_object **out_op) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci union acpi_parse_object *op; 10762306a36Sopenharmony_ci struct acpi_namespace_node *node; 10862306a36Sopenharmony_ci acpi_status status; 10962306a36Sopenharmony_ci acpi_object_type object_type; 11062306a36Sopenharmony_ci char *path; 11162306a36Sopenharmony_ci u32 flags; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ds_load1_begin_op, walk_state->op); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci op = walk_state->op; 11662306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, 11762306a36Sopenharmony_ci walk_state)); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci /* We are only interested in opcodes that have an associated name */ 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if (op) { 12262306a36Sopenharmony_ci if (!(walk_state->op_info->flags & AML_NAMED)) { 12362306a36Sopenharmony_ci *out_op = op; 12462306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci /* Check if this object has already been installed in the namespace */ 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci if (op->common.node) { 13062306a36Sopenharmony_ci *out_op = op; 13162306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci path = acpi_ps_get_next_namestring(&walk_state->parser_state); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* Map the raw opcode into an internal object type */ 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci object_type = walk_state->op_info->object_type; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 14262306a36Sopenharmony_ci "State=%p Op=%p [%s]\n", walk_state, op, 14362306a36Sopenharmony_ci acpi_ut_get_type_name(object_type))); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci switch (walk_state->opcode) { 14662306a36Sopenharmony_ci case AML_SCOPE_OP: 14762306a36Sopenharmony_ci /* 14862306a36Sopenharmony_ci * The target name of the Scope() operator must exist at this point so 14962306a36Sopenharmony_ci * that we can actually open the scope to enter new names underneath it. 15062306a36Sopenharmony_ci * Allow search-to-root for single namesegs. 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_ci status = 15362306a36Sopenharmony_ci acpi_ns_lookup(walk_state->scope_info, path, object_type, 15462306a36Sopenharmony_ci ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 15562306a36Sopenharmony_ci walk_state, &(node)); 15662306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 15762306a36Sopenharmony_ci if (status == AE_NOT_FOUND) { 15862306a36Sopenharmony_ci /* 15962306a36Sopenharmony_ci * Table disassembly: 16062306a36Sopenharmony_ci * Target of Scope() not found. Generate an External for it, and 16162306a36Sopenharmony_ci * insert the name into the namespace. 16262306a36Sopenharmony_ci */ 16362306a36Sopenharmony_ci acpi_dm_add_op_to_external_list(op, path, 16462306a36Sopenharmony_ci ACPI_TYPE_DEVICE, 0, 0); 16562306a36Sopenharmony_ci status = 16662306a36Sopenharmony_ci acpi_ns_lookup(walk_state->scope_info, path, 16762306a36Sopenharmony_ci object_type, ACPI_IMODE_LOAD_PASS1, 16862306a36Sopenharmony_ci ACPI_NS_SEARCH_PARENT, walk_state, 16962306a36Sopenharmony_ci &node); 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci#endif 17262306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 17362306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state->scope_info, path, 17462306a36Sopenharmony_ci status); 17562306a36Sopenharmony_ci return_ACPI_STATUS(status); 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci /* 17962306a36Sopenharmony_ci * Check to make sure that the target is 18062306a36Sopenharmony_ci * one of the opcodes that actually opens a scope 18162306a36Sopenharmony_ci */ 18262306a36Sopenharmony_ci switch (node->type) { 18362306a36Sopenharmony_ci case ACPI_TYPE_ANY: 18462306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ 18562306a36Sopenharmony_ci case ACPI_TYPE_DEVICE: 18662306a36Sopenharmony_ci case ACPI_TYPE_POWER: 18762306a36Sopenharmony_ci case ACPI_TYPE_PROCESSOR: 18862306a36Sopenharmony_ci case ACPI_TYPE_THERMAL: 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci /* These are acceptable types */ 19162306a36Sopenharmony_ci break; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 19462306a36Sopenharmony_ci case ACPI_TYPE_STRING: 19562306a36Sopenharmony_ci case ACPI_TYPE_BUFFER: 19662306a36Sopenharmony_ci /* 19762306a36Sopenharmony_ci * These types we will allow, but we will change the type. 19862306a36Sopenharmony_ci * This enables some existing code of the form: 19962306a36Sopenharmony_ci * 20062306a36Sopenharmony_ci * Name (DEB, 0) 20162306a36Sopenharmony_ci * Scope (DEB) { ... } 20262306a36Sopenharmony_ci * 20362306a36Sopenharmony_ci * Note: silently change the type here. On the second pass, 20462306a36Sopenharmony_ci * we will report a warning 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_INFO, 20762306a36Sopenharmony_ci "Type override - [%4.4s] had invalid type (%s) " 20862306a36Sopenharmony_ci "for Scope operator, changed to type ANY\n", 20962306a36Sopenharmony_ci acpi_ut_get_node_name(node), 21062306a36Sopenharmony_ci acpi_ut_get_type_name(node->type))); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci node->type = ACPI_TYPE_ANY; 21362306a36Sopenharmony_ci walk_state->scope_info->common.value = ACPI_TYPE_ANY; 21462306a36Sopenharmony_ci break; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci case ACPI_TYPE_METHOD: 21762306a36Sopenharmony_ci /* 21862306a36Sopenharmony_ci * Allow scope change to root during execution of module-level 21962306a36Sopenharmony_ci * code. Root is typed METHOD during this time. 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ci if ((node == acpi_gbl_root_node) && 22262306a36Sopenharmony_ci (walk_state-> 22362306a36Sopenharmony_ci parse_flags & ACPI_PARSE_MODULE_LEVEL)) { 22462306a36Sopenharmony_ci break; 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci ACPI_FALLTHROUGH; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci default: 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci /* All other types are an error */ 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 23462306a36Sopenharmony_ci "Invalid type (%s) for target of " 23562306a36Sopenharmony_ci "Scope operator [%4.4s] (Cannot override)", 23662306a36Sopenharmony_ci acpi_ut_get_type_name(node->type), 23762306a36Sopenharmony_ci acpi_ut_get_node_name(node))); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci break; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci default: 24462306a36Sopenharmony_ci /* 24562306a36Sopenharmony_ci * For all other named opcodes, we will enter the name into 24662306a36Sopenharmony_ci * the namespace. 24762306a36Sopenharmony_ci * 24862306a36Sopenharmony_ci * Setup the search flags. 24962306a36Sopenharmony_ci * Since we are entering a name into the namespace, we do not want to 25062306a36Sopenharmony_ci * enable the search-to-root upsearch. 25162306a36Sopenharmony_ci * 25262306a36Sopenharmony_ci * There are only two conditions where it is acceptable that the name 25362306a36Sopenharmony_ci * already exists: 25462306a36Sopenharmony_ci * 1) the Scope() operator can reopen a scoping object that was 25562306a36Sopenharmony_ci * previously defined (Scope, Method, Device, etc.) 25662306a36Sopenharmony_ci * 2) Whenever we are parsing a deferred opcode (op_region, Buffer, 25762306a36Sopenharmony_ci * buffer_field, or Package), the name of the object is already 25862306a36Sopenharmony_ci * in the namespace. 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ci if (walk_state->deferred_node) { 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* This name is already in the namespace, get the node */ 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci node = walk_state->deferred_node; 26562306a36Sopenharmony_ci status = AE_OK; 26662306a36Sopenharmony_ci break; 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* 27062306a36Sopenharmony_ci * If we are executing a method, do not create any namespace objects 27162306a36Sopenharmony_ci * during the load phase, only during execution. 27262306a36Sopenharmony_ci */ 27362306a36Sopenharmony_ci if (walk_state->method_node) { 27462306a36Sopenharmony_ci node = NULL; 27562306a36Sopenharmony_ci status = AE_OK; 27662306a36Sopenharmony_ci break; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci flags = ACPI_NS_NO_UPSEARCH; 28062306a36Sopenharmony_ci if ((walk_state->opcode != AML_SCOPE_OP) && 28162306a36Sopenharmony_ci (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) { 28262306a36Sopenharmony_ci if (walk_state->namespace_override) { 28362306a36Sopenharmony_ci flags |= ACPI_NS_OVERRIDE_IF_FOUND; 28462306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 28562306a36Sopenharmony_ci "[%s] Override allowed\n", 28662306a36Sopenharmony_ci acpi_ut_get_type_name 28762306a36Sopenharmony_ci (object_type))); 28862306a36Sopenharmony_ci } else { 28962306a36Sopenharmony_ci flags |= ACPI_NS_ERROR_IF_FOUND; 29062306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 29162306a36Sopenharmony_ci "[%s] Cannot already exist\n", 29262306a36Sopenharmony_ci acpi_ut_get_type_name 29362306a36Sopenharmony_ci (object_type))); 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci } else { 29662306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 29762306a36Sopenharmony_ci "[%s] Both Find or Create allowed\n", 29862306a36Sopenharmony_ci acpi_ut_get_type_name(object_type))); 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci /* 30262306a36Sopenharmony_ci * Enter the named type into the internal namespace. We enter the name 30362306a36Sopenharmony_ci * as we go downward in the parse tree. Any necessary subobjects that 30462306a36Sopenharmony_ci * involve arguments to the opcode must be created as we go back up the 30562306a36Sopenharmony_ci * parse tree later. 30662306a36Sopenharmony_ci */ 30762306a36Sopenharmony_ci status = 30862306a36Sopenharmony_ci acpi_ns_lookup(walk_state->scope_info, path, object_type, 30962306a36Sopenharmony_ci ACPI_IMODE_LOAD_PASS1, flags, walk_state, 31062306a36Sopenharmony_ci &node); 31162306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 31262306a36Sopenharmony_ci if (status == AE_ALREADY_EXISTS) { 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci /* The name already exists in this scope */ 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (node->flags & ANOBJ_IS_EXTERNAL) { 31762306a36Sopenharmony_ci /* 31862306a36Sopenharmony_ci * Allow one create on an object or segment that was 31962306a36Sopenharmony_ci * previously declared External 32062306a36Sopenharmony_ci */ 32162306a36Sopenharmony_ci node->flags &= ~ANOBJ_IS_EXTERNAL; 32262306a36Sopenharmony_ci node->type = (u8) object_type; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci /* Just retyped a node, probably will need to open a scope */ 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (acpi_ns_opens_scope(object_type)) { 32762306a36Sopenharmony_ci status = 32862306a36Sopenharmony_ci acpi_ds_scope_stack_push 32962306a36Sopenharmony_ci (node, object_type, 33062306a36Sopenharmony_ci walk_state); 33162306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 33262306a36Sopenharmony_ci return_ACPI_STATUS 33362306a36Sopenharmony_ci (status); 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci status = AE_OK; 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 34262306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state->scope_info, 34362306a36Sopenharmony_ci path, status); 34462306a36Sopenharmony_ci return_ACPI_STATUS(status); 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci break; 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci /* Common exit */ 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci if (!op) { 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci /* Create a new op */ 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml); 35762306a36Sopenharmony_ci if (!op) { 35862306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci /* Initialize the op */ 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci#ifdef ACPI_CONSTANT_EVAL_ONLY 36562306a36Sopenharmony_ci op->named.path = path; 36662306a36Sopenharmony_ci#endif 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci if (node) { 36962306a36Sopenharmony_ci /* 37062306a36Sopenharmony_ci * Put the Node in the "op" object that the parser uses, so we 37162306a36Sopenharmony_ci * can get it again quickly when this scope is closed 37262306a36Sopenharmony_ci */ 37362306a36Sopenharmony_ci op->common.node = node; 37462306a36Sopenharmony_ci op->named.name = node->name.integer; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state), 37862306a36Sopenharmony_ci op); 37962306a36Sopenharmony_ci *out_op = op; 38062306a36Sopenharmony_ci return_ACPI_STATUS(status); 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci/******************************************************************************* 38462306a36Sopenharmony_ci * 38562306a36Sopenharmony_ci * FUNCTION: acpi_ds_load1_end_op 38662306a36Sopenharmony_ci * 38762306a36Sopenharmony_ci * PARAMETERS: walk_state - Current state of the parse tree walk 38862306a36Sopenharmony_ci * 38962306a36Sopenharmony_ci * RETURN: Status 39062306a36Sopenharmony_ci * 39162306a36Sopenharmony_ci * DESCRIPTION: Ascending callback used during the loading of the namespace, 39262306a36Sopenharmony_ci * both control methods and everything else. 39362306a36Sopenharmony_ci * 39462306a36Sopenharmony_ci ******************************************************************************/ 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ciacpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci union acpi_parse_object *op; 39962306a36Sopenharmony_ci acpi_object_type object_type; 40062306a36Sopenharmony_ci acpi_status status = AE_OK; 40162306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 40262306a36Sopenharmony_ci u8 param_count; 40362306a36Sopenharmony_ci#endif 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ds_load1_end_op); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci op = walk_state->op; 40862306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, 40962306a36Sopenharmony_ci walk_state)); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci /* 41262306a36Sopenharmony_ci * Disassembler: handle create field operators here. 41362306a36Sopenharmony_ci * 41462306a36Sopenharmony_ci * create_buffer_field is a deferred op that is typically processed in load 41562306a36Sopenharmony_ci * pass 2. However, disassembly of control method contents walk the parse 41662306a36Sopenharmony_ci * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed 41762306a36Sopenharmony_ci * in a later walk. This is a problem when there is a control method that 41862306a36Sopenharmony_ci * has the same name as the AML_CREATE object. In this case, any use of the 41962306a36Sopenharmony_ci * name segment will be detected as a method call rather than a reference 42062306a36Sopenharmony_ci * to a buffer field. 42162306a36Sopenharmony_ci * 42262306a36Sopenharmony_ci * This earlier creation during disassembly solves this issue by inserting 42362306a36Sopenharmony_ci * the named object in the ACPI namespace so that references to this name 42462306a36Sopenharmony_ci * would be a name string rather than a method call. 42562306a36Sopenharmony_ci */ 42662306a36Sopenharmony_ci if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) && 42762306a36Sopenharmony_ci (walk_state->op_info->flags & AML_CREATE)) { 42862306a36Sopenharmony_ci status = acpi_ds_create_buffer_field(op, walk_state); 42962306a36Sopenharmony_ci return_ACPI_STATUS(status); 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci /* We are only interested in opcodes that have an associated name */ 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) { 43562306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 43662306a36Sopenharmony_ci } 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci /* Get the object type to determine if we should pop the scope */ 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci object_type = walk_state->op_info->object_type; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci if (walk_state->op_info->flags & AML_FIELD) { 44362306a36Sopenharmony_ci /* 44462306a36Sopenharmony_ci * If we are executing a method, do not create any namespace objects 44562306a36Sopenharmony_ci * during the load phase, only during execution. 44662306a36Sopenharmony_ci */ 44762306a36Sopenharmony_ci if (!walk_state->method_node) { 44862306a36Sopenharmony_ci if (walk_state->opcode == AML_FIELD_OP || 44962306a36Sopenharmony_ci walk_state->opcode == AML_BANK_FIELD_OP || 45062306a36Sopenharmony_ci walk_state->opcode == AML_INDEX_FIELD_OP) { 45162306a36Sopenharmony_ci status = 45262306a36Sopenharmony_ci acpi_ds_init_field_objects(op, walk_state); 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci return_ACPI_STATUS(status); 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci /* 45962306a36Sopenharmony_ci * If we are executing a method, do not create any namespace objects 46062306a36Sopenharmony_ci * during the load phase, only during execution. 46162306a36Sopenharmony_ci */ 46262306a36Sopenharmony_ci if (!walk_state->method_node) { 46362306a36Sopenharmony_ci if (op->common.aml_opcode == AML_REGION_OP) { 46462306a36Sopenharmony_ci status = 46562306a36Sopenharmony_ci acpi_ex_create_region(op->named.data, 46662306a36Sopenharmony_ci op->named.length, 46762306a36Sopenharmony_ci (acpi_adr_space_type) 46862306a36Sopenharmony_ci ((op->common.value.arg)-> 46962306a36Sopenharmony_ci common.value.integer), 47062306a36Sopenharmony_ci walk_state); 47162306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 47262306a36Sopenharmony_ci return_ACPI_STATUS(status); 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { 47562306a36Sopenharmony_ci status = 47662306a36Sopenharmony_ci acpi_ex_create_region(op->named.data, 47762306a36Sopenharmony_ci op->named.length, 47862306a36Sopenharmony_ci ACPI_ADR_SPACE_DATA_TABLE, 47962306a36Sopenharmony_ci walk_state); 48062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 48162306a36Sopenharmony_ci return_ACPI_STATUS(status); 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci } 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci if (op->common.aml_opcode == AML_NAME_OP) { 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci /* For Name opcode, get the object type from the argument */ 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci if (op->common.value.arg) { 49162306a36Sopenharmony_ci object_type = (acpi_ps_get_opcode_info((op->common. 49262306a36Sopenharmony_ci value.arg)-> 49362306a36Sopenharmony_ci common. 49462306a36Sopenharmony_ci aml_opcode))-> 49562306a36Sopenharmony_ci object_type; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci /* Set node type if we have a namespace node */ 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci if (op->common.node) { 50062306a36Sopenharmony_ci op->common.node->type = (u8) object_type; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 50562306a36Sopenharmony_ci /* 50662306a36Sopenharmony_ci * For external opcode, get the object type from the argument and 50762306a36Sopenharmony_ci * get the parameter count from the argument's next. 50862306a36Sopenharmony_ci */ 50962306a36Sopenharmony_ci if (acpi_gbl_disasm_flag && 51062306a36Sopenharmony_ci op->common.node && op->common.aml_opcode == AML_EXTERNAL_OP) { 51162306a36Sopenharmony_ci /* 51262306a36Sopenharmony_ci * Note, if this external is not a method 51362306a36Sopenharmony_ci * Op->Common.Value.Arg->Common.Next->Common.Value.Integer == 0 51462306a36Sopenharmony_ci * Therefore, param_count will be 0. 51562306a36Sopenharmony_ci */ 51662306a36Sopenharmony_ci param_count = 51762306a36Sopenharmony_ci (u8)op->common.value.arg->common.next->common.value.integer; 51862306a36Sopenharmony_ci object_type = (u8)op->common.value.arg->common.value.integer; 51962306a36Sopenharmony_ci op->common.node->flags |= ANOBJ_IS_EXTERNAL; 52062306a36Sopenharmony_ci op->common.node->type = (u8)object_type; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci acpi_dm_create_subobject_for_external((u8)object_type, 52362306a36Sopenharmony_ci &op->common.node, 52462306a36Sopenharmony_ci param_count); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* 52762306a36Sopenharmony_ci * Add the external to the external list because we may be 52862306a36Sopenharmony_ci * emitting code based off of the items within the external list. 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_ci acpi_dm_add_op_to_external_list(op, op->named.path, 53162306a36Sopenharmony_ci (u8)object_type, param_count, 53262306a36Sopenharmony_ci ACPI_EXT_ORIGIN_FROM_OPCODE | 53362306a36Sopenharmony_ci ACPI_EXT_RESOLVED_REFERENCE); 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci#endif 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci /* 53862306a36Sopenharmony_ci * If we are executing a method, do not create any namespace objects 53962306a36Sopenharmony_ci * during the load phase, only during execution. 54062306a36Sopenharmony_ci */ 54162306a36Sopenharmony_ci if (!walk_state->method_node) { 54262306a36Sopenharmony_ci if (op->common.aml_opcode == AML_METHOD_OP) { 54362306a36Sopenharmony_ci /* 54462306a36Sopenharmony_ci * method_op pkg_length name_string method_flags term_list 54562306a36Sopenharmony_ci * 54662306a36Sopenharmony_ci * Note: We must create the method node/object pair as soon as we 54762306a36Sopenharmony_ci * see the method declaration. This allows later pass1 parsing 54862306a36Sopenharmony_ci * of invocations of the method (need to know the number of 54962306a36Sopenharmony_ci * arguments.) 55062306a36Sopenharmony_ci */ 55162306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 55262306a36Sopenharmony_ci "LOADING-Method: State=%p Op=%p NamedObj=%p\n", 55362306a36Sopenharmony_ci walk_state, op, op->named.node)); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci if (!acpi_ns_get_attached_object(op->named.node)) { 55662306a36Sopenharmony_ci walk_state->operands[0] = 55762306a36Sopenharmony_ci ACPI_CAST_PTR(void, op->named.node); 55862306a36Sopenharmony_ci walk_state->num_operands = 1; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci status = 56162306a36Sopenharmony_ci acpi_ds_create_operands(walk_state, 56262306a36Sopenharmony_ci op->common.value. 56362306a36Sopenharmony_ci arg); 56462306a36Sopenharmony_ci if (ACPI_SUCCESS(status)) { 56562306a36Sopenharmony_ci status = 56662306a36Sopenharmony_ci acpi_ex_create_method(op->named. 56762306a36Sopenharmony_ci data, 56862306a36Sopenharmony_ci op->named. 56962306a36Sopenharmony_ci length, 57062306a36Sopenharmony_ci walk_state); 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci walk_state->operands[0] = NULL; 57462306a36Sopenharmony_ci walk_state->num_operands = 0; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 57762306a36Sopenharmony_ci return_ACPI_STATUS(status); 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci } 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci } 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci /* Pop the scope stack (only if loading a table) */ 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci if (!walk_state->method_node && 58662306a36Sopenharmony_ci op->common.aml_opcode != AML_EXTERNAL_OP && 58762306a36Sopenharmony_ci acpi_ns_opens_scope(object_type)) { 58862306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 58962306a36Sopenharmony_ci "(%s): Popping scope for Op %p\n", 59062306a36Sopenharmony_ci acpi_ut_get_type_name(object_type), op)); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci status = acpi_ds_scope_stack_pop(walk_state); 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci return_ACPI_STATUS(status); 59662306a36Sopenharmony_ci} 597