2 /******************************************************************************
4 * Module Name: ammonad - ACPI AML (p-code) execution for monadic operators
7 *****************************************************************************/
10 * Copyright (C) 2000, 2001 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 ACPI_EXECUTER
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.opcode) {
78 *ret_desc = (void *) acpi_ds_method_data_get_node (obj_desc->reference.opcode,
79 obj_desc->reference.offset, walk_state);
85 status = AE_AML_INTERNAL;
91 else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
92 /* Must be a named object; Just return the Node */
109 /*******************************************************************************
111 * FUNCTION: Acpi_aml_exec_monadic1
113 * PARAMETERS: Opcode - The opcode to be executed
117 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
120 ******************************************************************************/
123 acpi_aml_exec_monadic1 (
125 ACPI_WALK_STATE *walk_state)
127 ACPI_OPERAND_OBJECT *obj_desc;
131 /* Resolve all operands */
133 status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
134 /* Get all operands */
136 status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
137 if (ACPI_FAILURE (status)) {
142 /* Examine the opcode */
146 /* Def_release := Release_op Mutex_object */
150 status = acpi_aml_release_mutex (obj_desc, walk_state);
154 /* Def_reset := Reset_op Acpi_event_object */
158 status = acpi_aml_system_reset_event (obj_desc);
162 /* Def_signal := Signal_op Acpi_event_object */
166 status = acpi_aml_system_signal_event (obj_desc);
170 /* Def_sleep := Sleep_op Msec_time */
174 acpi_aml_system_do_suspend ((u32) obj_desc->integer.value);
178 /* Def_stall := Stall_op Usec_time */
182 acpi_aml_system_do_stall ((u32) obj_desc->integer.value);
190 REPORT_ERROR (("Acpi_aml_exec_monadic1: Unknown monadic opcode %X\n",
192 status = AE_AML_BAD_OPCODE;
200 /* Always delete the operand */
202 acpi_cm_remove_reference (obj_desc);
208 /*******************************************************************************
210 * FUNCTION: Acpi_aml_exec_monadic2_r
212 * PARAMETERS: Opcode - The opcode to be executed
216 * DESCRIPTION: Execute Type 2 monadic operator with numeric operand and
217 * result operand on operand stack
219 ******************************************************************************/
222 acpi_aml_exec_monadic2_r (
224 ACPI_WALK_STATE *walk_state,
225 ACPI_OPERAND_OBJECT **return_desc)
227 ACPI_OPERAND_OBJECT *obj_desc;
228 ACPI_OPERAND_OBJECT *res_desc;
229 ACPI_OPERAND_OBJECT *ret_desc = NULL;
230 ACPI_OPERAND_OBJECT *ret_desc2 = NULL;
238 /* Resolve all operands */
240 status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
241 /* Get all operands */
243 status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state);
244 status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
245 if (ACPI_FAILURE (status)) {
250 /* Create a return object of type NUMBER for most opcodes */
254 case AML_FIND_SET_LEFT_BIT_OP:
255 case AML_FIND_SET_RIGHT_BIT_OP:
256 case AML_FROM_BCD_OP:
258 case AML_COND_REF_OF_OP:
260 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
262 status = AE_NO_MEMORY;
271 /* Def_not := Not_op Operand Result */
275 ret_desc->integer.value = ~obj_desc->integer.value;
279 /* Def_find_set_left_bit := Find_set_left_bit_op Operand Result */
281 case AML_FIND_SET_LEFT_BIT_OP:
283 ret_desc->integer.value = obj_desc->integer.value;
286 * Acpi specification describes Integer type as a little
287 * endian unsigned value, so this boundry condition is valid.
289 for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
290 ret_desc->integer.value >>= 1;
293 ret_desc->integer.value = res_val;
297 /* Def_find_set_right_bit := Find_set_right_bit_op Operand Result */
299 case AML_FIND_SET_RIGHT_BIT_OP:
301 ret_desc->integer.value = obj_desc->integer.value;
304 * Acpi specification describes Integer type as a little
305 * endian unsigned value, so this boundry condition is valid.
307 for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
308 ret_desc->integer.value <<= 1;
311 /* Since returns must be 1-based, subtract from 33 (65) */
313 ret_desc->integer.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val;
317 /* Def_from_bDC := From_bCDOp BCDValue Result */
319 case AML_FROM_BCD_OP:
322 * The 64-bit ACPI integer can hold 16 4-bit BCD integers
324 ret_desc->integer.value = 0;
325 for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
326 /* Get one BCD digit */
328 digit = (ACPI_INTEGER) ((obj_desc->integer.value >> (i * 4)) & 0xF);
330 /* Check the range of the digit */
333 status = AE_AML_NUMERIC_OVERFLOW;
338 /* Sum into the result with the appropriate power of 10 */
340 for (j = 0; j < i; j++) {
344 ret_desc->integer.value += digit;
350 /* Def_to_bDC := To_bCDOp Operand Result */
355 if (obj_desc->integer.value > ACPI_MAX_BCD_VALUE) {
356 status = AE_AML_NUMERIC_OVERFLOW;
360 ret_desc->integer.value = 0;
361 for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
362 /* Divide by nth factor of 10 */
364 digit = obj_desc->integer.value;
365 for (j = 0; j < i; j++) {
369 /* Create the BCD digit */
372 ret_desc->integer.value += (ACPI_MODULO (digit, 10) << (i * 4));
378 /* Def_cond_ref_of := Cond_ref_of_op Source_object Result */
380 case AML_COND_REF_OF_OP:
383 * This op is a little strange because the internal return value is
384 * different than the return value stored in the result descriptor
385 * (There are really two return values)
388 if ((ACPI_NAMESPACE_NODE *) obj_desc == acpi_gbl_root_node) {
390 * This means that the object does not exist in the namespace,
394 ret_desc->integer.value = 0;
397 * Must delete the result descriptor since there is no reference
401 acpi_cm_remove_reference (res_desc);
405 /* Get the object reference and store it */
407 status = acpi_aml_get_object_reference (obj_desc, &ret_desc2, walk_state);
408 if (ACPI_FAILURE (status)) {
412 status = acpi_aml_exec_store (ret_desc2, res_desc, walk_state);
414 /* The object exists in the namespace, return TRUE */
416 ret_desc->integer.value = ACPI_INTEGER_MAX;
424 * A store operand is typically a number, string, buffer or lvalue
425 * TBD: [Unhandled] What about a store to a package?
429 * Do the store, and be careful about deleting the source object,
430 * since the object itself may have been stored.
433 status = acpi_aml_exec_store (obj_desc, res_desc, walk_state);
434 if (ACPI_FAILURE (status)) {
435 /* On failure, just delete the Obj_desc */
437 acpi_cm_remove_reference (obj_desc);
442 * Normally, we would remove a reference on the Obj_desc parameter;
443 * But since it is being used as the internal return object
444 * (meaning we would normally increment it), the two cancel out,
445 * and we simply don't do anything.
447 *return_desc = obj_desc;
458 /* Reference, returning an Reference */
465 * These are obsolete opcodes
468 /* Def_shift_left_bit := Shift_left_bit_op Source Bit_num */
469 /* Def_shift_right_bit := Shift_right_bit_op Source Bit_num */
471 case AML_SHIFT_LEFT_BIT_OP:
472 case AML_SHIFT_RIGHT_BIT_OP:
481 REPORT_ERROR (("Acpi_aml_exec_monadic2_r: Unknown monadic opcode %X\n",
483 status = AE_AML_BAD_OPCODE;
488 status = acpi_aml_exec_store (ret_desc, res_desc, walk_state);
492 /* Always delete the operand object */
494 acpi_cm_remove_reference (obj_desc);
496 /* Delete return object(s) on error */
498 if (ACPI_FAILURE (status)) {
499 acpi_cm_remove_reference (res_desc); /* Result descriptor */
501 acpi_cm_remove_reference (ret_desc);
506 /* Set the return object and exit */
508 *return_desc = ret_desc;
513 /*******************************************************************************
515 * FUNCTION: Acpi_aml_exec_monadic2
517 * PARAMETERS: Opcode - The opcode to be executed
521 * DESCRIPTION: Execute Type 2 monadic operator with numeric operand:
522 * Deref_of_op, Ref_of_op, Size_of_op, Type_op, Increment_op,
523 * Decrement_op, LNot_op,
525 ******************************************************************************/
528 acpi_aml_exec_monadic2 (
530 ACPI_WALK_STATE *walk_state,
531 ACPI_OPERAND_OBJECT **return_desc)
533 ACPI_OPERAND_OBJECT *obj_desc;
534 ACPI_OPERAND_OBJECT *tmp_desc;
535 ACPI_OPERAND_OBJECT *ret_desc = NULL;
536 ACPI_STATUS resolve_status;
542 /* Attempt to resolve the operands */
544 resolve_status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
545 /* Always get all operands */
547 status = acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
550 /* Now we can check the status codes */
552 if (ACPI_FAILURE (resolve_status)) {
556 if (ACPI_FAILURE (status)) {
561 /* Get the operand and decode the opcode */
566 /* Def_lNot := LNot_op Operand */
570 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
572 status = AE_NO_MEMORY;
576 ret_desc->integer.value = !obj_desc->integer.value;
580 /* Def_decrement := Decrement_op Target */
581 /* Def_increment := Increment_op Target */
583 case AML_DECREMENT_OP:
584 case AML_INCREMENT_OP:
587 * Since we are expecting an Reference on the top of the stack, it
588 * can be either an Node or an internal object.
590 * TBD: [Future] This may be the prototype code for all cases where
591 * an Reference is expected!! 10/99
594 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
600 * Duplicate the Reference in a new object so that we can resolve it
601 * without destroying the original Reference object
604 ret_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE);
606 status = AE_NO_MEMORY;
610 ret_desc->reference.opcode = obj_desc->reference.opcode;
611 ret_desc->reference.offset = obj_desc->reference.offset;
612 ret_desc->reference.object = obj_desc->reference.object;
617 * Convert the Ret_desc Reference to a Number
618 * (This deletes the original Ret_desc)
621 status = acpi_aml_resolve_operands (AML_LNOT_OP, &ret_desc, walk_state);
622 if (ACPI_FAILURE (status)) {
626 /* Do the actual increment or decrement */
628 if (AML_INCREMENT_OP == opcode) {
629 ret_desc->integer.value++;
632 ret_desc->integer.value--;
635 /* Store the result back in the original descriptor */
637 status = acpi_aml_exec_store (ret_desc, obj_desc, walk_state);
639 /* Objdesc was just deleted (because it is an Reference) */
646 /* Def_object_type := Object_type_op Source_object */
650 if (INTERNAL_TYPE_REFERENCE == obj_desc->common.type) {
652 * Not a Name -- an indirect name pointer would have
653 * been converted to a direct name pointer in Resolve_operands
655 switch (obj_desc->reference.opcode) {
660 /* Constants are of type Number */
662 type = ACPI_TYPE_INTEGER;
668 /* Per 1.0b spec, Debug object is of type Debug_object */
670 type = ACPI_TYPE_DEBUG_OBJECT;
676 /* Get the type of this reference (index into another object) */
678 type = obj_desc->reference.target_type;
679 if (type == ACPI_TYPE_PACKAGE) {
681 * The main object is a package, we want to get the type
682 * of the individual package element that is referenced by
685 type = (*(obj_desc->reference.where))->common.type;
694 type = acpi_ds_method_data_get_type (obj_desc->reference.opcode,
695 obj_desc->reference.offset, walk_state);
701 REPORT_ERROR (("Acpi_aml_exec_monadic2/Type_op: Internal error - Unknown Reference subtype %X\n",
702 obj_desc->reference.opcode));
703 status = AE_AML_INTERNAL;
710 * It's not a Reference, so it must be a direct name pointer.
712 type = acpi_ns_get_type ((ACPI_HANDLE) obj_desc);
715 /* Allocate a descriptor to hold the type. */
717 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
719 status = AE_NO_MEMORY;
723 ret_desc->integer.value = type;
727 /* Def_size_of := Size_of_op Source_object */
731 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
732 obj_desc = acpi_ns_get_attached_object (obj_desc);
740 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_INTEGER);
778 status = AE_NO_MEMORY;
782 ret_desc->integer.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.opcode) {
809 /* Set Obj_desc to the value of the local/arg */
814 acpi_ds_method_data_get_value (obj_desc->reference.opcode,
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);
827 /* Index op - handled below */
833 /* Obj_desc may have changed from the code above */
835 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
836 /* Get the actual object from the Node (This is the dereference) */
838 ret_desc = ((ACPI_NAMESPACE_NODE *) obj_desc)->object;
840 /* Returning a pointer to the object, add another reference! */
842 acpi_cm_add_reference (ret_desc);
847 * This must be a reference object produced by the Index
848 * ASL operation -- check internal opcode
851 if ((obj_desc->reference.opcode != AML_INDEX_OP) &&
852 (obj_desc->reference.opcode != AML_REF_OF_OP)) {
858 switch (obj_desc->reference.opcode) {
862 * Supported target types for the Index operator are
867 if (obj_desc->reference.target_type == ACPI_TYPE_BUFFER_FIELD) {
869 * The target is a buffer, we must create a new object that
870 * contains one element of the buffer, the element pointed
873 * NOTE: index into a buffer is NOT a pointer to a
874 * sub-buffer of the main buffer, it is only a pointer to a
875 * single element (byte) of the buffer!
877 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
879 status = AE_NO_MEMORY;
883 tmp_desc = obj_desc->reference.object;
884 ret_desc->integer.value =
885 tmp_desc->buffer.pointer[obj_desc->reference.offset];
887 /* TBD: [Investigate] (see below) Don't add an additional
892 else if (obj_desc->reference.target_type == ACPI_TYPE_PACKAGE) {
894 * The target is a package, we want to return the referenced
895 * element of the package. We must add another reference to
896 * this object, however.
899 ret_desc = *(obj_desc->reference.where);
902 * We can't return a NULL dereferenced value. This is
903 * an uninitialized package element and is thus a
907 status = AE_AML_UNINITIALIZED_ELEMENT;
911 acpi_cm_add_reference (ret_desc);
915 status = AE_AML_OPERAND_TYPE;
924 ret_desc = obj_desc->reference.object;
926 /* Add another reference to the object! */
928 acpi_cm_add_reference (ret_desc);
938 REPORT_ERROR (("Acpi_aml_exec_monadic2: Unknown monadic opcode %X\n",
940 status = AE_AML_BAD_OPCODE;
948 acpi_cm_remove_reference (obj_desc);
951 /* Delete return object on error */
953 if (ACPI_FAILURE (status) &&
955 acpi_cm_remove_reference (ret_desc);
959 *return_desc = ret_desc;