2 /******************************************************************************
4 * Module Name: ammonad - ACPI AML (p-code) execution for monadic operators
7 *****************************************************************************/
10 * Copyright (C) 2000 R. Byron Moore
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.
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.
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
36 #define _COMPONENT INTERPRETER
37 MODULE_NAME ("ammonad")
40 /*******************************************************************************
42 * FUNCTION: Acpi_aml_get_object_reference
44 * PARAMETERS: Obj_desc - Create a reference to this object
45 * Ret_desc - Where to store the reference
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.
52 ******************************************************************************/
55 acpi_aml_get_object_reference (
56 ACPI_OPERAND_OBJECT
*obj_desc
,
57 ACPI_OPERAND_OBJECT
**ret_desc
,
58 ACPI_WALK_STATE
*walk_state
)
60 ACPI_STATUS status
= AE_OK
;
63 if (VALID_DESCRIPTOR_TYPE (obj_desc
, ACPI_DESC_TYPE_INTERNAL
)) {
64 if (obj_desc
->common
.type
!= INTERNAL_TYPE_REFERENCE
) {
71 * Not a Name -- an indirect name pointer would have
72 * been converted to a direct name pointer in Acpi_aml_resolve_operands
74 switch (obj_desc
->reference
.op_code
)
78 *ret_desc
= (void *) acpi_ds_method_data_get_nte (MTH_TYPE_LOCAL
,
79 (obj_desc
->reference
.offset
), walk_state
);
85 *ret_desc
= (void *) acpi_ds_method_data_get_nte (MTH_TYPE_ARG
,
86 (obj_desc
->reference
.offset
), walk_state
);
93 status
= AE_AML_INTERNAL
;
99 else if (VALID_DESCRIPTOR_TYPE (obj_desc
, ACPI_DESC_TYPE_NAMED
)) {
100 /* Must be a named object; Just return the Node */
102 *ret_desc
= obj_desc
;
117 /*******************************************************************************
119 * FUNCTION: Acpi_aml_exec_monadic1
121 * PARAMETERS: Opcode - The opcode to be executed
125 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
128 ******************************************************************************/
131 acpi_aml_exec_monadic1 (
133 ACPI_WALK_STATE
*walk_state
)
135 ACPI_OPERAND_OBJECT
*obj_desc
;
139 /* Resolve all operands */
141 status
= acpi_aml_resolve_operands (opcode
, WALK_OPERANDS
, walk_state
);
142 /* Get all operands */
144 status
|= acpi_ds_obj_stack_pop_object (&obj_desc
, walk_state
);
145 if (ACPI_FAILURE (status
)) {
150 /* Examine the opcode */
155 /* Def_release := Release_op Mutex_object */
159 status
= acpi_aml_system_release_mutex (obj_desc
);
163 /* Def_reset := Reset_op Acpi_event_object */
167 status
= acpi_aml_system_reset_event (obj_desc
);
171 /* Def_signal := Signal_op Acpi_event_object */
175 status
= acpi_aml_system_signal_event (obj_desc
);
179 /* Def_sleep := Sleep_op Msec_time */
183 acpi_aml_system_do_suspend ((u32
) obj_desc
->number
.value
);
187 /* Def_stall := Stall_op Usec_time */
191 acpi_aml_system_do_stall ((u32
) obj_desc
->number
.value
);
199 REPORT_ERROR (("Acpi_aml_exec_monadic1: Unknown monadic opcode %X\n",
201 status
= AE_AML_BAD_OPCODE
;
209 /* Always delete the operand */
211 acpi_cm_remove_reference (obj_desc
);
217 /*******************************************************************************
219 * FUNCTION: Acpi_aml_exec_monadic2_r
221 * PARAMETERS: Opcode - The opcode to be executed
225 * DESCRIPTION: Execute Type 2 monadic operator with numeric operand and
226 * result operand on operand stack
228 ******************************************************************************/
231 acpi_aml_exec_monadic2_r (
233 ACPI_WALK_STATE
*walk_state
,
234 ACPI_OPERAND_OBJECT
**return_desc
)
236 ACPI_OPERAND_OBJECT
*obj_desc
;
237 ACPI_OPERAND_OBJECT
*res_desc
;
238 ACPI_OPERAND_OBJECT
*ret_desc
= NULL
;
239 ACPI_OPERAND_OBJECT
*ret_desc2
= NULL
;
248 /* Resolve all operands */
250 status
= acpi_aml_resolve_operands (opcode
, WALK_OPERANDS
, walk_state
);
251 /* Get all operands */
253 status
|= acpi_ds_obj_stack_pop_object (&res_desc
, walk_state
);
254 status
|= acpi_ds_obj_stack_pop_object (&obj_desc
, walk_state
);
255 if (ACPI_FAILURE (status
)) {
260 /* Create a return object of type NUMBER for most opcodes */
265 case AML_FIND_SET_LEFT_BIT_OP
:
266 case AML_FIND_SET_RIGHT_BIT_OP
:
267 case AML_FROM_BCD_OP
:
269 case AML_COND_REF_OF_OP
:
271 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_NUMBER
);
273 status
= AE_NO_MEMORY
;
283 /* Def_not := Not_op Operand Result */
287 ret_desc
->number
.value
= ~obj_desc
->number
.value
;
291 /* Def_find_set_left_bit := Find_set_left_bit_op Operand Result */
293 case AML_FIND_SET_LEFT_BIT_OP
:
295 ret_desc
->number
.value
= obj_desc
->number
.value
;
298 * Acpi specification describes Integer type as a little
299 * endian unsigned value, so this boundry condition is valid.
301 for (res_val
= 0; ret_desc
->number
.value
&& res_val
< ACPI_INTEGER_BIT_SIZE
; ++res_val
) {
302 ret_desc
->number
.value
>>= 1;
305 ret_desc
->number
.value
= res_val
;
309 /* Def_find_set_right_bit := Find_set_right_bit_op Operand Result */
311 case AML_FIND_SET_RIGHT_BIT_OP
:
313 ret_desc
->number
.value
= obj_desc
->number
.value
;
316 * Acpi specification describes Integer type as a little
317 * endian unsigned value, so this boundry condition is valid.
319 for (res_val
= 0; ret_desc
->number
.value
&& res_val
< ACPI_INTEGER_BIT_SIZE
; ++res_val
) {
320 ret_desc
->number
.value
<<= 1;
323 /* Since returns must be 1-based, subtract from 33 (65) */
325 ret_desc
->number
.value
= res_val
== 0 ? 0 : (ACPI_INTEGER_BIT_SIZE
+ 1) - res_val
;
329 /* Def_from_bDC := From_bCDOp BCDValue Result */
331 case AML_FROM_BCD_OP
:
333 /* TBD: for ACPI 2.0, expand to 64 bits */
335 d0
= (u32
) (obj_desc
->number
.value
& 15);
336 d1
= (u32
) (obj_desc
->number
.value
>> 4 & 15);
337 d2
= (u32
) (obj_desc
->number
.value
>> 8 & 15);
338 d3
= (u32
) (obj_desc
->number
.value
>> 12 & 15);
340 if (d0
> 9 || d1
> 9 || d2
> 9 || d3
> 9) {
341 status
= AE_AML_NUMERIC_OVERFLOW
;
345 ret_desc
->number
.value
= d0
+ d1
* 10 + d2
* 100 + d3
* 1000;
349 /* Def_to_bDC := To_bCDOp Operand Result */
353 /* TBD: for ACPI 2.0, expand to 64 bits */
355 if (obj_desc
->number
.value
> 9999) {
356 status
= AE_AML_NUMERIC_OVERFLOW
;
360 ret_desc
->number
.value
361 = ACPI_MODULO (obj_desc
->number
.value
, 10)
362 + (ACPI_MODULO (ACPI_DIVIDE (obj_desc
->number
.value
, 10), 10) << 4)
363 + (ACPI_MODULO (ACPI_DIVIDE (obj_desc
->number
.value
, 100), 10) << 8)
364 + (ACPI_MODULO (ACPI_DIVIDE (obj_desc
->number
.value
, 1000), 10) << 12);
369 /* Def_cond_ref_of := Cond_ref_of_op Source_object Result */
371 case AML_COND_REF_OF_OP
:
374 * This op is a little strange because the internal return value is
375 * different than the return value stored in the result descriptor
376 * (There are really two return values)
379 if ((ACPI_NAMESPACE_NODE
*) obj_desc
== acpi_gbl_root_node
) {
381 * This means that the object does not exist in the namespace,
385 ret_desc
->number
.value
= 0;
388 * Must delete the result descriptor since there is no reference
392 acpi_cm_remove_reference (res_desc
);
396 /* Get the object reference and store it */
398 status
= acpi_aml_get_object_reference (obj_desc
, &ret_desc2
, walk_state
);
399 if (ACPI_FAILURE (status
)) {
403 status
= acpi_aml_exec_store (ret_desc2
, res_desc
, walk_state
);
405 /* The object exists in the namespace, return TRUE */
407 ret_desc
->number
.value
= ACPI_INTEGER_MAX
415 * A store operand is typically a number, string, buffer or lvalue
416 * TBD: [Unhandled] What about a store to a package?
420 * Do the store, and be careful about deleting the source object,
421 * since the object itself may have been stored.
424 status
= acpi_aml_exec_store (obj_desc
, res_desc
, walk_state
);
425 if (ACPI_FAILURE (status
)) {
426 /* On failure, just delete the Obj_desc */
428 acpi_cm_remove_reference (obj_desc
);
433 * Normally, we would remove a reference on the Obj_desc parameter;
434 * But since it is being used as the internal return object
435 * (meaning we would normally increment it), the two cancel out,
436 * and we simply don't do anything.
438 *return_desc
= obj_desc
;
449 /* Reference, returning an Reference */
456 * These are obsolete opcodes
459 /* Def_shift_left_bit := Shift_left_bit_op Source Bit_num */
460 /* Def_shift_right_bit := Shift_right_bit_op Source Bit_num */
462 case AML_SHIFT_LEFT_BIT_OP
:
463 case AML_SHIFT_RIGHT_BIT_OP
:
472 REPORT_ERROR (("Acpi_aml_exec_monadic2_r: Unknown monadic opcode %X\n",
474 status
= AE_AML_BAD_OPCODE
;
479 status
= acpi_aml_exec_store (ret_desc
, res_desc
, walk_state
);
483 /* Always delete the operand object */
485 acpi_cm_remove_reference (obj_desc
);
487 /* Delete return object(s) on error */
489 if (ACPI_FAILURE (status
)) {
490 acpi_cm_remove_reference (res_desc
); /* Result descriptor */
492 acpi_cm_remove_reference (ret_desc
);
497 /* Set the return object and exit */
499 *return_desc
= ret_desc
;
504 /*******************************************************************************
506 * FUNCTION: Acpi_aml_exec_monadic2
508 * PARAMETERS: Opcode - The opcode to be executed
512 * DESCRIPTION: Execute Type 2 monadic operator with numeric operand:
513 * Deref_of_op, Ref_of_op, Size_of_op, Type_op, Increment_op,
514 * Decrement_op, LNot_op,
516 ******************************************************************************/
519 acpi_aml_exec_monadic2 (
521 ACPI_WALK_STATE
*walk_state
,
522 ACPI_OPERAND_OBJECT
**return_desc
)
524 ACPI_OPERAND_OBJECT
*obj_desc
;
525 ACPI_OPERAND_OBJECT
*tmp_desc
;
526 ACPI_OPERAND_OBJECT
*ret_desc
= NULL
;
527 ACPI_STATUS resolve_status
;
533 /* Attempt to resolve the operands */
535 resolve_status
= acpi_aml_resolve_operands (opcode
, WALK_OPERANDS
, walk_state
);
536 /* Always get all operands */
538 status
= acpi_ds_obj_stack_pop_object (&obj_desc
, walk_state
);
541 /* Now we can check the status codes */
543 if (ACPI_FAILURE (resolve_status
)) {
547 if (ACPI_FAILURE (status
)) {
552 /* Get the operand and decode the opcode */
558 /* Def_lNot := LNot_op Operand */
562 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_NUMBER
);
564 status
= AE_NO_MEMORY
;
568 ret_desc
->number
.value
= !obj_desc
->number
.value
;
572 /* Def_decrement := Decrement_op Target */
573 /* Def_increment := Increment_op Target */
575 case AML_DECREMENT_OP
:
576 case AML_INCREMENT_OP
:
579 * Since we are expecting an Reference on the top of the stack, it
580 * can be either an Node or an internal object.
582 * TBD: [Future] This may be the prototype code for all cases where
583 * an Reference is expected!! 10/99
586 if (VALID_DESCRIPTOR_TYPE (obj_desc
, ACPI_DESC_TYPE_NAMED
)) {
592 * Duplicate the Reference in a new object so that we can resolve it
593 * without destroying the original Reference object
596 ret_desc
= acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE
);
598 status
= AE_NO_MEMORY
;
602 ret_desc
->reference
.op_code
= obj_desc
->reference
.op_code
;
603 ret_desc
->reference
.offset
= obj_desc
->reference
.offset
;
604 ret_desc
->reference
.object
= obj_desc
->reference
.object
;
609 * Convert the Ret_desc Reference to a Number
610 * (This deletes the original Ret_desc)
613 status
= acpi_aml_resolve_operands (AML_LNOT_OP
, &ret_desc
, walk_state
);
614 if (ACPI_FAILURE (status
)) {
618 /* Do the actual increment or decrement */
620 if (AML_INCREMENT_OP
== opcode
) {
621 ret_desc
->number
.value
++;
624 ret_desc
->number
.value
--;
627 /* Store the result back in the original descriptor */
629 status
= acpi_aml_exec_store (ret_desc
, obj_desc
, walk_state
);
631 /* Objdesc was just deleted (because it is an Reference) */
638 /* Def_object_type := Object_type_op Source_object */
642 if (INTERNAL_TYPE_REFERENCE
== obj_desc
->common
.type
) {
644 * Not a Name -- an indirect name pointer would have
645 * been converted to a direct name pointer in Resolve_operands
647 switch (obj_desc
->reference
.op_code
)
653 /* Constants are of type Number */
655 type
= ACPI_TYPE_NUMBER
;
661 /* Per 1.0b spec, Debug object is of type Debug_object */
663 type
= ACPI_TYPE_DEBUG_OBJECT
;
669 /* Get the type of this reference (index into another object) */
671 type
= obj_desc
->reference
.target_type
;
672 if (type
== ACPI_TYPE_PACKAGE
) {
674 * The main object is a package, we want to get the type
675 * of the individual package element that is referenced by
678 type
= (*(obj_desc
->reference
.where
))->common
.type
;
686 type
= acpi_ds_method_data_get_type (MTH_TYPE_LOCAL
,
687 (obj_desc
->reference
.offset
), walk_state
);
693 type
= acpi_ds_method_data_get_type (MTH_TYPE_ARG
,
694 (obj_desc
->reference
.offset
), walk_state
);
700 REPORT_ERROR (("Acpi_aml_exec_monadic2/Type_op: Internal error - Unknown Reference subtype %X\n",
701 obj_desc
->reference
.op_code
));
702 status
= AE_AML_INTERNAL
;
709 * It's not a Reference, so it must be a direct name pointer.
711 type
= acpi_ns_get_type ((ACPI_HANDLE
) obj_desc
);
714 /* Allocate a descriptor to hold the type. */
716 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_NUMBER
);
718 status
= AE_NO_MEMORY
;
722 ret_desc
->number
.value
= type
;
726 /* Def_size_of := Size_of_op Source_object */
730 if (VALID_DESCRIPTOR_TYPE (obj_desc
, ACPI_DESC_TYPE_NAMED
)) {
731 obj_desc
= acpi_ns_get_attached_object (obj_desc
);
739 switch (obj_desc
->common
.type
)
742 case ACPI_TYPE_BUFFER
:
744 value
= obj_desc
->buffer
.length
;
748 case ACPI_TYPE_STRING
:
750 value
= obj_desc
->string
.length
;
754 case ACPI_TYPE_PACKAGE
:
756 value
= obj_desc
->package
.count
;
759 case INTERNAL_TYPE_REFERENCE
:
766 status
= AE_AML_OPERAND_TYPE
;
772 * Now that we have the size of the object, create a result
773 * object to hold the value
776 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_NUMBER
);
778 status
= AE_NO_MEMORY
;
782 ret_desc
->number
.value
= value
;
786 /* Def_ref_of := Ref_of_op Source_object */
790 status
= acpi_aml_get_object_reference (obj_desc
, &ret_desc
, walk_state
);
791 if (ACPI_FAILURE (status
)) {
797 /* Def_deref_of := Deref_of_op Obj_reference */
799 case AML_DEREF_OF_OP
:
802 /* Check for a method local or argument */
804 if (!VALID_DESCRIPTOR_TYPE (obj_desc
, ACPI_DESC_TYPE_NAMED
)) {
806 * Must resolve/dereference the local/arg reference first
808 switch (obj_desc
->reference
.op_code
)
810 /* Set Obj_desc to the value of the local/arg */
814 acpi_ds_method_data_get_value (MTH_TYPE_LOCAL
,
815 (obj_desc
->reference
.offset
), walk_state
, &tmp_desc
);
818 * Delete our reference to the input object and
819 * point to the object just retrieved
821 acpi_cm_remove_reference (obj_desc
);
828 acpi_ds_method_data_get_value (MTH_TYPE_ARG
,
829 (obj_desc
->reference
.offset
), walk_state
, &tmp_desc
);
832 * Delete our reference to the input object and
833 * point to the object just retrieved
835 acpi_cm_remove_reference (obj_desc
);
841 /* Index op - handled below */
847 /* Obj_desc may have changed from the code above */
849 if (VALID_DESCRIPTOR_TYPE (obj_desc
, ACPI_DESC_TYPE_NAMED
)) {
850 /* Get the actual object from the Node (This is the dereference) */
852 ret_desc
= ((ACPI_NAMESPACE_NODE
*) obj_desc
)->object
;
854 /* Returning a pointer to the object, add another reference! */
856 acpi_cm_add_reference (ret_desc
);
861 * This must be a reference object produced by the Index
862 * ASL operation -- check internal opcode
865 if ((obj_desc
->reference
.op_code
!= AML_INDEX_OP
) &&
866 (obj_desc
->reference
.op_code
!= AML_REF_OF_OP
))
873 switch (obj_desc
->reference
.op_code
)
878 * Supported target types for the Index operator are
883 if (obj_desc
->reference
.target_type
== ACPI_TYPE_BUFFER_FIELD
) {
885 * The target is a buffer, we must create a new object that
886 * contains one element of the buffer, the element pointed
889 * NOTE: index into a buffer is NOT a pointer to a
890 * sub-buffer of the main buffer, it is only a pointer to a
891 * single element (byte) of the buffer!
893 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_NUMBER
);
895 status
= AE_NO_MEMORY
;
899 tmp_desc
= obj_desc
->reference
.object
;
900 ret_desc
->number
.value
=
901 tmp_desc
->buffer
.pointer
[obj_desc
->reference
.offset
];
903 /* TBD: [Investigate] (see below) Don't add an additional
908 else if (obj_desc
->reference
.target_type
== ACPI_TYPE_PACKAGE
) {
910 * The target is a package, we want to return the referenced
911 * element of the package. We must add another reference to
912 * this object, however.
915 ret_desc
= *(obj_desc
->reference
.where
);
918 * We can't return a NULL dereferenced value. This is
919 * an uninitialized package element and is thus a
923 status
= AE_AML_UNINITIALIZED_ELEMENT
;
927 acpi_cm_add_reference (ret_desc
);
931 status
= AE_AML_OPERAND_TYPE
;
940 ret_desc
= obj_desc
->reference
.object
;
942 /* Add another reference to the object! */
944 acpi_cm_add_reference (ret_desc
);
954 REPORT_ERROR (("Acpi_aml_exec_monadic2: Unknown monadic opcode %X\n",
956 status
= AE_AML_BAD_OPCODE
;
964 acpi_cm_remove_reference (obj_desc
);
967 /* Delete return object on error */
969 if (ACPI_FAILURE (status
) &&
972 acpi_cm_remove_reference (ret_desc
);
976 *return_desc
= ret_desc
;