xref: /openbmc/linux/drivers/acpi/acpica/exresolv.c (revision 612c2932)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: exresolv - AML Interpreter object resolution
595b482a8SLen Brown  *
6*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
795b482a8SLen Brown  *
895857638SErik Schmauss  *****************************************************************************/
995b482a8SLen Brown 
1095b482a8SLen Brown #include <acpi/acpi.h>
11e2f7a777SLen Brown #include "accommon.h"
12e2f7a777SLen Brown #include "amlcode.h"
13e2f7a777SLen Brown #include "acdispat.h"
14e2f7a777SLen Brown #include "acinterp.h"
15e2f7a777SLen Brown #include "acnamesp.h"
1695b482a8SLen Brown 
1795b482a8SLen Brown #define _COMPONENT          ACPI_EXECUTER
1895b482a8SLen Brown ACPI_MODULE_NAME("exresolv")
1995b482a8SLen Brown 
2095b482a8SLen Brown /* Local prototypes */
2195b482a8SLen Brown static acpi_status
2295b482a8SLen Brown acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
2395b482a8SLen Brown 				struct acpi_walk_state *walk_state);
2495b482a8SLen Brown 
2595b482a8SLen Brown /*******************************************************************************
2695b482a8SLen Brown  *
2795b482a8SLen Brown  * FUNCTION:    acpi_ex_resolve_to_value
2895b482a8SLen Brown  *
2995b482a8SLen Brown  * PARAMETERS:  **stack_ptr         - Points to entry on obj_stack, which can
3095b482a8SLen Brown  *                                    be either an (union acpi_operand_object *)
3195b482a8SLen Brown  *                                    or an acpi_handle.
3295b482a8SLen Brown  *              walk_state          - Current method state
3395b482a8SLen Brown  *
3495b482a8SLen Brown  * RETURN:      Status
3595b482a8SLen Brown  *
3695b482a8SLen Brown  * DESCRIPTION: Convert Reference objects to values
3795b482a8SLen Brown  *
3895b482a8SLen Brown  ******************************************************************************/
3995b482a8SLen Brown 
4095b482a8SLen Brown acpi_status
acpi_ex_resolve_to_value(union acpi_operand_object ** stack_ptr,struct acpi_walk_state * walk_state)4195b482a8SLen Brown acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
4295b482a8SLen Brown 			 struct acpi_walk_state *walk_state)
4395b482a8SLen Brown {
4495b482a8SLen Brown 	acpi_status status;
4595b482a8SLen Brown 
4695b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr);
4795b482a8SLen Brown 
4895b482a8SLen Brown 	if (!stack_ptr || !*stack_ptr) {
4995b482a8SLen Brown 		ACPI_ERROR((AE_INFO, "Internal - null pointer"));
5095b482a8SLen Brown 		return_ACPI_STATUS(AE_AML_NO_OPERAND);
5195b482a8SLen Brown 	}
5295b482a8SLen Brown 
5395b482a8SLen Brown 	/*
5495b482a8SLen Brown 	 * The entity pointed to by the stack_ptr can be either
5595b482a8SLen Brown 	 * 1) A valid union acpi_operand_object, or
5695b482a8SLen Brown 	 * 2) A struct acpi_namespace_node (named_obj)
5795b482a8SLen Brown 	 */
5895b482a8SLen Brown 	if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
5995b482a8SLen Brown 		status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state);
6095b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
6195b482a8SLen Brown 			return_ACPI_STATUS(status);
6295b482a8SLen Brown 		}
6395b482a8SLen Brown 
6495b482a8SLen Brown 		if (!*stack_ptr) {
6595b482a8SLen Brown 			ACPI_ERROR((AE_INFO, "Internal - null pointer"));
6695b482a8SLen Brown 			return_ACPI_STATUS(AE_AML_NO_OPERAND);
6795b482a8SLen Brown 		}
6895b482a8SLen Brown 	}
6995b482a8SLen Brown 
7095b482a8SLen Brown 	/*
7195b482a8SLen Brown 	 * Object on the stack may have changed if acpi_ex_resolve_object_to_value()
7295b482a8SLen Brown 	 * was called (i.e., we can't use an _else_ here.)
7395b482a8SLen Brown 	 */
7495b482a8SLen Brown 	if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
7595b482a8SLen Brown 		status =
7695b482a8SLen Brown 		    acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
7795b482a8SLen Brown 						  (struct acpi_namespace_node,
7895b482a8SLen Brown 						   stack_ptr), walk_state);
7995b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
8095b482a8SLen Brown 			return_ACPI_STATUS(status);
8195b482a8SLen Brown 		}
8295b482a8SLen Brown 	}
8395b482a8SLen Brown 
8495b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
8595b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
8695b482a8SLen Brown }
8795b482a8SLen Brown 
8895b482a8SLen Brown /*******************************************************************************
8995b482a8SLen Brown  *
9095b482a8SLen Brown  * FUNCTION:    acpi_ex_resolve_object_to_value
9195b482a8SLen Brown  *
9295b482a8SLen Brown  * PARAMETERS:  stack_ptr       - Pointer to an internal object
9395b482a8SLen Brown  *              walk_state      - Current method state
9495b482a8SLen Brown  *
9595b482a8SLen Brown  * RETURN:      Status
9695b482a8SLen Brown  *
9795b482a8SLen Brown  * DESCRIPTION: Retrieve the value from an internal object. The Reference type
9895b482a8SLen Brown  *              uses the associated AML opcode to determine the value.
9995b482a8SLen Brown  *
10095b482a8SLen Brown  ******************************************************************************/
10195b482a8SLen Brown 
10295b482a8SLen Brown static acpi_status
acpi_ex_resolve_object_to_value(union acpi_operand_object ** stack_ptr,struct acpi_walk_state * walk_state)10395b482a8SLen Brown acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
10495b482a8SLen Brown 				struct acpi_walk_state *walk_state)
10595b482a8SLen Brown {
10695b482a8SLen Brown 	acpi_status status = AE_OK;
10795b482a8SLen Brown 	union acpi_operand_object *stack_desc;
10895b482a8SLen Brown 	union acpi_operand_object *obj_desc = NULL;
10995b482a8SLen Brown 	u8 ref_type;
11095b482a8SLen Brown 
11195b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
11295b482a8SLen Brown 
11395b482a8SLen Brown 	stack_desc = *stack_ptr;
11495b482a8SLen Brown 
115cf48958eSBob Moore 	/* This is an object of type union acpi_operand_object */
11695b482a8SLen Brown 
1173371c19cSBob Moore 	switch (stack_desc->common.type) {
11895b482a8SLen Brown 	case ACPI_TYPE_LOCAL_REFERENCE:
11995b482a8SLen Brown 
12095b482a8SLen Brown 		ref_type = stack_desc->reference.class;
12195b482a8SLen Brown 
12295b482a8SLen Brown 		switch (ref_type) {
12395b482a8SLen Brown 		case ACPI_REFCLASS_LOCAL:
12495b482a8SLen Brown 		case ACPI_REFCLASS_ARG:
12595b482a8SLen Brown 			/*
12695b482a8SLen Brown 			 * Get the local from the method's state info
12795b482a8SLen Brown 			 * Note: this increments the local's object reference count
12895b482a8SLen Brown 			 */
12995b482a8SLen Brown 			status = acpi_ds_method_data_get_value(ref_type,
13095b482a8SLen Brown 							       stack_desc->
13195b482a8SLen Brown 							       reference.value,
13295b482a8SLen Brown 							       walk_state,
13395b482a8SLen Brown 							       &obj_desc);
13495b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
13595b482a8SLen Brown 				return_ACPI_STATUS(status);
13695b482a8SLen Brown 			}
13795b482a8SLen Brown 
13895b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
13995b482a8SLen Brown 					  "[Arg/Local %X] ValueObj is %p\n",
14095b482a8SLen Brown 					  stack_desc->reference.value,
14195b482a8SLen Brown 					  obj_desc));
14295b482a8SLen Brown 
14395b482a8SLen Brown 			/*
14495b482a8SLen Brown 			 * Now we can delete the original Reference Object and
14595b482a8SLen Brown 			 * replace it with the resolved value
14695b482a8SLen Brown 			 */
14795b482a8SLen Brown 			acpi_ut_remove_reference(stack_desc);
14895b482a8SLen Brown 			*stack_ptr = obj_desc;
14995b482a8SLen Brown 			break;
15095b482a8SLen Brown 
15195b482a8SLen Brown 		case ACPI_REFCLASS_INDEX:
15295b482a8SLen Brown 
15395b482a8SLen Brown 			switch (stack_desc->reference.target_type) {
15495b482a8SLen Brown 			case ACPI_TYPE_BUFFER_FIELD:
15595b482a8SLen Brown 
15695b482a8SLen Brown 				/* Just return - do not dereference */
15795b482a8SLen Brown 				break;
15895b482a8SLen Brown 
15995b482a8SLen Brown 			case ACPI_TYPE_PACKAGE:
16095b482a8SLen Brown 
16195b482a8SLen Brown 				/* If method call or copy_object - do not dereference */
16295b482a8SLen Brown 
16395b482a8SLen Brown 				if ((walk_state->opcode ==
16495b482a8SLen Brown 				     AML_INT_METHODCALL_OP)
1659ff5a21aSBob Moore 				    || (walk_state->opcode ==
1669ff5a21aSBob Moore 					AML_COPY_OBJECT_OP)) {
16795b482a8SLen Brown 					break;
16895b482a8SLen Brown 				}
16995b482a8SLen Brown 
17095b482a8SLen Brown 				/* Otherwise, dereference the package_index to a package element */
17195b482a8SLen Brown 
17295b482a8SLen Brown 				obj_desc = *stack_desc->reference.where;
17395b482a8SLen Brown 				if (obj_desc) {
17495b482a8SLen Brown 					/*
17595b482a8SLen Brown 					 * Valid object descriptor, copy pointer to return value
17695b482a8SLen Brown 					 * (i.e., dereference the package index)
17795b482a8SLen Brown 					 * Delete the ref object, increment the returned object
17895b482a8SLen Brown 					 */
17995b482a8SLen Brown 					acpi_ut_add_reference(obj_desc);
18095b482a8SLen Brown 					*stack_ptr = obj_desc;
18195b482a8SLen Brown 				} else {
18295b482a8SLen Brown 					/*
18395b482a8SLen Brown 					 * A NULL object descriptor means an uninitialized element of
18495b482a8SLen Brown 					 * the package, can't dereference it
18595b482a8SLen Brown 					 */
18695b482a8SLen Brown 					ACPI_ERROR((AE_INFO,
1871fad8738SBob Moore 						    "Attempt to dereference an Index to "
1881fad8738SBob Moore 						    "NULL package element Idx=%p",
18995b482a8SLen Brown 						    stack_desc));
19095b482a8SLen Brown 					status = AE_AML_UNINITIALIZED_ELEMENT;
19195b482a8SLen Brown 				}
19295b482a8SLen Brown 				break;
19395b482a8SLen Brown 
19495b482a8SLen Brown 			default:
19595b482a8SLen Brown 
19695b482a8SLen Brown 				/* Invalid reference object */
19795b482a8SLen Brown 
19895b482a8SLen Brown 				ACPI_ERROR((AE_INFO,
199f6a22b0bSBob Moore 					    "Unknown TargetType 0x%X in Index/Reference object %p",
20095b482a8SLen Brown 					    stack_desc->reference.target_type,
20195b482a8SLen Brown 					    stack_desc));
20295b482a8SLen Brown 				status = AE_AML_INTERNAL;
20395b482a8SLen Brown 				break;
20495b482a8SLen Brown 			}
20595b482a8SLen Brown 			break;
20695b482a8SLen Brown 
20795b482a8SLen Brown 		case ACPI_REFCLASS_REFOF:
20895b482a8SLen Brown 		case ACPI_REFCLASS_DEBUG:
20995b482a8SLen Brown 		case ACPI_REFCLASS_TABLE:
21095b482a8SLen Brown 
21195b482a8SLen Brown 			/* Just leave the object as-is, do not dereference */
21295b482a8SLen Brown 
21395b482a8SLen Brown 			break;
21495b482a8SLen Brown 
21595b482a8SLen Brown 		case ACPI_REFCLASS_NAME:	/* Reference to a named object */
21695b482a8SLen Brown 
21795b482a8SLen Brown 			/* Dereference the name */
21895b482a8SLen Brown 
21995b482a8SLen Brown 			if ((stack_desc->reference.node->type ==
22095b482a8SLen Brown 			     ACPI_TYPE_DEVICE)
22195b482a8SLen Brown 			    || (stack_desc->reference.node->type ==
22295b482a8SLen Brown 				ACPI_TYPE_THERMAL)) {
22395b482a8SLen Brown 
22495b482a8SLen Brown 				/* These node types do not have 'real' subobjects */
22595b482a8SLen Brown 
22695b482a8SLen Brown 				*stack_ptr = (void *)stack_desc->reference.node;
22795b482a8SLen Brown 			} else {
22895b482a8SLen Brown 				/* Get the object pointed to by the namespace node */
22995b482a8SLen Brown 
23095b482a8SLen Brown 				*stack_ptr =
23195b482a8SLen Brown 				    (stack_desc->reference.node)->object;
23295b482a8SLen Brown 				acpi_ut_add_reference(*stack_ptr);
23395b482a8SLen Brown 			}
23495b482a8SLen Brown 
23595b482a8SLen Brown 			acpi_ut_remove_reference(stack_desc);
23695b482a8SLen Brown 			break;
23795b482a8SLen Brown 
23895b482a8SLen Brown 		default:
23995b482a8SLen Brown 
24095b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
241f6a22b0bSBob Moore 				    "Unknown Reference type 0x%X in %p",
242f6a22b0bSBob Moore 				    ref_type, stack_desc));
24395b482a8SLen Brown 			status = AE_AML_INTERNAL;
24495b482a8SLen Brown 			break;
24595b482a8SLen Brown 		}
24695b482a8SLen Brown 		break;
24795b482a8SLen Brown 
24895b482a8SLen Brown 	case ACPI_TYPE_BUFFER:
24995b482a8SLen Brown 
25095b482a8SLen Brown 		status = acpi_ds_get_buffer_arguments(stack_desc);
25195b482a8SLen Brown 		break;
25295b482a8SLen Brown 
25395b482a8SLen Brown 	case ACPI_TYPE_PACKAGE:
25495b482a8SLen Brown 
25595b482a8SLen Brown 		status = acpi_ds_get_package_arguments(stack_desc);
25695b482a8SLen Brown 		break;
25795b482a8SLen Brown 
25895b482a8SLen Brown 	case ACPI_TYPE_BUFFER_FIELD:
25995b482a8SLen Brown 	case ACPI_TYPE_LOCAL_REGION_FIELD:
26095b482a8SLen Brown 	case ACPI_TYPE_LOCAL_BANK_FIELD:
26195b482a8SLen Brown 	case ACPI_TYPE_LOCAL_INDEX_FIELD:
26295b482a8SLen Brown 
26395b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
26495b482a8SLen Brown 				  "FieldRead SourceDesc=%p Type=%X\n",
2653371c19cSBob Moore 				  stack_desc, stack_desc->common.type));
26695b482a8SLen Brown 
26795b482a8SLen Brown 		status =
26895b482a8SLen Brown 		    acpi_ex_read_data_from_field(walk_state, stack_desc,
26995b482a8SLen Brown 						 &obj_desc);
27095b482a8SLen Brown 
27195b482a8SLen Brown 		/* Remove a reference to the original operand, then override */
27295b482a8SLen Brown 
27395b482a8SLen Brown 		acpi_ut_remove_reference(*stack_ptr);
27495b482a8SLen Brown 		*stack_ptr = (void *)obj_desc;
27595b482a8SLen Brown 		break;
27695b482a8SLen Brown 
27795b482a8SLen Brown 	default:
2781d1ea1b7SChao Guan 
27995b482a8SLen Brown 		break;
28095b482a8SLen Brown 	}
28195b482a8SLen Brown 
28295b482a8SLen Brown 	return_ACPI_STATUS(status);
28395b482a8SLen Brown }
28495b482a8SLen Brown 
28595b482a8SLen Brown /*******************************************************************************
28695b482a8SLen Brown  *
28795b482a8SLen Brown  * FUNCTION:    acpi_ex_resolve_multiple
28895b482a8SLen Brown  *
28995b482a8SLen Brown  * PARAMETERS:  walk_state          - Current state (contains AML opcode)
290ba494beeSBob Moore  *              operand             - Starting point for resolution
29195b482a8SLen Brown  *              return_type         - Where the object type is returned
29295b482a8SLen Brown  *              return_desc         - Where the resolved object is returned
29395b482a8SLen Brown  *
29495b482a8SLen Brown  * RETURN:      Status
29595b482a8SLen Brown  *
29695b482a8SLen Brown  * DESCRIPTION: Return the base object and type. Traverse a reference list if
29795b482a8SLen Brown  *              necessary to get to the base object.
29895b482a8SLen Brown  *
29995b482a8SLen Brown  ******************************************************************************/
30095b482a8SLen Brown 
30195b482a8SLen Brown acpi_status
acpi_ex_resolve_multiple(struct acpi_walk_state * walk_state,union acpi_operand_object * operand,acpi_object_type * return_type,union acpi_operand_object ** return_desc)30295b482a8SLen Brown acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
30395b482a8SLen Brown 			 union acpi_operand_object *operand,
30495b482a8SLen Brown 			 acpi_object_type *return_type,
30595b482a8SLen Brown 			 union acpi_operand_object **return_desc)
30695b482a8SLen Brown {
3074712f71bSBob Moore 	union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
3084712f71bSBob Moore 	struct acpi_namespace_node *node =
3094712f71bSBob Moore 	    ACPI_CAST_PTR(struct acpi_namespace_node, operand);
31095b482a8SLen Brown 	acpi_object_type type;
31195b482a8SLen Brown 	acpi_status status;
31295b482a8SLen Brown 
31395b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple);
31495b482a8SLen Brown 
31595b482a8SLen Brown 	/* Operand can be either a namespace node or an operand descriptor */
31695b482a8SLen Brown 
31795b482a8SLen Brown 	switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
31895b482a8SLen Brown 	case ACPI_DESC_TYPE_OPERAND:
3191d1ea1b7SChao Guan 
32095b482a8SLen Brown 		type = obj_desc->common.type;
32195b482a8SLen Brown 		break;
32295b482a8SLen Brown 
32395b482a8SLen Brown 	case ACPI_DESC_TYPE_NAMED:
3241d1ea1b7SChao Guan 
32595b482a8SLen Brown 		type = ((struct acpi_namespace_node *)obj_desc)->type;
3264712f71bSBob Moore 		obj_desc = acpi_ns_get_attached_object(node);
32795b482a8SLen Brown 
32895b482a8SLen Brown 		/* If we had an Alias node, use the attached object for type info */
32995b482a8SLen Brown 
33095b482a8SLen Brown 		if (type == ACPI_TYPE_LOCAL_ALIAS) {
33195b482a8SLen Brown 			type = ((struct acpi_namespace_node *)obj_desc)->type;
3321fad8738SBob Moore 			obj_desc = acpi_ns_get_attached_object((struct
3331fad8738SBob Moore 								acpi_namespace_node
3341fad8738SBob Moore 								*)obj_desc);
33595b482a8SLen Brown 		}
3364712f71bSBob Moore 
3371d6e9cfaSBob Moore 		switch (type) {
3381d6e9cfaSBob Moore 		case ACPI_TYPE_DEVICE:
3391d6e9cfaSBob Moore 		case ACPI_TYPE_THERMAL:
3401d6e9cfaSBob Moore 
3411d6e9cfaSBob Moore 			/* These types have no attached subobject */
3421d6e9cfaSBob Moore 			break;
3431d6e9cfaSBob Moore 
3441d6e9cfaSBob Moore 		default:
3451d6e9cfaSBob Moore 
3461d6e9cfaSBob Moore 			/* All other types require a subobject */
3471d6e9cfaSBob Moore 
3484712f71bSBob Moore 			if (!obj_desc) {
3494712f71bSBob Moore 				ACPI_ERROR((AE_INFO,
3504712f71bSBob Moore 					    "[%4.4s] Node is unresolved or uninitialized",
3514712f71bSBob Moore 					    acpi_ut_get_node_name(node)));
3524712f71bSBob Moore 				return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
3534712f71bSBob Moore 			}
35495b482a8SLen Brown 			break;
3551d6e9cfaSBob Moore 		}
3561d6e9cfaSBob Moore 		break;
35795b482a8SLen Brown 
35895b482a8SLen Brown 	default:
35995b482a8SLen Brown 		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
36095b482a8SLen Brown 	}
36195b482a8SLen Brown 
36295b482a8SLen Brown 	/* If type is anything other than a reference, we are done */
36395b482a8SLen Brown 
36495b482a8SLen Brown 	if (type != ACPI_TYPE_LOCAL_REFERENCE) {
36595b482a8SLen Brown 		goto exit;
36695b482a8SLen Brown 	}
36795b482a8SLen Brown 
36895b482a8SLen Brown 	/*
36995b482a8SLen Brown 	 * For reference objects created via the ref_of, Index, or Load/load_table
37095b482a8SLen Brown 	 * operators, we need to get to the base object (as per the ACPI
37195b482a8SLen Brown 	 * specification of the object_type and size_of operators). This means
37295b482a8SLen Brown 	 * traversing the list of possibly many nested references.
37395b482a8SLen Brown 	 */
3743371c19cSBob Moore 	while (obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
37595b482a8SLen Brown 		switch (obj_desc->reference.class) {
37695b482a8SLen Brown 		case ACPI_REFCLASS_REFOF:
37795b482a8SLen Brown 		case ACPI_REFCLASS_NAME:
37895b482a8SLen Brown 
37995b482a8SLen Brown 			/* Dereference the reference pointer */
38095b482a8SLen Brown 
38195b482a8SLen Brown 			if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) {
38295b482a8SLen Brown 				node = obj_desc->reference.object;
38395b482a8SLen Brown 			} else {	/* AML_INT_NAMEPATH_OP */
38495b482a8SLen Brown 
38595b482a8SLen Brown 				node = obj_desc->reference.node;
38695b482a8SLen Brown 			}
38795b482a8SLen Brown 
38895b482a8SLen Brown 			/* All "References" point to a NS node */
38995b482a8SLen Brown 
39095b482a8SLen Brown 			if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
39195b482a8SLen Brown 			    ACPI_DESC_TYPE_NAMED) {
392f6a22b0bSBob Moore 				ACPI_ERROR((AE_INFO,
393f6a22b0bSBob Moore 					    "Not a namespace node %p [%s]",
39495b482a8SLen Brown 					    node,
39595b482a8SLen Brown 					    acpi_ut_get_descriptor_name(node)));
39695b482a8SLen Brown 				return_ACPI_STATUS(AE_AML_INTERNAL);
39795b482a8SLen Brown 			}
39895b482a8SLen Brown 
39995b482a8SLen Brown 			/* Get the attached object */
40095b482a8SLen Brown 
40195b482a8SLen Brown 			obj_desc = acpi_ns_get_attached_object(node);
40295b482a8SLen Brown 			if (!obj_desc) {
40395b482a8SLen Brown 
40495b482a8SLen Brown 				/* No object, use the NS node type */
40595b482a8SLen Brown 
40695b482a8SLen Brown 				type = acpi_ns_get_type(node);
40795b482a8SLen Brown 				goto exit;
40895b482a8SLen Brown 			}
40995b482a8SLen Brown 
41095b482a8SLen Brown 			/* Check for circular references */
41195b482a8SLen Brown 
41295b482a8SLen Brown 			if (obj_desc == operand) {
41395b482a8SLen Brown 				return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
41495b482a8SLen Brown 			}
41595b482a8SLen Brown 			break;
41695b482a8SLen Brown 
41795b482a8SLen Brown 		case ACPI_REFCLASS_INDEX:
41895b482a8SLen Brown 
41995b482a8SLen Brown 			/* Get the type of this reference (index into another object) */
42095b482a8SLen Brown 
42195b482a8SLen Brown 			type = obj_desc->reference.target_type;
42295b482a8SLen Brown 			if (type != ACPI_TYPE_PACKAGE) {
42395b482a8SLen Brown 				goto exit;
42495b482a8SLen Brown 			}
42595b482a8SLen Brown 
42695b482a8SLen Brown 			/*
42795b482a8SLen Brown 			 * The main object is a package, we want to get the type
42895b482a8SLen Brown 			 * of the individual package element that is referenced by
42995b482a8SLen Brown 			 * the index.
43095b482a8SLen Brown 			 *
43195b482a8SLen Brown 			 * This could of course in turn be another reference object.
43295b482a8SLen Brown 			 */
43395b482a8SLen Brown 			obj_desc = *(obj_desc->reference.where);
43495b482a8SLen Brown 			if (!obj_desc) {
43595b482a8SLen Brown 
43695b482a8SLen Brown 				/* NULL package elements are allowed */
43795b482a8SLen Brown 
43895b482a8SLen Brown 				type = 0;	/* Uninitialized */
43995b482a8SLen Brown 				goto exit;
44095b482a8SLen Brown 			}
44195b482a8SLen Brown 			break;
44295b482a8SLen Brown 
44395b482a8SLen Brown 		case ACPI_REFCLASS_TABLE:
44495b482a8SLen Brown 
44595b482a8SLen Brown 			type = ACPI_TYPE_DDB_HANDLE;
44695b482a8SLen Brown 			goto exit;
44795b482a8SLen Brown 
44895b482a8SLen Brown 		case ACPI_REFCLASS_LOCAL:
44995b482a8SLen Brown 		case ACPI_REFCLASS_ARG:
45095b482a8SLen Brown 
45195b482a8SLen Brown 			if (return_desc) {
45295b482a8SLen Brown 				status =
45395b482a8SLen Brown 				    acpi_ds_method_data_get_value(obj_desc->
45495b482a8SLen Brown 								  reference.
45595b482a8SLen Brown 								  class,
45695b482a8SLen Brown 								  obj_desc->
45795b482a8SLen Brown 								  reference.
45895b482a8SLen Brown 								  value,
45995b482a8SLen Brown 								  walk_state,
46095b482a8SLen Brown 								  &obj_desc);
46195b482a8SLen Brown 				if (ACPI_FAILURE(status)) {
46295b482a8SLen Brown 					return_ACPI_STATUS(status);
46395b482a8SLen Brown 				}
46495b482a8SLen Brown 				acpi_ut_remove_reference(obj_desc);
46595b482a8SLen Brown 			} else {
46695b482a8SLen Brown 				status =
46795b482a8SLen Brown 				    acpi_ds_method_data_get_node(obj_desc->
46895b482a8SLen Brown 								 reference.
46995b482a8SLen Brown 								 class,
47095b482a8SLen Brown 								 obj_desc->
47195b482a8SLen Brown 								 reference.
47295b482a8SLen Brown 								 value,
47395b482a8SLen Brown 								 walk_state,
47495b482a8SLen Brown 								 &node);
47595b482a8SLen Brown 				if (ACPI_FAILURE(status)) {
47695b482a8SLen Brown 					return_ACPI_STATUS(status);
47795b482a8SLen Brown 				}
47895b482a8SLen Brown 
47995b482a8SLen Brown 				obj_desc = acpi_ns_get_attached_object(node);
48095b482a8SLen Brown 				if (!obj_desc) {
48195b482a8SLen Brown 					type = ACPI_TYPE_ANY;
48295b482a8SLen Brown 					goto exit;
48395b482a8SLen Brown 				}
48495b482a8SLen Brown 			}
48595b482a8SLen Brown 			break;
48695b482a8SLen Brown 
48795b482a8SLen Brown 		case ACPI_REFCLASS_DEBUG:
48895b482a8SLen Brown 
48995b482a8SLen Brown 			/* The Debug Object is of type "DebugObject" */
49095b482a8SLen Brown 
49195b482a8SLen Brown 			type = ACPI_TYPE_DEBUG_OBJECT;
49295b482a8SLen Brown 			goto exit;
49395b482a8SLen Brown 
49495b482a8SLen Brown 		default:
49595b482a8SLen Brown 
49695b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
497f6a22b0bSBob Moore 				    "Unknown Reference Class 0x%2.2X",
49895b482a8SLen Brown 				    obj_desc->reference.class));
49995b482a8SLen Brown 			return_ACPI_STATUS(AE_AML_INTERNAL);
50095b482a8SLen Brown 		}
50195b482a8SLen Brown 	}
50295b482a8SLen Brown 
50395b482a8SLen Brown 	/*
50495b482a8SLen Brown 	 * Now we are guaranteed to have an object that has not been created
50595b482a8SLen Brown 	 * via the ref_of or Index operators.
50695b482a8SLen Brown 	 */
5073371c19cSBob Moore 	type = obj_desc->common.type;
50895b482a8SLen Brown 
50995b482a8SLen Brown exit:
51095b482a8SLen Brown 	/* Convert internal types to external types */
51195b482a8SLen Brown 
51295b482a8SLen Brown 	switch (type) {
51395b482a8SLen Brown 	case ACPI_TYPE_LOCAL_REGION_FIELD:
51495b482a8SLen Brown 	case ACPI_TYPE_LOCAL_BANK_FIELD:
51595b482a8SLen Brown 	case ACPI_TYPE_LOCAL_INDEX_FIELD:
51695b482a8SLen Brown 
51795b482a8SLen Brown 		type = ACPI_TYPE_FIELD_UNIT;
51895b482a8SLen Brown 		break;
51995b482a8SLen Brown 
52095b482a8SLen Brown 	case ACPI_TYPE_LOCAL_SCOPE:
52195b482a8SLen Brown 
52295b482a8SLen Brown 		/* Per ACPI Specification, Scope is untyped */
52395b482a8SLen Brown 
52495b482a8SLen Brown 		type = ACPI_TYPE_ANY;
52595b482a8SLen Brown 		break;
52695b482a8SLen Brown 
52795b482a8SLen Brown 	default:
5281d1ea1b7SChao Guan 
52995b482a8SLen Brown 		/* No change to Type required */
5301d1ea1b7SChao Guan 
53195b482a8SLen Brown 		break;
53295b482a8SLen Brown 	}
53395b482a8SLen Brown 
53495b482a8SLen Brown 	*return_type = type;
53595b482a8SLen Brown 	if (return_desc) {
53695b482a8SLen Brown 		*return_desc = obj_desc;
53795b482a8SLen Brown 	}
53895b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
53995b482a8SLen Brown }
540