xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/executer/exmisc.c (revision a5a3b2d9a3d95cbae71eaf371708c73a1780ac0d)
1 /******************************************************************************
2  *
3  * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2016, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government. In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116 
117 #include "acpi.h"
118 #include "accommon.h"
119 #include "acinterp.h"
120 #include "amlcode.h"
121 #include "amlresrc.h"
122 
123 
124 #define _COMPONENT          ACPI_EXECUTER
125         ACPI_MODULE_NAME    ("exmisc")
126 
127 
128 /*******************************************************************************
129  *
130  * FUNCTION:    AcpiExGetObjectReference
131  *
132  * PARAMETERS:  ObjDesc             - Create a reference to this object
133  *              ReturnDesc          - Where to store the reference
134  *              WalkState           - Current state
135  *
136  * RETURN:      Status
137  *
138  * DESCRIPTION: Obtain and return a "reference" to the target object
139  *              Common code for the RefOfOp and the CondRefOfOp.
140  *
141  ******************************************************************************/
142 
143 ACPI_STATUS
144 AcpiExGetObjectReference (
145     ACPI_OPERAND_OBJECT     *ObjDesc,
146     ACPI_OPERAND_OBJECT     **ReturnDesc,
147     ACPI_WALK_STATE         *WalkState)
148 {
149     ACPI_OPERAND_OBJECT     *ReferenceObj;
150     ACPI_OPERAND_OBJECT     *ReferencedObj;
151 
152 
153     ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
154 
155 
156     *ReturnDesc = NULL;
157 
158     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
159     {
160     case ACPI_DESC_TYPE_OPERAND:
161 
162         if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
163         {
164             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
165         }
166 
167         /*
168          * Must be a reference to a Local or Arg
169          */
170         switch (ObjDesc->Reference.Class)
171         {
172         case ACPI_REFCLASS_LOCAL:
173         case ACPI_REFCLASS_ARG:
174         case ACPI_REFCLASS_DEBUG:
175 
176             /* The referenced object is the pseudo-node for the local/arg */
177 
178             ReferencedObj = ObjDesc->Reference.Object;
179             break;
180 
181         default:
182 
183             ACPI_ERROR ((AE_INFO, "Invalid Reference Class 0x%2.2X",
184                 ObjDesc->Reference.Class));
185             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
186         }
187         break;
188 
189     case ACPI_DESC_TYPE_NAMED:
190         /*
191          * A named reference that has already been resolved to a Node
192          */
193         ReferencedObj = ObjDesc;
194         break;
195 
196     default:
197 
198         ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",
199             ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
200         return_ACPI_STATUS (AE_TYPE);
201     }
202 
203 
204     /* Create a new reference object */
205 
206     ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
207     if (!ReferenceObj)
208     {
209         return_ACPI_STATUS (AE_NO_MEMORY);
210     }
211 
212     ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
213     ReferenceObj->Reference.Object = ReferencedObj;
214     *ReturnDesc = ReferenceObj;
215 
216     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
217         "Object %p Type [%s], returning Reference %p\n",
218         ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
219 
220     return_ACPI_STATUS (AE_OK);
221 }
222 
223 
224 /*******************************************************************************
225  *
226  * FUNCTION:    AcpiExConcatTemplate
227  *
228  * PARAMETERS:  Operand0            - First source object
229  *              Operand1            - Second source object
230  *              ActualReturnDesc    - Where to place the return object
231  *              WalkState           - Current walk state
232  *
233  * RETURN:      Status
234  *
235  * DESCRIPTION: Concatenate two resource templates
236  *
237  ******************************************************************************/
238 
239 ACPI_STATUS
240 AcpiExConcatTemplate (
241     ACPI_OPERAND_OBJECT     *Operand0,
242     ACPI_OPERAND_OBJECT     *Operand1,
243     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
244     ACPI_WALK_STATE         *WalkState)
245 {
246     ACPI_STATUS             Status;
247     ACPI_OPERAND_OBJECT     *ReturnDesc;
248     UINT8                   *NewBuf;
249     UINT8                   *EndTag;
250     ACPI_SIZE               Length0;
251     ACPI_SIZE               Length1;
252     ACPI_SIZE               NewLength;
253 
254 
255     ACPI_FUNCTION_TRACE (ExConcatTemplate);
256 
257 
258     /*
259      * Find the EndTag descriptor in each resource template.
260      * Note1: returned pointers point TO the EndTag, not past it.
261      * Note2: zero-length buffers are allowed; treated like one EndTag
262      */
263 
264     /* Get the length of the first resource template */
265 
266     Status = AcpiUtGetResourceEndTag (Operand0, &EndTag);
267     if (ACPI_FAILURE (Status))
268     {
269         return_ACPI_STATUS (Status);
270     }
271 
272     Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer);
273 
274     /* Get the length of the second resource template */
275 
276     Status = AcpiUtGetResourceEndTag (Operand1, &EndTag);
277     if (ACPI_FAILURE (Status))
278     {
279         return_ACPI_STATUS (Status);
280     }
281 
282     Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer);
283 
284     /* Combine both lengths, minimum size will be 2 for EndTag */
285 
286     NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG);
287 
288     /* Create a new buffer object for the result (with one EndTag) */
289 
290     ReturnDesc = AcpiUtCreateBufferObject (NewLength);
291     if (!ReturnDesc)
292     {
293         return_ACPI_STATUS (AE_NO_MEMORY);
294     }
295 
296     /*
297      * Copy the templates to the new buffer, 0 first, then 1 follows. One
298      * EndTag descriptor is copied from Operand1.
299      */
300     NewBuf = ReturnDesc->Buffer.Pointer;
301     memcpy (NewBuf, Operand0->Buffer.Pointer, Length0);
302     memcpy (NewBuf + Length0, Operand1->Buffer.Pointer, Length1);
303 
304     /* Insert EndTag and set the checksum to zero, means "ignore checksum" */
305 
306     NewBuf[NewLength - 1] = 0;
307     NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
308 
309     /* Return the completed resource template */
310 
311     *ActualReturnDesc = ReturnDesc;
312     return_ACPI_STATUS (AE_OK);
313 }
314 
315 
316 /*******************************************************************************
317  *
318  * FUNCTION:    AcpiExDoConcatenate
319  *
320  * PARAMETERS:  Operand0            - First source object
321  *              Operand1            - Second source object
322  *              ActualReturnDesc    - Where to place the return object
323  *              WalkState           - Current walk state
324  *
325  * RETURN:      Status
326  *
327  * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
328  *
329  ******************************************************************************/
330 
331 ACPI_STATUS
332 AcpiExDoConcatenate (
333     ACPI_OPERAND_OBJECT     *Operand0,
334     ACPI_OPERAND_OBJECT     *Operand1,
335     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
336     ACPI_WALK_STATE         *WalkState)
337 {
338     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
339     ACPI_OPERAND_OBJECT     *ReturnDesc;
340     char                    *NewBuf;
341     const char              *TypeString;
342     ACPI_STATUS             Status;
343 
344 
345     ACPI_FUNCTION_TRACE (ExDoConcatenate);
346 
347 
348     /*
349      * Convert the second operand if necessary. The first operand
350      * determines the type of the second operand, (See the Data Types
351      * section of the ACPI specification.)  Both object types are
352      * guaranteed to be either Integer/String/Buffer by the operand
353      * resolution mechanism.
354      */
355     switch (Operand0->Common.Type)
356     {
357     case ACPI_TYPE_INTEGER:
358 
359         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
360         break;
361 
362     case ACPI_TYPE_STRING:
363         /*
364          * Per the ACPI spec, Concatenate only supports int/str/buf.
365          * However, we support all objects here as an extension.
366          * This improves the usefulness of the Printf() macro.
367          * 12/2015.
368          */
369         switch (Operand1->Common.Type)
370         {
371         case ACPI_TYPE_INTEGER:
372         case ACPI_TYPE_STRING:
373         case ACPI_TYPE_BUFFER:
374 
375             Status = AcpiExConvertToString (
376                 Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX);
377             break;
378 
379         default:
380             /*
381              * Just emit a string containing the object type.
382              */
383             TypeString = AcpiUtGetTypeName (Operand1->Common.Type);
384 
385             LocalOperand1 = AcpiUtCreateStringObject (
386                 ((ACPI_SIZE) strlen (TypeString) + 9)); /* 9 For "[Object]" */
387             if (!LocalOperand1)
388             {
389                 Status = AE_NO_MEMORY;
390                 goto Cleanup;
391             }
392 
393             strcpy (LocalOperand1->String.Pointer, "[");
394             strcat (LocalOperand1->String.Pointer, TypeString);
395             strcat (LocalOperand1->String.Pointer, " Object]");
396             Status = AE_OK;
397             break;
398         }
399         break;
400 
401     case ACPI_TYPE_BUFFER:
402 
403         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
404         break;
405 
406     default:
407 
408         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
409             Operand0->Common.Type));
410         Status = AE_AML_INTERNAL;
411     }
412 
413     if (ACPI_FAILURE (Status))
414     {
415         goto Cleanup;
416     }
417 
418     /*
419      * Both operands are now known to be the same object type
420      * (Both are Integer, String, or Buffer), and we can now perform the
421      * concatenation.
422      */
423 
424     /*
425      * There are three cases to handle:
426      *
427      * 1) Two Integers concatenated to produce a new Buffer
428      * 2) Two Strings concatenated to produce a new String
429      * 3) Two Buffers concatenated to produce a new Buffer
430      */
431     switch (Operand0->Common.Type)
432     {
433     case ACPI_TYPE_INTEGER:
434 
435         /* Result of two Integers is a Buffer */
436         /* Need enough buffer space for two integers */
437 
438         ReturnDesc = AcpiUtCreateBufferObject (
439             (ACPI_SIZE) ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
440         if (!ReturnDesc)
441         {
442             Status = AE_NO_MEMORY;
443             goto Cleanup;
444         }
445 
446         NewBuf = (char *) ReturnDesc->Buffer.Pointer;
447 
448         /* Copy the first integer, LSB first */
449 
450         memcpy (NewBuf, &Operand0->Integer.Value,
451             AcpiGbl_IntegerByteWidth);
452 
453         /* Copy the second integer (LSB first) after the first */
454 
455         memcpy (NewBuf + AcpiGbl_IntegerByteWidth,
456             &LocalOperand1->Integer.Value, AcpiGbl_IntegerByteWidth);
457         break;
458 
459     case ACPI_TYPE_STRING:
460 
461         /* Result of two Strings is a String */
462 
463         ReturnDesc = AcpiUtCreateStringObject (
464             ((ACPI_SIZE) Operand0->String.Length +
465             LocalOperand1->String.Length));
466         if (!ReturnDesc)
467         {
468             Status = AE_NO_MEMORY;
469             goto Cleanup;
470         }
471 
472         NewBuf = ReturnDesc->String.Pointer;
473 
474         /* Concatenate the strings */
475 
476         strcpy (NewBuf, Operand0->String.Pointer);
477         strcat (NewBuf, LocalOperand1->String.Pointer);
478         break;
479 
480     case ACPI_TYPE_BUFFER:
481 
482         /* Result of two Buffers is a Buffer */
483 
484         ReturnDesc = AcpiUtCreateBufferObject (
485             ((ACPI_SIZE) Operand0->Buffer.Length +
486             LocalOperand1->Buffer.Length));
487         if (!ReturnDesc)
488         {
489             Status = AE_NO_MEMORY;
490             goto Cleanup;
491         }
492 
493         NewBuf = (char *) ReturnDesc->Buffer.Pointer;
494 
495         /* Concatenate the buffers */
496 
497         memcpy (NewBuf, Operand0->Buffer.Pointer,
498             Operand0->Buffer.Length);
499         memcpy (NewBuf + Operand0->Buffer.Length,
500             LocalOperand1->Buffer.Pointer,
501             LocalOperand1->Buffer.Length);
502         break;
503 
504     default:
505 
506         /* Invalid object type, should not happen here */
507 
508         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
509             Operand0->Common.Type));
510         Status =AE_AML_INTERNAL;
511         goto Cleanup;
512     }
513 
514     *ActualReturnDesc = ReturnDesc;
515 
516 Cleanup:
517     if (LocalOperand1 != Operand1)
518     {
519         AcpiUtRemoveReference (LocalOperand1);
520     }
521     return_ACPI_STATUS (Status);
522 }
523 
524 
525 /*******************************************************************************
526  *
527  * FUNCTION:    AcpiExDoMathOp
528  *
529  * PARAMETERS:  Opcode              - AML opcode
530  *              Integer0            - Integer operand #0
531  *              Integer1            - Integer operand #1
532  *
533  * RETURN:      Integer result of the operation
534  *
535  * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
536  *              math functions here is to prevent a lot of pointer dereferencing
537  *              to obtain the operands.
538  *
539  ******************************************************************************/
540 
541 UINT64
542 AcpiExDoMathOp (
543     UINT16                  Opcode,
544     UINT64                  Integer0,
545     UINT64                  Integer1)
546 {
547 
548     ACPI_FUNCTION_ENTRY ();
549 
550 
551     switch (Opcode)
552     {
553     case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
554 
555         return (Integer0 + Integer1);
556 
557     case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
558 
559         return (Integer0 & Integer1);
560 
561     case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
562 
563         return (~(Integer0 & Integer1));
564 
565     case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
566 
567         return (Integer0 | Integer1);
568 
569     case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
570 
571         return (~(Integer0 | Integer1));
572 
573     case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
574 
575         return (Integer0 ^ Integer1);
576 
577     case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
578 
579         return (Integer0 * Integer1);
580 
581     case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
582 
583         /*
584          * We need to check if the shiftcount is larger than the integer bit
585          * width since the behavior of this is not well-defined in the C language.
586          */
587         if (Integer1 >= AcpiGbl_IntegerBitWidth)
588         {
589             return (0);
590         }
591         return (Integer0 << Integer1);
592 
593     case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
594 
595         /*
596          * We need to check if the shiftcount is larger than the integer bit
597          * width since the behavior of this is not well-defined in the C language.
598          */
599         if (Integer1 >= AcpiGbl_IntegerBitWidth)
600         {
601             return (0);
602         }
603         return (Integer0 >> Integer1);
604 
605     case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
606 
607         return (Integer0 - Integer1);
608 
609     default:
610 
611         return (0);
612     }
613 }
614 
615 
616 /*******************************************************************************
617  *
618  * FUNCTION:    AcpiExDoLogicalNumericOp
619  *
620  * PARAMETERS:  Opcode              - AML opcode
621  *              Integer0            - Integer operand #0
622  *              Integer1            - Integer operand #1
623  *              LogicalResult       - TRUE/FALSE result of the operation
624  *
625  * RETURN:      Status
626  *
627  * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
628  *              operators (LAnd and LOr), both operands must be integers.
629  *
630  *              Note: cleanest machine code seems to be produced by the code
631  *              below, rather than using statements of the form:
632  *                  Result = (Integer0 && Integer1);
633  *
634  ******************************************************************************/
635 
636 ACPI_STATUS
637 AcpiExDoLogicalNumericOp (
638     UINT16                  Opcode,
639     UINT64                  Integer0,
640     UINT64                  Integer1,
641     BOOLEAN                 *LogicalResult)
642 {
643     ACPI_STATUS             Status = AE_OK;
644     BOOLEAN                 LocalResult = FALSE;
645 
646 
647     ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
648 
649 
650     switch (Opcode)
651     {
652     case AML_LAND_OP:               /* LAnd (Integer0, Integer1) */
653 
654         if (Integer0 && Integer1)
655         {
656             LocalResult = TRUE;
657         }
658         break;
659 
660     case AML_LOR_OP:                /* LOr (Integer0, Integer1) */
661 
662         if (Integer0 || Integer1)
663         {
664             LocalResult = TRUE;
665         }
666         break;
667 
668     default:
669 
670         Status = AE_AML_INTERNAL;
671         break;
672     }
673 
674     /* Return the logical result and status */
675 
676     *LogicalResult = LocalResult;
677     return_ACPI_STATUS (Status);
678 }
679 
680 
681 /*******************************************************************************
682  *
683  * FUNCTION:    AcpiExDoLogicalOp
684  *
685  * PARAMETERS:  Opcode              - AML opcode
686  *              Operand0            - operand #0
687  *              Operand1            - operand #1
688  *              LogicalResult       - TRUE/FALSE result of the operation
689  *
690  * RETURN:      Status
691  *
692  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
693  *              functions here is to prevent a lot of pointer dereferencing
694  *              to obtain the operands and to simplify the generation of the
695  *              logical value. For the Numeric operators (LAnd and LOr), both
696  *              operands must be integers. For the other logical operators,
697  *              operands can be any combination of Integer/String/Buffer. The
698  *              first operand determines the type to which the second operand
699  *              will be converted.
700  *
701  *              Note: cleanest machine code seems to be produced by the code
702  *              below, rather than using statements of the form:
703  *                  Result = (Operand0 == Operand1);
704  *
705  ******************************************************************************/
706 
707 ACPI_STATUS
708 AcpiExDoLogicalOp (
709     UINT16                  Opcode,
710     ACPI_OPERAND_OBJECT     *Operand0,
711     ACPI_OPERAND_OBJECT     *Operand1,
712     BOOLEAN                 *LogicalResult)
713 {
714     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
715     UINT64                  Integer0;
716     UINT64                  Integer1;
717     UINT32                  Length0;
718     UINT32                  Length1;
719     ACPI_STATUS             Status = AE_OK;
720     BOOLEAN                 LocalResult = FALSE;
721     int                     Compare;
722 
723 
724     ACPI_FUNCTION_TRACE (ExDoLogicalOp);
725 
726 
727     /*
728      * Convert the second operand if necessary. The first operand
729      * determines the type of the second operand, (See the Data Types
730      * section of the ACPI 3.0+ specification.)  Both object types are
731      * guaranteed to be either Integer/String/Buffer by the operand
732      * resolution mechanism.
733      */
734     switch (Operand0->Common.Type)
735     {
736     case ACPI_TYPE_INTEGER:
737 
738         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
739         break;
740 
741     case ACPI_TYPE_STRING:
742 
743         Status = AcpiExConvertToString (
744             Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX);
745         break;
746 
747     case ACPI_TYPE_BUFFER:
748 
749         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
750         break;
751 
752     default:
753 
754         Status = AE_AML_INTERNAL;
755         break;
756     }
757 
758     if (ACPI_FAILURE (Status))
759     {
760         goto Cleanup;
761     }
762 
763     /*
764      * Two cases: 1) Both Integers, 2) Both Strings or Buffers
765      */
766     if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
767     {
768         /*
769          * 1) Both operands are of type integer
770          *    Note: LocalOperand1 may have changed above
771          */
772         Integer0 = Operand0->Integer.Value;
773         Integer1 = LocalOperand1->Integer.Value;
774 
775         switch (Opcode)
776         {
777         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
778 
779             if (Integer0 == Integer1)
780             {
781                 LocalResult = TRUE;
782             }
783             break;
784 
785         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
786 
787             if (Integer0 > Integer1)
788             {
789                 LocalResult = TRUE;
790             }
791             break;
792 
793         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
794 
795             if (Integer0 < Integer1)
796             {
797                 LocalResult = TRUE;
798             }
799             break;
800 
801         default:
802 
803             Status = AE_AML_INTERNAL;
804             break;
805         }
806     }
807     else
808     {
809         /*
810          * 2) Both operands are Strings or both are Buffers
811          *    Note: Code below takes advantage of common Buffer/String
812          *          object fields. LocalOperand1 may have changed above. Use
813          *          memcmp to handle nulls in buffers.
814          */
815         Length0 = Operand0->Buffer.Length;
816         Length1 = LocalOperand1->Buffer.Length;
817 
818         /* Lexicographic compare: compare the data bytes */
819 
820         Compare = memcmp (Operand0->Buffer.Pointer,
821             LocalOperand1->Buffer.Pointer,
822             (Length0 > Length1) ? Length1 : Length0);
823 
824         switch (Opcode)
825         {
826         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
827 
828             /* Length and all bytes must be equal */
829 
830             if ((Length0 == Length1) &&
831                 (Compare == 0))
832             {
833                 /* Length and all bytes match ==> TRUE */
834 
835                 LocalResult = TRUE;
836             }
837             break;
838 
839         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
840 
841             if (Compare > 0)
842             {
843                 LocalResult = TRUE;
844                 goto Cleanup;   /* TRUE */
845             }
846             if (Compare < 0)
847             {
848                 goto Cleanup;   /* FALSE */
849             }
850 
851             /* Bytes match (to shortest length), compare lengths */
852 
853             if (Length0 > Length1)
854             {
855                 LocalResult = TRUE;
856             }
857             break;
858 
859         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
860 
861             if (Compare > 0)
862             {
863                 goto Cleanup;   /* FALSE */
864             }
865             if (Compare < 0)
866             {
867                 LocalResult = TRUE;
868                 goto Cleanup;   /* TRUE */
869             }
870 
871             /* Bytes match (to shortest length), compare lengths */
872 
873             if (Length0 < Length1)
874             {
875                 LocalResult = TRUE;
876             }
877             break;
878 
879         default:
880 
881             Status = AE_AML_INTERNAL;
882             break;
883         }
884     }
885 
886 Cleanup:
887 
888     /* New object was created if implicit conversion performed - delete */
889 
890     if (LocalOperand1 != Operand1)
891     {
892         AcpiUtRemoveReference (LocalOperand1);
893     }
894 
895     /* Return the logical result and status */
896 
897     *LogicalResult = LocalResult;
898     return_ACPI_STATUS (Status);
899 }
900