Sync ACPICA with Intel's version 20140828.
[dragonfly.git] / sys / contrib / dev / acpica / source / components / executer / exoparg2.c
1 /******************************************************************************
2  *
3  * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2014, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
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.
25  *
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.
29  *
30  * NO WARRANTY
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.
42  */
43
44 #define __EXOPARG2_C__
45
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acparser.h"
49 #include "acinterp.h"
50 #include "acevents.h"
51 #include "amlcode.h"
52
53
54 #define _COMPONENT          ACPI_EXECUTER
55         ACPI_MODULE_NAME    ("exoparg2")
56
57
58 /*!
59  * Naming convention for AML interpreter execution routines.
60  *
61  * The routines that begin execution of AML opcodes are named with a common
62  * convention based upon the number of arguments, the number of target operands,
63  * and whether or not a value is returned:
64  *
65  *      AcpiExOpcode_xA_yT_zR
66  *
67  * Where:
68  *
69  * xA - ARGUMENTS:    The number of arguments (input operands) that are
70  *                    required for this opcode type (1 through 6 args).
71  * yT - TARGETS:      The number of targets (output operands) that are required
72  *                    for this opcode type (0, 1, or 2 targets).
73  * zR - RETURN VALUE: Indicates whether this opcode type returns a value
74  *                    as the function return (0 or 1).
75  *
76  * The AcpiExOpcode* functions are called via the Dispatcher component with
77  * fully resolved operands.
78 !*/
79
80
81 /*******************************************************************************
82  *
83  * FUNCTION:    AcpiExOpcode_2A_0T_0R
84  *
85  * PARAMETERS:  WalkState           - Current walk state
86  *
87  * RETURN:      Status
88  *
89  * DESCRIPTION: Execute opcode with two arguments, no target, and no return
90  *              value.
91  *
92  * ALLOCATION:  Deletes both operands
93  *
94  ******************************************************************************/
95
96 ACPI_STATUS
97 AcpiExOpcode_2A_0T_0R (
98     ACPI_WALK_STATE         *WalkState)
99 {
100     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
101     ACPI_NAMESPACE_NODE     *Node;
102     UINT32                  Value;
103     ACPI_STATUS             Status = AE_OK;
104
105
106     ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_0R,
107             AcpiPsGetOpcodeName (WalkState->Opcode));
108
109
110     /* Examine the opcode */
111
112     switch (WalkState->Opcode)
113     {
114     case AML_NOTIFY_OP:         /* Notify (NotifyObject, NotifyValue) */
115
116         /* The first operand is a namespace node */
117
118         Node = (ACPI_NAMESPACE_NODE *) Operand[0];
119
120         /* Second value is the notify value */
121
122         Value = (UINT32) Operand[1]->Integer.Value;
123
124         /* Are notifies allowed on this object? */
125
126         if (!AcpiEvIsNotifyObject (Node))
127         {
128             ACPI_ERROR ((AE_INFO,
129                 "Unexpected notify object type [%s]",
130                 AcpiUtGetTypeName (Node->Type)));
131
132             Status = AE_AML_OPERAND_TYPE;
133             break;
134         }
135
136         /*
137          * Dispatch the notify to the appropriate handler
138          * NOTE: the request is queued for execution after this method
139          * completes. The notify handlers are NOT invoked synchronously
140          * from this thread -- because handlers may in turn run other
141          * control methods.
142          */
143         Status = AcpiEvQueueNotifyRequest (Node, Value);
144         break;
145
146     default:
147
148         ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
149             WalkState->Opcode));
150         Status = AE_AML_BAD_OPCODE;
151     }
152
153     return_ACPI_STATUS (Status);
154 }
155
156
157 /*******************************************************************************
158  *
159  * FUNCTION:    AcpiExOpcode_2A_2T_1R
160  *
161  * PARAMETERS:  WalkState           - Current walk state
162  *
163  * RETURN:      Status
164  *
165  * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
166  *              and one implicit return value.
167  *
168  ******************************************************************************/
169
170 ACPI_STATUS
171 AcpiExOpcode_2A_2T_1R (
172     ACPI_WALK_STATE         *WalkState)
173 {
174     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
175     ACPI_OPERAND_OBJECT     *ReturnDesc1 = NULL;
176     ACPI_OPERAND_OBJECT     *ReturnDesc2 = NULL;
177     ACPI_STATUS             Status;
178
179
180     ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_2T_1R,
181         AcpiPsGetOpcodeName (WalkState->Opcode));
182
183
184     /* Execute the opcode */
185
186     switch (WalkState->Opcode)
187     {
188     case AML_DIVIDE_OP:
189
190         /* Divide (Dividend, Divisor, RemainderResult QuotientResult) */
191
192         ReturnDesc1 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
193         if (!ReturnDesc1)
194         {
195             Status = AE_NO_MEMORY;
196             goto Cleanup;
197         }
198
199         ReturnDesc2 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
200         if (!ReturnDesc2)
201         {
202             Status = AE_NO_MEMORY;
203             goto Cleanup;
204         }
205
206         /* Quotient to ReturnDesc1, remainder to ReturnDesc2 */
207
208         Status = AcpiUtDivide (Operand[0]->Integer.Value,
209                                Operand[1]->Integer.Value,
210                                &ReturnDesc1->Integer.Value,
211                                &ReturnDesc2->Integer.Value);
212         if (ACPI_FAILURE (Status))
213         {
214             goto Cleanup;
215         }
216         break;
217
218     default:
219
220         ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
221             WalkState->Opcode));
222         Status = AE_AML_BAD_OPCODE;
223         goto Cleanup;
224     }
225
226     /* Store the results to the target reference operands */
227
228     Status = AcpiExStore (ReturnDesc2, Operand[2], WalkState);
229     if (ACPI_FAILURE (Status))
230     {
231         goto Cleanup;
232     }
233
234     Status = AcpiExStore (ReturnDesc1, Operand[3], WalkState);
235     if (ACPI_FAILURE (Status))
236     {
237         goto Cleanup;
238     }
239
240 Cleanup:
241     /*
242      * Since the remainder is not returned indirectly, remove a reference to
243      * it. Only the quotient is returned indirectly.
244      */
245     AcpiUtRemoveReference (ReturnDesc2);
246
247     if (ACPI_FAILURE (Status))
248     {
249         /* Delete the return object */
250
251         AcpiUtRemoveReference (ReturnDesc1);
252     }
253
254     /* Save return object (the remainder) on success */
255
256     else
257     {
258         WalkState->ResultObj = ReturnDesc1;
259     }
260
261     return_ACPI_STATUS (Status);
262 }
263
264
265 /*******************************************************************************
266  *
267  * FUNCTION:    AcpiExOpcode_2A_1T_1R
268  *
269  * PARAMETERS:  WalkState           - Current walk state
270  *
271  * RETURN:      Status
272  *
273  * DESCRIPTION: Execute opcode with two arguments, one target, and a return
274  *              value.
275  *
276  ******************************************************************************/
277
278 ACPI_STATUS
279 AcpiExOpcode_2A_1T_1R (
280     ACPI_WALK_STATE         *WalkState)
281 {
282     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
283     ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
284     UINT64                  Index;
285     ACPI_STATUS             Status = AE_OK;
286     ACPI_SIZE               Length = 0;
287
288
289     ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_1T_1R,
290         AcpiPsGetOpcodeName (WalkState->Opcode));
291
292
293     /* Execute the opcode */
294
295     if (WalkState->OpInfo->Flags & AML_MATH)
296     {
297         /* All simple math opcodes (add, etc.) */
298
299         ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
300         if (!ReturnDesc)
301         {
302             Status = AE_NO_MEMORY;
303             goto Cleanup;
304         }
305
306         ReturnDesc->Integer.Value = AcpiExDoMathOp (WalkState->Opcode,
307                                                 Operand[0]->Integer.Value,
308                                                 Operand[1]->Integer.Value);
309         goto StoreResultToTarget;
310     }
311
312     switch (WalkState->Opcode)
313     {
314     case AML_MOD_OP: /* Mod (Dividend, Divisor, RemainderResult (ACPI 2.0) */
315
316         ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
317         if (!ReturnDesc)
318         {
319             Status = AE_NO_MEMORY;
320             goto Cleanup;
321         }
322
323         /* ReturnDesc will contain the remainder */
324
325         Status = AcpiUtDivide (Operand[0]->Integer.Value,
326                                Operand[1]->Integer.Value,
327                                NULL,
328                                &ReturnDesc->Integer.Value);
329         break;
330
331     case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */
332
333         Status = AcpiExDoConcatenate (Operand[0], Operand[1],
334                     &ReturnDesc, WalkState);
335         break;
336
337     case AML_TO_STRING_OP: /* ToString (Buffer, Length, Result) (ACPI 2.0) */
338         /*
339          * Input object is guaranteed to be a buffer at this point (it may have
340          * been converted.)  Copy the raw buffer data to a new object of
341          * type String.
342          */
343
344         /*
345          * Get the length of the new string. It is the smallest of:
346          * 1) Length of the input buffer
347          * 2) Max length as specified in the ToString operator
348          * 3) Length of input buffer up to a zero byte (null terminator)
349          *
350          * NOTE: A length of zero is ok, and will create a zero-length, null
351          *       terminated string.
352          */
353         while ((Length < Operand[0]->Buffer.Length) &&
354                (Length < Operand[1]->Integer.Value) &&
355                (Operand[0]->Buffer.Pointer[Length]))
356         {
357             Length++;
358         }
359
360         /* Allocate a new string object */
361
362         ReturnDesc = AcpiUtCreateStringObject (Length);
363         if (!ReturnDesc)
364         {
365             Status = AE_NO_MEMORY;
366             goto Cleanup;
367         }
368
369         /*
370          * Copy the raw buffer data with no transform.
371          * (NULL terminated already)
372          */
373         ACPI_MEMCPY (ReturnDesc->String.Pointer,
374             Operand[0]->Buffer.Pointer, Length);
375         break;
376
377     case AML_CONCAT_RES_OP:
378
379         /* ConcatenateResTemplate (Buffer, Buffer, Result) (ACPI 2.0) */
380
381         Status = AcpiExConcatTemplate (Operand[0], Operand[1],
382                     &ReturnDesc, WalkState);
383         break;
384
385     case AML_INDEX_OP:              /* Index (Source Index Result) */
386
387         /* Create the internal return object */
388
389         ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
390         if (!ReturnDesc)
391         {
392             Status = AE_NO_MEMORY;
393             goto Cleanup;
394         }
395
396         /* Initialize the Index reference object */
397
398         Index = Operand[1]->Integer.Value;
399         ReturnDesc->Reference.Value = (UINT32) Index;
400         ReturnDesc->Reference.Class = ACPI_REFCLASS_INDEX;
401
402         /*
403          * At this point, the Source operand is a String, Buffer, or Package.
404          * Verify that the index is within range.
405          */
406         switch ((Operand[0])->Common.Type)
407         {
408         case ACPI_TYPE_STRING:
409
410             if (Index >= Operand[0]->String.Length)
411             {
412                 Length = Operand[0]->String.Length;
413                 Status = AE_AML_STRING_LIMIT;
414             }
415
416             ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD;
417             break;
418
419         case ACPI_TYPE_BUFFER:
420
421             if (Index >= Operand[0]->Buffer.Length)
422             {
423                 Length = Operand[0]->Buffer.Length;
424                 Status = AE_AML_BUFFER_LIMIT;
425             }
426
427             ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD;
428             break;
429
430         case ACPI_TYPE_PACKAGE:
431
432             if (Index >= Operand[0]->Package.Count)
433             {
434                 Length = Operand[0]->Package.Count;
435                 Status = AE_AML_PACKAGE_LIMIT;
436             }
437
438             ReturnDesc->Reference.TargetType = ACPI_TYPE_PACKAGE;
439             ReturnDesc->Reference.Where = &Operand[0]->Package.Elements [Index];
440             break;
441
442         default:
443
444             Status = AE_AML_INTERNAL;
445             goto Cleanup;
446         }
447
448         /* Failure means that the Index was beyond the end of the object */
449
450         if (ACPI_FAILURE (Status))
451         {
452             ACPI_EXCEPTION ((AE_INFO, Status,
453                 "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
454                 ACPI_FORMAT_UINT64 (Index), (UINT32) Length));
455             goto Cleanup;
456         }
457
458         /*
459          * Save the target object and add a reference to it for the life
460          * of the index
461          */
462         ReturnDesc->Reference.Object = Operand[0];
463         AcpiUtAddReference (Operand[0]);
464
465         /* Store the reference to the Target */
466
467         Status = AcpiExStore (ReturnDesc, Operand[2], WalkState);
468
469         /* Return the reference */
470
471         WalkState->ResultObj = ReturnDesc;
472         goto Cleanup;
473
474     default:
475
476         ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
477             WalkState->Opcode));
478         Status = AE_AML_BAD_OPCODE;
479         break;
480     }
481
482
483 StoreResultToTarget:
484
485     if (ACPI_SUCCESS (Status))
486     {
487         /*
488          * Store the result of the operation (which is now in ReturnDesc) into
489          * the Target descriptor.
490          */
491         Status = AcpiExStore (ReturnDesc, Operand[2], WalkState);
492         if (ACPI_FAILURE (Status))
493         {
494             goto Cleanup;
495         }
496
497         if (!WalkState->ResultObj)
498         {
499             WalkState->ResultObj = ReturnDesc;
500         }
501     }
502
503
504 Cleanup:
505
506     /* Delete return object on error */
507
508     if (ACPI_FAILURE (Status))
509     {
510         AcpiUtRemoveReference (ReturnDesc);
511         WalkState->ResultObj = NULL;
512     }
513
514     return_ACPI_STATUS (Status);
515 }
516
517
518 /*******************************************************************************
519  *
520  * FUNCTION:    AcpiExOpcode_2A_0T_1R
521  *
522  * PARAMETERS:  WalkState           - Current walk state
523  *
524  * RETURN:      Status
525  *
526  * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
527  *
528  ******************************************************************************/
529
530 ACPI_STATUS
531 AcpiExOpcode_2A_0T_1R (
532     ACPI_WALK_STATE         *WalkState)
533 {
534     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
535     ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
536     ACPI_STATUS             Status = AE_OK;
537     BOOLEAN                 LogicalResult = FALSE;
538
539
540     ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_1R,
541         AcpiPsGetOpcodeName (WalkState->Opcode));
542
543
544     /* Create the internal return object */
545
546     ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
547     if (!ReturnDesc)
548     {
549         Status = AE_NO_MEMORY;
550         goto Cleanup;
551     }
552
553     /* Execute the Opcode */
554
555     if (WalkState->OpInfo->Flags & AML_LOGICAL_NUMERIC)
556     {
557         /* LogicalOp  (Operand0, Operand1) */
558
559         Status = AcpiExDoLogicalNumericOp (WalkState->Opcode,
560                         Operand[0]->Integer.Value, Operand[1]->Integer.Value,
561                         &LogicalResult);
562         goto StoreLogicalResult;
563     }
564     else if (WalkState->OpInfo->Flags & AML_LOGICAL)
565     {
566         /* LogicalOp  (Operand0, Operand1) */
567
568         Status = AcpiExDoLogicalOp (WalkState->Opcode, Operand[0],
569                     Operand[1], &LogicalResult);
570         goto StoreLogicalResult;
571     }
572
573     switch (WalkState->Opcode)
574     {
575     case AML_ACQUIRE_OP:            /* Acquire (MutexObject, Timeout) */
576
577         Status = AcpiExAcquireMutex (Operand[1], Operand[0], WalkState);
578         if (Status == AE_TIME)
579         {
580             LogicalResult = TRUE;       /* TRUE = Acquire timed out */
581             Status = AE_OK;
582         }
583         break;
584
585
586     case AML_WAIT_OP:               /* Wait (EventObject, Timeout) */
587
588         Status = AcpiExSystemWaitEvent (Operand[1], Operand[0]);
589         if (Status == AE_TIME)
590         {
591             LogicalResult = TRUE;       /* TRUE, Wait timed out */
592             Status = AE_OK;
593         }
594         break;
595
596     default:
597
598         ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
599             WalkState->Opcode));
600         Status = AE_AML_BAD_OPCODE;
601         goto Cleanup;
602     }
603
604
605 StoreLogicalResult:
606     /*
607      * Set return value to according to LogicalResult. logical TRUE (all ones)
608      * Default is FALSE (zero)
609      */
610     if (LogicalResult)
611     {
612         ReturnDesc->Integer.Value = ACPI_UINT64_MAX;
613     }
614
615 Cleanup:
616
617     /* Delete return object on error */
618
619     if (ACPI_FAILURE (Status))
620     {
621         AcpiUtRemoveReference (ReturnDesc);
622     }
623
624     /* Save return object on success */
625
626     else
627     {
628         WalkState->ResultObj = ReturnDesc;
629     }
630
631     return_ACPI_STATUS (Status);
632 }