File: /usr/src/linux/drivers/acpi/executer/exmonad.c
1
2 /******************************************************************************
3 *
4 * Module Name: exmonad - ACPI AML execution for monadic (1 operand) operators
5 * $Revision: 111 $
6 *
7 *****************************************************************************/
8
9 /*
10 * Copyright (C) 2000, 2001 R. Byron Moore
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27
28 #include "acpi.h"
29 #include "acparser.h"
30 #include "acdispat.h"
31 #include "acinterp.h"
32 #include "amlcode.h"
33 #include "acnamesp.h"
34
35
36 #define _COMPONENT ACPI_EXECUTER
37 MODULE_NAME ("exmonad")
38
39
40 /*******************************************************************************
41 *
42 * FUNCTION: Acpi_ex_get_object_reference
43 *
44 * PARAMETERS: Obj_desc - Create a reference to this object
45 * Ret_desc - Where to store the reference
46 *
47 * RETURN: Status
48 *
49 * DESCRIPTION: Obtain and return a "reference" to the target object
50 * Common code for the Ref_of_op and the Cond_ref_of_op.
51 *
52 ******************************************************************************/
53
54 static acpi_status
55 acpi_ex_get_object_reference (
56 acpi_operand_object *obj_desc,
57 acpi_operand_object **ret_desc,
58 acpi_walk_state *walk_state)
59 {
60 acpi_status status = AE_OK;
61
62
63 FUNCTION_TRACE_PTR ("Ex_get_object_reference", obj_desc);
64
65
66 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) {
67 if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) {
68 *ret_desc = NULL;
69 status = AE_TYPE;
70 goto cleanup;
71 }
72
73 /*
74 * Not a Name -- an indirect name pointer would have
75 * been converted to a direct name pointer in Acpi_ex_resolve_operands
76 */
77 switch (obj_desc->reference.opcode) {
78 case AML_LOCAL_OP:
79 case AML_ARG_OP:
80
81 *ret_desc = (void *) acpi_ds_method_data_get_node (obj_desc->reference.opcode,
82 obj_desc->reference.offset, walk_state);
83 break;
84
85 default:
86
87 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(Internal) Unknown Ref subtype %02x\n",
88 obj_desc->reference.opcode));
89 *ret_desc = NULL;
90 status = AE_AML_INTERNAL;
91 goto cleanup;
92 }
93
94 }
95
96 else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
97 /* Must be a named object; Just return the Node */
98
99 *ret_desc = obj_desc;
100 }
101
102 else {
103 *ret_desc = NULL;
104 status = AE_TYPE;
105 }
106
107
108 cleanup:
109
110 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p Ref=%p\n", obj_desc, *ret_desc));
111 return_ACPI_STATUS (status);
112 }
113
114 #define obj_desc operand[0]
115 #define res_desc operand[1]
116
117
118 /*******************************************************************************
119 *
120 * FUNCTION: Acpi_ex_monadic1
121 *
122 * PARAMETERS: Opcode - The opcode to be executed
123 *
124 * RETURN: Status
125 *
126 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
127 * object stack
128 *
129 ******************************************************************************/
130
131 acpi_status
132 acpi_ex_monadic1 (
133 u16 opcode,
134 acpi_walk_state *walk_state)
135 {
136 acpi_operand_object **operand = &walk_state->operands[0];
137 acpi_status status;
138
139
140 FUNCTION_TRACE_PTR ("Ex_monadic1", WALK_OPERANDS);
141
142
143 /* Examine the opcode */
144
145 switch (opcode) {
146
147 /* Def_release := Release_op Mutex_object */
148
149 case AML_RELEASE_OP:
150
151 status = acpi_ex_release_mutex (obj_desc, walk_state);
152 break;
153
154
155 /* Def_reset := Reset_op Acpi_event_object */
156
157 case AML_RESET_OP:
158
159 status = acpi_ex_system_reset_event (obj_desc);
160 break;
161
162
163 /* Def_signal := Signal_op Acpi_event_object */
164
165 case AML_SIGNAL_OP:
166
167 status = acpi_ex_system_signal_event (obj_desc);
168 break;
169
170
171 /* Def_sleep := Sleep_op Msec_time */
172
173 case AML_SLEEP_OP:
174
175 acpi_ex_system_do_suspend ((u32) obj_desc->integer.value);
176 break;
177
178
179 /* Def_stall := Stall_op Usec_time */
180
181 case AML_STALL_OP:
182
183 acpi_ex_system_do_stall ((u32) obj_desc->integer.value);
184 break;
185
186
187 /* Unknown opcode */
188
189 default:
190
191 REPORT_ERROR (("Acpi_ex_monadic1: Unknown monadic opcode %X\n",
192 opcode));
193 status = AE_AML_BAD_OPCODE;
194 break;
195
196 } /* switch */
197
198
199 /* Always delete the operand */
200
201 acpi_ut_remove_reference (obj_desc);
202
203 return_ACPI_STATUS (AE_OK);
204 }
205
206
207 /*******************************************************************************
208 *
209 * FUNCTION: Acpi_ex_monadic2_r
210 *
211 * PARAMETERS: Opcode - The opcode to be executed
212 *
213 * RETURN: Status
214 *
215 * DESCRIPTION: Execute Type 2 monadic operator with numeric operand and
216 * result operand on operand stack
217 *
218 ******************************************************************************/
219
220 acpi_status
221 acpi_ex_monadic2_r (
222 u16 opcode,
223 acpi_walk_state *walk_state,
224 acpi_operand_object **return_desc)
225 {
226 acpi_operand_object **operand = &walk_state->operands[0];
227 acpi_operand_object *ret_desc = NULL;
228 acpi_operand_object *ret_desc2 = NULL;
229 u32 res_val;
230 acpi_status status = AE_OK;
231 u32 i;
232 u32 j;
233 acpi_integer digit;
234
235
236 FUNCTION_TRACE_PTR ("Ex_monadic2_r", WALK_OPERANDS);
237
238
239 /* Create a return object of type NUMBER for most opcodes */
240
241 switch (opcode) {
242 case AML_BIT_NOT_OP:
243 case AML_FIND_SET_LEFT_BIT_OP:
244 case AML_FIND_SET_RIGHT_BIT_OP:
245 case AML_FROM_BCD_OP:
246 case AML_TO_BCD_OP:
247 case AML_COND_REF_OF_OP:
248
249 ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
250 if (!ret_desc) {
251 status = AE_NO_MEMORY;
252 goto cleanup;
253 }
254
255 break;
256 }
257
258
259 switch (opcode) {
260 /* Def_not := Not_op Operand Result */
261
262 case AML_BIT_NOT_OP:
263
264 ret_desc->integer.value = ~obj_desc->integer.value;
265 break;
266
267
268 /* Def_find_set_left_bit := Find_set_left_bit_op Operand Result */
269
270 case AML_FIND_SET_LEFT_BIT_OP:
271
272 ret_desc->integer.value = obj_desc->integer.value;
273
274 /*
275 * Acpi specification describes Integer type as a little
276 * endian unsigned value, so this boundary condition is valid.
277 */
278 for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
279 ret_desc->integer.value >>= 1;
280 }
281
282 ret_desc->integer.value = res_val;
283 break;
284
285
286 /* Def_find_set_right_bit := Find_set_right_bit_op Operand Result */
287
288 case AML_FIND_SET_RIGHT_BIT_OP:
289
290 ret_desc->integer.value = obj_desc->integer.value;
291
292 /*
293 * Acpi specification describes Integer type as a little
294 * endian unsigned value, so this boundary condition is valid.
295 */
296 for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
297 ret_desc->integer.value <<= 1;
298 }
299
300 /* Since returns must be 1-based, subtract from 33 (65) */
301
302 ret_desc->integer.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val;
303 break;
304
305
306 /* Def_from_bDC := From_bCDOp BCDValue Result */
307
308 case AML_FROM_BCD_OP:
309
310 /*
311 * The 64-bit ACPI integer can hold 16 4-bit BCD integers
312 */
313 ret_desc->integer.value = 0;
314 for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
315 /* Get one BCD digit */
316
317 digit = (acpi_integer) ((obj_desc->integer.value >> (i * 4)) & 0xF);
318
319 /* Check the range of the digit */
320
321 if (digit > 9) {
322 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD digit too large: \n",
323 digit));
324 status = AE_AML_NUMERIC_OVERFLOW;
325 goto cleanup;
326 }
327
328 if (digit > 0) {
329 /* Sum into the result with the appropriate power of 10 */
330
331 for (j = 0; j < i; j++) {
332 digit *= 10;
333 }
334
335 ret_desc->integer.value += digit;
336 }
337 }
338 break;
339
340
341 /* Def_to_bDC := To_bCDOp Operand Result */
342
343 case AML_TO_BCD_OP:
344
345
346 if (obj_desc->integer.value > ACPI_MAX_BCD_VALUE) {
347 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD overflow: %d\n",
348 obj_desc->integer.value));
349 status = AE_AML_NUMERIC_OVERFLOW;
350 goto cleanup;
351 }
352
353 ret_desc->integer.value = 0;
354 for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
355 /* Divide by nth factor of 10 */
356
357 digit = obj_desc->integer.value;
358 for (j = 0; j < i; j++) {
359 digit = ACPI_DIVIDE (digit, 10);
360 }
361
362 /* Create the BCD digit */
363
364 if (digit > 0) {
365 ret_desc->integer.value += (ACPI_MODULO (digit, 10) << (i * 4));
366 }
367 }
368 break;
369
370
371 /* Def_cond_ref_of := Cond_ref_of_op Source_object Result */
372
373 case AML_COND_REF_OF_OP:
374
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 ((acpi_namespace_node *) obj_desc == acpi_gbl_root_node) {
381 /*
382 * This means that the object does not exist in the namespace,
383 * return FALSE
384 */
385 ret_desc->integer.value = 0;
386
387 /*
388 * Must delete the result descriptor since there is no reference
389 * being returned
390 */
391 acpi_ut_remove_reference (res_desc);
392 goto cleanup;
393 }
394
395 /* Get the object reference and store it */
396
397 status = acpi_ex_get_object_reference (obj_desc, &ret_desc2, walk_state);
398 if (ACPI_FAILURE (status)) {
399 goto cleanup;
400 }
401
402 status = acpi_ex_store (ret_desc2, res_desc, walk_state);
403
404 /* The object exists in the namespace, return TRUE */
405
406 ret_desc->integer.value = ACPI_INTEGER_MAX;
407 goto cleanup;
408 break;
409
410
411 case AML_STORE_OP:
412
413 /*
414 * A store operand is typically a number, string, buffer or lvalue
415 * TBD: [Unhandled] What about a store to a package?
416 */
417
418 /*
419 * Do the store, and be careful about deleting the source object,
420 * since the object itself may have been stored.
421 */
422 status = acpi_ex_store (obj_desc, res_desc, walk_state);
423 if (ACPI_FAILURE (status)) {
424 /* On failure, just delete the Obj_desc */
425
426 acpi_ut_remove_reference (obj_desc);
427 return_ACPI_STATUS (status);
428 }
429
430 /*
431 * Normally, we would remove a reference on the Obj_desc parameter;
432 * But since it is being used as the internal return object
433 * (meaning we would normally increment it), the two cancel out,
434 * and we simply don't do anything.
435 */
436 *return_desc = obj_desc;
437 return_ACPI_STATUS (status);
438 break;
439
440
441 case AML_DEBUG_OP:
442
443 /* Reference, returning an Reference */
444
445 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Debug_op should never get here!\n"));
446 return_ACPI_STATUS (AE_OK);
447 break;
448
449
450 /*
451 * ACPI 2.0 Opcodes
452 */
453 case AML_TO_DECSTRING_OP:
454 status = acpi_ex_convert_to_string (obj_desc, &ret_desc, 10, ACPI_UINT32_MAX, walk_state);
455 break;
456
457
458 case AML_TO_HEXSTRING_OP:
459 status = acpi_ex_convert_to_string (obj_desc, &ret_desc, 16, ACPI_UINT32_MAX, walk_state);
460 break;
461
462 case AML_TO_BUFFER_OP:
463 status = acpi_ex_convert_to_buffer (obj_desc, &ret_desc, walk_state);
464 break;
465
466 case AML_TO_INTEGER_OP:
467 status = acpi_ex_convert_to_integer (obj_desc, &ret_desc, walk_state);
468 break;
469
470
471 /*
472 * These are obsolete opcodes
473 */
474
475 /* Def_shift_left_bit := Shift_left_bit_op Source Bit_num */
476 /* Def_shift_right_bit := Shift_right_bit_op Source Bit_num */
477
478 case AML_SHIFT_LEFT_BIT_OP:
479 case AML_SHIFT_RIGHT_BIT_OP:
480
481 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s is unimplemented\n",
482 acpi_ps_get_opcode_name (opcode)));
483 status = AE_SUPPORT;
484 goto cleanup;
485 break;
486
487
488 default:
489
490 REPORT_ERROR (("Acpi_ex_monadic2_r: Unknown monadic opcode %X\n",
491 opcode));
492 status = AE_AML_BAD_OPCODE;
493 goto cleanup;
494 }
495
496
497 status = acpi_ex_store (ret_desc, res_desc, walk_state);
498
499
500 cleanup:
501 /* Always delete the operand object */
502
503 acpi_ut_remove_reference (obj_desc);
504
505 /* Delete return object(s) on error */
506
507 if (ACPI_FAILURE (status)) {
508 acpi_ut_remove_reference (res_desc); /* Result descriptor */
509 if (ret_desc) {
510 acpi_ut_remove_reference (ret_desc);
511 ret_desc = NULL;
512 }
513 }
514
515 /* Set the return object and exit */
516
517 *return_desc = ret_desc;
518 return_ACPI_STATUS (status);
519 }
520
521
522 /*******************************************************************************
523 *
524 * FUNCTION: Acpi_ex_monadic2
525 *
526 * PARAMETERS: Opcode - The opcode to be executed
527 *
528 * RETURN: Status
529 *
530 * DESCRIPTION: Execute Type 2 monadic operator with numeric operand:
531 * Deref_of_op, Ref_of_op, Size_of_op, Type_op, Increment_op,
532 * Decrement_op, LNot_op,
533 *
534 ******************************************************************************/
535
536 acpi_status
537 acpi_ex_monadic2 (
538 u16 opcode,
539 acpi_walk_state *walk_state,
540 acpi_operand_object **return_desc)
541 {
542 acpi_operand_object **operand = &walk_state->operands[0];
543 acpi_operand_object *tmp_desc;
544 acpi_operand_object *ret_desc = NULL;
545 acpi_status status = AE_OK;
546 u32 type;
547 acpi_integer value;
548
549
550 FUNCTION_TRACE_PTR ("Ex_monadic2", WALK_OPERANDS);
551
552
553 /* Get the operand and decode the opcode */
554
555 switch (opcode) {
556
557 /* Def_lNot := LNot_op Operand */
558
559 case AML_LNOT_OP:
560
561 ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
562 if (!ret_desc) {
563 status = AE_NO_MEMORY;
564 goto cleanup;
565 }
566
567 ret_desc->integer.value = !obj_desc->integer.value;
568 break;
569
570
571 /* Def_decrement := Decrement_op Target */
572 /* Def_increment := Increment_op Target */
573
574 case AML_DECREMENT_OP:
575 case AML_INCREMENT_OP:
576
577 /*
578 * Since we are expecting an Reference on the top of the stack, it
579 * can be either an Node or an internal object.
580 *
581 * TBD: [Future] This may be the prototype code for all cases where
582 * a Reference is expected!! 10/99
583 */
584 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
585 ret_desc = obj_desc;
586 }
587
588 else {
589 /*
590 * Duplicate the Reference in a new object so that we can resolve it
591 * without destroying the original Reference object
592 */
593 ret_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE);
594 if (!ret_desc) {
595 status = AE_NO_MEMORY;
596 goto cleanup;
597 }
598
599 ret_desc->reference.opcode = obj_desc->reference.opcode;
600 ret_desc->reference.offset = obj_desc->reference.offset;
601 ret_desc->reference.object = obj_desc->reference.object;
602 }
603
604
605 /*
606 * Convert the Ret_desc Reference to a Number
607 * (This deletes the original Ret_desc)
608 */
609 status = acpi_ex_resolve_operands (AML_LNOT_OP, &ret_desc, walk_state);
610 if (ACPI_FAILURE (status)) {
611 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s: bad operand(s) %s\n",
612 acpi_ps_get_opcode_name (opcode), acpi_format_exception(status)));
613
614 goto cleanup;
615 }
616
617 /* Do the actual increment or decrement */
618
619 if (AML_INCREMENT_OP == opcode) {
620 ret_desc->integer.value++;
621 }
622 else {
623 ret_desc->integer.value--;
624 }
625
626 /* Store the result back in the original descriptor */
627
628 status = acpi_ex_store (ret_desc, obj_desc, walk_state);
629
630 /* Objdesc was just deleted (because it is an Reference) */
631
632 obj_desc = NULL;
633
634 break;
635
636
637 /* Def_object_type := Object_type_op Source_object */
638
639 case AML_TYPE_OP:
640
641 if (INTERNAL_TYPE_REFERENCE == obj_desc->common.type) {
642 /*
643 * Not a Name -- an indirect name pointer would have
644 * been converted to a direct name pointer in Resolve_operands
645 */
646 switch (obj_desc->reference.opcode) {
647 case AML_ZERO_OP:
648 case AML_ONE_OP:
649 case AML_ONES_OP:
650 case AML_REVISION_OP:
651
652 /* Constants are of type Number */
653
654 type = ACPI_TYPE_INTEGER;
655 break;
656
657
658 case AML_DEBUG_OP:
659
660 /* Per 1.0b spec, Debug object is of type Debug_object */
661
662 type = ACPI_TYPE_DEBUG_OBJECT;
663 break;
664
665
666 case AML_INDEX_OP:
667
668 /* Get the type of this reference (index into another object) */
669
670 type = obj_desc->reference.target_type;
671 if (type == ACPI_TYPE_PACKAGE) {
672 /*
673 * The main object is a package, we want to get the type
674 * of the individual package element that is referenced by
675 * the index.
676 */
677 type = (*(obj_desc->reference.where))->common.type;
678 }
679
680 break;
681
682
683 case AML_LOCAL_OP:
684 case AML_ARG_OP:
685
686 type = acpi_ds_method_data_get_type (obj_desc->reference.opcode,
687 obj_desc->reference.offset, walk_state);
688 break;
689
690
691 default:
692
693 REPORT_ERROR (("Acpi_ex_monadic2/Type_op: Internal error - Unknown Reference subtype %X\n",
694 obj_desc->reference.opcode));
695 status = AE_AML_INTERNAL;
696 goto cleanup;
697 }
698 }
699
700 else {
701 /*
702 * It's not a Reference, so it must be a direct name pointer.
703 */
704 type = acpi_ns_get_type ((acpi_namespace_node *) obj_desc);
705
706 /* Convert internal types to external types */
707
708 switch (type) {
709 case INTERNAL_TYPE_REGION_FIELD:
710 case INTERNAL_TYPE_BANK_FIELD:
711 case INTERNAL_TYPE_INDEX_FIELD:
712
713 type = ACPI_TYPE_FIELD_UNIT;
714 }
715
716 }
717
718 /* Allocate a descriptor to hold the type. */
719
720 ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
721 if (!ret_desc) {
722 status = AE_NO_MEMORY;
723 goto cleanup;
724 }
725
726 ret_desc->integer.value = type;
727 break;
728
729
730 /* Def_size_of := Size_of_op Source_object */
731
732 case AML_SIZE_OF_OP:
733
734 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
735 obj_desc = acpi_ns_get_attached_object ((acpi_namespace_node *) obj_desc);
736 }
737
738 if (!obj_desc) {
739 value = 0;
740 }
741
742 else {
743 switch (obj_desc->common.type) {
744
745 case ACPI_TYPE_BUFFER:
746
747 value = obj_desc->buffer.length;
748 break;
749
750
751 case ACPI_TYPE_STRING:
752
753 value = obj_desc->string.length;
754 break;
755
756
757 case ACPI_TYPE_PACKAGE:
758
759 value = obj_desc->package.count;
760 break;
761
762 case INTERNAL_TYPE_REFERENCE:
763
764 value = 4;
765 break;
766
767 default:
768
769 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Not Buf/Str/Pkg - found type %X\n",
770 obj_desc->common.type));
771 status = AE_AML_OPERAND_TYPE;
772 goto cleanup;
773 }
774 }
775
776 /*
777 * Now that we have the size of the object, create a result
778 * object to hold the value
779 */
780 ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
781 if (!ret_desc) {
782 status = AE_NO_MEMORY;
783 goto cleanup;
784 }
785
786 ret_desc->integer.value = value;
787 break;
788
789
790 /* Def_ref_of := Ref_of_op Source_object */
791
792 case AML_REF_OF_OP:
793
794 status = acpi_ex_get_object_reference (obj_desc, &ret_desc, walk_state);
795 if (ACPI_FAILURE (status)) {
796 goto cleanup;
797 }
798 break;
799
800
801 /* Def_deref_of := Deref_of_op Obj_reference */
802
803 case AML_DEREF_OF_OP:
804
805
806 /* Check for a method local or argument */
807
808 if (!VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
809 /*
810 * Must resolve/dereference the local/arg reference first
811 */
812 switch (obj_desc->reference.opcode) {
813 /* Set Obj_desc to the value of the local/arg */
814
815 case AML_LOCAL_OP:
816 case AML_ARG_OP:
817
818 acpi_ds_method_data_get_value (obj_desc->reference.opcode,
819 obj_desc->reference.offset, walk_state, &tmp_desc);
820
821 /*
822 * Delete our reference to the input object and
823 * point to the object just retrieved
824 */
825 acpi_ut_remove_reference (obj_desc);
826 obj_desc = tmp_desc;
827 break;
828
829 default:
830
831 /* Index op - handled below */
832 break;
833 }
834 }
835
836
837 /* Obj_desc may have changed from the code above */
838
839 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
840 /* Get the actual object from the Node (This is the dereference) */
841
842 ret_desc = ((acpi_namespace_node *) obj_desc)->object;
843
844 /* Returning a pointer to the object, add another reference! */
845
846 acpi_ut_add_reference (ret_desc);
847 }
848
849 else {
850 /*
851 * This must be a reference object produced by the Index
852 * ASL operation -- check internal opcode
853 */
854 if ((obj_desc->reference.opcode != AML_INDEX_OP) &&
855 (obj_desc->reference.opcode != AML_REF_OF_OP)) {
856 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode in ref(%p) - %X\n",
857 obj_desc, obj_desc->reference.opcode));
858
859 status = AE_TYPE;
860 goto cleanup;
861 }
862
863
864 switch (obj_desc->reference.opcode) {
865 case AML_INDEX_OP:
866
867 /*
868 * Supported target types for the Index operator are
869 * 1) A Buffer
870 * 2) A Package
871 */
872 if (obj_desc->reference.target_type == ACPI_TYPE_BUFFER_FIELD) {
873 /*
874 * The target is a buffer, we must create a new object that
875 * contains one element of the buffer, the element pointed
876 * to by the index.
877 *
878 * NOTE: index into a buffer is NOT a pointer to a
879 * sub-buffer of the main buffer, it is only a pointer to a
880 * single element (byte) of the buffer!
881 */
882 ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
883 if (!ret_desc) {
884 status = AE_NO_MEMORY;
885 goto cleanup;
886 }
887
888 tmp_desc = obj_desc->reference.object;
889 ret_desc->integer.value =
890 tmp_desc->buffer.pointer[obj_desc->reference.offset];
891
892 /* TBD: [Investigate] (see below) Don't add an additional
893 * ref!
894 */
895 }
896
897 else if (obj_desc->reference.target_type == ACPI_TYPE_PACKAGE) {
898 /*
899 * The target is a package, we want to return the referenced
900 * element of the package. We must add another reference to
901 * this object, however.
902 */
903 ret_desc = *(obj_desc->reference.where);
904 if (!ret_desc) {
905 /*
906 * We can't return a NULL dereferenced value. This is
907 * an uninitialized package element and is thus a
908 * severe error.
909 */
910
911 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "NULL package element obj %p\n",
912 obj_desc));
913 status = AE_AML_UNINITIALIZED_ELEMENT;
914 goto cleanup;
915 }
916
917 acpi_ut_add_reference (ret_desc);
918 }
919
920 else {
921 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Target_type %X in obj %p\n",
922 obj_desc->reference.target_type, obj_desc));
923 status = AE_AML_OPERAND_TYPE;
924 goto cleanup;
925 }
926
927 break;
928
929
930 case AML_REF_OF_OP:
931
932 ret_desc = obj_desc->reference.object;
933
934 /* Add another reference to the object! */
935
936 acpi_ut_add_reference (ret_desc);
937 break;
938 }
939 }
940
941 break;
942
943
944 default:
945
946 REPORT_ERROR (("Acpi_ex_monadic2: Unknown monadic opcode %X\n",
947 opcode));
948 status = AE_AML_BAD_OPCODE;
949 goto cleanup;
950 }
951
952
953 cleanup:
954
955 if (obj_desc) {
956 acpi_ut_remove_reference (obj_desc);
957 }
958
959 /* Delete return object on error */
960
961 if (ACPI_FAILURE (status) &&
962 (ret_desc)) {
963 acpi_ut_remove_reference (ret_desc);
964 ret_desc = NULL;
965 }
966
967 *return_desc = ret_desc;
968 return_ACPI_STATUS (status);
969 }
970
971