2 /******************************************************************************
4 * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
7 *****************************************************************************/
9 /******************************************************************************
13 * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
14 * All rights reserved.
18 * 2.1. This is your license from Intel Corp. under its intellectual property
19 * rights. You may have additional license terms from the party that provided
20 * you this software, covering your right to use that party's intellectual
23 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24 * copy of the source code appearing in this file ("Covered Code") an
25 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
26 * base code distributed originally by Intel ("Original Intel Code") to copy,
27 * make derivatives, distribute, use and display any portion of the Covered
28 * Code in any form, with the right to sublicense such rights; and
30 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31 * license (with the right to sublicense), under only those claims of Intel
32 * patents that are infringed by the Original Intel Code, to make, use, sell,
33 * offer to sell, and import the Covered Code and derivative works thereof
34 * solely to the minimum extent necessary to exercise the above copyright
35 * license, and in no event shall the patent license extend to any additions
36 * to or modifications of the Original Intel Code. No other license or right
37 * is granted directly or by implication, estoppel or otherwise;
39 * The above copyright and patent license is granted only if the following
44 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45 * Redistribution of source code of any substantial portion of the Covered
46 * Code or modification with rights to further distribute source must include
47 * the above Copyright Notice, the above License, this list of Conditions,
48 * and the following Disclaimer and Export Compliance provision. In addition,
49 * Licensee must cause all Covered Code to which Licensee contributes to
50 * contain a file documenting the changes Licensee made to create that Covered
51 * Code and the date of any change. Licensee must include in that file the
52 * documentation of any changes made by any predecessor Licensee. Licensee
53 * must include a prominent statement that the modification is derived,
54 * directly or indirectly, from Original Intel Code.
56 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
57 * Redistribution of source code of any substantial portion of the Covered
58 * Code or modification without rights to further distribute source must
59 * include the following Disclaimer and Export Compliance provision in the
60 * documentation and/or other materials provided with distribution. In
61 * addition, Licensee may not authorize further sublicense of source of any
62 * portion of the Covered Code, and must include terms to the effect that the
63 * license from Licensee to its licensee is limited to the intellectual
64 * property embodied in the software Licensee provides to its licensee, and
65 * not to intellectual property embodied in modifications its licensee may
68 * 3.3. Redistribution of Executable. Redistribution in executable form of any
69 * substantial portion of the Covered Code or modification must reproduce the
70 * above Copyright Notice, and the following Disclaimer and Export Compliance
71 * provision in the documentation and/or other materials provided with the
74 * 3.4. Intel retains all right, title, and interest in and to the Original
77 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
78 * Intel shall be used in advertising or otherwise to promote the sale, use or
79 * other dealings in products derived from or relating to the Covered Code
80 * without prior written authorization from Intel.
82 * 4. Disclaimer and Export Compliance
84 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
85 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
86 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
87 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
89 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
90 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
93 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
94 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
95 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
96 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
97 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
98 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
99 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
102 * 4.3. Licensee shall not export, either directly or indirectly, any of this
103 * software or system incorporating such software without first obtaining any
104 * required license or other approval from the U. S. Department of Commerce or
105 * any other agency or department of the United States Government. In the
106 * event Licensee exports any such software from the United States or
107 * re-exports any such software from a foreign destination, Licensee shall
108 * ensure that the distribution and export/re-export of the software is in
109 * compliance with all laws, regulations, orders, or other restrictions of the
110 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
111 * any of its subsidiaries will export/re-export any technical data, process,
112 * software, or service, directly or indirectly, to any country for which the
113 * United States government or any agency thereof requires an export license,
114 * other governmental approval, or letter of assurance, without first obtaining
115 * such license, approval or letter.
117 *****************************************************************************/
122 #include "acinterp.h"
126 #define _COMPONENT ACPI_EXECUTER
127 ACPI_MODULE_NAME ("exmisc")
130 /*******************************************************************************
132 * FUNCTION: AcpiExGetObjectReference
134 * PARAMETERS: ObjDesc - Create a reference to this object
135 * ReturnDesc - Where to store the reference
136 * WalkState - Current state
140 * DESCRIPTION: Obtain and return a "reference" to the target object
141 * Common code for the RefOfOp and the CondRefOfOp.
143 ******************************************************************************/
146 AcpiExGetObjectReference (
147 ACPI_OPERAND_OBJECT *ObjDesc,
148 ACPI_OPERAND_OBJECT **ReturnDesc,
149 ACPI_WALK_STATE *WalkState)
151 ACPI_OPERAND_OBJECT *ReferenceObj;
152 ACPI_OPERAND_OBJECT *ReferencedObj;
155 ACPI_FUNCTION_TRACE_PTR ("ExGetObjectReference", ObjDesc);
160 switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
162 case ACPI_DESC_TYPE_OPERAND:
164 if (ACPI_GET_OBJECT_TYPE (ObjDesc) != ACPI_TYPE_LOCAL_REFERENCE)
166 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
170 * Must be a reference to a Local or Arg
172 switch (ObjDesc->Reference.Opcode)
178 /* The referenced object is the pseudo-node for the local/arg */
180 ReferencedObj = ObjDesc->Reference.Object;
185 ACPI_REPORT_ERROR (("Unknown Reference opcode in GetReference %X\n",
186 ObjDesc->Reference.Opcode));
187 return_ACPI_STATUS (AE_AML_INTERNAL);
192 case ACPI_DESC_TYPE_NAMED:
195 * A named reference that has already been resolved to a Node
197 ReferencedObj = ObjDesc;
203 ACPI_REPORT_ERROR (("Invalid descriptor type in GetReference: %X\n",
204 ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
205 return_ACPI_STATUS (AE_TYPE);
209 /* Create a new reference object */
211 ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
214 return_ACPI_STATUS (AE_NO_MEMORY);
217 ReferenceObj->Reference.Opcode = AML_REF_OF_OP;
218 ReferenceObj->Reference.Object = ReferencedObj;
219 *ReturnDesc = ReferenceObj;
221 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p Type [%s], returning Reference %p\n",
222 ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
224 return_ACPI_STATUS (AE_OK);
228 /*******************************************************************************
230 * FUNCTION: AcpiExConcatTemplate
232 * PARAMETERS: Operand0 - First source object
233 * Operand1 - Second source object
234 * ActualReturnDesc - Where to place the return object
235 * WalkState - Current walk state
239 * DESCRIPTION: Concatenate two resource templates
241 ******************************************************************************/
244 AcpiExConcatTemplate (
245 ACPI_OPERAND_OBJECT *Operand0,
246 ACPI_OPERAND_OBJECT *Operand1,
247 ACPI_OPERAND_OBJECT **ActualReturnDesc,
248 ACPI_WALK_STATE *WalkState)
250 ACPI_OPERAND_OBJECT *ReturnDesc;
258 ACPI_FUNCTION_TRACE ("ExConcatTemplate");
261 /* Find the EndTags in each resource template */
263 EndTag1 = AcpiUtGetResourceEndTag (Operand0);
264 EndTag2 = AcpiUtGetResourceEndTag (Operand1);
265 if (!EndTag1 || !EndTag2)
267 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
270 /* Compute the length of each part */
272 Length1 = ACPI_PTR_DIFF (EndTag1, Operand0->Buffer.Pointer);
273 Length2 = ACPI_PTR_DIFF (EndTag2, Operand1->Buffer.Pointer) +
274 2; /* Size of END_TAG */
276 /* Create a new buffer object for the result */
278 ReturnDesc = AcpiUtCreateBufferObject (Length1 + Length2);
281 return_ACPI_STATUS (AE_NO_MEMORY);
284 /* Copy the templates to the new descriptor */
286 NewBuf = ReturnDesc->Buffer.Pointer;
287 ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length1);
288 ACPI_MEMCPY (NewBuf + Length1, Operand1->Buffer.Pointer, Length2);
290 /* Compute the new checksum */
292 NewBuf[ReturnDesc->Buffer.Length - 1] =
293 AcpiUtGenerateChecksum (ReturnDesc->Buffer.Pointer,
294 (ReturnDesc->Buffer.Length - 1));
296 /* Return the completed template descriptor */
298 *ActualReturnDesc = ReturnDesc;
299 return_ACPI_STATUS (AE_OK);
303 /*******************************************************************************
305 * FUNCTION: AcpiExDoConcatenate
307 * PARAMETERS: Operand0 - First source object
308 * Operand1 - Second source object
309 * ActualReturnDesc - Where to place the return object
310 * WalkState - Current walk state
314 * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
316 ******************************************************************************/
319 AcpiExDoConcatenate (
320 ACPI_OPERAND_OBJECT *Operand0,
321 ACPI_OPERAND_OBJECT *Operand1,
322 ACPI_OPERAND_OBJECT **ActualReturnDesc,
323 ACPI_WALK_STATE *WalkState)
325 ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1;
326 ACPI_OPERAND_OBJECT *ReturnDesc;
332 ACPI_FUNCTION_TRACE ("ExDoConcatenate");
336 * Convert the second operand if necessary. The first operand
337 * determines the type of the second operand, (See the Data Types
338 * section of the ACPI specification.) Both object types are
339 * guaranteed to be either Integer/String/Buffer by the operand
340 * resolution mechanism.
342 switch (ACPI_GET_OBJECT_TYPE (Operand0))
344 case ACPI_TYPE_INTEGER:
345 Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
348 case ACPI_TYPE_STRING:
349 Status = AcpiExConvertToString (Operand1, &LocalOperand1,
350 ACPI_IMPLICIT_CONVERT_HEX);
353 case ACPI_TYPE_BUFFER:
354 Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
358 ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
359 ACPI_GET_OBJECT_TYPE (Operand0)));
360 Status = AE_AML_INTERNAL;
363 if (ACPI_FAILURE (Status))
369 * Both operands are now known to be the same object type
370 * (Both are Integer, String, or Buffer), and we can now perform the
375 * There are three cases to handle:
377 * 1) Two Integers concatenated to produce a new Buffer
378 * 2) Two Strings concatenated to produce a new String
379 * 3) Two Buffers concatenated to produce a new Buffer
381 switch (ACPI_GET_OBJECT_TYPE (Operand0))
383 case ACPI_TYPE_INTEGER:
385 /* Result of two Integers is a Buffer */
386 /* Need enough buffer space for two integers */
388 ReturnDesc = AcpiUtCreateBufferObject (
389 ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
392 Status = AE_NO_MEMORY;
396 NewBuf = (char *) ReturnDesc->Buffer.Pointer;
398 /* Copy the first integer, LSB first */
401 &Operand0->Integer.Value,
402 AcpiGbl_IntegerByteWidth);
404 /* Copy the second integer (LSB first) after the first */
406 ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth,
407 &LocalOperand1->Integer.Value,
408 AcpiGbl_IntegerByteWidth);
411 case ACPI_TYPE_STRING:
413 /* Result of two Strings is a String */
415 NewLength = (ACPI_SIZE) Operand0->String.Length +
416 (ACPI_SIZE) LocalOperand1->String.Length;
417 if (NewLength > ACPI_MAX_STRING_CONVERSION)
419 Status = AE_AML_STRING_LIMIT;
423 ReturnDesc = AcpiUtCreateStringObject (NewLength);
426 Status = AE_NO_MEMORY;
430 NewBuf = ReturnDesc->String.Pointer;
432 /* Concatenate the strings */
435 Operand0->String.Pointer);
436 ACPI_STRCPY (NewBuf + Operand0->String.Length,
437 LocalOperand1->String.Pointer);
440 case ACPI_TYPE_BUFFER:
442 /* Result of two Buffers is a Buffer */
444 ReturnDesc = AcpiUtCreateBufferObject (
445 (ACPI_SIZE) Operand0->Buffer.Length +
446 (ACPI_SIZE) LocalOperand1->Buffer.Length);
449 Status = AE_NO_MEMORY;
453 NewBuf = (char *) ReturnDesc->Buffer.Pointer;
455 /* Concatenate the buffers */
458 Operand0->Buffer.Pointer,
459 Operand0->Buffer.Length);
460 ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length,
461 LocalOperand1->Buffer.Pointer,
462 LocalOperand1->Buffer.Length);
467 /* Invalid object type, should not happen here */
469 ACPI_REPORT_ERROR (("Concatenate - Invalid object type: %X\n",
470 ACPI_GET_OBJECT_TYPE (Operand0)));
471 Status =AE_AML_INTERNAL;
475 *ActualReturnDesc = ReturnDesc;
478 if (LocalOperand1 != Operand1)
480 AcpiUtRemoveReference (LocalOperand1);
482 return_ACPI_STATUS (Status);
486 /*******************************************************************************
488 * FUNCTION: AcpiExDoMathOp
490 * PARAMETERS: Opcode - AML opcode
491 * Integer0 - Integer operand #0
492 * Integer1 - Integer operand #1
494 * RETURN: Integer result of the operation
496 * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
497 * math functions here is to prevent a lot of pointer dereferencing
498 * to obtain the operands.
500 ******************************************************************************/
505 ACPI_INTEGER Integer0,
506 ACPI_INTEGER Integer1)
509 ACPI_FUNCTION_ENTRY ();
514 case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */
516 return (Integer0 + Integer1);
519 case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */
521 return (Integer0 & Integer1);
524 case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */
526 return (~(Integer0 & Integer1));
529 case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */
531 return (Integer0 | Integer1);
534 case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */
536 return (~(Integer0 | Integer1));
539 case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */
541 return (Integer0 ^ Integer1);
544 case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */
546 return (Integer0 * Integer1);
549 case AML_SHIFT_LEFT_OP: /* ShiftLeft (Operand, ShiftCount, Result) */
551 return (Integer0 << Integer1);
554 case AML_SHIFT_RIGHT_OP: /* ShiftRight (Operand, ShiftCount, Result) */
556 return (Integer0 >> Integer1);
559 case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
561 return (Integer0 - Integer1);
570 /*******************************************************************************
572 * FUNCTION: AcpiExDoLogicalNumericOp
574 * PARAMETERS: Opcode - AML opcode
575 * Integer0 - Integer operand #0
576 * Integer1 - Integer operand #1
577 * LogicalResult - TRUE/FALSE result of the operation
581 * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
582 * operators (LAnd and LOr), both operands must be integers.
584 * Note: cleanest machine code seems to be produced by the code
585 * below, rather than using statements of the form:
586 * Result = (Integer0 && Integer1);
588 ******************************************************************************/
591 AcpiExDoLogicalNumericOp (
593 ACPI_INTEGER Integer0,
594 ACPI_INTEGER Integer1,
595 BOOLEAN *LogicalResult)
597 ACPI_STATUS Status = AE_OK;
598 BOOLEAN LocalResult = FALSE;
601 ACPI_FUNCTION_TRACE ("ExDoLogicalNumericOp");
606 case AML_LAND_OP: /* LAnd (Integer0, Integer1) */
608 if (Integer0 && Integer1)
614 case AML_LOR_OP: /* LOr (Integer0, Integer1) */
616 if (Integer0 || Integer1)
623 Status = AE_AML_INTERNAL;
627 /* Return the logical result and status */
629 *LogicalResult = LocalResult;
630 return_ACPI_STATUS (Status);
634 /*******************************************************************************
636 * FUNCTION: AcpiExDoLogicalOp
638 * PARAMETERS: Opcode - AML opcode
639 * Operand0 - operand #0
640 * Operand1 - operand #1
641 * LogicalResult - TRUE/FALSE result of the operation
645 * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
646 * functions here is to prevent a lot of pointer dereferencing
647 * to obtain the operands and to simplify the generation of the
648 * logical value. For the Numeric operators (LAnd and LOr), both
649 * operands must be integers. For the other logical operators,
650 * operands can be any combination of Integer/String/Buffer. The
651 * first operand determines the type to which the second operand
654 * Note: cleanest machine code seems to be produced by the code
655 * below, rather than using statements of the form:
656 * Result = (Operand0 == Operand1);
658 ******************************************************************************/
663 ACPI_OPERAND_OBJECT *Operand0,
664 ACPI_OPERAND_OBJECT *Operand1,
665 BOOLEAN *LogicalResult)
667 ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1;
668 ACPI_INTEGER Integer0;
669 ACPI_INTEGER Integer1;
672 ACPI_STATUS Status = AE_OK;
673 BOOLEAN LocalResult = FALSE;
677 ACPI_FUNCTION_TRACE ("ExDoLogicalOp");
681 * Convert the second operand if necessary. The first operand
682 * determines the type of the second operand, (See the Data Types
683 * section of the ACPI 3.0+ specification.) Both object types are
684 * guaranteed to be either Integer/String/Buffer by the operand
685 * resolution mechanism.
687 switch (ACPI_GET_OBJECT_TYPE (Operand0))
689 case ACPI_TYPE_INTEGER:
690 Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
693 case ACPI_TYPE_STRING:
694 Status = AcpiExConvertToString (Operand1, &LocalOperand1,
695 ACPI_IMPLICIT_CONVERT_HEX);
698 case ACPI_TYPE_BUFFER:
699 Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
703 Status = AE_AML_INTERNAL;
707 if (ACPI_FAILURE (Status))
713 * Two cases: 1) Both Integers, 2) Both Strings or Buffers
715 if (ACPI_GET_OBJECT_TYPE (Operand0) == ACPI_TYPE_INTEGER)
718 * 1) Both operands are of type integer
719 * Note: LocalOperand1 may have changed above
721 Integer0 = Operand0->Integer.Value;
722 Integer1 = LocalOperand1->Integer.Value;
726 case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
728 if (Integer0 == Integer1)
734 case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
736 if (Integer0 > Integer1)
742 case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
744 if (Integer0 < Integer1)
751 Status = AE_AML_INTERNAL;
758 * 2) Both operands are Strings or both are Buffers
759 * Note: Code below takes advantage of common Buffer/String
760 * object fields. LocalOperand1 may have changed above. Use
761 * memcmp to handle nulls in buffers.
763 Length0 = Operand0->Buffer.Length;
764 Length1 = LocalOperand1->Buffer.Length;
766 /* Lexicographic compare: compare the data bytes */
768 Compare = ACPI_MEMCMP ((const char * ) Operand0->Buffer.Pointer,
769 (const char * ) LocalOperand1->Buffer.Pointer,
770 (Length0 > Length1) ? Length1 : Length0);
774 case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
776 /* Length and all bytes must be equal */
778 if ((Length0 == Length1) &&
781 /* Length and all bytes match ==> TRUE */
787 case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
792 goto Cleanup; /* TRUE */
796 goto Cleanup; /* FALSE */
799 /* Bytes match (to shortest length), compare lengths */
801 if (Length0 > Length1)
807 case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
811 goto Cleanup; /* FALSE */
816 goto Cleanup; /* TRUE */
819 /* Bytes match (to shortest length), compare lengths */
821 if (Length0 < Length1)
828 Status = AE_AML_INTERNAL;
835 /* New object was created if implicit conversion performed - delete */
837 if (LocalOperand1 != Operand1)
839 AcpiUtRemoveReference (LocalOperand1);
842 /* Return the logical result and status */
844 *LogicalResult = LocalResult;
845 return_ACPI_STATUS (Status);