1 /******************************************************************************
3 * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2017, 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.
52 #define _COMPONENT ACPI_EXECUTER
53 ACPI_MODULE_NAME ("exoparg2")
57 * Naming convention for AML interpreter execution routines.
59 * The routines that begin execution of AML opcodes are named with a common
60 * convention based upon the number of arguments, the number of target operands,
61 * and whether or not a value is returned:
63 * AcpiExOpcode_xA_yT_zR
67 * xA - ARGUMENTS: The number of arguments (input operands) that are
68 * required for this opcode type (1 through 6 args).
69 * yT - TARGETS: The number of targets (output operands) that are required
70 * for this opcode type (0, 1, or 2 targets).
71 * zR - RETURN VALUE: Indicates whether this opcode type returns a value
72 * as the function return (0 or 1).
74 * The AcpiExOpcode* functions are called via the Dispatcher component with
75 * fully resolved operands.
79 /*******************************************************************************
81 * FUNCTION: AcpiExOpcode_2A_0T_0R
83 * PARAMETERS: WalkState - Current walk state
87 * DESCRIPTION: Execute opcode with two arguments, no target, and no return
90 * ALLOCATION: Deletes both operands
92 ******************************************************************************/
95 AcpiExOpcode_2A_0T_0R (
96 ACPI_WALK_STATE
*WalkState
)
98 ACPI_OPERAND_OBJECT
**Operand
= &WalkState
->Operands
[0];
99 ACPI_NAMESPACE_NODE
*Node
;
101 ACPI_STATUS Status
= AE_OK
;
104 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_0R
,
105 AcpiPsGetOpcodeName (WalkState
->Opcode
));
108 /* Examine the opcode */
110 switch (WalkState
->Opcode
)
112 case AML_NOTIFY_OP
: /* Notify (NotifyObject, NotifyValue) */
114 /* The first operand is a namespace node */
116 Node
= (ACPI_NAMESPACE_NODE
*) Operand
[0];
118 /* Second value is the notify value */
120 Value
= (UINT32
) Operand
[1]->Integer
.Value
;
122 /* Are notifies allowed on this object? */
124 if (!AcpiEvIsNotifyObject (Node
))
126 ACPI_ERROR ((AE_INFO
,
127 "Unexpected notify object type [%s]",
128 AcpiUtGetTypeName (Node
->Type
)));
130 Status
= AE_AML_OPERAND_TYPE
;
135 * Dispatch the notify to the appropriate handler
136 * NOTE: the request is queued for execution after this method
137 * completes. The notify handlers are NOT invoked synchronously
138 * from this thread -- because handlers may in turn run other
141 Status
= AcpiEvQueueNotifyRequest (Node
, Value
);
146 ACPI_ERROR ((AE_INFO
, "Unknown AML opcode 0x%X",
148 Status
= AE_AML_BAD_OPCODE
;
151 return_ACPI_STATUS (Status
);
155 /*******************************************************************************
157 * FUNCTION: AcpiExOpcode_2A_2T_1R
159 * PARAMETERS: WalkState - Current walk state
163 * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
164 * and one implicit return value.
166 ******************************************************************************/
169 AcpiExOpcode_2A_2T_1R (
170 ACPI_WALK_STATE
*WalkState
)
172 ACPI_OPERAND_OBJECT
**Operand
= &WalkState
->Operands
[0];
173 ACPI_OPERAND_OBJECT
*ReturnDesc1
= NULL
;
174 ACPI_OPERAND_OBJECT
*ReturnDesc2
= NULL
;
178 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_2T_1R
,
179 AcpiPsGetOpcodeName (WalkState
->Opcode
));
182 /* Execute the opcode */
184 switch (WalkState
->Opcode
)
188 /* Divide (Dividend, Divisor, RemainderResult QuotientResult) */
190 ReturnDesc1
= AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER
);
193 Status
= AE_NO_MEMORY
;
197 ReturnDesc2
= AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER
);
200 Status
= AE_NO_MEMORY
;
204 /* Quotient to ReturnDesc1, remainder to ReturnDesc2 */
206 Status
= AcpiUtDivide (
207 Operand
[0]->Integer
.Value
,
208 Operand
[1]->Integer
.Value
,
209 &ReturnDesc1
->Integer
.Value
,
210 &ReturnDesc2
->Integer
.Value
);
211 if (ACPI_FAILURE (Status
))
219 ACPI_ERROR ((AE_INFO
, "Unknown AML opcode 0x%X",
222 Status
= AE_AML_BAD_OPCODE
;
226 /* Store the results to the target reference operands */
228 Status
= AcpiExStore (ReturnDesc2
, Operand
[2], WalkState
);
229 if (ACPI_FAILURE (Status
))
234 Status
= AcpiExStore (ReturnDesc1
, Operand
[3], WalkState
);
235 if (ACPI_FAILURE (Status
))
242 * Since the remainder is not returned indirectly, remove a reference to
243 * it. Only the quotient is returned indirectly.
245 AcpiUtRemoveReference (ReturnDesc2
);
247 if (ACPI_FAILURE (Status
))
249 /* Delete the return object */
251 AcpiUtRemoveReference (ReturnDesc1
);
254 /* Save return object (the remainder) on success */
258 WalkState
->ResultObj
= ReturnDesc1
;
261 return_ACPI_STATUS (Status
);
265 /*******************************************************************************
267 * FUNCTION: AcpiExOpcode_2A_1T_1R
269 * PARAMETERS: WalkState - Current walk state
273 * DESCRIPTION: Execute opcode with two arguments, one target, and a return
276 ******************************************************************************/
279 AcpiExOpcode_2A_1T_1R (
280 ACPI_WALK_STATE
*WalkState
)
282 ACPI_OPERAND_OBJECT
**Operand
= &WalkState
->Operands
[0];
283 ACPI_OPERAND_OBJECT
*ReturnDesc
= NULL
;
285 ACPI_STATUS Status
= AE_OK
;
286 ACPI_SIZE Length
= 0;
289 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_1T_1R
,
290 AcpiPsGetOpcodeName (WalkState
->Opcode
));
293 /* Execute the opcode */
295 if (WalkState
->OpInfo
->Flags
& AML_MATH
)
297 /* All simple math opcodes (add, etc.) */
299 ReturnDesc
= AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER
);
302 Status
= AE_NO_MEMORY
;
306 ReturnDesc
->Integer
.Value
= AcpiExDoMathOp (
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 (
327 Operand
[0]->Integer
.Value
,
328 Operand
[1]->Integer
.Value
,
330 &ReturnDesc
->Integer
.Value
);
333 case AML_CONCATENATE_OP
: /* Concatenate (Data1, Data2, Result) */
335 Status
= AcpiExDoConcatenate (
336 Operand
[0], Operand
[1], &ReturnDesc
, WalkState
);
339 case AML_TO_STRING_OP
: /* ToString (Buffer, Length, Result) (ACPI 2.0) */
341 * Input object is guaranteed to be a buffer at this point (it may have
342 * been converted.) Copy the raw buffer data to a new object of
347 * Get the length of the new string. It is the smallest of:
348 * 1) Length of the input buffer
349 * 2) Max length as specified in the ToString operator
350 * 3) Length of input buffer up to a zero byte (null terminator)
352 * NOTE: A length of zero is ok, and will create a zero-length, null
355 while ((Length
< Operand
[0]->Buffer
.Length
) &&
356 (Length
< Operand
[1]->Integer
.Value
) &&
357 (Operand
[0]->Buffer
.Pointer
[Length
]))
362 /* Allocate a new string object */
364 ReturnDesc
= AcpiUtCreateStringObject (Length
);
367 Status
= AE_NO_MEMORY
;
372 * Copy the raw buffer data with no transform.
373 * (NULL terminated already)
375 memcpy (ReturnDesc
->String
.Pointer
,
376 Operand
[0]->Buffer
.Pointer
, Length
);
379 case AML_CONCATENATE_TEMPLATE_OP
:
381 /* ConcatenateResTemplate (Buffer, Buffer, Result) (ACPI 2.0) */
383 Status
= AcpiExConcatTemplate (
384 Operand
[0], Operand
[1], &ReturnDesc
, WalkState
);
387 case AML_INDEX_OP
: /* Index (Source Index Result) */
389 /* Create the internal return object */
391 ReturnDesc
= AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE
);
394 Status
= AE_NO_MEMORY
;
398 /* Initialize the Index reference object */
400 Index
= Operand
[1]->Integer
.Value
;
401 ReturnDesc
->Reference
.Value
= (UINT32
) Index
;
402 ReturnDesc
->Reference
.Class
= ACPI_REFCLASS_INDEX
;
405 * At this point, the Source operand is a String, Buffer, or Package.
406 * Verify that the index is within range.
408 switch ((Operand
[0])->Common
.Type
)
410 case ACPI_TYPE_STRING
:
412 if (Index
>= Operand
[0]->String
.Length
)
414 Length
= Operand
[0]->String
.Length
;
415 Status
= AE_AML_STRING_LIMIT
;
418 ReturnDesc
->Reference
.TargetType
= ACPI_TYPE_BUFFER_FIELD
;
419 ReturnDesc
->Reference
.IndexPointer
=
420 &(Operand
[0]->Buffer
.Pointer
[Index
]);
423 case ACPI_TYPE_BUFFER
:
425 if (Index
>= Operand
[0]->Buffer
.Length
)
427 Length
= Operand
[0]->Buffer
.Length
;
428 Status
= AE_AML_BUFFER_LIMIT
;
431 ReturnDesc
->Reference
.TargetType
= ACPI_TYPE_BUFFER_FIELD
;
432 ReturnDesc
->Reference
.IndexPointer
=
433 &(Operand
[0]->Buffer
.Pointer
[Index
]);
436 case ACPI_TYPE_PACKAGE
:
438 if (Index
>= Operand
[0]->Package
.Count
)
440 Length
= Operand
[0]->Package
.Count
;
441 Status
= AE_AML_PACKAGE_LIMIT
;
444 ReturnDesc
->Reference
.TargetType
= ACPI_TYPE_PACKAGE
;
445 ReturnDesc
->Reference
.Where
=
446 &Operand
[0]->Package
.Elements
[Index
];
451 ACPI_ERROR ((AE_INFO
,
452 "Invalid object type: %X", (Operand
[0])->Common
.Type
));
453 Status
= AE_AML_INTERNAL
;
457 /* Failure means that the Index was beyond the end of the object */
459 if (ACPI_FAILURE (Status
))
461 ACPI_EXCEPTION ((AE_INFO
, Status
,
462 "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
463 ACPI_FORMAT_UINT64 (Index
), (UINT32
) Length
));
468 * Save the target object and add a reference to it for the life
471 ReturnDesc
->Reference
.Object
= Operand
[0];
472 AcpiUtAddReference (Operand
[0]);
474 /* Store the reference to the Target */
476 Status
= AcpiExStore (ReturnDesc
, Operand
[2], WalkState
);
478 /* Return the reference */
480 WalkState
->ResultObj
= ReturnDesc
;
485 ACPI_ERROR ((AE_INFO
, "Unknown AML opcode 0x%X",
487 Status
= AE_AML_BAD_OPCODE
;
494 if (ACPI_SUCCESS (Status
))
497 * Store the result of the operation (which is now in ReturnDesc) into
498 * the Target descriptor.
500 Status
= AcpiExStore (ReturnDesc
, Operand
[2], WalkState
);
501 if (ACPI_FAILURE (Status
))
506 if (!WalkState
->ResultObj
)
508 WalkState
->ResultObj
= ReturnDesc
;
515 /* Delete return object on error */
517 if (ACPI_FAILURE (Status
))
519 AcpiUtRemoveReference (ReturnDesc
);
520 WalkState
->ResultObj
= NULL
;
523 return_ACPI_STATUS (Status
);
527 /*******************************************************************************
529 * FUNCTION: AcpiExOpcode_2A_0T_1R
531 * PARAMETERS: WalkState - Current walk state
535 * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
537 ******************************************************************************/
540 AcpiExOpcode_2A_0T_1R (
541 ACPI_WALK_STATE
*WalkState
)
543 ACPI_OPERAND_OBJECT
**Operand
= &WalkState
->Operands
[0];
544 ACPI_OPERAND_OBJECT
*ReturnDesc
= NULL
;
545 ACPI_STATUS Status
= AE_OK
;
546 BOOLEAN LogicalResult
= FALSE
;
549 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_1R
,
550 AcpiPsGetOpcodeName (WalkState
->Opcode
));
553 /* Create the internal return object */
555 ReturnDesc
= AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER
);
558 Status
= AE_NO_MEMORY
;
562 /* Execute the Opcode */
564 if (WalkState
->OpInfo
->Flags
& AML_LOGICAL_NUMERIC
)
566 /* LogicalOp (Operand0, Operand1) */
568 Status
= AcpiExDoLogicalNumericOp (WalkState
->Opcode
,
569 Operand
[0]->Integer
.Value
, Operand
[1]->Integer
.Value
,
571 goto StoreLogicalResult
;
573 else if (WalkState
->OpInfo
->Flags
& AML_LOGICAL
)
575 /* LogicalOp (Operand0, Operand1) */
577 Status
= AcpiExDoLogicalOp (WalkState
->Opcode
, Operand
[0],
578 Operand
[1], &LogicalResult
);
579 goto StoreLogicalResult
;
582 switch (WalkState
->Opcode
)
584 case AML_ACQUIRE_OP
: /* Acquire (MutexObject, Timeout) */
586 Status
= AcpiExAcquireMutex (Operand
[1], Operand
[0], WalkState
);
587 if (Status
== AE_TIME
)
589 LogicalResult
= TRUE
; /* TRUE = Acquire timed out */
595 case AML_WAIT_OP
: /* Wait (EventObject, Timeout) */
597 Status
= AcpiExSystemWaitEvent (Operand
[1], Operand
[0]);
598 if (Status
== AE_TIME
)
600 LogicalResult
= TRUE
; /* TRUE, Wait timed out */
607 ACPI_ERROR ((AE_INFO
, "Unknown AML opcode 0x%X",
610 Status
= AE_AML_BAD_OPCODE
;
617 * Set return value to according to LogicalResult. logical TRUE (all ones)
618 * Default is FALSE (zero)
622 ReturnDesc
->Integer
.Value
= ACPI_UINT64_MAX
;
627 /* Delete return object on error */
629 if (ACPI_FAILURE (Status
))
631 AcpiUtRemoveReference (ReturnDesc
);
634 /* Save return object on success */
638 WalkState
->ResultObj
= ReturnDesc
;
641 return_ACPI_STATUS (Status
);