xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/executer/exmisc.c (revision ca8ed5ea660fb6275799a3b7f138b201c41a667b)
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 - 2014, 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 #define __EXMISC_C__
118 
119 #include "acpi.h"
120 #include "accommon.h"
121 #include "acinterp.h"
122 #include "amlcode.h"
123 #include "amlresrc.h"
124 
125 
126 #define _COMPONENT          ACPI_EXECUTER
127         ACPI_MODULE_NAME    ("exmisc")
128 
129 
130 /*******************************************************************************
131  *
132  * FUNCTION:    AcpiExGetObjectReference
133  *
134  * PARAMETERS:  ObjDesc             - Create a reference to this object
135  *              ReturnDesc          - Where to store the reference
136  *              WalkState           - Current state
137  *
138  * RETURN:      Status
139  *
140  * DESCRIPTION: Obtain and return a "reference" to the target object
141  *              Common code for the RefOfOp and the CondRefOfOp.
142  *
143  ******************************************************************************/
144 
145 ACPI_STATUS
146 AcpiExGetObjectReference (
147     ACPI_OPERAND_OBJECT     *ObjDesc,
148     ACPI_OPERAND_OBJECT     **ReturnDesc,
149     ACPI_WALK_STATE         *WalkState)
150 {
151     ACPI_OPERAND_OBJECT     *ReferenceObj;
152     ACPI_OPERAND_OBJECT     *ReferencedObj;
153 
154 
155     ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
156 
157 
158     *ReturnDesc = NULL;
159 
160     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
161     {
162     case ACPI_DESC_TYPE_OPERAND:
163 
164         if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
165         {
166             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
167         }
168 
169         /*
170          * Must be a reference to a Local or Arg
171          */
172         switch (ObjDesc->Reference.Class)
173         {
174         case ACPI_REFCLASS_LOCAL:
175         case ACPI_REFCLASS_ARG:
176         case ACPI_REFCLASS_DEBUG:
177 
178             /* The referenced object is the pseudo-node for the local/arg */
179 
180             ReferencedObj = ObjDesc->Reference.Object;
181             break;
182 
183         default:
184 
185             ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X",
186                 ObjDesc->Reference.Class));
187             return_ACPI_STATUS (AE_AML_INTERNAL);
188         }
189         break;
190 
191     case ACPI_DESC_TYPE_NAMED:
192         /*
193          * A named reference that has already been resolved to a Node
194          */
195         ReferencedObj = ObjDesc;
196         break;
197 
198     default:
199 
200         ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",
201             ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
202         return_ACPI_STATUS (AE_TYPE);
203     }
204 
205 
206     /* Create a new reference object */
207 
208     ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
209     if (!ReferenceObj)
210     {
211         return_ACPI_STATUS (AE_NO_MEMORY);
212     }
213 
214     ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
215     ReferenceObj->Reference.Object = ReferencedObj;
216     *ReturnDesc = ReferenceObj;
217 
218     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
219         "Object %p Type [%s], returning Reference %p\n",
220         ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
221 
222     return_ACPI_STATUS (AE_OK);
223 }
224 
225 
226 /*******************************************************************************
227  *
228  * FUNCTION:    AcpiExConcatTemplate
229  *
230  * PARAMETERS:  Operand0            - First source object
231  *              Operand1            - Second source object
232  *              ActualReturnDesc    - Where to place the return object
233  *              WalkState           - Current walk state
234  *
235  * RETURN:      Status
236  *
237  * DESCRIPTION: Concatenate two resource templates
238  *
239  ******************************************************************************/
240 
241 ACPI_STATUS
242 AcpiExConcatTemplate (
243     ACPI_OPERAND_OBJECT     *Operand0,
244     ACPI_OPERAND_OBJECT     *Operand1,
245     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
246     ACPI_WALK_STATE         *WalkState)
247 {
248     ACPI_STATUS             Status;
249     ACPI_OPERAND_OBJECT     *ReturnDesc;
250     UINT8                   *NewBuf;
251     UINT8                   *EndTag;
252     ACPI_SIZE               Length0;
253     ACPI_SIZE               Length1;
254     ACPI_SIZE               NewLength;
255 
256 
257     ACPI_FUNCTION_TRACE (ExConcatTemplate);
258 
259 
260     /*
261      * Find the EndTag descriptor in each resource template.
262      * Note1: returned pointers point TO the EndTag, not past it.
263      * Note2: zero-length buffers are allowed; treated like one EndTag
264      */
265 
266     /* Get the length of the first resource template */
267 
268     Status = AcpiUtGetResourceEndTag (Operand0, &EndTag);
269     if (ACPI_FAILURE (Status))
270     {
271         return_ACPI_STATUS (Status);
272     }
273 
274     Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer);
275 
276     /* Get the length of the second resource template */
277 
278     Status = AcpiUtGetResourceEndTag (Operand1, &EndTag);
279     if (ACPI_FAILURE (Status))
280     {
281         return_ACPI_STATUS (Status);
282     }
283 
284     Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer);
285 
286     /* Combine both lengths, minimum size will be 2 for EndTag */
287 
288     NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG);
289 
290     /* Create a new buffer object for the result (with one EndTag) */
291 
292     ReturnDesc = AcpiUtCreateBufferObject (NewLength);
293     if (!ReturnDesc)
294     {
295         return_ACPI_STATUS (AE_NO_MEMORY);
296     }
297 
298     /*
299      * Copy the templates to the new buffer, 0 first, then 1 follows. One
300      * EndTag descriptor is copied from Operand1.
301      */
302     NewBuf = ReturnDesc->Buffer.Pointer;
303     ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length0);
304     ACPI_MEMCPY (NewBuf + Length0, Operand1->Buffer.Pointer, Length1);
305 
306     /* Insert EndTag and set the checksum to zero, means "ignore checksum" */
307 
308     NewBuf[NewLength - 1] = 0;
309     NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
310 
311     /* Return the completed resource template */
312 
313     *ActualReturnDesc = ReturnDesc;
314     return_ACPI_STATUS (AE_OK);
315 }
316 
317 
318 /*******************************************************************************
319  *
320  * FUNCTION:    AcpiExDoConcatenate
321  *
322  * PARAMETERS:  Operand0            - First source object
323  *              Operand1            - Second source object
324  *              ActualReturnDesc    - Where to place the return object
325  *              WalkState           - Current walk state
326  *
327  * RETURN:      Status
328  *
329  * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
330  *
331  ******************************************************************************/
332 
333 ACPI_STATUS
334 AcpiExDoConcatenate (
335     ACPI_OPERAND_OBJECT     *Operand0,
336     ACPI_OPERAND_OBJECT     *Operand1,
337     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
338     ACPI_WALK_STATE         *WalkState)
339 {
340     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
341     ACPI_OPERAND_OBJECT     *ReturnDesc;
342     char                    *NewBuf;
343     ACPI_STATUS             Status;
344 
345 
346     ACPI_FUNCTION_TRACE (ExDoConcatenate);
347 
348 
349     /*
350      * Convert the second operand if necessary. The first operand
351      * determines the type of the second operand, (See the Data Types
352      * section of the ACPI specification.)  Both object types are
353      * guaranteed to be either Integer/String/Buffer by the operand
354      * resolution mechanism.
355      */
356     switch (Operand0->Common.Type)
357     {
358     case ACPI_TYPE_INTEGER:
359 
360         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
361         break;
362 
363     case ACPI_TYPE_STRING:
364 
365         Status = AcpiExConvertToString (Operand1, &LocalOperand1,
366                     ACPI_IMPLICIT_CONVERT_HEX);
367         break;
368 
369     case ACPI_TYPE_BUFFER:
370 
371         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
372         break;
373 
374     default:
375 
376         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
377             Operand0->Common.Type));
378         Status = AE_AML_INTERNAL;
379     }
380 
381     if (ACPI_FAILURE (Status))
382     {
383         goto Cleanup;
384     }
385 
386     /*
387      * Both operands are now known to be the same object type
388      * (Both are Integer, String, or Buffer), and we can now perform the
389      * concatenation.
390      */
391 
392     /*
393      * There are three cases to handle:
394      *
395      * 1) Two Integers concatenated to produce a new Buffer
396      * 2) Two Strings concatenated to produce a new String
397      * 3) Two Buffers concatenated to produce a new Buffer
398      */
399     switch (Operand0->Common.Type)
400     {
401     case ACPI_TYPE_INTEGER:
402 
403         /* Result of two Integers is a Buffer */
404         /* Need enough buffer space for two integers */
405 
406         ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE)
407                             ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
408         if (!ReturnDesc)
409         {
410             Status = AE_NO_MEMORY;
411             goto Cleanup;
412         }
413 
414         NewBuf = (char *) ReturnDesc->Buffer.Pointer;
415 
416         /* Copy the first integer, LSB first */
417 
418         ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value,
419                         AcpiGbl_IntegerByteWidth);
420 
421         /* Copy the second integer (LSB first) after the first */
422 
423         ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth,
424                         &LocalOperand1->Integer.Value,
425                         AcpiGbl_IntegerByteWidth);
426         break;
427 
428     case ACPI_TYPE_STRING:
429 
430         /* Result of two Strings is a String */
431 
432         ReturnDesc = AcpiUtCreateStringObject (
433                         ((ACPI_SIZE) Operand0->String.Length +
434                         LocalOperand1->String.Length));
435         if (!ReturnDesc)
436         {
437             Status = AE_NO_MEMORY;
438             goto Cleanup;
439         }
440 
441         NewBuf = ReturnDesc->String.Pointer;
442 
443         /* Concatenate the strings */
444 
445         ACPI_STRCPY (NewBuf, Operand0->String.Pointer);
446         ACPI_STRCPY (NewBuf + Operand0->String.Length,
447                         LocalOperand1->String.Pointer);
448         break;
449 
450     case ACPI_TYPE_BUFFER:
451 
452         /* Result of two Buffers is a Buffer */
453 
454         ReturnDesc = AcpiUtCreateBufferObject (
455                         ((ACPI_SIZE) Operand0->Buffer.Length +
456                         LocalOperand1->Buffer.Length));
457         if (!ReturnDesc)
458         {
459             Status = AE_NO_MEMORY;
460             goto Cleanup;
461         }
462 
463         NewBuf = (char *) ReturnDesc->Buffer.Pointer;
464 
465         /* Concatenate the buffers */
466 
467         ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer,
468                         Operand0->Buffer.Length);
469         ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length,
470                         LocalOperand1->Buffer.Pointer,
471                         LocalOperand1->Buffer.Length);
472         break;
473 
474     default:
475 
476         /* Invalid object type, should not happen here */
477 
478         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
479             Operand0->Common.Type));
480         Status =AE_AML_INTERNAL;
481         goto Cleanup;
482     }
483 
484     *ActualReturnDesc = ReturnDesc;
485 
486 Cleanup:
487     if (LocalOperand1 != Operand1)
488     {
489         AcpiUtRemoveReference (LocalOperand1);
490     }
491     return_ACPI_STATUS (Status);
492 }
493 
494 
495 /*******************************************************************************
496  *
497  * FUNCTION:    AcpiExDoMathOp
498  *
499  * PARAMETERS:  Opcode              - AML opcode
500  *              Integer0            - Integer operand #0
501  *              Integer1            - Integer operand #1
502  *
503  * RETURN:      Integer result of the operation
504  *
505  * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
506  *              math functions here is to prevent a lot of pointer dereferencing
507  *              to obtain the operands.
508  *
509  ******************************************************************************/
510 
511 UINT64
512 AcpiExDoMathOp (
513     UINT16                  Opcode,
514     UINT64                  Integer0,
515     UINT64                  Integer1)
516 {
517 
518     ACPI_FUNCTION_ENTRY ();
519 
520 
521     switch (Opcode)
522     {
523     case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
524 
525         return (Integer0 + Integer1);
526 
527     case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
528 
529         return (Integer0 & Integer1);
530 
531     case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
532 
533         return (~(Integer0 & Integer1));
534 
535     case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
536 
537         return (Integer0 | Integer1);
538 
539     case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
540 
541         return (~(Integer0 | Integer1));
542 
543     case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
544 
545         return (Integer0 ^ Integer1);
546 
547     case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
548 
549         return (Integer0 * Integer1);
550 
551     case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
552 
553         /*
554          * We need to check if the shiftcount is larger than the integer bit
555          * width since the behavior of this is not well-defined in the C language.
556          */
557         if (Integer1 >= AcpiGbl_IntegerBitWidth)
558         {
559             return (0);
560         }
561         return (Integer0 << Integer1);
562 
563     case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
564 
565         /*
566          * We need to check if the shiftcount is larger than the integer bit
567          * width since the behavior of this is not well-defined in the C language.
568          */
569         if (Integer1 >= AcpiGbl_IntegerBitWidth)
570         {
571             return (0);
572         }
573         return (Integer0 >> Integer1);
574 
575     case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
576 
577         return (Integer0 - Integer1);
578 
579     default:
580 
581         return (0);
582     }
583 }
584 
585 
586 /*******************************************************************************
587  *
588  * FUNCTION:    AcpiExDoLogicalNumericOp
589  *
590  * PARAMETERS:  Opcode              - AML opcode
591  *              Integer0            - Integer operand #0
592  *              Integer1            - Integer operand #1
593  *              LogicalResult       - TRUE/FALSE result of the operation
594  *
595  * RETURN:      Status
596  *
597  * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
598  *              operators (LAnd and LOr), both operands must be integers.
599  *
600  *              Note: cleanest machine code seems to be produced by the code
601  *              below, rather than using statements of the form:
602  *                  Result = (Integer0 && Integer1);
603  *
604  ******************************************************************************/
605 
606 ACPI_STATUS
607 AcpiExDoLogicalNumericOp (
608     UINT16                  Opcode,
609     UINT64                  Integer0,
610     UINT64                  Integer1,
611     BOOLEAN                 *LogicalResult)
612 {
613     ACPI_STATUS             Status = AE_OK;
614     BOOLEAN                 LocalResult = FALSE;
615 
616 
617     ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
618 
619 
620     switch (Opcode)
621     {
622     case AML_LAND_OP:               /* LAnd (Integer0, Integer1) */
623 
624         if (Integer0 && Integer1)
625         {
626             LocalResult = TRUE;
627         }
628         break;
629 
630     case AML_LOR_OP:                /* LOr (Integer0, Integer1) */
631 
632         if (Integer0 || Integer1)
633         {
634             LocalResult = TRUE;
635         }
636         break;
637 
638     default:
639 
640         Status = AE_AML_INTERNAL;
641         break;
642     }
643 
644     /* Return the logical result and status */
645 
646     *LogicalResult = LocalResult;
647     return_ACPI_STATUS (Status);
648 }
649 
650 
651 /*******************************************************************************
652  *
653  * FUNCTION:    AcpiExDoLogicalOp
654  *
655  * PARAMETERS:  Opcode              - AML opcode
656  *              Operand0            - operand #0
657  *              Operand1            - operand #1
658  *              LogicalResult       - TRUE/FALSE result of the operation
659  *
660  * RETURN:      Status
661  *
662  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
663  *              functions here is to prevent a lot of pointer dereferencing
664  *              to obtain the operands and to simplify the generation of the
665  *              logical value. For the Numeric operators (LAnd and LOr), both
666  *              operands must be integers. For the other logical operators,
667  *              operands can be any combination of Integer/String/Buffer. The
668  *              first operand determines the type to which the second operand
669  *              will be converted.
670  *
671  *              Note: cleanest machine code seems to be produced by the code
672  *              below, rather than using statements of the form:
673  *                  Result = (Operand0 == Operand1);
674  *
675  ******************************************************************************/
676 
677 ACPI_STATUS
678 AcpiExDoLogicalOp (
679     UINT16                  Opcode,
680     ACPI_OPERAND_OBJECT     *Operand0,
681     ACPI_OPERAND_OBJECT     *Operand1,
682     BOOLEAN                 *LogicalResult)
683 {
684     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
685     UINT64                  Integer0;
686     UINT64                  Integer1;
687     UINT32                  Length0;
688     UINT32                  Length1;
689     ACPI_STATUS             Status = AE_OK;
690     BOOLEAN                 LocalResult = FALSE;
691     int                     Compare;
692 
693 
694     ACPI_FUNCTION_TRACE (ExDoLogicalOp);
695 
696 
697     /*
698      * Convert the second operand if necessary. The first operand
699      * determines the type of the second operand, (See the Data Types
700      * section of the ACPI 3.0+ specification.)  Both object types are
701      * guaranteed to be either Integer/String/Buffer by the operand
702      * resolution mechanism.
703      */
704     switch (Operand0->Common.Type)
705     {
706     case ACPI_TYPE_INTEGER:
707 
708         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
709         break;
710 
711     case ACPI_TYPE_STRING:
712 
713         Status = AcpiExConvertToString (Operand1, &LocalOperand1,
714                     ACPI_IMPLICIT_CONVERT_HEX);
715         break;
716 
717     case ACPI_TYPE_BUFFER:
718 
719         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
720         break;
721 
722     default:
723 
724         Status = AE_AML_INTERNAL;
725         break;
726     }
727 
728     if (ACPI_FAILURE (Status))
729     {
730         goto Cleanup;
731     }
732 
733     /*
734      * Two cases: 1) Both Integers, 2) Both Strings or Buffers
735      */
736     if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
737     {
738         /*
739          * 1) Both operands are of type integer
740          *    Note: LocalOperand1 may have changed above
741          */
742         Integer0 = Operand0->Integer.Value;
743         Integer1 = LocalOperand1->Integer.Value;
744 
745         switch (Opcode)
746         {
747         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
748 
749             if (Integer0 == Integer1)
750             {
751                 LocalResult = TRUE;
752             }
753             break;
754 
755         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
756 
757             if (Integer0 > Integer1)
758             {
759                 LocalResult = TRUE;
760             }
761             break;
762 
763         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
764 
765             if (Integer0 < Integer1)
766             {
767                 LocalResult = TRUE;
768             }
769             break;
770 
771         default:
772 
773             Status = AE_AML_INTERNAL;
774             break;
775         }
776     }
777     else
778     {
779         /*
780          * 2) Both operands are Strings or both are Buffers
781          *    Note: Code below takes advantage of common Buffer/String
782          *          object fields. LocalOperand1 may have changed above. Use
783          *          memcmp to handle nulls in buffers.
784          */
785         Length0 = Operand0->Buffer.Length;
786         Length1 = LocalOperand1->Buffer.Length;
787 
788         /* Lexicographic compare: compare the data bytes */
789 
790         Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer,
791                     LocalOperand1->Buffer.Pointer,
792                     (Length0 > Length1) ? Length1 : Length0);
793 
794         switch (Opcode)
795         {
796         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
797 
798             /* Length and all bytes must be equal */
799 
800             if ((Length0 == Length1) &&
801                 (Compare == 0))
802             {
803                 /* Length and all bytes match ==> TRUE */
804 
805                 LocalResult = TRUE;
806             }
807             break;
808 
809         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
810 
811             if (Compare > 0)
812             {
813                 LocalResult = TRUE;
814                 goto Cleanup;   /* TRUE */
815             }
816             if (Compare < 0)
817             {
818                 goto Cleanup;   /* FALSE */
819             }
820 
821             /* Bytes match (to shortest length), compare lengths */
822 
823             if (Length0 > Length1)
824             {
825                 LocalResult = TRUE;
826             }
827             break;
828 
829         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
830 
831             if (Compare > 0)
832             {
833                 goto Cleanup;   /* FALSE */
834             }
835             if (Compare < 0)
836             {
837                 LocalResult = TRUE;
838                 goto Cleanup;   /* TRUE */
839             }
840 
841             /* Bytes match (to shortest length), compare lengths */
842 
843             if (Length0 < Length1)
844             {
845                 LocalResult = TRUE;
846             }
847             break;
848 
849         default:
850 
851             Status = AE_AML_INTERNAL;
852             break;
853         }
854     }
855 
856 Cleanup:
857 
858     /* New object was created if implicit conversion performed - delete */
859 
860     if (LocalOperand1 != Operand1)
861     {
862         AcpiUtRemoveReference (LocalOperand1);
863     }
864 
865     /* Return the logical result and status */
866 
867     *LogicalResult = LocalResult;
868     return_ACPI_STATUS (Status);
869 }
870