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
145ACPI_STATUS
146AcpiExGetObjectReference (
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
244ACPI_STATUS
245AcpiExConcatTemplate (
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
336ACPI_STATUS
337AcpiExDoConcatenate (
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
485Cleanup:
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
510UINT64
511AcpiExDoMathOp (
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
614ACPI_STATUS
615AcpiExDoLogicalNumericOp (
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
684ACPI_STATUS
685AcpiExDoLogicalOp (
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
857Cleanup:
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