exmisc.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/include/accommon.h>
46#include <contrib/dev/acpica/include/acinterp.h>
47#include <contrib/dev/acpica/include/amlcode.h>
48#include <contrib/dev/acpica/include/amlresrc.h>
49
50
51#define _COMPONENT          ACPI_EXECUTER
52        ACPI_MODULE_NAME    ("exmisc")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION:    AcpiExGetObjectReference
58 *
59 * PARAMETERS:  ObjDesc             - Create a reference to this object
60 *              ReturnDesc          - Where to store the reference
61 *              WalkState           - Current state
62 *
63 * RETURN:      Status
64 *
65 * DESCRIPTION: Obtain and return a "reference" to the target object
66 *              Common code for the RefOfOp and the CondRefOfOp.
67 *
68 ******************************************************************************/
69
70ACPI_STATUS
71AcpiExGetObjectReference (
72    ACPI_OPERAND_OBJECT     *ObjDesc,
73    ACPI_OPERAND_OBJECT     **ReturnDesc,
74    ACPI_WALK_STATE         *WalkState)
75{
76    ACPI_OPERAND_OBJECT     *ReferenceObj;
77    ACPI_OPERAND_OBJECT     *ReferencedObj;
78
79
80    ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
81
82
83    *ReturnDesc = NULL;
84
85    switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
86    {
87    case ACPI_DESC_TYPE_OPERAND:
88
89        if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
90        {
91            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
92        }
93
94        /*
95         * Must be a reference to a Local or Arg
96         */
97        switch (ObjDesc->Reference.Class)
98        {
99        case ACPI_REFCLASS_LOCAL:
100        case ACPI_REFCLASS_ARG:
101        case ACPI_REFCLASS_DEBUG:
102
103            /* The referenced object is the pseudo-node for the local/arg */
104
105            ReferencedObj = ObjDesc->Reference.Object;
106            break;
107
108        default:
109
110            ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X",
111                ObjDesc->Reference.Class));
112            return_ACPI_STATUS (AE_AML_INTERNAL);
113        }
114        break;
115
116    case ACPI_DESC_TYPE_NAMED:
117        /*
118         * A named reference that has already been resolved to a Node
119         */
120        ReferencedObj = ObjDesc;
121        break;
122
123    default:
124
125        ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",
126            ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
127        return_ACPI_STATUS (AE_TYPE);
128    }
129
130
131    /* Create a new reference object */
132
133    ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
134    if (!ReferenceObj)
135    {
136        return_ACPI_STATUS (AE_NO_MEMORY);
137    }
138
139    ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
140    ReferenceObj->Reference.Object = ReferencedObj;
141    *ReturnDesc = ReferenceObj;
142
143    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
144        "Object %p Type [%s], returning Reference %p\n",
145        ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
146
147    return_ACPI_STATUS (AE_OK);
148}
149
150
151/*******************************************************************************
152 *
153 * FUNCTION:    AcpiExConcatTemplate
154 *
155 * PARAMETERS:  Operand0            - First source object
156 *              Operand1            - Second source object
157 *              ActualReturnDesc    - Where to place the return object
158 *              WalkState           - Current walk state
159 *
160 * RETURN:      Status
161 *
162 * DESCRIPTION: Concatenate two resource templates
163 *
164 ******************************************************************************/
165
166ACPI_STATUS
167AcpiExConcatTemplate (
168    ACPI_OPERAND_OBJECT     *Operand0,
169    ACPI_OPERAND_OBJECT     *Operand1,
170    ACPI_OPERAND_OBJECT     **ActualReturnDesc,
171    ACPI_WALK_STATE         *WalkState)
172{
173    ACPI_STATUS             Status;
174    ACPI_OPERAND_OBJECT     *ReturnDesc;
175    UINT8                   *NewBuf;
176    UINT8                   *EndTag;
177    ACPI_SIZE               Length0;
178    ACPI_SIZE               Length1;
179    ACPI_SIZE               NewLength;
180
181
182    ACPI_FUNCTION_TRACE (ExConcatTemplate);
183
184
185    /*
186     * Find the EndTag descriptor in each resource template.
187     * Note1: returned pointers point TO the EndTag, not past it.
188     * Note2: zero-length buffers are allowed; treated like one EndTag
189     */
190
191    /* Get the length of the first resource template */
192
193    Status = AcpiUtGetResourceEndTag (Operand0, &EndTag);
194    if (ACPI_FAILURE (Status))
195    {
196        return_ACPI_STATUS (Status);
197    }
198
199    Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer);
200
201    /* Get the length of the second resource template */
202
203    Status = AcpiUtGetResourceEndTag (Operand1, &EndTag);
204    if (ACPI_FAILURE (Status))
205    {
206        return_ACPI_STATUS (Status);
207    }
208
209    Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer);
210
211    /* Combine both lengths, minimum size will be 2 for EndTag */
212
213    NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG);
214
215    /* Create a new buffer object for the result (with one EndTag) */
216
217    ReturnDesc = AcpiUtCreateBufferObject (NewLength);
218    if (!ReturnDesc)
219    {
220        return_ACPI_STATUS (AE_NO_MEMORY);
221    }
222
223    /*
224     * Copy the templates to the new buffer, 0 first, then 1 follows. One
225     * EndTag descriptor is copied from Operand1.
226     */
227    NewBuf = ReturnDesc->Buffer.Pointer;
228    ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length0);
229    ACPI_MEMCPY (NewBuf + Length0, Operand1->Buffer.Pointer, Length1);
230
231    /* Insert EndTag and set the checksum to zero, means "ignore checksum" */
232
233    NewBuf[NewLength - 1] = 0;
234    NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
235
236    /* Return the completed resource template */
237
238    *ActualReturnDesc = ReturnDesc;
239    return_ACPI_STATUS (AE_OK);
240}
241
242
243/*******************************************************************************
244 *
245 * FUNCTION:    AcpiExDoConcatenate
246 *
247 * PARAMETERS:  Operand0            - First source object
248 *              Operand1            - Second source object
249 *              ActualReturnDesc    - Where to place the return object
250 *              WalkState           - Current walk state
251 *
252 * RETURN:      Status
253 *
254 * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
255 *
256 ******************************************************************************/
257
258ACPI_STATUS
259AcpiExDoConcatenate (
260    ACPI_OPERAND_OBJECT     *Operand0,
261    ACPI_OPERAND_OBJECT     *Operand1,
262    ACPI_OPERAND_OBJECT     **ActualReturnDesc,
263    ACPI_WALK_STATE         *WalkState)
264{
265    ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
266    ACPI_OPERAND_OBJECT     *ReturnDesc;
267    char                    *NewBuf;
268    ACPI_STATUS             Status;
269
270
271    ACPI_FUNCTION_TRACE (ExDoConcatenate);
272
273
274    /*
275     * Convert the second operand if necessary. The first operand
276     * determines the type of the second operand, (See the Data Types
277     * section of the ACPI specification.)  Both object types are
278     * guaranteed to be either Integer/String/Buffer by the operand
279     * resolution mechanism.
280     */
281    switch (Operand0->Common.Type)
282    {
283    case ACPI_TYPE_INTEGER:
284
285        Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
286        break;
287
288    case ACPI_TYPE_STRING:
289
290        Status = AcpiExConvertToString (Operand1, &LocalOperand1,
291                    ACPI_IMPLICIT_CONVERT_HEX);
292        break;
293
294    case ACPI_TYPE_BUFFER:
295
296        Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
297        break;
298
299    default:
300
301        ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
302            Operand0->Common.Type));
303        Status = AE_AML_INTERNAL;
304    }
305
306    if (ACPI_FAILURE (Status))
307    {
308        goto Cleanup;
309    }
310
311    /*
312     * Both operands are now known to be the same object type
313     * (Both are Integer, String, or Buffer), and we can now perform the
314     * concatenation.
315     */
316
317    /*
318     * There are three cases to handle:
319     *
320     * 1) Two Integers concatenated to produce a new Buffer
321     * 2) Two Strings concatenated to produce a new String
322     * 3) Two Buffers concatenated to produce a new Buffer
323     */
324    switch (Operand0->Common.Type)
325    {
326    case ACPI_TYPE_INTEGER:
327
328        /* Result of two Integers is a Buffer */
329        /* Need enough buffer space for two integers */
330
331        ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE)
332                            ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
333        if (!ReturnDesc)
334        {
335            Status = AE_NO_MEMORY;
336            goto Cleanup;
337        }
338
339        NewBuf = (char *) ReturnDesc->Buffer.Pointer;
340
341        /* Copy the first integer, LSB first */
342
343        ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value,
344                        AcpiGbl_IntegerByteWidth);
345
346        /* Copy the second integer (LSB first) after the first */
347
348        ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth,
349                        &LocalOperand1->Integer.Value,
350                        AcpiGbl_IntegerByteWidth);
351        break;
352
353    case ACPI_TYPE_STRING:
354
355        /* Result of two Strings is a String */
356
357        ReturnDesc = AcpiUtCreateStringObject (
358                        ((ACPI_SIZE) Operand0->String.Length +
359                        LocalOperand1->String.Length));
360        if (!ReturnDesc)
361        {
362            Status = AE_NO_MEMORY;
363            goto Cleanup;
364        }
365
366        NewBuf = ReturnDesc->String.Pointer;
367
368        /* Concatenate the strings */
369
370        ACPI_STRCPY (NewBuf, Operand0->String.Pointer);
371        ACPI_STRCPY (NewBuf + Operand0->String.Length,
372                        LocalOperand1->String.Pointer);
373        break;
374
375    case ACPI_TYPE_BUFFER:
376
377        /* Result of two Buffers is a Buffer */
378
379        ReturnDesc = AcpiUtCreateBufferObject (
380                        ((ACPI_SIZE) Operand0->Buffer.Length +
381                        LocalOperand1->Buffer.Length));
382        if (!ReturnDesc)
383        {
384            Status = AE_NO_MEMORY;
385            goto Cleanup;
386        }
387
388        NewBuf = (char *) ReturnDesc->Buffer.Pointer;
389
390        /* Concatenate the buffers */
391
392        ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer,
393                        Operand0->Buffer.Length);
394        ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length,
395                        LocalOperand1->Buffer.Pointer,
396                        LocalOperand1->Buffer.Length);
397        break;
398
399    default:
400
401        /* Invalid object type, should not happen here */
402
403        ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
404            Operand0->Common.Type));
405        Status =AE_AML_INTERNAL;
406        goto Cleanup;
407    }
408
409    *ActualReturnDesc = ReturnDesc;
410
411Cleanup:
412    if (LocalOperand1 != Operand1)
413    {
414        AcpiUtRemoveReference (LocalOperand1);
415    }
416    return_ACPI_STATUS (Status);
417}
418
419
420/*******************************************************************************
421 *
422 * FUNCTION:    AcpiExDoMathOp
423 *
424 * PARAMETERS:  Opcode              - AML opcode
425 *              Integer0            - Integer operand #0
426 *              Integer1            - Integer operand #1
427 *
428 * RETURN:      Integer result of the operation
429 *
430 * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
431 *              math functions here is to prevent a lot of pointer dereferencing
432 *              to obtain the operands.
433 *
434 ******************************************************************************/
435
436UINT64
437AcpiExDoMathOp (
438    UINT16                  Opcode,
439    UINT64                  Integer0,
440    UINT64                  Integer1)
441{
442
443    ACPI_FUNCTION_ENTRY ();
444
445
446    switch (Opcode)
447    {
448    case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
449
450        return (Integer0 + Integer1);
451
452    case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
453
454        return (Integer0 & Integer1);
455
456    case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
457
458        return (~(Integer0 & Integer1));
459
460    case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
461
462        return (Integer0 | Integer1);
463
464    case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
465
466        return (~(Integer0 | Integer1));
467
468    case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
469
470        return (Integer0 ^ Integer1);
471
472    case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
473
474        return (Integer0 * Integer1);
475
476    case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
477
478        /*
479         * We need to check if the shiftcount is larger than the integer bit
480         * width since the behavior of this is not well-defined in the C language.
481         */
482        if (Integer1 >= AcpiGbl_IntegerBitWidth)
483        {
484            return (0);
485        }
486        return (Integer0 << Integer1);
487
488    case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
489
490        /*
491         * We need to check if the shiftcount is larger than the integer bit
492         * width since the behavior of this is not well-defined in the C language.
493         */
494        if (Integer1 >= AcpiGbl_IntegerBitWidth)
495        {
496            return (0);
497        }
498        return (Integer0 >> Integer1);
499
500    case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
501
502        return (Integer0 - Integer1);
503
504    default:
505
506        return (0);
507    }
508}
509
510
511/*******************************************************************************
512 *
513 * FUNCTION:    AcpiExDoLogicalNumericOp
514 *
515 * PARAMETERS:  Opcode              - AML opcode
516 *              Integer0            - Integer operand #0
517 *              Integer1            - Integer operand #1
518 *              LogicalResult       - TRUE/FALSE result of the operation
519 *
520 * RETURN:      Status
521 *
522 * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
523 *              operators (LAnd and LOr), both operands must be integers.
524 *
525 *              Note: cleanest machine code seems to be produced by the code
526 *              below, rather than using statements of the form:
527 *                  Result = (Integer0 && Integer1);
528 *
529 ******************************************************************************/
530
531ACPI_STATUS
532AcpiExDoLogicalNumericOp (
533    UINT16                  Opcode,
534    UINT64                  Integer0,
535    UINT64                  Integer1,
536    BOOLEAN                 *LogicalResult)
537{
538    ACPI_STATUS             Status = AE_OK;
539    BOOLEAN                 LocalResult = FALSE;
540
541
542    ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
543
544
545    switch (Opcode)
546    {
547    case AML_LAND_OP:               /* LAnd (Integer0, Integer1) */
548
549        if (Integer0 && Integer1)
550        {
551            LocalResult = TRUE;
552        }
553        break;
554
555    case AML_LOR_OP:                /* LOr (Integer0, Integer1) */
556
557        if (Integer0 || Integer1)
558        {
559            LocalResult = TRUE;
560        }
561        break;
562
563    default:
564
565        Status = AE_AML_INTERNAL;
566        break;
567    }
568
569    /* Return the logical result and status */
570
571    *LogicalResult = LocalResult;
572    return_ACPI_STATUS (Status);
573}
574
575
576/*******************************************************************************
577 *
578 * FUNCTION:    AcpiExDoLogicalOp
579 *
580 * PARAMETERS:  Opcode              - AML opcode
581 *              Operand0            - operand #0
582 *              Operand1            - operand #1
583 *              LogicalResult       - TRUE/FALSE result of the operation
584 *
585 * RETURN:      Status
586 *
587 * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
588 *              functions here is to prevent a lot of pointer dereferencing
589 *              to obtain the operands and to simplify the generation of the
590 *              logical value. For the Numeric operators (LAnd and LOr), both
591 *              operands must be integers. For the other logical operators,
592 *              operands can be any combination of Integer/String/Buffer. The
593 *              first operand determines the type to which the second operand
594 *              will be converted.
595 *
596 *              Note: cleanest machine code seems to be produced by the code
597 *              below, rather than using statements of the form:
598 *                  Result = (Operand0 == Operand1);
599 *
600 ******************************************************************************/
601
602ACPI_STATUS
603AcpiExDoLogicalOp (
604    UINT16                  Opcode,
605    ACPI_OPERAND_OBJECT     *Operand0,
606    ACPI_OPERAND_OBJECT     *Operand1,
607    BOOLEAN                 *LogicalResult)
608{
609    ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
610    UINT64                  Integer0;
611    UINT64                  Integer1;
612    UINT32                  Length0;
613    UINT32                  Length1;
614    ACPI_STATUS             Status = AE_OK;
615    BOOLEAN                 LocalResult = FALSE;
616    int                     Compare;
617
618
619    ACPI_FUNCTION_TRACE (ExDoLogicalOp);
620
621
622    /*
623     * Convert the second operand if necessary. The first operand
624     * determines the type of the second operand, (See the Data Types
625     * section of the ACPI 3.0+ specification.)  Both object types are
626     * guaranteed to be either Integer/String/Buffer by the operand
627     * resolution mechanism.
628     */
629    switch (Operand0->Common.Type)
630    {
631    case ACPI_TYPE_INTEGER:
632
633        Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
634        break;
635
636    case ACPI_TYPE_STRING:
637
638        Status = AcpiExConvertToString (Operand1, &LocalOperand1,
639                    ACPI_IMPLICIT_CONVERT_HEX);
640        break;
641
642    case ACPI_TYPE_BUFFER:
643
644        Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
645        break;
646
647    default:
648
649        Status = AE_AML_INTERNAL;
650        break;
651    }
652
653    if (ACPI_FAILURE (Status))
654    {
655        goto Cleanup;
656    }
657
658    /*
659     * Two cases: 1) Both Integers, 2) Both Strings or Buffers
660     */
661    if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
662    {
663        /*
664         * 1) Both operands are of type integer
665         *    Note: LocalOperand1 may have changed above
666         */
667        Integer0 = Operand0->Integer.Value;
668        Integer1 = LocalOperand1->Integer.Value;
669
670        switch (Opcode)
671        {
672        case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
673
674            if (Integer0 == Integer1)
675            {
676                LocalResult = TRUE;
677            }
678            break;
679
680        case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
681
682            if (Integer0 > Integer1)
683            {
684                LocalResult = TRUE;
685            }
686            break;
687
688        case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
689
690            if (Integer0 < Integer1)
691            {
692                LocalResult = TRUE;
693            }
694            break;
695
696        default:
697
698            Status = AE_AML_INTERNAL;
699            break;
700        }
701    }
702    else
703    {
704        /*
705         * 2) Both operands are Strings or both are Buffers
706         *    Note: Code below takes advantage of common Buffer/String
707         *          object fields. LocalOperand1 may have changed above. Use
708         *          memcmp to handle nulls in buffers.
709         */
710        Length0 = Operand0->Buffer.Length;
711        Length1 = LocalOperand1->Buffer.Length;
712
713        /* Lexicographic compare: compare the data bytes */
714
715        Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer,
716                    LocalOperand1->Buffer.Pointer,
717                    (Length0 > Length1) ? Length1 : Length0);
718
719        switch (Opcode)
720        {
721        case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
722
723            /* Length and all bytes must be equal */
724
725            if ((Length0 == Length1) &&
726                (Compare == 0))
727            {
728                /* Length and all bytes match ==> TRUE */
729
730                LocalResult = TRUE;
731            }
732            break;
733
734        case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
735
736            if (Compare > 0)
737            {
738                LocalResult = TRUE;
739                goto Cleanup;   /* TRUE */
740            }
741            if (Compare < 0)
742            {
743                goto Cleanup;   /* FALSE */
744            }
745
746            /* Bytes match (to shortest length), compare lengths */
747
748            if (Length0 > Length1)
749            {
750                LocalResult = TRUE;
751            }
752            break;
753
754        case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
755
756            if (Compare > 0)
757            {
758                goto Cleanup;   /* FALSE */
759            }
760            if (Compare < 0)
761            {
762                LocalResult = TRUE;
763                goto Cleanup;   /* TRUE */
764            }
765
766            /* Bytes match (to shortest length), compare lengths */
767
768            if (Length0 < Length1)
769            {
770                LocalResult = TRUE;
771            }
772            break;
773
774        default:
775
776            Status = AE_AML_INTERNAL;
777            break;
778        }
779    }
780
781Cleanup:
782
783    /* New object was created if implicit conversion performed - delete */
784
785    if (LocalOperand1 != Operand1)
786    {
787        AcpiUtRemoveReference (LocalOperand1);
788    }
789
790    /* Return the logical result and status */
791
792    *LogicalResult = LocalResult;
793    return_ACPI_STATUS (Status);
794}
795