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