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