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