162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
262306a36Sopenharmony_ci/******************************************************************************
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Module Name: exresnte - AML Interpreter object resolution
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 "acdispat.h"
1362306a36Sopenharmony_ci#include "acinterp.h"
1462306a36Sopenharmony_ci#include "acnamesp.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define _COMPONENT          ACPI_EXECUTER
1762306a36Sopenharmony_ciACPI_MODULE_NAME("exresnte")
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/*******************************************************************************
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * FUNCTION:    acpi_ex_resolve_node_to_value
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * PARAMETERS:  object_ptr      - Pointer to a location that contains
2462306a36Sopenharmony_ci *                                a pointer to a NS node, and will receive a
2562306a36Sopenharmony_ci *                                pointer to the resolved object.
2662306a36Sopenharmony_ci *              walk_state      - Current state. Valid only if executing AML
2762306a36Sopenharmony_ci *                                code. NULL if simply resolving an object
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci * RETURN:      Status
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * DESCRIPTION: Resolve a Namespace node to a valued object
3262306a36Sopenharmony_ci *
3362306a36Sopenharmony_ci * Note: for some of the data types, the pointer attached to the Node
3462306a36Sopenharmony_ci * can be either a pointer to an actual internal object or a pointer into the
3562306a36Sopenharmony_ci * AML stream itself. These types are currently:
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci *      ACPI_TYPE_INTEGER
3862306a36Sopenharmony_ci *      ACPI_TYPE_STRING
3962306a36Sopenharmony_ci *      ACPI_TYPE_BUFFER
4062306a36Sopenharmony_ci *      ACPI_TYPE_MUTEX
4162306a36Sopenharmony_ci *      ACPI_TYPE_PACKAGE
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci ******************************************************************************/
4462306a36Sopenharmony_ciacpi_status
4562306a36Sopenharmony_ciacpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
4662306a36Sopenharmony_ci			      struct acpi_walk_state *walk_state)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	acpi_status status = AE_OK;
4962306a36Sopenharmony_ci	union acpi_operand_object *source_desc;
5062306a36Sopenharmony_ci	union acpi_operand_object *obj_desc = NULL;
5162306a36Sopenharmony_ci	struct acpi_namespace_node *node;
5262306a36Sopenharmony_ci	acpi_object_type entry_type;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ex_resolve_node_to_value);
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	/*
5762306a36Sopenharmony_ci	 * The stack pointer points to a struct acpi_namespace_node (Node). Get the
5862306a36Sopenharmony_ci	 * object that is attached to the Node.
5962306a36Sopenharmony_ci	 */
6062306a36Sopenharmony_ci	node = *object_ptr;
6162306a36Sopenharmony_ci	source_desc = acpi_ns_get_attached_object(node);
6262306a36Sopenharmony_ci	entry_type = acpi_ns_get_type((acpi_handle)node);
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n",
6562306a36Sopenharmony_ci			  node, source_desc,
6662306a36Sopenharmony_ci			  acpi_ut_get_type_name(entry_type)));
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) ||
6962306a36Sopenharmony_ci	    (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci		/* There is always exactly one level of indirection */
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci		node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object);
7462306a36Sopenharmony_ci		source_desc = acpi_ns_get_attached_object(node);
7562306a36Sopenharmony_ci		entry_type = acpi_ns_get_type((acpi_handle)node);
7662306a36Sopenharmony_ci		*object_ptr = node;
7762306a36Sopenharmony_ci	}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	/*
8062306a36Sopenharmony_ci	 * Several object types require no further processing:
8162306a36Sopenharmony_ci	 * 1) Device/Thermal objects don't have a "real" subobject, return Node
8262306a36Sopenharmony_ci	 * 2) Method locals and arguments have a pseudo-Node
8362306a36Sopenharmony_ci	 * 3) 10/2007: Added method type to assist with Package construction.
8462306a36Sopenharmony_ci	 */
8562306a36Sopenharmony_ci	if ((entry_type == ACPI_TYPE_DEVICE) ||
8662306a36Sopenharmony_ci	    (entry_type == ACPI_TYPE_THERMAL) ||
8762306a36Sopenharmony_ci	    (entry_type == ACPI_TYPE_METHOD) ||
8862306a36Sopenharmony_ci	    (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
8962306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
9062306a36Sopenharmony_ci	}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	if (!source_desc) {
9362306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p",
9462306a36Sopenharmony_ci			    node->name.ascii, node));
9562306a36Sopenharmony_ci		return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	/*
9962306a36Sopenharmony_ci	 * Action is based on the type of the Node, which indicates the type
10062306a36Sopenharmony_ci	 * of the attached object or pointer
10162306a36Sopenharmony_ci	 */
10262306a36Sopenharmony_ci	switch (entry_type) {
10362306a36Sopenharmony_ci	case ACPI_TYPE_PACKAGE:
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci		if (source_desc->common.type != ACPI_TYPE_PACKAGE) {
10662306a36Sopenharmony_ci			ACPI_ERROR((AE_INFO, "Object not a Package, type %s",
10762306a36Sopenharmony_ci				    acpi_ut_get_object_type_name(source_desc)));
10862306a36Sopenharmony_ci			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
10962306a36Sopenharmony_ci		}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		status = acpi_ds_get_package_arguments(source_desc);
11262306a36Sopenharmony_ci		if (ACPI_SUCCESS(status)) {
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci			/* Return an additional reference to the object */
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci			obj_desc = source_desc;
11762306a36Sopenharmony_ci			acpi_ut_add_reference(obj_desc);
11862306a36Sopenharmony_ci		}
11962306a36Sopenharmony_ci		break;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	case ACPI_TYPE_BUFFER:
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci		if (source_desc->common.type != ACPI_TYPE_BUFFER) {
12462306a36Sopenharmony_ci			ACPI_ERROR((AE_INFO, "Object not a Buffer, type %s",
12562306a36Sopenharmony_ci				    acpi_ut_get_object_type_name(source_desc)));
12662306a36Sopenharmony_ci			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
12762306a36Sopenharmony_ci		}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci		status = acpi_ds_get_buffer_arguments(source_desc);
13062306a36Sopenharmony_ci		if (ACPI_SUCCESS(status)) {
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci			/* Return an additional reference to the object */
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci			obj_desc = source_desc;
13562306a36Sopenharmony_ci			acpi_ut_add_reference(obj_desc);
13662306a36Sopenharmony_ci		}
13762306a36Sopenharmony_ci		break;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	case ACPI_TYPE_STRING:
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci		if (source_desc->common.type != ACPI_TYPE_STRING) {
14262306a36Sopenharmony_ci			ACPI_ERROR((AE_INFO, "Object not a String, type %s",
14362306a36Sopenharmony_ci				    acpi_ut_get_object_type_name(source_desc)));
14462306a36Sopenharmony_ci			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
14562306a36Sopenharmony_ci		}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci		/* Return an additional reference to the object */
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci		obj_desc = source_desc;
15062306a36Sopenharmony_ci		acpi_ut_add_reference(obj_desc);
15162306a36Sopenharmony_ci		break;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	case ACPI_TYPE_INTEGER:
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci		if (source_desc->common.type != ACPI_TYPE_INTEGER) {
15662306a36Sopenharmony_ci			ACPI_ERROR((AE_INFO, "Object not a Integer, type %s",
15762306a36Sopenharmony_ci				    acpi_ut_get_object_type_name(source_desc)));
15862306a36Sopenharmony_ci			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
15962306a36Sopenharmony_ci		}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci		/* Return an additional reference to the object */
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci		obj_desc = source_desc;
16462306a36Sopenharmony_ci		acpi_ut_add_reference(obj_desc);
16562306a36Sopenharmony_ci		break;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	case ACPI_TYPE_BUFFER_FIELD:
16862306a36Sopenharmony_ci	case ACPI_TYPE_LOCAL_REGION_FIELD:
16962306a36Sopenharmony_ci	case ACPI_TYPE_LOCAL_BANK_FIELD:
17062306a36Sopenharmony_ci	case ACPI_TYPE_LOCAL_INDEX_FIELD:
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
17362306a36Sopenharmony_ci				  "FieldRead Node=%p SourceDesc=%p Type=%X\n",
17462306a36Sopenharmony_ci				  node, source_desc, entry_type));
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci		status =
17762306a36Sopenharmony_ci		    acpi_ex_read_data_from_field(walk_state, source_desc,
17862306a36Sopenharmony_ci						 &obj_desc);
17962306a36Sopenharmony_ci		break;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci		/* For these objects, just return the object attached to the Node */
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	case ACPI_TYPE_MUTEX:
18462306a36Sopenharmony_ci	case ACPI_TYPE_POWER:
18562306a36Sopenharmony_ci	case ACPI_TYPE_PROCESSOR:
18662306a36Sopenharmony_ci	case ACPI_TYPE_EVENT:
18762306a36Sopenharmony_ci	case ACPI_TYPE_REGION:
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci		/* Return an additional reference to the object */
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci		obj_desc = source_desc;
19262306a36Sopenharmony_ci		acpi_ut_add_reference(obj_desc);
19362306a36Sopenharmony_ci		break;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci		/* TYPE_ANY is untyped, and thus there is no object associated with it */
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	case ACPI_TYPE_ANY:
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO,
20062306a36Sopenharmony_ci			    "Untyped entry %p, no attached object!", node));
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);	/* Cannot be AE_TYPE */
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	case ACPI_TYPE_LOCAL_REFERENCE:
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci		switch (source_desc->reference.class) {
20762306a36Sopenharmony_ci		case ACPI_REFCLASS_TABLE:	/* This is a ddb_handle */
20862306a36Sopenharmony_ci		case ACPI_REFCLASS_REFOF:
20962306a36Sopenharmony_ci		case ACPI_REFCLASS_INDEX:
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci			/* Return an additional reference to the object */
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci			obj_desc = source_desc;
21462306a36Sopenharmony_ci			acpi_ut_add_reference(obj_desc);
21562306a36Sopenharmony_ci			break;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci		default:
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci			/* No named references are allowed here */
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci			ACPI_ERROR((AE_INFO,
22262306a36Sopenharmony_ci				    "Unsupported Reference type 0x%X",
22362306a36Sopenharmony_ci				    source_desc->reference.class));
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
22662306a36Sopenharmony_ci		}
22762306a36Sopenharmony_ci		break;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	default:
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci		/* Default case is for unknown types */
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO,
23462306a36Sopenharmony_ci			    "Node %p - Unknown object type 0x%X",
23562306a36Sopenharmony_ci			    node, entry_type));
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	}			/* switch (entry_type) */
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	/* Return the object descriptor */
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	*object_ptr = (void *)obj_desc;
24462306a36Sopenharmony_ci	return_ACPI_STATUS(status);
24562306a36Sopenharmony_ci}
246