162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
262306a36Sopenharmony_ci/******************************************************************************
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Module Name: dswload2 - Dispatcher second 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#include "acevents.h"
1862306a36Sopenharmony_ci#ifdef ACPI_EXEC_APP
1962306a36Sopenharmony_ci#include "aecommon.h"
2062306a36Sopenharmony_ci#endif
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define _COMPONENT          ACPI_DISPATCHER
2362306a36Sopenharmony_ciACPI_MODULE_NAME("dswload2")
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/*******************************************************************************
2662306a36Sopenharmony_ci *
2762306a36Sopenharmony_ci * FUNCTION:    acpi_ds_load2_begin_op
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci * PARAMETERS:  walk_state      - Current state of the parse tree walk
3062306a36Sopenharmony_ci *              out_op          - Where to return op if a new one is created
3162306a36Sopenharmony_ci *
3262306a36Sopenharmony_ci * RETURN:      Status
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * DESCRIPTION: Descending callback used during the loading of ACPI tables.
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci ******************************************************************************/
3762306a36Sopenharmony_ciacpi_status
3862306a36Sopenharmony_ciacpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
3962306a36Sopenharmony_ci		       union acpi_parse_object **out_op)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	union acpi_parse_object *op;
4262306a36Sopenharmony_ci	struct acpi_namespace_node *node;
4362306a36Sopenharmony_ci	acpi_status status;
4462306a36Sopenharmony_ci	acpi_object_type object_type;
4562306a36Sopenharmony_ci	char *buffer_ptr;
4662306a36Sopenharmony_ci	u32 flags;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ds_load2_begin_op);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	op = walk_state->op;
5162306a36Sopenharmony_ci	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
5262306a36Sopenharmony_ci			  walk_state));
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	if (op) {
5562306a36Sopenharmony_ci		if ((walk_state->control_state) &&
5662306a36Sopenharmony_ci		    (walk_state->control_state->common.state ==
5762306a36Sopenharmony_ci		     ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci			/* We are executing a while loop outside of a method */
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci			status = acpi_ds_exec_begin_op(walk_state, out_op);
6262306a36Sopenharmony_ci			return_ACPI_STATUS(status);
6362306a36Sopenharmony_ci		}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci		/* We only care about Namespace opcodes here */
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci		if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
6862306a36Sopenharmony_ci		     (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
6962306a36Sopenharmony_ci		    (!(walk_state->op_info->flags & AML_NAMED))) {
7062306a36Sopenharmony_ci			return_ACPI_STATUS(AE_OK);
7162306a36Sopenharmony_ci		}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci		/* Get the name we are going to enter or lookup in the namespace */
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci		if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci			/* For Namepath op, get the path string */
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci			buffer_ptr = op->common.value.string;
8062306a36Sopenharmony_ci			if (!buffer_ptr) {
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci				/* No name, just exit */
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci				return_ACPI_STATUS(AE_OK);
8562306a36Sopenharmony_ci			}
8662306a36Sopenharmony_ci		} else {
8762306a36Sopenharmony_ci			/* Get name from the op */
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci			buffer_ptr = ACPI_CAST_PTR(char, &op->named.name);
9062306a36Sopenharmony_ci		}
9162306a36Sopenharmony_ci	} else {
9262306a36Sopenharmony_ci		/* Get the namestring from the raw AML */
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci		buffer_ptr =
9562306a36Sopenharmony_ci		    acpi_ps_get_next_namestring(&walk_state->parser_state);
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	/* Map the opcode into an internal object type */
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	object_type = walk_state->op_info->object_type;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
10362306a36Sopenharmony_ci			  "State=%p Op=%p Type=%X\n", walk_state, op,
10462306a36Sopenharmony_ci			  object_type));
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	switch (walk_state->opcode) {
10762306a36Sopenharmony_ci	case AML_FIELD_OP:
10862306a36Sopenharmony_ci	case AML_BANK_FIELD_OP:
10962306a36Sopenharmony_ci	case AML_INDEX_FIELD_OP:
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		node = NULL;
11262306a36Sopenharmony_ci		status = AE_OK;
11362306a36Sopenharmony_ci		break;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	case AML_INT_NAMEPATH_OP:
11662306a36Sopenharmony_ci		/*
11762306a36Sopenharmony_ci		 * The name_path is an object reference to an existing object.
11862306a36Sopenharmony_ci		 * Don't enter the name into the namespace, but look it up
11962306a36Sopenharmony_ci		 * for use later.
12062306a36Sopenharmony_ci		 */
12162306a36Sopenharmony_ci		status =
12262306a36Sopenharmony_ci		    acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
12362306a36Sopenharmony_ci				   object_type, ACPI_IMODE_EXECUTE,
12462306a36Sopenharmony_ci				   ACPI_NS_SEARCH_PARENT, walk_state, &(node));
12562306a36Sopenharmony_ci		break;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	case AML_SCOPE_OP:
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci		/* Special case for Scope(\) -> refers to the Root node */
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci		if (op && (op->named.node == acpi_gbl_root_node)) {
13262306a36Sopenharmony_ci			node = op->named.node;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci			status =
13562306a36Sopenharmony_ci			    acpi_ds_scope_stack_push(node, object_type,
13662306a36Sopenharmony_ci						     walk_state);
13762306a36Sopenharmony_ci			if (ACPI_FAILURE(status)) {
13862306a36Sopenharmony_ci				return_ACPI_STATUS(status);
13962306a36Sopenharmony_ci			}
14062306a36Sopenharmony_ci		} else {
14162306a36Sopenharmony_ci			/*
14262306a36Sopenharmony_ci			 * The Path is an object reference to an existing object.
14362306a36Sopenharmony_ci			 * Don't enter the name into the namespace, but look it up
14462306a36Sopenharmony_ci			 * for use later.
14562306a36Sopenharmony_ci			 */
14662306a36Sopenharmony_ci			status =
14762306a36Sopenharmony_ci			    acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
14862306a36Sopenharmony_ci					   object_type, ACPI_IMODE_EXECUTE,
14962306a36Sopenharmony_ci					   ACPI_NS_SEARCH_PARENT, walk_state,
15062306a36Sopenharmony_ci					   &(node));
15162306a36Sopenharmony_ci			if (ACPI_FAILURE(status)) {
15262306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER
15362306a36Sopenharmony_ci				if (status == AE_NOT_FOUND) {
15462306a36Sopenharmony_ci					status = AE_OK;
15562306a36Sopenharmony_ci				} else {
15662306a36Sopenharmony_ci					ACPI_ERROR_NAMESPACE(walk_state->
15762306a36Sopenharmony_ci							     scope_info,
15862306a36Sopenharmony_ci							     buffer_ptr,
15962306a36Sopenharmony_ci							     status);
16062306a36Sopenharmony_ci				}
16162306a36Sopenharmony_ci#else
16262306a36Sopenharmony_ci				ACPI_ERROR_NAMESPACE(walk_state->scope_info,
16362306a36Sopenharmony_ci						     buffer_ptr, status);
16462306a36Sopenharmony_ci#endif
16562306a36Sopenharmony_ci				return_ACPI_STATUS(status);
16662306a36Sopenharmony_ci			}
16762306a36Sopenharmony_ci		}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci		/*
17062306a36Sopenharmony_ci		 * We must check to make sure that the target is
17162306a36Sopenharmony_ci		 * one of the opcodes that actually opens a scope
17262306a36Sopenharmony_ci		 */
17362306a36Sopenharmony_ci		switch (node->type) {
17462306a36Sopenharmony_ci		case ACPI_TYPE_ANY:
17562306a36Sopenharmony_ci		case ACPI_TYPE_LOCAL_SCOPE:	/* Scope */
17662306a36Sopenharmony_ci		case ACPI_TYPE_DEVICE:
17762306a36Sopenharmony_ci		case ACPI_TYPE_POWER:
17862306a36Sopenharmony_ci		case ACPI_TYPE_PROCESSOR:
17962306a36Sopenharmony_ci		case ACPI_TYPE_THERMAL:
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci			/* These are acceptable types */
18262306a36Sopenharmony_ci			break;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci		case ACPI_TYPE_INTEGER:
18562306a36Sopenharmony_ci		case ACPI_TYPE_STRING:
18662306a36Sopenharmony_ci		case ACPI_TYPE_BUFFER:
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci			/*
18962306a36Sopenharmony_ci			 * These types we will allow, but we will change the type.
19062306a36Sopenharmony_ci			 * This enables some existing code of the form:
19162306a36Sopenharmony_ci			 *
19262306a36Sopenharmony_ci			 *  Name (DEB, 0)
19362306a36Sopenharmony_ci			 *  Scope (DEB) { ... }
19462306a36Sopenharmony_ci			 */
19562306a36Sopenharmony_ci			ACPI_WARNING((AE_INFO,
19662306a36Sopenharmony_ci				      "Type override - [%4.4s] had invalid type (%s) "
19762306a36Sopenharmony_ci				      "for Scope operator, changed to type ANY",
19862306a36Sopenharmony_ci				      acpi_ut_get_node_name(node),
19962306a36Sopenharmony_ci				      acpi_ut_get_type_name(node->type)));
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci			node->type = ACPI_TYPE_ANY;
20262306a36Sopenharmony_ci			walk_state->scope_info->common.value = ACPI_TYPE_ANY;
20362306a36Sopenharmony_ci			break;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci		case ACPI_TYPE_METHOD:
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci			/*
20862306a36Sopenharmony_ci			 * Allow scope change to root during execution of module-level
20962306a36Sopenharmony_ci			 * code. Root is typed METHOD during this time.
21062306a36Sopenharmony_ci			 */
21162306a36Sopenharmony_ci			if ((node == acpi_gbl_root_node) &&
21262306a36Sopenharmony_ci			    (walk_state->
21362306a36Sopenharmony_ci			     parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
21462306a36Sopenharmony_ci				break;
21562306a36Sopenharmony_ci			}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci			ACPI_FALLTHROUGH;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci		default:
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci			/* All other types are an error */
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci			ACPI_ERROR((AE_INFO,
22462306a36Sopenharmony_ci				    "Invalid type (%s) for target of "
22562306a36Sopenharmony_ci				    "Scope operator [%4.4s] (Cannot override)",
22662306a36Sopenharmony_ci				    acpi_ut_get_type_name(node->type),
22762306a36Sopenharmony_ci				    acpi_ut_get_node_name(node)));
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
23062306a36Sopenharmony_ci		}
23162306a36Sopenharmony_ci		break;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	default:
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci		/* All other opcodes */
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci		if (op && op->common.node) {
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci			/* This op/node was previously entered into the namespace */
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci			node = op->common.node;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci			if (acpi_ns_opens_scope(object_type)) {
24462306a36Sopenharmony_ci				status =
24562306a36Sopenharmony_ci				    acpi_ds_scope_stack_push(node, object_type,
24662306a36Sopenharmony_ci							     walk_state);
24762306a36Sopenharmony_ci				if (ACPI_FAILURE(status)) {
24862306a36Sopenharmony_ci					return_ACPI_STATUS(status);
24962306a36Sopenharmony_ci				}
25062306a36Sopenharmony_ci			}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci			return_ACPI_STATUS(AE_OK);
25362306a36Sopenharmony_ci		}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci		/*
25662306a36Sopenharmony_ci		 * Enter the named type into the internal namespace. We enter the name
25762306a36Sopenharmony_ci		 * as we go downward in the parse tree. Any necessary subobjects that
25862306a36Sopenharmony_ci		 * involve arguments to the opcode must be created as we go back up the
25962306a36Sopenharmony_ci		 * parse tree later.
26062306a36Sopenharmony_ci		 *
26162306a36Sopenharmony_ci		 * Note: Name may already exist if we are executing a deferred opcode.
26262306a36Sopenharmony_ci		 */
26362306a36Sopenharmony_ci		if (walk_state->deferred_node) {
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci			/* This name is already in the namespace, get the node */
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci			node = walk_state->deferred_node;
26862306a36Sopenharmony_ci			status = AE_OK;
26962306a36Sopenharmony_ci			break;
27062306a36Sopenharmony_ci		}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci		flags = ACPI_NS_NO_UPSEARCH;
27362306a36Sopenharmony_ci		if (walk_state->pass_number == ACPI_IMODE_EXECUTE) {
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci			/* Execution mode, node cannot already exist, node is temporary */
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci			flags |= ACPI_NS_ERROR_IF_FOUND;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci			if (!
28062306a36Sopenharmony_ci			    (walk_state->
28162306a36Sopenharmony_ci			     parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
28262306a36Sopenharmony_ci				flags |= ACPI_NS_TEMPORARY;
28362306a36Sopenharmony_ci			}
28462306a36Sopenharmony_ci		}
28562306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci		/*
28862306a36Sopenharmony_ci		 * Do not open a scope for AML_EXTERNAL_OP
28962306a36Sopenharmony_ci		 * acpi_ns_lookup can open a new scope based on the object type
29062306a36Sopenharmony_ci		 * of this op. AML_EXTERNAL_OP is a declaration rather than a
29162306a36Sopenharmony_ci		 * definition. In the case that this external is a method object,
29262306a36Sopenharmony_ci		 * acpi_ns_lookup will open a new scope. However, an AML_EXTERNAL_OP
29362306a36Sopenharmony_ci		 * associated with the ACPI_TYPE_METHOD is a declaration, rather than
29462306a36Sopenharmony_ci		 * a definition. Flags is set to avoid opening a scope for any
29562306a36Sopenharmony_ci		 * AML_EXTERNAL_OP.
29662306a36Sopenharmony_ci		 */
29762306a36Sopenharmony_ci		if (walk_state->opcode == AML_EXTERNAL_OP) {
29862306a36Sopenharmony_ci			flags |= ACPI_NS_DONT_OPEN_SCOPE;
29962306a36Sopenharmony_ci		}
30062306a36Sopenharmony_ci#endif
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci		/*
30362306a36Sopenharmony_ci		 * For name creation opcodes, the full namepath prefix must
30462306a36Sopenharmony_ci		 * exist, except for the final (new) nameseg.
30562306a36Sopenharmony_ci		 */
30662306a36Sopenharmony_ci		if (walk_state->op_info->flags & AML_NAMED) {
30762306a36Sopenharmony_ci			flags |= ACPI_NS_PREFIX_MUST_EXIST;
30862306a36Sopenharmony_ci		}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci		/* Add new entry or lookup existing entry */
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci		status =
31362306a36Sopenharmony_ci		    acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
31462306a36Sopenharmony_ci				   object_type, ACPI_IMODE_LOAD_PASS2, flags,
31562306a36Sopenharmony_ci				   walk_state, &node);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci		if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) {
31862306a36Sopenharmony_ci			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
31962306a36Sopenharmony_ci					  "***New Node [%4.4s] %p is temporary\n",
32062306a36Sopenharmony_ci					  acpi_ut_get_node_name(node), node));
32162306a36Sopenharmony_ci		}
32262306a36Sopenharmony_ci		break;
32362306a36Sopenharmony_ci	}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	if (ACPI_FAILURE(status)) {
32662306a36Sopenharmony_ci		ACPI_ERROR_NAMESPACE(walk_state->scope_info,
32762306a36Sopenharmony_ci				     buffer_ptr, status);
32862306a36Sopenharmony_ci		return_ACPI_STATUS(status);
32962306a36Sopenharmony_ci	}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	if (!op) {
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci		/* Create a new op */
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci		op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml);
33662306a36Sopenharmony_ci		if (!op) {
33762306a36Sopenharmony_ci			return_ACPI_STATUS(AE_NO_MEMORY);
33862306a36Sopenharmony_ci		}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci		/* Initialize the new op */
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci		if (node) {
34362306a36Sopenharmony_ci			op->named.name = node->name.integer;
34462306a36Sopenharmony_ci		}
34562306a36Sopenharmony_ci		*out_op = op;
34662306a36Sopenharmony_ci	}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	/*
34962306a36Sopenharmony_ci	 * Put the Node in the "op" object that the parser uses, so we
35062306a36Sopenharmony_ci	 * can get it again quickly when this scope is closed
35162306a36Sopenharmony_ci	 */
35262306a36Sopenharmony_ci	op->common.node = node;
35362306a36Sopenharmony_ci	return_ACPI_STATUS(status);
35462306a36Sopenharmony_ci}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci/*******************************************************************************
35762306a36Sopenharmony_ci *
35862306a36Sopenharmony_ci * FUNCTION:    acpi_ds_load2_end_op
35962306a36Sopenharmony_ci *
36062306a36Sopenharmony_ci * PARAMETERS:  walk_state      - Current state of the parse tree walk
36162306a36Sopenharmony_ci *
36262306a36Sopenharmony_ci * RETURN:      Status
36362306a36Sopenharmony_ci *
36462306a36Sopenharmony_ci * DESCRIPTION: Ascending callback used during the loading of the namespace,
36562306a36Sopenharmony_ci *              both control methods and everything else.
36662306a36Sopenharmony_ci *
36762306a36Sopenharmony_ci ******************************************************************************/
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ciacpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
37062306a36Sopenharmony_ci{
37162306a36Sopenharmony_ci	union acpi_parse_object *op;
37262306a36Sopenharmony_ci	acpi_status status = AE_OK;
37362306a36Sopenharmony_ci	acpi_object_type object_type;
37462306a36Sopenharmony_ci	struct acpi_namespace_node *node;
37562306a36Sopenharmony_ci	union acpi_parse_object *arg;
37662306a36Sopenharmony_ci	struct acpi_namespace_node *new_node;
37762306a36Sopenharmony_ci	u32 i;
37862306a36Sopenharmony_ci	u8 region_space;
37962306a36Sopenharmony_ci#ifdef ACPI_EXEC_APP
38062306a36Sopenharmony_ci	union acpi_operand_object *obj_desc;
38162306a36Sopenharmony_ci	char *namepath;
38262306a36Sopenharmony_ci#endif
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ds_load2_end_op);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	op = walk_state->op;
38762306a36Sopenharmony_ci	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
38862306a36Sopenharmony_ci			  walk_state->op_info->name, op, walk_state));
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	/* Check if opcode had an associated namespace object */
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
39362306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
39462306a36Sopenharmony_ci	}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	if (op->common.aml_opcode == AML_SCOPE_OP) {
39762306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
39862306a36Sopenharmony_ci				  "Ending scope Op=%p State=%p\n", op,
39962306a36Sopenharmony_ci				  walk_state));
40062306a36Sopenharmony_ci	}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	object_type = walk_state->op_info->object_type;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	/*
40562306a36Sopenharmony_ci	 * Get the Node/name from the earlier lookup
40662306a36Sopenharmony_ci	 * (It was saved in the *op structure)
40762306a36Sopenharmony_ci	 */
40862306a36Sopenharmony_ci	node = op->common.node;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	/*
41162306a36Sopenharmony_ci	 * Put the Node on the object stack (Contains the ACPI Name of
41262306a36Sopenharmony_ci	 * this object)
41362306a36Sopenharmony_ci	 */
41462306a36Sopenharmony_ci	walk_state->operands[0] = (void *)node;
41562306a36Sopenharmony_ci	walk_state->num_operands = 1;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	/* Pop the scope stack */
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	if (acpi_ns_opens_scope(object_type) &&
42062306a36Sopenharmony_ci	    (op->common.aml_opcode != AML_INT_METHODCALL_OP)) {
42162306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
42262306a36Sopenharmony_ci				  "(%s) Popping scope for Op %p\n",
42362306a36Sopenharmony_ci				  acpi_ut_get_type_name(object_type), op));
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci		status = acpi_ds_scope_stack_pop(walk_state);
42662306a36Sopenharmony_ci		if (ACPI_FAILURE(status)) {
42762306a36Sopenharmony_ci			goto cleanup;
42862306a36Sopenharmony_ci		}
42962306a36Sopenharmony_ci	}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	/*
43262306a36Sopenharmony_ci	 * Named operations are as follows:
43362306a36Sopenharmony_ci	 *
43462306a36Sopenharmony_ci	 * AML_ALIAS
43562306a36Sopenharmony_ci	 * AML_BANKFIELD
43662306a36Sopenharmony_ci	 * AML_CREATEBITFIELD
43762306a36Sopenharmony_ci	 * AML_CREATEBYTEFIELD
43862306a36Sopenharmony_ci	 * AML_CREATEDWORDFIELD
43962306a36Sopenharmony_ci	 * AML_CREATEFIELD
44062306a36Sopenharmony_ci	 * AML_CREATEQWORDFIELD
44162306a36Sopenharmony_ci	 * AML_CREATEWORDFIELD
44262306a36Sopenharmony_ci	 * AML_DATA_REGION
44362306a36Sopenharmony_ci	 * AML_DEVICE
44462306a36Sopenharmony_ci	 * AML_EVENT
44562306a36Sopenharmony_ci	 * AML_FIELD
44662306a36Sopenharmony_ci	 * AML_INDEXFIELD
44762306a36Sopenharmony_ci	 * AML_METHOD
44862306a36Sopenharmony_ci	 * AML_METHODCALL
44962306a36Sopenharmony_ci	 * AML_MUTEX
45062306a36Sopenharmony_ci	 * AML_NAME
45162306a36Sopenharmony_ci	 * AML_NAMEDFIELD
45262306a36Sopenharmony_ci	 * AML_OPREGION
45362306a36Sopenharmony_ci	 * AML_POWERRES
45462306a36Sopenharmony_ci	 * AML_PROCESSOR
45562306a36Sopenharmony_ci	 * AML_SCOPE
45662306a36Sopenharmony_ci	 * AML_THERMALZONE
45762306a36Sopenharmony_ci	 */
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
46062306a36Sopenharmony_ci			  "Create-Load [%s] State=%p Op=%p NamedObj=%p\n",
46162306a36Sopenharmony_ci			  acpi_ps_get_opcode_name(op->common.aml_opcode),
46262306a36Sopenharmony_ci			  walk_state, op, node));
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	/* Decode the opcode */
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	arg = op->common.value.arg;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	switch (walk_state->op_info->type) {
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	case AML_TYPE_CREATE_FIELD:
47162306a36Sopenharmony_ci		/*
47262306a36Sopenharmony_ci		 * Create the field object, but the field buffer and index must
47362306a36Sopenharmony_ci		 * be evaluated later during the execution phase
47462306a36Sopenharmony_ci		 */
47562306a36Sopenharmony_ci		status = acpi_ds_create_buffer_field(op, walk_state);
47662306a36Sopenharmony_ci		if (ACPI_FAILURE(status)) {
47762306a36Sopenharmony_ci			ACPI_EXCEPTION((AE_INFO, status,
47862306a36Sopenharmony_ci					"CreateBufferField failure"));
47962306a36Sopenharmony_ci			goto cleanup;
48062306a36Sopenharmony_ci			}
48162306a36Sopenharmony_ci		break;
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	case AML_TYPE_NAMED_FIELD:
48462306a36Sopenharmony_ci		/*
48562306a36Sopenharmony_ci		 * If we are executing a method, initialize the field
48662306a36Sopenharmony_ci		 */
48762306a36Sopenharmony_ci		if (walk_state->method_node) {
48862306a36Sopenharmony_ci			status = acpi_ds_init_field_objects(op, walk_state);
48962306a36Sopenharmony_ci		}
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci		switch (op->common.aml_opcode) {
49262306a36Sopenharmony_ci		case AML_INDEX_FIELD_OP:
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci			status =
49562306a36Sopenharmony_ci			    acpi_ds_create_index_field(op,
49662306a36Sopenharmony_ci						       (acpi_handle)arg->common.
49762306a36Sopenharmony_ci						       node, walk_state);
49862306a36Sopenharmony_ci			break;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci		case AML_BANK_FIELD_OP:
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci			status =
50362306a36Sopenharmony_ci			    acpi_ds_create_bank_field(op, arg->common.node,
50462306a36Sopenharmony_ci						      walk_state);
50562306a36Sopenharmony_ci			break;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci		case AML_FIELD_OP:
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci			status =
51062306a36Sopenharmony_ci			    acpi_ds_create_field(op, arg->common.node,
51162306a36Sopenharmony_ci						 walk_state);
51262306a36Sopenharmony_ci			break;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci		default:
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci			/* All NAMED_FIELD opcodes must be handled above */
51762306a36Sopenharmony_ci			break;
51862306a36Sopenharmony_ci		}
51962306a36Sopenharmony_ci		break;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	case AML_TYPE_NAMED_SIMPLE:
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci		status = acpi_ds_create_operands(walk_state, arg);
52462306a36Sopenharmony_ci		if (ACPI_FAILURE(status)) {
52562306a36Sopenharmony_ci			goto cleanup;
52662306a36Sopenharmony_ci		}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci		switch (op->common.aml_opcode) {
52962306a36Sopenharmony_ci		case AML_PROCESSOR_OP:
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci			status = acpi_ex_create_processor(walk_state);
53262306a36Sopenharmony_ci			break;
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci		case AML_POWER_RESOURCE_OP:
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci			status = acpi_ex_create_power_resource(walk_state);
53762306a36Sopenharmony_ci			break;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci		case AML_MUTEX_OP:
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci			status = acpi_ex_create_mutex(walk_state);
54262306a36Sopenharmony_ci			break;
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci		case AML_EVENT_OP:
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci			status = acpi_ex_create_event(walk_state);
54762306a36Sopenharmony_ci			break;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci		case AML_ALIAS_OP:
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci			status = acpi_ex_create_alias(walk_state);
55262306a36Sopenharmony_ci			break;
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci		default:
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci			/* Unknown opcode */
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci			status = AE_OK;
55962306a36Sopenharmony_ci			goto cleanup;
56062306a36Sopenharmony_ci		}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci		/* Delete operands */
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci		for (i = 1; i < walk_state->num_operands; i++) {
56562306a36Sopenharmony_ci			acpi_ut_remove_reference(walk_state->operands[i]);
56662306a36Sopenharmony_ci			walk_state->operands[i] = NULL;
56762306a36Sopenharmony_ci		}
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci		break;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	case AML_TYPE_NAMED_COMPLEX:
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci		switch (op->common.aml_opcode) {
57462306a36Sopenharmony_ci		case AML_REGION_OP:
57562306a36Sopenharmony_ci		case AML_DATA_REGION_OP:
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci			if (op->common.aml_opcode == AML_REGION_OP) {
57862306a36Sopenharmony_ci				region_space = (acpi_adr_space_type)
57962306a36Sopenharmony_ci				    ((op->common.value.arg)->common.value.
58062306a36Sopenharmony_ci				     integer);
58162306a36Sopenharmony_ci			} else {
58262306a36Sopenharmony_ci				region_space = ACPI_ADR_SPACE_DATA_TABLE;
58362306a36Sopenharmony_ci			}
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci			/*
58662306a36Sopenharmony_ci			 * The op_region is not fully parsed at this time. The only valid
58762306a36Sopenharmony_ci			 * argument is the space_id. (We must save the address of the
58862306a36Sopenharmony_ci			 * AML of the address and length operands)
58962306a36Sopenharmony_ci			 *
59062306a36Sopenharmony_ci			 * If we have a valid region, initialize it. The namespace is
59162306a36Sopenharmony_ci			 * unlocked at this point.
59262306a36Sopenharmony_ci			 *
59362306a36Sopenharmony_ci			 * Need to unlock interpreter if it is locked (if we are running
59462306a36Sopenharmony_ci			 * a control method), in order to allow _REG methods to be run
59562306a36Sopenharmony_ci			 * during acpi_ev_initialize_region.
59662306a36Sopenharmony_ci			 */
59762306a36Sopenharmony_ci			if (walk_state->method_node) {
59862306a36Sopenharmony_ci				/*
59962306a36Sopenharmony_ci				 * Executing a method: initialize the region and unlock
60062306a36Sopenharmony_ci				 * the interpreter
60162306a36Sopenharmony_ci				 */
60262306a36Sopenharmony_ci				status = acpi_ex_create_region(op->named.data,
60362306a36Sopenharmony_ci							       op->named.length,
60462306a36Sopenharmony_ci							       region_space,
60562306a36Sopenharmony_ci							       walk_state);
60662306a36Sopenharmony_ci				if (ACPI_FAILURE(status)) {
60762306a36Sopenharmony_ci					return_ACPI_STATUS(status);
60862306a36Sopenharmony_ci				}
60962306a36Sopenharmony_ci			}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci			status =
61262306a36Sopenharmony_ci			    acpi_ev_initialize_region
61362306a36Sopenharmony_ci			    (acpi_ns_get_attached_object(node));
61462306a36Sopenharmony_ci			break;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci		case AML_NAME_OP:
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci			status = acpi_ds_create_node(walk_state, node, op);
61962306a36Sopenharmony_ci			if (ACPI_FAILURE(status)) {
62062306a36Sopenharmony_ci				goto cleanup;
62162306a36Sopenharmony_ci			}
62262306a36Sopenharmony_ci#ifdef ACPI_EXEC_APP
62362306a36Sopenharmony_ci			/*
62462306a36Sopenharmony_ci			 * acpi_exec support for namespace initialization file (initialize
62562306a36Sopenharmony_ci			 * Name opcodes in this code.)
62662306a36Sopenharmony_ci			 */
62762306a36Sopenharmony_ci			namepath = acpi_ns_get_external_pathname(node);
62862306a36Sopenharmony_ci			status = ae_lookup_init_file_entry(namepath, &obj_desc);
62962306a36Sopenharmony_ci			if (ACPI_SUCCESS(status)) {
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci				/* Detach any existing object, attach new object */
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci				if (node->object) {
63462306a36Sopenharmony_ci					acpi_ns_detach_object(node);
63562306a36Sopenharmony_ci				}
63662306a36Sopenharmony_ci				acpi_ns_attach_object(node, obj_desc,
63762306a36Sopenharmony_ci						      obj_desc->common.type);
63862306a36Sopenharmony_ci			}
63962306a36Sopenharmony_ci			ACPI_FREE(namepath);
64062306a36Sopenharmony_ci			status = AE_OK;
64162306a36Sopenharmony_ci#endif
64262306a36Sopenharmony_ci			break;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci		case AML_METHOD_OP:
64562306a36Sopenharmony_ci			/*
64662306a36Sopenharmony_ci			 * method_op pkg_length name_string method_flags term_list
64762306a36Sopenharmony_ci			 *
64862306a36Sopenharmony_ci			 * Note: We must create the method node/object pair as soon as we
64962306a36Sopenharmony_ci			 * see the method declaration. This allows later pass1 parsing
65062306a36Sopenharmony_ci			 * of invocations of the method (need to know the number of
65162306a36Sopenharmony_ci			 * arguments.)
65262306a36Sopenharmony_ci			 */
65362306a36Sopenharmony_ci			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
65462306a36Sopenharmony_ci					  "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
65562306a36Sopenharmony_ci					  walk_state, op, op->named.node));
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci			if (!acpi_ns_get_attached_object(op->named.node)) {
65862306a36Sopenharmony_ci				walk_state->operands[0] =
65962306a36Sopenharmony_ci				    ACPI_CAST_PTR(void, op->named.node);
66062306a36Sopenharmony_ci				walk_state->num_operands = 1;
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci				status =
66362306a36Sopenharmony_ci				    acpi_ds_create_operands(walk_state,
66462306a36Sopenharmony_ci							    op->common.value.
66562306a36Sopenharmony_ci							    arg);
66662306a36Sopenharmony_ci				if (ACPI_SUCCESS(status)) {
66762306a36Sopenharmony_ci					status =
66862306a36Sopenharmony_ci					    acpi_ex_create_method(op->named.
66962306a36Sopenharmony_ci								  data,
67062306a36Sopenharmony_ci								  op->named.
67162306a36Sopenharmony_ci								  length,
67262306a36Sopenharmony_ci								  walk_state);
67362306a36Sopenharmony_ci				}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci				walk_state->operands[0] = NULL;
67662306a36Sopenharmony_ci				walk_state->num_operands = 0;
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci				if (ACPI_FAILURE(status)) {
67962306a36Sopenharmony_ci					return_ACPI_STATUS(status);
68062306a36Sopenharmony_ci				}
68162306a36Sopenharmony_ci			}
68262306a36Sopenharmony_ci			break;
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci		default:
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci			/* All NAMED_COMPLEX opcodes must be handled above */
68762306a36Sopenharmony_ci			break;
68862306a36Sopenharmony_ci		}
68962306a36Sopenharmony_ci		break;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	case AML_CLASS_INTERNAL:
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci		/* case AML_INT_NAMEPATH_OP: */
69462306a36Sopenharmony_ci		break;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	case AML_CLASS_METHOD_CALL:
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
69962306a36Sopenharmony_ci				  "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n",
70062306a36Sopenharmony_ci				  walk_state, op, node));
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci		/*
70362306a36Sopenharmony_ci		 * Lookup the method name and save the Node
70462306a36Sopenharmony_ci		 */
70562306a36Sopenharmony_ci		status =
70662306a36Sopenharmony_ci		    acpi_ns_lookup(walk_state->scope_info,
70762306a36Sopenharmony_ci				   arg->common.value.string, ACPI_TYPE_ANY,
70862306a36Sopenharmony_ci				   ACPI_IMODE_LOAD_PASS2,
70962306a36Sopenharmony_ci				   ACPI_NS_SEARCH_PARENT |
71062306a36Sopenharmony_ci				   ACPI_NS_DONT_OPEN_SCOPE, walk_state,
71162306a36Sopenharmony_ci				   &(new_node));
71262306a36Sopenharmony_ci		if (ACPI_SUCCESS(status)) {
71362306a36Sopenharmony_ci			/*
71462306a36Sopenharmony_ci			 * Make sure that what we found is indeed a method
71562306a36Sopenharmony_ci			 * We didn't search for a method on purpose, to see if the name
71662306a36Sopenharmony_ci			 * would resolve
71762306a36Sopenharmony_ci			 */
71862306a36Sopenharmony_ci			if (new_node->type != ACPI_TYPE_METHOD) {
71962306a36Sopenharmony_ci				status = AE_AML_OPERAND_TYPE;
72062306a36Sopenharmony_ci			}
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci			/* We could put the returned object (Node) on the object stack for
72362306a36Sopenharmony_ci			 * later, but for now, we will put it in the "op" object that the
72462306a36Sopenharmony_ci			 * parser uses, so we can get it again at the end of this scope
72562306a36Sopenharmony_ci			 */
72662306a36Sopenharmony_ci			op->common.node = new_node;
72762306a36Sopenharmony_ci		} else {
72862306a36Sopenharmony_ci			ACPI_ERROR_NAMESPACE(walk_state->scope_info,
72962306a36Sopenharmony_ci					     arg->common.value.string, status);
73062306a36Sopenharmony_ci		}
73162306a36Sopenharmony_ci		break;
73262306a36Sopenharmony_ci
73362306a36Sopenharmony_ci	default:
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci		break;
73662306a36Sopenharmony_ci	}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_cicleanup:
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	/* Remove the Node pushed at the very beginning */
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	walk_state->operands[0] = NULL;
74362306a36Sopenharmony_ci	walk_state->num_operands = 0;
74462306a36Sopenharmony_ci	return_ACPI_STATUS(status);
74562306a36Sopenharmony_ci}
746