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 "acpi.h"
45 #include "accommon.h"
46 #include "acinterp.h"
47 #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,
364             ACPI_STRTOUL_BASE16);
365         break;
366 
367     case ACPI_TYPE_STRING:
368 
369         Status = AcpiExConvertToString (
370             Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX);
371         break;
372 
373     case ACPI_TYPE_BUFFER:
374 
375         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
376         break;
377 
378     default:
379 
380         Status = AE_AML_INTERNAL;
381         break;
382     }
383 
384     if (ACPI_FAILURE (Status))
385     {
386         goto Cleanup;
387     }
388 
389     /*
390      * Two cases: 1) Both Integers, 2) Both Strings or Buffers
391      */
392     if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
393     {
394         /*
395          * 1) Both operands are of type integer
396          *    Note: LocalOperand1 may have changed above
397          */
398         Integer0 = Operand0->Integer.Value;
399         Integer1 = LocalOperand1->Integer.Value;
400 
401         switch (Opcode)
402         {
403         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
404 
405             if (Integer0 == Integer1)
406             {
407                 LocalResult = TRUE;
408             }
409             break;
410 
411         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
412 
413             if (Integer0 > Integer1)
414             {
415                 LocalResult = TRUE;
416             }
417             break;
418 
419         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
420 
421             if (Integer0 < Integer1)
422             {
423                 LocalResult = TRUE;
424             }
425             break;
426 
427         default:
428 
429             Status = AE_AML_INTERNAL;
430             break;
431         }
432     }
433     else
434     {
435         /*
436          * 2) Both operands are Strings or both are Buffers
437          *    Note: Code below takes advantage of common Buffer/String
438          *          object fields. LocalOperand1 may have changed above. Use
439          *          memcmp to handle nulls in buffers.
440          */
441         Length0 = Operand0->Buffer.Length;
442         Length1 = LocalOperand1->Buffer.Length;
443 
444         /* Lexicographic compare: compare the data bytes */
445 
446         Compare = memcmp (Operand0->Buffer.Pointer,
447             LocalOperand1->Buffer.Pointer,
448             (Length0 > Length1) ? Length1 : Length0);
449 
450         switch (Opcode)
451         {
452         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
453 
454             /* Length and all bytes must be equal */
455 
456             if ((Length0 == Length1) &&
457                 (Compare == 0))
458             {
459                 /* Length and all bytes match ==> TRUE */
460 
461                 LocalResult = TRUE;
462             }
463             break;
464 
465         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
466 
467             if (Compare > 0)
468             {
469                 LocalResult = TRUE;
470                 goto Cleanup;   /* TRUE */
471             }
472             if (Compare < 0)
473             {
474                 goto Cleanup;   /* FALSE */
475             }
476 
477             /* Bytes match (to shortest length), compare lengths */
478 
479             if (Length0 > Length1)
480             {
481                 LocalResult = TRUE;
482             }
483             break;
484 
485         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
486 
487             if (Compare > 0)
488             {
489                 goto Cleanup;   /* FALSE */
490             }
491             if (Compare < 0)
492             {
493                 LocalResult = TRUE;
494                 goto Cleanup;   /* TRUE */
495             }
496 
497             /* Bytes match (to shortest length), compare lengths */
498 
499             if (Length0 < Length1)
500             {
501                 LocalResult = TRUE;
502             }
503             break;
504 
505         default:
506 
507             Status = AE_AML_INTERNAL;
508             break;
509         }
510     }
511 
512 Cleanup:
513 
514     /* New object was created if implicit conversion performed - delete */
515 
516     if (LocalOperand1 != Operand1)
517     {
518         AcpiUtRemoveReference (LocalOperand1);
519     }
520 
521     /* Return the logical result and status */
522 
523     *LogicalResult = LocalResult;
524     return_ACPI_STATUS (Status);
525 }
526