xref: /openbmc/linux/drivers/acpi/acpica/exoparg1.c (revision dd21bfa4)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: exoparg1 - AML execution - opcodes with 1 argument
5  *
6  * Copyright (C) 2000 - 2021, Intel Corp.
7  *
8  *****************************************************************************/
9 
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acparser.h"
13 #include "acdispat.h"
14 #include "acinterp.h"
15 #include "amlcode.h"
16 #include "acnamesp.h"
17 
18 #define _COMPONENT          ACPI_EXECUTER
19 ACPI_MODULE_NAME("exoparg1")
20 
21 /*!
22  * Naming convention for AML interpreter execution routines.
23  *
24  * The routines that begin execution of AML opcodes are named with a common
25  * convention based upon the number of arguments, the number of target operands,
26  * and whether or not a value is returned:
27  *
28  *      AcpiExOpcode_xA_yT_zR
29  *
30  * Where:
31  *
32  * xA - ARGUMENTS:    The number of arguments (input operands) that are
33  *                    required for this opcode type (0 through 6 args).
34  * yT - TARGETS:      The number of targets (output operands) that are required
35  *                    for this opcode type (0, 1, or 2 targets).
36  * zR - RETURN VALUE: Indicates whether this opcode type returns a value
37  *                    as the function return (0 or 1).
38  *
39  * The AcpiExOpcode* functions are called via the Dispatcher component with
40  * fully resolved operands.
41 !*/
42 /*******************************************************************************
43  *
44  * FUNCTION:    acpi_ex_opcode_0A_0T_1R
45  *
46  * PARAMETERS:  walk_state          - Current state (contains AML opcode)
47  *
48  * RETURN:      Status
49  *
50  * DESCRIPTION: Execute operator with no operands, one return value
51  *
52  ******************************************************************************/
53 acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
54 {
55 	acpi_status status = AE_OK;
56 	union acpi_operand_object *return_desc = NULL;
57 
58 	ACPI_FUNCTION_TRACE_STR(ex_opcode_0A_0T_1R,
59 				acpi_ps_get_opcode_name(walk_state->opcode));
60 
61 	/* Examine the AML opcode */
62 
63 	switch (walk_state->opcode) {
64 	case AML_TIMER_OP:	/*  Timer () */
65 
66 		/* Create a return object of type Integer */
67 
68 		return_desc =
69 		    acpi_ut_create_integer_object(acpi_os_get_timer());
70 		if (!return_desc) {
71 			status = AE_NO_MEMORY;
72 			goto cleanup;
73 		}
74 		break;
75 
76 	default:		/*  Unknown opcode  */
77 
78 		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
79 			    walk_state->opcode));
80 		status = AE_AML_BAD_OPCODE;
81 		break;
82 	}
83 
84 cleanup:
85 
86 	/* Delete return object on error */
87 
88 	if ((ACPI_FAILURE(status)) || walk_state->result_obj) {
89 		acpi_ut_remove_reference(return_desc);
90 		walk_state->result_obj = NULL;
91 	} else {
92 		/* Save the return value */
93 
94 		walk_state->result_obj = return_desc;
95 	}
96 
97 	return_ACPI_STATUS(status);
98 }
99 
100 /*******************************************************************************
101  *
102  * FUNCTION:    acpi_ex_opcode_1A_0T_0R
103  *
104  * PARAMETERS:  walk_state          - Current state (contains AML opcode)
105  *
106  * RETURN:      Status
107  *
108  * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
109  *              object stack
110  *
111  ******************************************************************************/
112 
113 acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state)
114 {
115 	union acpi_operand_object **operand = &walk_state->operands[0];
116 	acpi_status status = AE_OK;
117 
118 	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_0R,
119 				acpi_ps_get_opcode_name(walk_state->opcode));
120 
121 	/* Examine the AML opcode */
122 
123 	switch (walk_state->opcode) {
124 	case AML_RELEASE_OP:	/*  Release (mutex_object) */
125 
126 		status = acpi_ex_release_mutex(operand[0], walk_state);
127 		break;
128 
129 	case AML_RESET_OP:	/*  Reset (event_object) */
130 
131 		status = acpi_ex_system_reset_event(operand[0]);
132 		break;
133 
134 	case AML_SIGNAL_OP:	/*  Signal (event_object) */
135 
136 		status = acpi_ex_system_signal_event(operand[0]);
137 		break;
138 
139 	case AML_SLEEP_OP:	/*  Sleep (msec_time) */
140 
141 		status = acpi_ex_system_do_sleep(operand[0]->integer.value);
142 		break;
143 
144 	case AML_STALL_OP:	/*  Stall (usec_time) */
145 
146 		status =
147 		    acpi_ex_system_do_stall((u32) operand[0]->integer.value);
148 		break;
149 
150 	case AML_UNLOAD_OP:	/*  Unload (Handle) */
151 
152 		status = acpi_ex_unload_table(operand[0]);
153 		break;
154 
155 	default:		/*  Unknown opcode  */
156 
157 		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
158 			    walk_state->opcode));
159 		status = AE_AML_BAD_OPCODE;
160 		break;
161 	}
162 
163 	return_ACPI_STATUS(status);
164 }
165 
166 /*******************************************************************************
167  *
168  * FUNCTION:    acpi_ex_opcode_1A_1T_0R
169  *
170  * PARAMETERS:  walk_state          - Current state (contains AML opcode)
171  *
172  * RETURN:      Status
173  *
174  * DESCRIPTION: Execute opcode with one argument, one target, and no
175  *              return value.
176  *
177  ******************************************************************************/
178 
179 acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state)
180 {
181 	acpi_status status = AE_OK;
182 	union acpi_operand_object **operand = &walk_state->operands[0];
183 
184 	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_0R,
185 				acpi_ps_get_opcode_name(walk_state->opcode));
186 
187 	/* Examine the AML opcode */
188 
189 	switch (walk_state->opcode) {
190 	case AML_LOAD_OP:
191 
192 		status = acpi_ex_load_op(operand[0], operand[1], walk_state);
193 		break;
194 
195 	default:		/* Unknown opcode */
196 
197 		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
198 			    walk_state->opcode));
199 		status = AE_AML_BAD_OPCODE;
200 		goto cleanup;
201 	}
202 
203 cleanup:
204 
205 	return_ACPI_STATUS(status);
206 }
207 
208 /*******************************************************************************
209  *
210  * FUNCTION:    acpi_ex_opcode_1A_1T_1R
211  *
212  * PARAMETERS:  walk_state          - Current state (contains AML opcode)
213  *
214  * RETURN:      Status
215  *
216  * DESCRIPTION: Execute opcode with one argument, one target, and a
217  *              return value.
218  *
219  ******************************************************************************/
220 
221 acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
222 {
223 	acpi_status status = AE_OK;
224 	union acpi_operand_object **operand = &walk_state->operands[0];
225 	union acpi_operand_object *return_desc = NULL;
226 	union acpi_operand_object *return_desc2 = NULL;
227 	u32 temp32;
228 	u32 i;
229 	u64 power_of_ten;
230 	u64 digit;
231 
232 	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_1R,
233 				acpi_ps_get_opcode_name(walk_state->opcode));
234 
235 	/* Examine the AML opcode */
236 
237 	switch (walk_state->opcode) {
238 	case AML_BIT_NOT_OP:
239 	case AML_FIND_SET_LEFT_BIT_OP:
240 	case AML_FIND_SET_RIGHT_BIT_OP:
241 	case AML_FROM_BCD_OP:
242 	case AML_TO_BCD_OP:
243 	case AML_CONDITIONAL_REF_OF_OP:
244 
245 		/* Create a return object of type Integer for these opcodes */
246 
247 		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
248 		if (!return_desc) {
249 			status = AE_NO_MEMORY;
250 			goto cleanup;
251 		}
252 
253 		switch (walk_state->opcode) {
254 		case AML_BIT_NOT_OP:	/* Not (Operand, Result)  */
255 
256 			return_desc->integer.value = ~operand[0]->integer.value;
257 			break;
258 
259 		case AML_FIND_SET_LEFT_BIT_OP:	/* find_set_left_bit (Operand, Result) */
260 
261 			return_desc->integer.value = operand[0]->integer.value;
262 
263 			/*
264 			 * Acpi specification describes Integer type as a little
265 			 * endian unsigned value, so this boundary condition is valid.
266 			 */
267 			for (temp32 = 0; return_desc->integer.value &&
268 			     temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
269 				return_desc->integer.value >>= 1;
270 			}
271 
272 			return_desc->integer.value = temp32;
273 			break;
274 
275 		case AML_FIND_SET_RIGHT_BIT_OP:	/* find_set_right_bit (Operand, Result) */
276 
277 			return_desc->integer.value = operand[0]->integer.value;
278 
279 			/*
280 			 * The Acpi specification describes Integer type as a little
281 			 * endian unsigned value, so this boundary condition is valid.
282 			 */
283 			for (temp32 = 0; return_desc->integer.value &&
284 			     temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
285 				return_desc->integer.value <<= 1;
286 			}
287 
288 			/* Since the bit position is one-based, subtract from 33 (65) */
289 
290 			return_desc->integer.value =
291 			    temp32 ==
292 			    0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
293 			break;
294 
295 		case AML_FROM_BCD_OP:	/* from_bcd (BCDValue, Result) */
296 			/*
297 			 * The 64-bit ACPI integer can hold 16 4-bit BCD characters
298 			 * (if table is 32-bit, integer can hold 8 BCD characters)
299 			 * Convert each 4-bit BCD value
300 			 */
301 			power_of_ten = 1;
302 			return_desc->integer.value = 0;
303 			digit = operand[0]->integer.value;
304 
305 			/* Convert each BCD digit (each is one nybble wide) */
306 
307 			for (i = 0;
308 			     (i < acpi_gbl_integer_nybble_width) && (digit > 0);
309 			     i++) {
310 
311 				/* Get the least significant 4-bit BCD digit */
312 
313 				temp32 = ((u32) digit) & 0xF;
314 
315 				/* Check the range of the digit */
316 
317 				if (temp32 > 9) {
318 					ACPI_ERROR((AE_INFO,
319 						    "BCD digit too large (not decimal): 0x%X",
320 						    temp32));
321 
322 					status = AE_AML_NUMERIC_OVERFLOW;
323 					goto cleanup;
324 				}
325 
326 				/* Sum the digit into the result with the current power of 10 */
327 
328 				return_desc->integer.value +=
329 				    (((u64) temp32) * power_of_ten);
330 
331 				/* Shift to next BCD digit */
332 
333 				digit >>= 4;
334 
335 				/* Next power of 10 */
336 
337 				power_of_ten *= 10;
338 			}
339 			break;
340 
341 		case AML_TO_BCD_OP:	/* to_bcd (Operand, Result) */
342 
343 			return_desc->integer.value = 0;
344 			digit = operand[0]->integer.value;
345 
346 			/* Each BCD digit is one nybble wide */
347 
348 			for (i = 0;
349 			     (i < acpi_gbl_integer_nybble_width) && (digit > 0);
350 			     i++) {
351 				(void)acpi_ut_short_divide(digit, 10, &digit,
352 							   &temp32);
353 
354 				/*
355 				 * Insert the BCD digit that resides in the
356 				 * remainder from above
357 				 */
358 				return_desc->integer.value |=
359 				    (((u64) temp32) << ACPI_MUL_4(i));
360 			}
361 
362 			/* Overflow if there is any data left in Digit */
363 
364 			if (digit > 0) {
365 				ACPI_ERROR((AE_INFO,
366 					    "Integer too large to convert to BCD: 0x%8.8X%8.8X",
367 					    ACPI_FORMAT_UINT64(operand[0]->
368 							       integer.value)));
369 				status = AE_AML_NUMERIC_OVERFLOW;
370 				goto cleanup;
371 			}
372 			break;
373 
374 		case AML_CONDITIONAL_REF_OF_OP:	/* cond_ref_of (source_object, Result) */
375 			/*
376 			 * This op is a little strange because the internal return value is
377 			 * different than the return value stored in the result descriptor
378 			 * (There are really two return values)
379 			 */
380 			if ((struct acpi_namespace_node *)operand[0] ==
381 			    acpi_gbl_root_node) {
382 				/*
383 				 * This means that the object does not exist in the namespace,
384 				 * return FALSE
385 				 */
386 				return_desc->integer.value = 0;
387 				goto cleanup;
388 			}
389 
390 			/* Get the object reference, store it, and remove our reference */
391 
392 			status = acpi_ex_get_object_reference(operand[0],
393 							      &return_desc2,
394 							      walk_state);
395 			if (ACPI_FAILURE(status)) {
396 				goto cleanup;
397 			}
398 
399 			status =
400 			    acpi_ex_store(return_desc2, operand[1], walk_state);
401 			acpi_ut_remove_reference(return_desc2);
402 
403 			/* The object exists in the namespace, return TRUE */
404 
405 			return_desc->integer.value = ACPI_UINT64_MAX;
406 			goto cleanup;
407 
408 		default:
409 
410 			/* No other opcodes get here */
411 
412 			break;
413 		}
414 		break;
415 
416 	case AML_STORE_OP:	/* Store (Source, Target) */
417 		/*
418 		 * A store operand is typically a number, string, buffer or lvalue
419 		 * Be careful about deleting the source object,
420 		 * since the object itself may have been stored.
421 		 */
422 		status = acpi_ex_store(operand[0], operand[1], walk_state);
423 		if (ACPI_FAILURE(status)) {
424 			return_ACPI_STATUS(status);
425 		}
426 
427 		/* It is possible that the Store already produced a return object */
428 
429 		if (!walk_state->result_obj) {
430 			/*
431 			 * Normally, we would remove a reference on the Operand[0]
432 			 * parameter; But since it is being used as the internal return
433 			 * object (meaning we would normally increment it), the two
434 			 * cancel out, and we simply don't do anything.
435 			 */
436 			walk_state->result_obj = operand[0];
437 			walk_state->operands[0] = NULL;	/* Prevent deletion */
438 		}
439 		return_ACPI_STATUS(status);
440 
441 		/*
442 		 * ACPI 2.0 Opcodes
443 		 */
444 	case AML_COPY_OBJECT_OP:	/* copy_object (Source, Target) */
445 
446 		status =
447 		    acpi_ut_copy_iobject_to_iobject(operand[0], &return_desc,
448 						    walk_state);
449 		break;
450 
451 	case AML_TO_DECIMAL_STRING_OP:	/* to_decimal_string (Data, Result) */
452 
453 		status =
454 		    acpi_ex_convert_to_string(operand[0], &return_desc,
455 					      ACPI_EXPLICIT_CONVERT_DECIMAL);
456 		if (return_desc == operand[0]) {
457 
458 			/* No conversion performed, add ref to handle return value */
459 
460 			acpi_ut_add_reference(return_desc);
461 		}
462 		break;
463 
464 	case AML_TO_HEX_STRING_OP:	/* to_hex_string (Data, Result) */
465 
466 		status =
467 		    acpi_ex_convert_to_string(operand[0], &return_desc,
468 					      ACPI_EXPLICIT_CONVERT_HEX);
469 		if (return_desc == operand[0]) {
470 
471 			/* No conversion performed, add ref to handle return value */
472 
473 			acpi_ut_add_reference(return_desc);
474 		}
475 		break;
476 
477 	case AML_TO_BUFFER_OP:	/* to_buffer (Data, Result) */
478 
479 		status = acpi_ex_convert_to_buffer(operand[0], &return_desc);
480 		if (return_desc == operand[0]) {
481 
482 			/* No conversion performed, add ref to handle return value */
483 
484 			acpi_ut_add_reference(return_desc);
485 		}
486 		break;
487 
488 	case AML_TO_INTEGER_OP:	/* to_integer (Data, Result) */
489 
490 		/* Perform "explicit" conversion */
491 
492 		status =
493 		    acpi_ex_convert_to_integer(operand[0], &return_desc, 0);
494 		if (return_desc == operand[0]) {
495 
496 			/* No conversion performed, add ref to handle return value */
497 
498 			acpi_ut_add_reference(return_desc);
499 		}
500 		break;
501 
502 	case AML_SHIFT_LEFT_BIT_OP:	/* shift_left_bit (Source, bit_num) */
503 	case AML_SHIFT_RIGHT_BIT_OP:	/* shift_right_bit (Source, bit_num) */
504 
505 		/* These are two obsolete opcodes */
506 
507 		ACPI_ERROR((AE_INFO,
508 			    "%s is obsolete and not implemented",
509 			    acpi_ps_get_opcode_name(walk_state->opcode)));
510 		status = AE_SUPPORT;
511 		goto cleanup;
512 
513 	default:		/* Unknown opcode */
514 
515 		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
516 			    walk_state->opcode));
517 		status = AE_AML_BAD_OPCODE;
518 		goto cleanup;
519 	}
520 
521 	if (ACPI_SUCCESS(status)) {
522 
523 		/* Store the return value computed above into the target object */
524 
525 		status = acpi_ex_store(return_desc, operand[1], walk_state);
526 	}
527 
528 cleanup:
529 
530 	/* Delete return object on error */
531 
532 	if (ACPI_FAILURE(status)) {
533 		acpi_ut_remove_reference(return_desc);
534 	}
535 
536 	/* Save return object on success */
537 
538 	else if (!walk_state->result_obj) {
539 		walk_state->result_obj = return_desc;
540 	}
541 
542 	return_ACPI_STATUS(status);
543 }
544 
545 /*******************************************************************************
546  *
547  * FUNCTION:    acpi_ex_opcode_1A_0T_1R
548  *
549  * PARAMETERS:  walk_state          - Current state (contains AML opcode)
550  *
551  * RETURN:      Status
552  *
553  * DESCRIPTION: Execute opcode with one argument, no target, and a return value
554  *
555  ******************************************************************************/
556 
557 acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
558 {
559 	union acpi_operand_object **operand = &walk_state->operands[0];
560 	union acpi_operand_object *temp_desc;
561 	union acpi_operand_object *return_desc = NULL;
562 	acpi_status status = AE_OK;
563 	u32 type;
564 	u64 value;
565 
566 	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_1R,
567 				acpi_ps_get_opcode_name(walk_state->opcode));
568 
569 	/* Examine the AML opcode */
570 
571 	switch (walk_state->opcode) {
572 	case AML_LOGICAL_NOT_OP:	/* LNot (Operand) */
573 
574 		return_desc = acpi_ut_create_integer_object((u64) 0);
575 		if (!return_desc) {
576 			status = AE_NO_MEMORY;
577 			goto cleanup;
578 		}
579 
580 		/*
581 		 * Set result to ONES (TRUE) if Value == 0. Note:
582 		 * return_desc->Integer.Value is initially == 0 (FALSE) from above.
583 		 */
584 		if (!operand[0]->integer.value) {
585 			return_desc->integer.value = ACPI_UINT64_MAX;
586 		}
587 		break;
588 
589 	case AML_DECREMENT_OP:	/* Decrement (Operand)  */
590 	case AML_INCREMENT_OP:	/* Increment (Operand)  */
591 		/*
592 		 * Create a new integer. Can't just get the base integer and
593 		 * increment it because it may be an Arg or Field.
594 		 */
595 		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
596 		if (!return_desc) {
597 			status = AE_NO_MEMORY;
598 			goto cleanup;
599 		}
600 
601 		/*
602 		 * Since we are expecting a Reference operand, it can be either a
603 		 * NS Node or an internal object.
604 		 */
605 		temp_desc = operand[0];
606 		if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) ==
607 		    ACPI_DESC_TYPE_OPERAND) {
608 
609 			/* Internal reference object - prevent deletion */
610 
611 			acpi_ut_add_reference(temp_desc);
612 		}
613 
614 		/*
615 		 * Convert the Reference operand to an Integer (This removes a
616 		 * reference on the Operand[0] object)
617 		 *
618 		 * NOTE:  We use LNOT_OP here in order to force resolution of the
619 		 * reference operand to an actual integer.
620 		 */
621 		status = acpi_ex_resolve_operands(AML_LOGICAL_NOT_OP,
622 						  &temp_desc, walk_state);
623 		if (ACPI_FAILURE(status)) {
624 			ACPI_EXCEPTION((AE_INFO, status,
625 					"While resolving operands for [%s]",
626 					acpi_ps_get_opcode_name(walk_state->
627 								opcode)));
628 
629 			goto cleanup;
630 		}
631 
632 		/*
633 		 * temp_desc is now guaranteed to be an Integer object --
634 		 * Perform the actual increment or decrement
635 		 */
636 		if (walk_state->opcode == AML_INCREMENT_OP) {
637 			return_desc->integer.value =
638 			    temp_desc->integer.value + 1;
639 		} else {
640 			return_desc->integer.value =
641 			    temp_desc->integer.value - 1;
642 		}
643 
644 		/* Finished with this Integer object */
645 
646 		acpi_ut_remove_reference(temp_desc);
647 
648 		/*
649 		 * Store the result back (indirectly) through the original
650 		 * Reference object
651 		 */
652 		status = acpi_ex_store(return_desc, operand[0], walk_state);
653 		break;
654 
655 	case AML_OBJECT_TYPE_OP:	/* object_type (source_object) */
656 		/*
657 		 * Note: The operand is not resolved at this point because we want to
658 		 * get the associated object, not its value. For example, we don't
659 		 * want to resolve a field_unit to its value, we want the actual
660 		 * field_unit object.
661 		 */
662 
663 		/* Get the type of the base object */
664 
665 		status =
666 		    acpi_ex_resolve_multiple(walk_state, operand[0], &type,
667 					     NULL);
668 		if (ACPI_FAILURE(status)) {
669 			goto cleanup;
670 		}
671 
672 		/* Allocate a descriptor to hold the type. */
673 
674 		return_desc = acpi_ut_create_integer_object((u64) type);
675 		if (!return_desc) {
676 			status = AE_NO_MEMORY;
677 			goto cleanup;
678 		}
679 		break;
680 
681 	case AML_SIZE_OF_OP:	/* size_of (source_object) */
682 		/*
683 		 * Note: The operand is not resolved at this point because we want to
684 		 * get the associated object, not its value.
685 		 */
686 
687 		/* Get the base object */
688 
689 		status =
690 		    acpi_ex_resolve_multiple(walk_state, operand[0], &type,
691 					     &temp_desc);
692 		if (ACPI_FAILURE(status)) {
693 			goto cleanup;
694 		}
695 
696 		/*
697 		 * The type of the base object must be integer, buffer, string, or
698 		 * package. All others are not supported.
699 		 *
700 		 * NOTE: Integer is not specifically supported by the ACPI spec,
701 		 * but is supported implicitly via implicit operand conversion.
702 		 * rather than bother with conversion, we just use the byte width
703 		 * global (4 or 8 bytes).
704 		 */
705 		switch (type) {
706 		case ACPI_TYPE_INTEGER:
707 
708 			value = acpi_gbl_integer_byte_width;
709 			break;
710 
711 		case ACPI_TYPE_STRING:
712 
713 			value = temp_desc->string.length;
714 			break;
715 
716 		case ACPI_TYPE_BUFFER:
717 
718 			/* Buffer arguments may not be evaluated at this point */
719 
720 			status = acpi_ds_get_buffer_arguments(temp_desc);
721 			value = temp_desc->buffer.length;
722 			break;
723 
724 		case ACPI_TYPE_PACKAGE:
725 
726 			/* Package arguments may not be evaluated at this point */
727 
728 			status = acpi_ds_get_package_arguments(temp_desc);
729 			value = temp_desc->package.count;
730 			break;
731 
732 		default:
733 
734 			ACPI_ERROR((AE_INFO,
735 				    "Operand must be Buffer/Integer/String/Package"
736 				    " - found type %s",
737 				    acpi_ut_get_type_name(type)));
738 
739 			status = AE_AML_OPERAND_TYPE;
740 			goto cleanup;
741 		}
742 
743 		if (ACPI_FAILURE(status)) {
744 			goto cleanup;
745 		}
746 
747 		/*
748 		 * Now that we have the size of the object, create a result
749 		 * object to hold the value
750 		 */
751 		return_desc = acpi_ut_create_integer_object(value);
752 		if (!return_desc) {
753 			status = AE_NO_MEMORY;
754 			goto cleanup;
755 		}
756 		break;
757 
758 	case AML_REF_OF_OP:	/* ref_of (source_object) */
759 
760 		status =
761 		    acpi_ex_get_object_reference(operand[0], &return_desc,
762 						 walk_state);
763 		if (ACPI_FAILURE(status)) {
764 			goto cleanup;
765 		}
766 		break;
767 
768 	case AML_DEREF_OF_OP:	/* deref_of (obj_reference | String) */
769 
770 		/* Check for a method local or argument, or standalone String */
771 
772 		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
773 		    ACPI_DESC_TYPE_NAMED) {
774 			temp_desc =
775 			    acpi_ns_get_attached_object((struct
776 							 acpi_namespace_node *)
777 							operand[0]);
778 			if (temp_desc
779 			    && ((temp_desc->common.type == ACPI_TYPE_STRING)
780 				|| (temp_desc->common.type ==
781 				    ACPI_TYPE_LOCAL_REFERENCE))) {
782 				operand[0] = temp_desc;
783 				acpi_ut_add_reference(temp_desc);
784 			} else {
785 				status = AE_AML_OPERAND_TYPE;
786 				goto cleanup;
787 			}
788 		} else {
789 			switch ((operand[0])->common.type) {
790 			case ACPI_TYPE_LOCAL_REFERENCE:
791 				/*
792 				 * This is a deref_of (local_x | arg_x)
793 				 *
794 				 * Must resolve/dereference the local/arg reference first
795 				 */
796 				switch (operand[0]->reference.class) {
797 				case ACPI_REFCLASS_LOCAL:
798 				case ACPI_REFCLASS_ARG:
799 
800 					/* Set Operand[0] to the value of the local/arg */
801 
802 					status =
803 					    acpi_ds_method_data_get_value
804 					    (operand[0]->reference.class,
805 					     operand[0]->reference.value,
806 					     walk_state, &temp_desc);
807 					if (ACPI_FAILURE(status)) {
808 						goto cleanup;
809 					}
810 
811 					/*
812 					 * Delete our reference to the input object and
813 					 * point to the object just retrieved
814 					 */
815 					acpi_ut_remove_reference(operand[0]);
816 					operand[0] = temp_desc;
817 					break;
818 
819 				case ACPI_REFCLASS_REFOF:
820 
821 					/* Get the object to which the reference refers */
822 
823 					temp_desc =
824 					    operand[0]->reference.object;
825 					acpi_ut_remove_reference(operand[0]);
826 					operand[0] = temp_desc;
827 					break;
828 
829 				default:
830 
831 					/* Must be an Index op - handled below */
832 					break;
833 				}
834 				break;
835 
836 			case ACPI_TYPE_STRING:
837 
838 				break;
839 
840 			default:
841 
842 				status = AE_AML_OPERAND_TYPE;
843 				goto cleanup;
844 			}
845 		}
846 
847 		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) !=
848 		    ACPI_DESC_TYPE_NAMED) {
849 			if ((operand[0])->common.type == ACPI_TYPE_STRING) {
850 				/*
851 				 * This is a deref_of (String). The string is a reference
852 				 * to a named ACPI object.
853 				 *
854 				 * 1) Find the owning Node
855 				 * 2) Dereference the node to an actual object. Could be a
856 				 *    Field, so we need to resolve the node to a value.
857 				 */
858 				status =
859 				    acpi_ns_get_node_unlocked(walk_state->
860 							      scope_info->scope.
861 							      node,
862 							      operand[0]->
863 							      string.pointer,
864 							      ACPI_NS_SEARCH_PARENT,
865 							      ACPI_CAST_INDIRECT_PTR
866 							      (struct
867 							       acpi_namespace_node,
868 							       &return_desc));
869 				if (ACPI_FAILURE(status)) {
870 					goto cleanup;
871 				}
872 
873 				status =
874 				    acpi_ex_resolve_node_to_value
875 				    (ACPI_CAST_INDIRECT_PTR
876 				     (struct acpi_namespace_node, &return_desc),
877 				     walk_state);
878 				goto cleanup;
879 			}
880 		}
881 
882 		/* Operand[0] may have changed from the code above */
883 
884 		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
885 		    ACPI_DESC_TYPE_NAMED) {
886 			/*
887 			 * This is a deref_of (object_reference)
888 			 * Get the actual object from the Node (This is the dereference).
889 			 * This case may only happen when a local_x or arg_x is
890 			 * dereferenced above, or for references to device and
891 			 * thermal objects.
892 			 */
893 			switch (((struct acpi_namespace_node *)operand[0])->
894 				type) {
895 			case ACPI_TYPE_DEVICE:
896 			case ACPI_TYPE_THERMAL:
897 
898 				/* These types have no node subobject, return the NS node */
899 
900 				return_desc = operand[0];
901 				break;
902 
903 			default:
904 				/* For most types, get the object attached to the node */
905 
906 				return_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *)operand[0]);
907 				acpi_ut_add_reference(return_desc);
908 				break;
909 			}
910 		} else {
911 			/*
912 			 * This must be a reference object produced by either the
913 			 * Index() or ref_of() operator
914 			 */
915 			switch (operand[0]->reference.class) {
916 			case ACPI_REFCLASS_INDEX:
917 				/*
918 				 * The target type for the Index operator must be
919 				 * either a Buffer or a Package
920 				 */
921 				switch (operand[0]->reference.target_type) {
922 				case ACPI_TYPE_BUFFER_FIELD:
923 
924 					temp_desc =
925 					    operand[0]->reference.object;
926 
927 					/*
928 					 * Create a new object that contains one element of the
929 					 * buffer -- the element pointed to by the index.
930 					 *
931 					 * NOTE: index into a buffer is NOT a pointer to a
932 					 * sub-buffer of the main buffer, it is only a pointer to a
933 					 * single element (byte) of the buffer!
934 					 *
935 					 * Since we are returning the value of the buffer at the
936 					 * indexed location, we don't need to add an additional
937 					 * reference to the buffer itself.
938 					 */
939 					return_desc =
940 					    acpi_ut_create_integer_object((u64)
941 									  temp_desc->buffer.pointer[operand[0]->reference.value]);
942 					if (!return_desc) {
943 						status = AE_NO_MEMORY;
944 						goto cleanup;
945 					}
946 					break;
947 
948 				case ACPI_TYPE_PACKAGE:
949 					/*
950 					 * Return the referenced element of the package. We must
951 					 * add another reference to the referenced object, however.
952 					 */
953 					return_desc =
954 					    *(operand[0]->reference.where);
955 					if (!return_desc) {
956 						/*
957 						 * Element is NULL, do not allow the dereference.
958 						 * This provides compatibility with other ACPI
959 						 * implementations.
960 						 */
961 						return_ACPI_STATUS
962 						    (AE_AML_UNINITIALIZED_ELEMENT);
963 					}
964 
965 					acpi_ut_add_reference(return_desc);
966 					break;
967 
968 				default:
969 
970 					ACPI_ERROR((AE_INFO,
971 						    "Unknown Index TargetType 0x%X in reference object %p",
972 						    operand[0]->reference.
973 						    target_type, operand[0]));
974 
975 					status = AE_AML_OPERAND_TYPE;
976 					goto cleanup;
977 				}
978 				break;
979 
980 			case ACPI_REFCLASS_REFOF:
981 
982 				return_desc = operand[0]->reference.object;
983 
984 				if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) ==
985 				    ACPI_DESC_TYPE_NAMED) {
986 					return_desc =
987 					    acpi_ns_get_attached_object((struct
988 									 acpi_namespace_node
989 									 *)
990 									return_desc);
991 					if (!return_desc) {
992 						break;
993 					}
994 
995 					/*
996 					 * June 2013:
997 					 * buffer_fields/field_units require additional resolution
998 					 */
999 					switch (return_desc->common.type) {
1000 					case ACPI_TYPE_BUFFER_FIELD:
1001 					case ACPI_TYPE_LOCAL_REGION_FIELD:
1002 					case ACPI_TYPE_LOCAL_BANK_FIELD:
1003 					case ACPI_TYPE_LOCAL_INDEX_FIELD:
1004 
1005 						status =
1006 						    acpi_ex_read_data_from_field
1007 						    (walk_state, return_desc,
1008 						     &temp_desc);
1009 						if (ACPI_FAILURE(status)) {
1010 							return_ACPI_STATUS
1011 							    (status);
1012 						}
1013 
1014 						return_desc = temp_desc;
1015 						break;
1016 
1017 					default:
1018 
1019 						/* Add another reference to the object */
1020 
1021 						acpi_ut_add_reference
1022 						    (return_desc);
1023 						break;
1024 					}
1025 				}
1026 				break;
1027 
1028 			default:
1029 
1030 				ACPI_ERROR((AE_INFO,
1031 					    "Unknown class in reference(%p) - 0x%2.2X",
1032 					    operand[0],
1033 					    operand[0]->reference.class));
1034 
1035 				status = AE_TYPE;
1036 				goto cleanup;
1037 			}
1038 		}
1039 		break;
1040 
1041 	default:
1042 
1043 		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
1044 			    walk_state->opcode));
1045 
1046 		status = AE_AML_BAD_OPCODE;
1047 		goto cleanup;
1048 	}
1049 
1050 cleanup:
1051 
1052 	/* Delete return object on error */
1053 
1054 	if (ACPI_FAILURE(status)) {
1055 		acpi_ut_remove_reference(return_desc);
1056 	}
1057 
1058 	/* Save return object on success */
1059 
1060 	else {
1061 		walk_state->result_obj = return_desc;
1062 	}
1063 
1064 	return_ACPI_STATUS(status);
1065 }
1066