1 /******************************************************************************
3 * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2013, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
45 #define __EXOPARG2_C__
55 #define _COMPONENT ACPI_EXECUTER
56 ACPI_MODULE_NAME ("exoparg2")
60 * Naming convention for AML interpreter execution routines.
62 * The routines that begin execution of AML opcodes are named with a common
63 * convention based upon the number of arguments, the number of target operands,
64 * and whether or not a value is returned:
66 * AcpiExOpcode_xA_yT_zR
70 * xA - ARGUMENTS: The number of arguments (input operands) that are
71 * required for this opcode type (1 through 6 args).
72 * yT - TARGETS: The number of targets (output operands) that are required
73 * for this opcode type (0, 1, or 2 targets).
74 * zR - RETURN VALUE: Indicates whether this opcode type returns a value
75 * as the function return (0 or 1).
77 * The AcpiExOpcode* functions are called via the Dispatcher component with
78 * fully resolved operands.
82 /*******************************************************************************
84 * FUNCTION: AcpiExOpcode_2A_0T_0R
86 * PARAMETERS: WalkState - Current walk state
90 * DESCRIPTION: Execute opcode with two arguments, no target, and no return
93 * ALLOCATION: Deletes both operands
95 ******************************************************************************/
98 AcpiExOpcode_2A_0T_0R (
99 ACPI_WALK_STATE
*WalkState
)
101 ACPI_OPERAND_OBJECT
**Operand
= &WalkState
->Operands
[0];
102 ACPI_NAMESPACE_NODE
*Node
;
104 ACPI_STATUS Status
= AE_OK
;
107 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_0R
,
108 AcpiPsGetOpcodeName (WalkState
->Opcode
));
111 /* Examine the opcode */
113 switch (WalkState
->Opcode
)
115 case AML_NOTIFY_OP
: /* Notify (NotifyObject, NotifyValue) */
117 /* The first operand is a namespace node */
119 Node
= (ACPI_NAMESPACE_NODE
*) Operand
[0];
121 /* Second value is the notify value */
123 Value
= (UINT32
) Operand
[1]->Integer
.Value
;
125 /* Are notifies allowed on this object? */
127 if (!AcpiEvIsNotifyObject (Node
))
129 ACPI_ERROR ((AE_INFO
,
130 "Unexpected notify object type [%s]",
131 AcpiUtGetTypeName (Node
->Type
)));
133 Status
= AE_AML_OPERAND_TYPE
;
138 * Dispatch the notify to the appropriate handler
139 * NOTE: the request is queued for execution after this method
140 * completes. The notify handlers are NOT invoked synchronously
141 * from this thread -- because handlers may in turn run other
144 Status
= AcpiEvQueueNotifyRequest (Node
, Value
);
149 ACPI_ERROR ((AE_INFO
, "Unknown AML opcode 0x%X",
151 Status
= AE_AML_BAD_OPCODE
;
154 return_ACPI_STATUS (Status
);
158 /*******************************************************************************
160 * FUNCTION: AcpiExOpcode_2A_2T_1R
162 * PARAMETERS: WalkState - Current walk state
166 * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
167 * and one implicit return value.
169 ******************************************************************************/
172 AcpiExOpcode_2A_2T_1R (
173 ACPI_WALK_STATE
*WalkState
)
175 ACPI_OPERAND_OBJECT
**Operand
= &WalkState
->Operands
[0];
176 ACPI_OPERAND_OBJECT
*ReturnDesc1
= NULL
;
177 ACPI_OPERAND_OBJECT
*ReturnDesc2
= NULL
;
181 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_2T_1R
,
182 AcpiPsGetOpcodeName (WalkState
->Opcode
));
185 /* Execute the opcode */
187 switch (WalkState
->Opcode
)
191 /* Divide (Dividend, Divisor, RemainderResult QuotientResult) */
193 ReturnDesc1
= AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER
);
196 Status
= AE_NO_MEMORY
;
200 ReturnDesc2
= AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER
);
203 Status
= AE_NO_MEMORY
;
207 /* Quotient to ReturnDesc1, remainder to ReturnDesc2 */
209 Status
= AcpiUtDivide (Operand
[0]->Integer
.Value
,
210 Operand
[1]->Integer
.Value
,
211 &ReturnDesc1
->Integer
.Value
,
212 &ReturnDesc2
->Integer
.Value
);
213 if (ACPI_FAILURE (Status
))
221 ACPI_ERROR ((AE_INFO
, "Unknown AML opcode 0x%X",
223 Status
= AE_AML_BAD_OPCODE
;
227 /* Store the results to the target reference operands */
229 Status
= AcpiExStore (ReturnDesc2
, Operand
[2], WalkState
);
230 if (ACPI_FAILURE (Status
))
235 Status
= AcpiExStore (ReturnDesc1
, Operand
[3], WalkState
);
236 if (ACPI_FAILURE (Status
))
243 * Since the remainder is not returned indirectly, remove a reference to
244 * it. Only the quotient is returned indirectly.
246 AcpiUtRemoveReference (ReturnDesc2
);
248 if (ACPI_FAILURE (Status
))
250 /* Delete the return object */
252 AcpiUtRemoveReference (ReturnDesc1
);
255 /* Save return object (the remainder) on success */
259 WalkState
->ResultObj
= ReturnDesc1
;
262 return_ACPI_STATUS (Status
);
266 /*******************************************************************************
268 * FUNCTION: AcpiExOpcode_2A_1T_1R
270 * PARAMETERS: WalkState - Current walk state
274 * DESCRIPTION: Execute opcode with two arguments, one target, and a return
277 ******************************************************************************/
280 AcpiExOpcode_2A_1T_1R (
281 ACPI_WALK_STATE
*WalkState
)
283 ACPI_OPERAND_OBJECT
**Operand
= &WalkState
->Operands
[0];
284 ACPI_OPERAND_OBJECT
*ReturnDesc
= NULL
;
286 ACPI_STATUS Status
= AE_OK
;
287 ACPI_SIZE Length
= 0;
290 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_1T_1R
,
291 AcpiPsGetOpcodeName (WalkState
->Opcode
));
294 /* Execute the opcode */
296 if (WalkState
->OpInfo
->Flags
& AML_MATH
)
298 /* All simple math opcodes (add, etc.) */
300 ReturnDesc
= AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER
);
303 Status
= AE_NO_MEMORY
;
307 ReturnDesc
->Integer
.Value
= AcpiExDoMathOp (WalkState
->Opcode
,
308 Operand
[0]->Integer
.Value
,
309 Operand
[1]->Integer
.Value
);
310 goto StoreResultToTarget
;
313 switch (WalkState
->Opcode
)
315 case AML_MOD_OP
: /* Mod (Dividend, Divisor, RemainderResult (ACPI 2.0) */
317 ReturnDesc
= AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER
);
320 Status
= AE_NO_MEMORY
;
324 /* ReturnDesc will contain the remainder */
326 Status
= AcpiUtDivide (Operand
[0]->Integer
.Value
,
327 Operand
[1]->Integer
.Value
,
329 &ReturnDesc
->Integer
.Value
);
332 case AML_CONCAT_OP
: /* Concatenate (Data1, Data2, Result) */
334 Status
= AcpiExDoConcatenate (Operand
[0], Operand
[1],
335 &ReturnDesc
, WalkState
);
338 case AML_TO_STRING_OP
: /* ToString (Buffer, Length, Result) (ACPI 2.0) */
340 * Input object is guaranteed to be a buffer at this point (it may have
341 * been converted.) Copy the raw buffer data to a new object of
346 * Get the length of the new string. It is the smallest of:
347 * 1) Length of the input buffer
348 * 2) Max length as specified in the ToString operator
349 * 3) Length of input buffer up to a zero byte (null terminator)
351 * NOTE: A length of zero is ok, and will create a zero-length, null
354 while ((Length
< Operand
[0]->Buffer
.Length
) &&
355 (Length
< Operand
[1]->Integer
.Value
) &&
356 (Operand
[0]->Buffer
.Pointer
[Length
]))
361 /* Allocate a new string object */
363 ReturnDesc
= AcpiUtCreateStringObject (Length
);
366 Status
= AE_NO_MEMORY
;
371 * Copy the raw buffer data with no transform.
372 * (NULL terminated already)
374 ACPI_MEMCPY (ReturnDesc
->String
.Pointer
,
375 Operand
[0]->Buffer
.Pointer
, Length
);
378 case AML_CONCAT_RES_OP
:
380 /* ConcatenateResTemplate (Buffer, Buffer, Result) (ACPI 2.0) */
382 Status
= AcpiExConcatTemplate (Operand
[0], Operand
[1],
383 &ReturnDesc
, WalkState
);
386 case AML_INDEX_OP
: /* Index (Source Index Result) */
388 /* Create the internal return object */
390 ReturnDesc
= AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE
);
393 Status
= AE_NO_MEMORY
;
397 /* Initialize the Index reference object */
399 Index
= Operand
[1]->Integer
.Value
;
400 ReturnDesc
->Reference
.Value
= (UINT32
) Index
;
401 ReturnDesc
->Reference
.Class
= ACPI_REFCLASS_INDEX
;
404 * At this point, the Source operand is a String, Buffer, or Package.
405 * Verify that the index is within range.
407 switch ((Operand
[0])->Common
.Type
)
409 case ACPI_TYPE_STRING
:
411 if (Index
>= Operand
[0]->String
.Length
)
413 Length
= Operand
[0]->String
.Length
;
414 Status
= AE_AML_STRING_LIMIT
;
417 ReturnDesc
->Reference
.TargetType
= ACPI_TYPE_BUFFER_FIELD
;
420 case ACPI_TYPE_BUFFER
:
422 if (Index
>= Operand
[0]->Buffer
.Length
)
424 Length
= Operand
[0]->Buffer
.Length
;
425 Status
= AE_AML_BUFFER_LIMIT
;
428 ReturnDesc
->Reference
.TargetType
= ACPI_TYPE_BUFFER_FIELD
;
431 case ACPI_TYPE_PACKAGE
:
433 if (Index
>= Operand
[0]->Package
.Count
)
435 Length
= Operand
[0]->Package
.Count
;
436 Status
= AE_AML_PACKAGE_LIMIT
;
439 ReturnDesc
->Reference
.TargetType
= ACPI_TYPE_PACKAGE
;
440 ReturnDesc
->Reference
.Where
= &Operand
[0]->Package
.Elements
[Index
];
445 Status
= AE_AML_INTERNAL
;
449 /* Failure means that the Index was beyond the end of the object */
451 if (ACPI_FAILURE (Status
))
453 ACPI_EXCEPTION ((AE_INFO
, Status
,
454 "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
455 ACPI_FORMAT_UINT64 (Index
), (UINT32
) Length
));
460 * Save the target object and add a reference to it for the life
463 ReturnDesc
->Reference
.Object
= Operand
[0];
464 AcpiUtAddReference (Operand
[0]);
466 /* Store the reference to the Target */
468 Status
= AcpiExStore (ReturnDesc
, Operand
[2], WalkState
);
470 /* Return the reference */
472 WalkState
->ResultObj
= ReturnDesc
;
477 ACPI_ERROR ((AE_INFO
, "Unknown AML opcode 0x%X",
479 Status
= AE_AML_BAD_OPCODE
;
486 if (ACPI_SUCCESS (Status
))
489 * Store the result of the operation (which is now in ReturnDesc) into
490 * the Target descriptor.
492 Status
= AcpiExStore (ReturnDesc
, Operand
[2], WalkState
);
493 if (ACPI_FAILURE (Status
))
498 if (!WalkState
->ResultObj
)
500 WalkState
->ResultObj
= ReturnDesc
;
507 /* Delete return object on error */
509 if (ACPI_FAILURE (Status
))
511 AcpiUtRemoveReference (ReturnDesc
);
512 WalkState
->ResultObj
= NULL
;
515 return_ACPI_STATUS (Status
);
519 /*******************************************************************************
521 * FUNCTION: AcpiExOpcode_2A_0T_1R
523 * PARAMETERS: WalkState - Current walk state
527 * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
529 ******************************************************************************/
532 AcpiExOpcode_2A_0T_1R (
533 ACPI_WALK_STATE
*WalkState
)
535 ACPI_OPERAND_OBJECT
**Operand
= &WalkState
->Operands
[0];
536 ACPI_OPERAND_OBJECT
*ReturnDesc
= NULL
;
537 ACPI_STATUS Status
= AE_OK
;
538 BOOLEAN LogicalResult
= FALSE
;
541 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_1R
,
542 AcpiPsGetOpcodeName (WalkState
->Opcode
));
545 /* Create the internal return object */
547 ReturnDesc
= AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER
);
550 Status
= AE_NO_MEMORY
;
554 /* Execute the Opcode */
556 if (WalkState
->OpInfo
->Flags
& AML_LOGICAL_NUMERIC
)
558 /* LogicalOp (Operand0, Operand1) */
560 Status
= AcpiExDoLogicalNumericOp (WalkState
->Opcode
,
561 Operand
[0]->Integer
.Value
, Operand
[1]->Integer
.Value
,
563 goto StoreLogicalResult
;
565 else if (WalkState
->OpInfo
->Flags
& AML_LOGICAL
)
567 /* LogicalOp (Operand0, Operand1) */
569 Status
= AcpiExDoLogicalOp (WalkState
->Opcode
, Operand
[0],
570 Operand
[1], &LogicalResult
);
571 goto StoreLogicalResult
;
574 switch (WalkState
->Opcode
)
576 case AML_ACQUIRE_OP
: /* Acquire (MutexObject, Timeout) */
578 Status
= AcpiExAcquireMutex (Operand
[1], Operand
[0], WalkState
);
579 if (Status
== AE_TIME
)
581 LogicalResult
= TRUE
; /* TRUE = Acquire timed out */
587 case AML_WAIT_OP
: /* Wait (EventObject, Timeout) */
589 Status
= AcpiExSystemWaitEvent (Operand
[1], Operand
[0]);
590 if (Status
== AE_TIME
)
592 LogicalResult
= TRUE
; /* TRUE, Wait timed out */
599 ACPI_ERROR ((AE_INFO
, "Unknown AML opcode 0x%X",
601 Status
= AE_AML_BAD_OPCODE
;
608 * Set return value to according to LogicalResult. logical TRUE (all ones)
609 * Default is FALSE (zero)
613 ReturnDesc
->Integer
.Value
= ACPI_UINT64_MAX
;
618 /* Delete return object on error */
620 if (ACPI_FAILURE (Status
))
622 AcpiUtRemoveReference (ReturnDesc
);
625 /* Save return object on success */
629 WalkState
->ResultObj
= ReturnDesc
;
632 return_ACPI_STATUS (Status
);