]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/contrib/dev/acpica/components/executer/exmisc.c
MFC: r284583, r285797, r285799, r287168, r298714, r298720, r298838,
[FreeBSD/stable/10.git] / sys / contrib / dev / acpica / components / executer / exmisc.c
1 /******************************************************************************
2  *
3  * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2016, 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 #include <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/acinterp.h>
47 #include <contrib/dev/acpica/include/amlcode.h>
48
49
50 #define _COMPONENT          ACPI_EXECUTER
51         ACPI_MODULE_NAME    ("exmisc")
52
53
54 /*******************************************************************************
55  *
56  * FUNCTION:    AcpiExGetObjectReference
57  *
58  * PARAMETERS:  ObjDesc             - Create a reference to this object
59  *              ReturnDesc          - Where to store the reference
60  *              WalkState           - Current state
61  *
62  * RETURN:      Status
63  *
64  * DESCRIPTION: Obtain and return a "reference" to the target object
65  *              Common code for the RefOfOp and the CondRefOfOp.
66  *
67  ******************************************************************************/
68
69 ACPI_STATUS
70 AcpiExGetObjectReference (
71     ACPI_OPERAND_OBJECT     *ObjDesc,
72     ACPI_OPERAND_OBJECT     **ReturnDesc,
73     ACPI_WALK_STATE         *WalkState)
74 {
75     ACPI_OPERAND_OBJECT     *ReferenceObj;
76     ACPI_OPERAND_OBJECT     *ReferencedObj;
77
78
79     ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
80
81
82     *ReturnDesc = NULL;
83
84     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
85     {
86     case ACPI_DESC_TYPE_OPERAND:
87
88         if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
89         {
90             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
91         }
92
93         /*
94          * Must be a reference to a Local or Arg
95          */
96         switch (ObjDesc->Reference.Class)
97         {
98         case ACPI_REFCLASS_LOCAL:
99         case ACPI_REFCLASS_ARG:
100         case ACPI_REFCLASS_DEBUG:
101
102             /* The referenced object is the pseudo-node for the local/arg */
103
104             ReferencedObj = ObjDesc->Reference.Object;
105             break;
106
107         default:
108
109             ACPI_ERROR ((AE_INFO, "Invalid Reference Class 0x%2.2X",
110                 ObjDesc->Reference.Class));
111             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
112         }
113         break;
114
115     case ACPI_DESC_TYPE_NAMED:
116         /*
117          * A named reference that has already been resolved to a Node
118          */
119         ReferencedObj = ObjDesc;
120         break;
121
122     default:
123
124         ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",
125             ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
126         return_ACPI_STATUS (AE_TYPE);
127     }
128
129
130     /* Create a new reference object */
131
132     ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
133     if (!ReferenceObj)
134     {
135         return_ACPI_STATUS (AE_NO_MEMORY);
136     }
137
138     ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
139     ReferenceObj->Reference.Object = ReferencedObj;
140     *ReturnDesc = ReferenceObj;
141
142     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
143         "Object %p Type [%s], returning Reference %p\n",
144         ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
145
146     return_ACPI_STATUS (AE_OK);
147 }
148
149
150 /*******************************************************************************
151  *
152  * FUNCTION:    AcpiExDoMathOp
153  *
154  * PARAMETERS:  Opcode              - AML opcode
155  *              Integer0            - Integer operand #0
156  *              Integer1            - Integer operand #1
157  *
158  * RETURN:      Integer result of the operation
159  *
160  * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
161  *              math functions here is to prevent a lot of pointer dereferencing
162  *              to obtain the operands.
163  *
164  ******************************************************************************/
165
166 UINT64
167 AcpiExDoMathOp (
168     UINT16                  Opcode,
169     UINT64                  Integer0,
170     UINT64                  Integer1)
171 {
172
173     ACPI_FUNCTION_ENTRY ();
174
175
176     switch (Opcode)
177     {
178     case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
179
180         return (Integer0 + Integer1);
181
182     case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
183
184         return (Integer0 & Integer1);
185
186     case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
187
188         return (~(Integer0 & Integer1));
189
190     case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
191
192         return (Integer0 | Integer1);
193
194     case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
195
196         return (~(Integer0 | Integer1));
197
198     case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
199
200         return (Integer0 ^ Integer1);
201
202     case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
203
204         return (Integer0 * Integer1);
205
206     case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
207
208         /*
209          * We need to check if the shiftcount is larger than the integer bit
210          * width since the behavior of this is not well-defined in the C language.
211          */
212         if (Integer1 >= AcpiGbl_IntegerBitWidth)
213         {
214             return (0);
215         }
216         return (Integer0 << Integer1);
217
218     case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
219
220         /*
221          * We need to check if the shiftcount is larger than the integer bit
222          * width since the behavior of this is not well-defined in the C language.
223          */
224         if (Integer1 >= AcpiGbl_IntegerBitWidth)
225         {
226             return (0);
227         }
228         return (Integer0 >> Integer1);
229
230     case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
231
232         return (Integer0 - Integer1);
233
234     default:
235
236         return (0);
237     }
238 }
239
240
241 /*******************************************************************************
242  *
243  * FUNCTION:    AcpiExDoLogicalNumericOp
244  *
245  * PARAMETERS:  Opcode              - AML opcode
246  *              Integer0            - Integer operand #0
247  *              Integer1            - Integer operand #1
248  *              LogicalResult       - TRUE/FALSE result of the operation
249  *
250  * RETURN:      Status
251  *
252  * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
253  *              operators (LAnd and LOr), both operands must be integers.
254  *
255  *              Note: cleanest machine code seems to be produced by the code
256  *              below, rather than using statements of the form:
257  *                  Result = (Integer0 && Integer1);
258  *
259  ******************************************************************************/
260
261 ACPI_STATUS
262 AcpiExDoLogicalNumericOp (
263     UINT16                  Opcode,
264     UINT64                  Integer0,
265     UINT64                  Integer1,
266     BOOLEAN                 *LogicalResult)
267 {
268     ACPI_STATUS             Status = AE_OK;
269     BOOLEAN                 LocalResult = FALSE;
270
271
272     ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
273
274
275     switch (Opcode)
276     {
277     case AML_LAND_OP:               /* LAnd (Integer0, Integer1) */
278
279         if (Integer0 && Integer1)
280         {
281             LocalResult = TRUE;
282         }
283         break;
284
285     case AML_LOR_OP:                /* LOr (Integer0, Integer1) */
286
287         if (Integer0 || Integer1)
288         {
289             LocalResult = TRUE;
290         }
291         break;
292
293     default:
294
295         Status = AE_AML_INTERNAL;
296         break;
297     }
298
299     /* Return the logical result and status */
300
301     *LogicalResult = LocalResult;
302     return_ACPI_STATUS (Status);
303 }
304
305
306 /*******************************************************************************
307  *
308  * FUNCTION:    AcpiExDoLogicalOp
309  *
310  * PARAMETERS:  Opcode              - AML opcode
311  *              Operand0            - operand #0
312  *              Operand1            - operand #1
313  *              LogicalResult       - TRUE/FALSE result of the operation
314  *
315  * RETURN:      Status
316  *
317  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
318  *              functions here is to prevent a lot of pointer dereferencing
319  *              to obtain the operands and to simplify the generation of the
320  *              logical value. For the Numeric operators (LAnd and LOr), both
321  *              operands must be integers. For the other logical operators,
322  *              operands can be any combination of Integer/String/Buffer. The
323  *              first operand determines the type to which the second operand
324  *              will be converted.
325  *
326  *              Note: cleanest machine code seems to be produced by the code
327  *              below, rather than using statements of the form:
328  *                  Result = (Operand0 == Operand1);
329  *
330  ******************************************************************************/
331
332 ACPI_STATUS
333 AcpiExDoLogicalOp (
334     UINT16                  Opcode,
335     ACPI_OPERAND_OBJECT     *Operand0,
336     ACPI_OPERAND_OBJECT     *Operand1,
337     BOOLEAN                 *LogicalResult)
338 {
339     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
340     UINT64                  Integer0;
341     UINT64                  Integer1;
342     UINT32                  Length0;
343     UINT32                  Length1;
344     ACPI_STATUS             Status = AE_OK;
345     BOOLEAN                 LocalResult = FALSE;
346     int                     Compare;
347
348
349     ACPI_FUNCTION_TRACE (ExDoLogicalOp);
350
351
352     /*
353      * Convert the second operand if necessary. The first operand
354      * determines the type of the second operand, (See the Data Types
355      * section of the ACPI 3.0+ specification.)  Both object types are
356      * guaranteed to be either Integer/String/Buffer by the operand
357      * resolution mechanism.
358      */
359     switch (Operand0->Common.Type)
360     {
361     case ACPI_TYPE_INTEGER:
362
363         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
364         break;
365
366     case ACPI_TYPE_STRING:
367
368         Status = AcpiExConvertToString (
369             Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX);
370         break;
371
372     case ACPI_TYPE_BUFFER:
373
374         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
375         break;
376
377     default:
378
379         Status = AE_AML_INTERNAL;
380         break;
381     }
382
383     if (ACPI_FAILURE (Status))
384     {
385         goto Cleanup;
386     }
387
388     /*
389      * Two cases: 1) Both Integers, 2) Both Strings or Buffers
390      */
391     if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
392     {
393         /*
394          * 1) Both operands are of type integer
395          *    Note: LocalOperand1 may have changed above
396          */
397         Integer0 = Operand0->Integer.Value;
398         Integer1 = LocalOperand1->Integer.Value;
399
400         switch (Opcode)
401         {
402         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
403
404             if (Integer0 == Integer1)
405             {
406                 LocalResult = TRUE;
407             }
408             break;
409
410         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
411
412             if (Integer0 > Integer1)
413             {
414                 LocalResult = TRUE;
415             }
416             break;
417
418         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
419
420             if (Integer0 < Integer1)
421             {
422                 LocalResult = TRUE;
423             }
424             break;
425
426         default:
427
428             Status = AE_AML_INTERNAL;
429             break;
430         }
431     }
432     else
433     {
434         /*
435          * 2) Both operands are Strings or both are Buffers
436          *    Note: Code below takes advantage of common Buffer/String
437          *          object fields. LocalOperand1 may have changed above. Use
438          *          memcmp to handle nulls in buffers.
439          */
440         Length0 = Operand0->Buffer.Length;
441         Length1 = LocalOperand1->Buffer.Length;
442
443         /* Lexicographic compare: compare the data bytes */
444
445         Compare = memcmp (Operand0->Buffer.Pointer,
446             LocalOperand1->Buffer.Pointer,
447             (Length0 > Length1) ? Length1 : Length0);
448
449         switch (Opcode)
450         {
451         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
452
453             /* Length and all bytes must be equal */
454
455             if ((Length0 == Length1) &&
456                 (Compare == 0))
457             {
458                 /* Length and all bytes match ==> TRUE */
459
460                 LocalResult = TRUE;
461             }
462             break;
463
464         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
465
466             if (Compare > 0)
467             {
468                 LocalResult = TRUE;
469                 goto Cleanup;   /* TRUE */
470             }
471             if (Compare < 0)
472             {
473                 goto Cleanup;   /* FALSE */
474             }
475
476             /* Bytes match (to shortest length), compare lengths */
477
478             if (Length0 > Length1)
479             {
480                 LocalResult = TRUE;
481             }
482             break;
483
484         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
485
486             if (Compare > 0)
487             {
488                 goto Cleanup;   /* FALSE */
489             }
490             if (Compare < 0)
491             {
492                 LocalResult = TRUE;
493                 goto Cleanup;   /* TRUE */
494             }
495
496             /* Bytes match (to shortest length), compare lengths */
497
498             if (Length0 < Length1)
499             {
500                 LocalResult = TRUE;
501             }
502             break;
503
504         default:
505
506             Status = AE_AML_INTERNAL;
507             break;
508         }
509     }
510
511 Cleanup:
512
513     /* New object was created if implicit conversion performed - delete */
514
515     if (LocalOperand1 != Operand1)
516     {
517         AcpiUtRemoveReference (LocalOperand1);
518     }
519
520     /* Return the logical result and status */
521
522     *LogicalResult = LocalResult;
523     return_ACPI_STATUS (Status);
524 }