xref: /linux/drivers/acpi/acpica/dsmthdat.c (revision 3702a515edec515fcc7e085053da636fefac88d6)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*******************************************************************************
3  *
4  * Module Name: dsmthdat - control method arguments and local variables
5  *
6  ******************************************************************************/
7 
8 #include <acpi/acpi.h>
9 #include "accommon.h"
10 #include "acdispat.h"
11 #include "acnamesp.h"
12 #include "acinterp.h"
13 
14 #define _COMPONENT          ACPI_DISPATCHER
15 ACPI_MODULE_NAME("dsmthdat")
16 
17 /* Local prototypes */
18 static void
19 acpi_ds_method_data_delete_value(u8 type,
20 				 u32 index, struct acpi_walk_state *walk_state);
21 
22 static acpi_status
23 acpi_ds_method_data_set_value(u8 type,
24 			      u32 index,
25 			      union acpi_operand_object *object,
26 			      struct acpi_walk_state *walk_state);
27 
28 #ifdef ACPI_OBSOLETE_FUNCTIONS
29 acpi_object_type
30 acpi_ds_method_data_get_type(u16 opcode,
31 			     u32 index, struct acpi_walk_state *walk_state);
32 #endif
33 
34 /*******************************************************************************
35  *
36  * FUNCTION:    acpi_ds_method_data_init
37  *
38  * PARAMETERS:  walk_state          - Current walk state object
39  *
40  * RETURN:      Status
41  *
42  * DESCRIPTION: Initialize the data structures that hold the method's arguments
43  *              and locals. The data struct is an array of namespace nodes for
44  *              each - this allows ref_of and de_ref_of to work properly for these
45  *              special data types.
46  *
47  * NOTES:       walk_state fields are initialized to zero by the
48  *              ACPI_ALLOCATE_ZEROED().
49  *
50  *              A pseudo-Namespace Node is assigned to each argument and local
51  *              so that ref_of() can return a pointer to the Node.
52  *
53  ******************************************************************************/
54 
acpi_ds_method_data_init(struct acpi_walk_state * walk_state)55 void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
56 {
57 	u32 i;
58 
59 	ACPI_FUNCTION_TRACE(ds_method_data_init);
60 
61 	/* Init the method arguments */
62 
63 	for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
64 		ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name,
65 				   NAMEOF_ARG_NTE);
66 
67 		walk_state->arguments[i].name.integer |= (i << 24);
68 		walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED;
69 		walk_state->arguments[i].type = ACPI_TYPE_ANY;
70 		walk_state->arguments[i].flags = ANOBJ_METHOD_ARG;
71 	}
72 
73 	/* Init the method locals */
74 
75 	for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
76 		ACPI_MOVE_32_TO_32(&walk_state->local_variables[i].name,
77 				   NAMEOF_LOCAL_NTE);
78 
79 		walk_state->local_variables[i].name.integer |= (i << 24);
80 		walk_state->local_variables[i].descriptor_type =
81 		    ACPI_DESC_TYPE_NAMED;
82 		walk_state->local_variables[i].type = ACPI_TYPE_ANY;
83 		walk_state->local_variables[i].flags = ANOBJ_METHOD_LOCAL;
84 	}
85 
86 	return_VOID;
87 }
88 
89 /*******************************************************************************
90  *
91  * FUNCTION:    acpi_ds_method_data_delete_all
92  *
93  * PARAMETERS:  walk_state          - Current walk state object
94  *
95  * RETURN:      None
96  *
97  * DESCRIPTION: Delete method locals and arguments. Arguments are only
98  *              deleted if this method was called from another method.
99  *
100  ******************************************************************************/
101 
acpi_ds_method_data_delete_all(struct acpi_walk_state * walk_state)102 void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state)
103 {
104 	u32 index;
105 
106 	ACPI_FUNCTION_TRACE(ds_method_data_delete_all);
107 
108 	/* Detach the locals */
109 
110 	for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) {
111 		if (walk_state->local_variables[index].object) {
112 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Local%u=%p\n",
113 					  index,
114 					  walk_state->local_variables[index].
115 					  object));
116 
117 			/* Detach object (if present) and remove a reference */
118 
119 			acpi_ns_detach_object(&walk_state->
120 					      local_variables[index]);
121 		}
122 	}
123 
124 	/* Detach the arguments */
125 
126 	for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) {
127 		if (walk_state->arguments[index].object) {
128 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Arg%u=%p\n",
129 					  index,
130 					  walk_state->arguments[index].object));
131 
132 			/* Detach object (if present) and remove a reference */
133 
134 			acpi_ns_detach_object(&walk_state->arguments[index]);
135 		}
136 	}
137 
138 	return_VOID;
139 }
140 
141 /*******************************************************************************
142  *
143  * FUNCTION:    acpi_ds_method_data_init_args
144  *
145  * PARAMETERS:  *params         - Pointer to a parameter list for the method
146  *              max_param_count - The arg count for this method
147  *              walk_state      - Current walk state object
148  *
149  * RETURN:      Status
150  *
151  * DESCRIPTION: Initialize arguments for a method. The parameter list is a list
152  *              of ACPI operand objects, either null terminated or whose length
153  *              is defined by max_param_count.
154  *
155  ******************************************************************************/
156 
157 acpi_status
acpi_ds_method_data_init_args(union acpi_operand_object ** params,u32 max_param_count,struct acpi_walk_state * walk_state)158 acpi_ds_method_data_init_args(union acpi_operand_object **params,
159 			      u32 max_param_count,
160 			      struct acpi_walk_state *walk_state)
161 {
162 	acpi_status status;
163 	u32 index = 0;
164 
165 	ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params);
166 
167 	if (!params) {
168 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
169 				  "No parameter list passed to method\n"));
170 		return_ACPI_STATUS(AE_OK);
171 	}
172 
173 	/* Copy passed parameters into the new method stack frame */
174 
175 	while ((index < ACPI_METHOD_NUM_ARGS) &&
176 	       (index < max_param_count) && params[index]) {
177 		/*
178 		 * A valid parameter.
179 		 * Store the argument in the method/walk descriptor.
180 		 * Do not copy the arg in order to implement call by reference
181 		 */
182 		status =
183 		    acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index,
184 						  params[index], walk_state);
185 		if (ACPI_FAILURE(status)) {
186 			return_ACPI_STATUS(status);
187 		}
188 
189 		index++;
190 	}
191 	acpi_ex_trace_args(params, index);
192 
193 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%u args passed to method\n", index));
194 	return_ACPI_STATUS(AE_OK);
195 }
196 
197 /*******************************************************************************
198  *
199  * FUNCTION:    acpi_ds_method_data_get_node
200  *
201  * PARAMETERS:  type                - Either ACPI_REFCLASS_LOCAL or
202  *                                    ACPI_REFCLASS_ARG
203  *              index               - Which Local or Arg whose type to get
204  *              walk_state          - Current walk state object
205  *              node                - Where the node is returned.
206  *
207  * RETURN:      Status and node
208  *
209  * DESCRIPTION: Get the Node associated with a local or arg.
210  *
211  ******************************************************************************/
212 
213 acpi_status
acpi_ds_method_data_get_node(u8 type,u32 index,struct acpi_walk_state * walk_state,struct acpi_namespace_node ** node)214 acpi_ds_method_data_get_node(u8 type,
215 			     u32 index,
216 			     struct acpi_walk_state *walk_state,
217 			     struct acpi_namespace_node **node)
218 {
219 	ACPI_FUNCTION_TRACE(ds_method_data_get_node);
220 
221 	/*
222 	 * Method Locals and Arguments are supported
223 	 */
224 	switch (type) {
225 	case ACPI_REFCLASS_LOCAL:
226 
227 		if (index > ACPI_METHOD_MAX_LOCAL) {
228 			ACPI_ERROR((AE_INFO,
229 				    "Local index %u is invalid (max %u)",
230 				    index, ACPI_METHOD_MAX_LOCAL));
231 			return_ACPI_STATUS(AE_AML_INVALID_INDEX);
232 		}
233 
234 		/* Return a pointer to the pseudo-node */
235 
236 		*node = &walk_state->local_variables[index];
237 		break;
238 
239 	case ACPI_REFCLASS_ARG:
240 
241 		if (index > ACPI_METHOD_MAX_ARG) {
242 			ACPI_ERROR((AE_INFO,
243 				    "Arg index %u is invalid (max %u)",
244 				    index, ACPI_METHOD_MAX_ARG));
245 			return_ACPI_STATUS(AE_AML_INVALID_INDEX);
246 		}
247 
248 		/* Return a pointer to the pseudo-node */
249 
250 		*node = &walk_state->arguments[index];
251 		break;
252 
253 	default:
254 
255 		ACPI_ERROR((AE_INFO, "Type %u is invalid", type));
256 		return_ACPI_STATUS(AE_TYPE);
257 	}
258 
259 	return_ACPI_STATUS(AE_OK);
260 }
261 
262 /*******************************************************************************
263  *
264  * FUNCTION:    acpi_ds_method_data_set_value
265  *
266  * PARAMETERS:  type                - Either ACPI_REFCLASS_LOCAL or
267  *                                    ACPI_REFCLASS_ARG
268  *              index               - Which Local or Arg to get
269  *              object              - Object to be inserted into the stack entry
270  *              walk_state          - Current walk state object
271  *
272  * RETURN:      Status
273  *
274  * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index.
275  *              Note: There is no "implicit conversion" for locals.
276  *
277  ******************************************************************************/
278 
279 static acpi_status
acpi_ds_method_data_set_value(u8 type,u32 index,union acpi_operand_object * object,struct acpi_walk_state * walk_state)280 acpi_ds_method_data_set_value(u8 type,
281 			      u32 index,
282 			      union acpi_operand_object *object,
283 			      struct acpi_walk_state *walk_state)
284 {
285 	acpi_status status;
286 	struct acpi_namespace_node *node;
287 
288 	ACPI_FUNCTION_TRACE(ds_method_data_set_value);
289 
290 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
291 			  "NewObj %p Type %2.2X, Refs=%u [%s]\n", object,
292 			  type, object->common.reference_count,
293 			  acpi_ut_get_type_name(object->common.type)));
294 
295 	/* Get the namespace node for the arg/local */
296 
297 	status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
298 	if (ACPI_FAILURE(status)) {
299 		return_ACPI_STATUS(status);
300 	}
301 
302 	/*
303 	 * Increment ref count so object can't be deleted while installed.
304 	 * NOTE: We do not copy the object in order to preserve the call by
305 	 * reference semantics of ACPI Control Method invocation.
306 	 * (See ACPI Specification 2.0C)
307 	 */
308 	acpi_ut_add_reference(object);
309 
310 	/* Install the object */
311 
312 	node->object = object;
313 	return_ACPI_STATUS(status);
314 }
315 
316 /*******************************************************************************
317  *
318  * FUNCTION:    acpi_ds_method_data_get_value
319  *
320  * PARAMETERS:  type                - Either ACPI_REFCLASS_LOCAL or
321  *                                    ACPI_REFCLASS_ARG
322  *              index               - Which localVar or argument to get
323  *              walk_state          - Current walk state object
324  *              dest_desc           - Where Arg or Local value is returned
325  *
326  * RETURN:      Status
327  *
328  * DESCRIPTION: Retrieve value of selected Arg or Local for this method
329  *              Used only in acpi_ex_resolve_to_value().
330  *
331  ******************************************************************************/
332 
333 acpi_status
acpi_ds_method_data_get_value(u8 type,u32 index,struct acpi_walk_state * walk_state,union acpi_operand_object ** dest_desc)334 acpi_ds_method_data_get_value(u8 type,
335 			      u32 index,
336 			      struct acpi_walk_state *walk_state,
337 			      union acpi_operand_object **dest_desc)
338 {
339 	acpi_status status;
340 	struct acpi_namespace_node *node;
341 	union acpi_operand_object *object;
342 
343 	ACPI_FUNCTION_TRACE(ds_method_data_get_value);
344 
345 	/* Validate the object descriptor */
346 
347 	if (!dest_desc) {
348 		ACPI_ERROR((AE_INFO, "Null object descriptor pointer"));
349 		return_ACPI_STATUS(AE_BAD_PARAMETER);
350 	}
351 
352 	/* Get the namespace node for the arg/local */
353 
354 	status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
355 	if (ACPI_FAILURE(status)) {
356 		return_ACPI_STATUS(status);
357 	}
358 
359 	/* Get the object from the node */
360 
361 	object = node->object;
362 
363 	/* Examine the returned object, it must be valid. */
364 
365 	if (!object) {
366 		/*
367 		 * Index points to uninitialized object.
368 		 * This means that either 1) The expected argument was
369 		 * not passed to the method, or 2) A local variable
370 		 * was referenced by the method (via the ASL)
371 		 * before it was initialized. Either case is an error.
372 		 */
373 
374 		/* If slack enabled, init the local_x/arg_x to an Integer of value zero */
375 
376 		if (acpi_gbl_enable_interpreter_slack) {
377 			object = acpi_ut_create_integer_object((u64) 0);
378 			if (!object) {
379 				return_ACPI_STATUS(AE_NO_MEMORY);
380 			}
381 
382 			node->object = object;
383 		}
384 
385 		/* Otherwise, return the error */
386 
387 		else
388 			switch (type) {
389 			case ACPI_REFCLASS_ARG:
390 
391 				ACPI_ERROR((AE_INFO,
392 					    "Uninitialized Arg[%u] at node %p",
393 					    index, node));
394 
395 				return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG);
396 
397 			case ACPI_REFCLASS_LOCAL:
398 				/*
399 				 * No error message for this case, will be trapped again later to
400 				 * detect and ignore cases of Store(local_x,local_x)
401 				 */
402 				return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
403 
404 			default:
405 
406 				ACPI_ERROR((AE_INFO,
407 					    "Not a Arg/Local opcode: 0x%X",
408 					    type));
409 				return_ACPI_STATUS(AE_AML_INTERNAL);
410 			}
411 	}
412 
413 	/*
414 	 * The Index points to an initialized and valid object.
415 	 * Return an additional reference to the object
416 	 */
417 	*dest_desc = object;
418 	acpi_ut_add_reference(object);
419 
420 	return_ACPI_STATUS(AE_OK);
421 }
422 
423 /*******************************************************************************
424  *
425  * FUNCTION:    acpi_ds_method_data_delete_value
426  *
427  * PARAMETERS:  type                - Either ACPI_REFCLASS_LOCAL or
428  *                                    ACPI_REFCLASS_ARG
429  *              index               - Which localVar or argument to delete
430  *              walk_state          - Current walk state object
431  *
432  * RETURN:      None
433  *
434  * DESCRIPTION: Delete the entry at Opcode:Index. Inserts
435  *              a null into the stack slot after the object is deleted.
436  *
437  ******************************************************************************/
438 
439 static void
acpi_ds_method_data_delete_value(u8 type,u32 index,struct acpi_walk_state * walk_state)440 acpi_ds_method_data_delete_value(u8 type,
441 				 u32 index, struct acpi_walk_state *walk_state)
442 {
443 	acpi_status status;
444 	struct acpi_namespace_node *node;
445 	union acpi_operand_object *object;
446 
447 	ACPI_FUNCTION_TRACE(ds_method_data_delete_value);
448 
449 	/* Get the namespace node for the arg/local */
450 
451 	status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
452 	if (ACPI_FAILURE(status)) {
453 		return_VOID;
454 	}
455 
456 	/* Get the associated object */
457 
458 	object = acpi_ns_get_attached_object(node);
459 
460 	/*
461 	 * Undefine the Arg or Local by setting its descriptor
462 	 * pointer to NULL. Locals/Args can contain both
463 	 * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs
464 	 */
465 	node->object = NULL;
466 
467 	if ((object) &&
468 	    (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_OPERAND)) {
469 		/*
470 		 * There is a valid object.
471 		 * Decrement the reference count by one to balance the
472 		 * increment when the object was stored.
473 		 */
474 		acpi_ut_remove_reference(object);
475 	}
476 
477 	return_VOID;
478 }
479 
480 /*******************************************************************************
481  *
482  * FUNCTION:    acpi_ds_store_object_to_local
483  *
484  * PARAMETERS:  type                - Either ACPI_REFCLASS_LOCAL or
485  *                                    ACPI_REFCLASS_ARG
486  *              index               - Which Local or Arg to set
487  *              obj_desc            - Value to be stored
488  *              walk_state          - Current walk state
489  *
490  * RETURN:      Status
491  *
492  * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed
493  *              as the new value for the Arg or Local and the reference count
494  *              for obj_desc is incremented.
495  *
496  ******************************************************************************/
497 
498 acpi_status
acpi_ds_store_object_to_local(u8 type,u32 index,union acpi_operand_object * obj_desc,struct acpi_walk_state * walk_state)499 acpi_ds_store_object_to_local(u8 type,
500 			      u32 index,
501 			      union acpi_operand_object *obj_desc,
502 			      struct acpi_walk_state *walk_state)
503 {
504 	acpi_status status;
505 	struct acpi_namespace_node *node;
506 	union acpi_operand_object *current_obj_desc;
507 	union acpi_operand_object *new_obj_desc;
508 
509 	ACPI_FUNCTION_TRACE(ds_store_object_to_local);
510 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%u Obj=%p\n",
511 			  type, index, obj_desc));
512 
513 	/* Parameter validation */
514 
515 	if (!obj_desc) {
516 		return_ACPI_STATUS(AE_BAD_PARAMETER);
517 	}
518 
519 	/* Get the namespace node for the arg/local */
520 
521 	status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
522 	if (ACPI_FAILURE(status)) {
523 		return_ACPI_STATUS(status);
524 	}
525 
526 	current_obj_desc = acpi_ns_get_attached_object(node);
527 	if (current_obj_desc == obj_desc) {
528 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n",
529 				  obj_desc));
530 		return_ACPI_STATUS(status);
531 	}
532 
533 	/*
534 	 * If the reference count on the object is more than one, we must
535 	 * take a copy of the object before we store. A reference count
536 	 * of exactly 1 means that the object was just created during the
537 	 * evaluation of an expression, and we can safely use it since it
538 	 * is not used anywhere else.
539 	 */
540 	new_obj_desc = obj_desc;
541 	if (obj_desc->common.reference_count > 1) {
542 		status =
543 		    acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc,
544 						    walk_state);
545 		if (ACPI_FAILURE(status)) {
546 			return_ACPI_STATUS(status);
547 		}
548 	}
549 
550 	/*
551 	 * If there is an object already in this slot, we either
552 	 * have to delete it, or if this is an argument and there
553 	 * is an object reference stored there, we have to do
554 	 * an indirect store!
555 	 */
556 	if (current_obj_desc) {
557 		/*
558 		 * Check for an indirect store if an argument
559 		 * contains an object reference (stored as an Node).
560 		 * We don't allow this automatic dereferencing for
561 		 * locals, since a store to a local should overwrite
562 		 * anything there, including an object reference.
563 		 *
564 		 * If both Arg0 and Local0 contain ref_of (Local4):
565 		 *
566 		 * Store (1, Arg0)             - Causes indirect store to local4
567 		 * Store (1, Local0)           - Stores 1 in local0, overwriting
568 		 *                                  the reference to local4
569 		 * Store (1, de_refof (Local0)) - Causes indirect store to local4
570 		 *
571 		 * Weird, but true.
572 		 */
573 		if (type == ACPI_REFCLASS_ARG) {
574 			/*
575 			 * If we have a valid reference object that came from ref_of(),
576 			 * do the indirect store
577 			 */
578 			if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) ==
579 			     ACPI_DESC_TYPE_OPERAND) &&
580 			    (current_obj_desc->common.type ==
581 			     ACPI_TYPE_LOCAL_REFERENCE) &&
582 			    (current_obj_desc->reference.class ==
583 			     ACPI_REFCLASS_REFOF)) {
584 				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
585 						  "Arg (%p) is an ObjRef(Node), storing in node %p\n",
586 						  new_obj_desc,
587 						  current_obj_desc));
588 
589 				/*
590 				 * Store this object to the Node (perform the indirect store)
591 				 * NOTE: No implicit conversion is performed, as per the ACPI
592 				 * specification rules on storing to Locals/Args.
593 				 */
594 				status =
595 				    acpi_ex_store_object_to_node(new_obj_desc,
596 								 current_obj_desc->
597 								 reference.
598 								 object,
599 								 walk_state,
600 								 ACPI_NO_IMPLICIT_CONVERSION);
601 
602 				/* Remove local reference if we copied the object above */
603 
604 				if (new_obj_desc != obj_desc) {
605 					acpi_ut_remove_reference(new_obj_desc);
606 				}
607 
608 				return_ACPI_STATUS(status);
609 			}
610 		}
611 
612 		/* Delete the existing object before storing the new one */
613 
614 		acpi_ds_method_data_delete_value(type, index, walk_state);
615 	}
616 
617 	/*
618 	 * Install the Obj descriptor (*new_obj_desc) into
619 	 * the descriptor for the Arg or Local.
620 	 * (increments the object reference count by one)
621 	 */
622 	status =
623 	    acpi_ds_method_data_set_value(type, index, new_obj_desc,
624 					  walk_state);
625 
626 	/* Remove local reference if we copied the object above */
627 
628 	if (new_obj_desc != obj_desc) {
629 		acpi_ut_remove_reference(new_obj_desc);
630 	}
631 
632 	return_ACPI_STATUS(status);
633 }
634 
635 #ifdef ACPI_OBSOLETE_FUNCTIONS
636 /*******************************************************************************
637  *
638  * FUNCTION:    acpi_ds_method_data_get_type
639  *
640  * PARAMETERS:  opcode              - Either AML_FIRST LOCAL_OP or
641  *                                    AML_FIRST_ARG_OP
642  *              index               - Which Local or Arg whose type to get
643  *              walk_state          - Current walk state object
644  *
645  * RETURN:      Data type of current value of the selected Arg or Local
646  *
647  * DESCRIPTION: Get the type of the object stored in the Local or Arg
648  *
649  ******************************************************************************/
650 
651 acpi_object_type
acpi_ds_method_data_get_type(u16 opcode,u32 index,struct acpi_walk_state * walk_state)652 acpi_ds_method_data_get_type(u16 opcode,
653 			     u32 index, struct acpi_walk_state *walk_state)
654 {
655 	acpi_status status;
656 	struct acpi_namespace_node *node;
657 	union acpi_operand_object *object;
658 
659 	ACPI_FUNCTION_TRACE(ds_method_data_get_type);
660 
661 	/* Get the namespace node for the arg/local */
662 
663 	status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
664 	if (ACPI_FAILURE(status)) {
665 		return_VALUE((ACPI_TYPE_NOT_FOUND));
666 	}
667 
668 	/* Get the object */
669 
670 	object = acpi_ns_get_attached_object(node);
671 	if (!object) {
672 
673 		/* Uninitialized local/arg, return TYPE_ANY */
674 
675 		return_VALUE(ACPI_TYPE_ANY);
676 	}
677 
678 	/* Get the object type */
679 
680 	return_VALUE(object->type);
681 }
682 #endif
683