exmisc.c revision 151937
1
2/******************************************************************************
3 *
4 * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
5 *              $Revision: 1.132 $
6 *
7 *****************************************************************************/
8
9/******************************************************************************
10 *
11 * 1. Copyright Notice
12 *
13 * Some or all of this work - Copyright (c) 1999 - 2005, 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 <contrib/dev/acpica/acpi.h>
122#include <contrib/dev/acpica/acinterp.h>
123#include <contrib/dev/acpica/amlcode.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 (ACPI_GET_OBJECT_TYPE (ObjDesc) != 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.Opcode)
173        {
174        case AML_LOCAL_OP:
175        case AML_ARG_OP:
176        case AML_DEBUG_OP:
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_REPORT_ERROR (("Unknown Reference opcode in GetReference %X\n",
186                ObjDesc->Reference.Opcode));
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_REPORT_ERROR (("Invalid descriptor type in GetReference: %X\n",
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.Opcode = AML_REF_OF_OP;
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_OPERAND_OBJECT     *ReturnDesc;
252    UINT8                   *NewBuf;
253    UINT8                   *EndTag1;
254    UINT8                   *EndTag2;
255    ACPI_SIZE               Length1;
256    ACPI_SIZE               Length2;
257
258
259    ACPI_FUNCTION_TRACE ("ExConcatTemplate");
260
261
262    /* Find the EndTags in each resource template */
263
264    EndTag1 = AcpiUtGetResourceEndTag (Operand0);
265    EndTag2 = AcpiUtGetResourceEndTag (Operand1);
266    if (!EndTag1 || !EndTag2)
267    {
268        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
269    }
270
271    /* Compute the length of each part */
272
273    Length1 = ACPI_PTR_DIFF (EndTag1, Operand0->Buffer.Pointer);
274    Length2 = ACPI_PTR_DIFF (EndTag2, Operand1->Buffer.Pointer) +
275                             2; /* Size of END_TAG */
276
277    /* Create a new buffer object for the result */
278
279    ReturnDesc = AcpiUtCreateBufferObject (Length1 + Length2);
280    if (!ReturnDesc)
281    {
282        return_ACPI_STATUS (AE_NO_MEMORY);
283    }
284
285    /* Copy the templates to the new descriptor */
286
287    NewBuf = ReturnDesc->Buffer.Pointer;
288    ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length1);
289    ACPI_MEMCPY (NewBuf + Length1, Operand1->Buffer.Pointer, Length2);
290
291    /* Compute the new checksum */
292
293    NewBuf[ReturnDesc->Buffer.Length - 1] =
294            AcpiUtGenerateChecksum (ReturnDesc->Buffer.Pointer,
295                                   (ReturnDesc->Buffer.Length - 1));
296
297    /* Return the completed template descriptor */
298
299    *ActualReturnDesc = ReturnDesc;
300    return_ACPI_STATUS (AE_OK);
301}
302
303
304/*******************************************************************************
305 *
306 * FUNCTION:    AcpiExDoConcatenate
307 *
308 * PARAMETERS:  Operand0            - First source object
309 *              Operand1            - Second source object
310 *              ActualReturnDesc    - Where to place the return object
311 *              WalkState           - Current walk state
312 *
313 * RETURN:      Status
314 *
315 * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
316 *
317 ******************************************************************************/
318
319ACPI_STATUS
320AcpiExDoConcatenate (
321    ACPI_OPERAND_OBJECT     *Operand0,
322    ACPI_OPERAND_OBJECT     *Operand1,
323    ACPI_OPERAND_OBJECT     **ActualReturnDesc,
324    ACPI_WALK_STATE         *WalkState)
325{
326    ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
327    ACPI_OPERAND_OBJECT     *ReturnDesc;
328    char                    *NewBuf;
329    ACPI_STATUS             Status;
330    ACPI_SIZE               NewLength;
331
332
333    ACPI_FUNCTION_TRACE ("ExDoConcatenate");
334
335
336    /*
337     * Convert the second operand if necessary.  The first operand
338     * determines the type of the second operand, (See the Data Types
339     * section of the ACPI specification.)  Both object types are
340     * guaranteed to be either Integer/String/Buffer by the operand
341     * resolution mechanism.
342     */
343    switch (ACPI_GET_OBJECT_TYPE (Operand0))
344    {
345    case ACPI_TYPE_INTEGER:
346        Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
347        break;
348
349    case ACPI_TYPE_STRING:
350        Status = AcpiExConvertToString (Operand1, &LocalOperand1,
351                    ACPI_IMPLICIT_CONVERT_HEX);
352        break;
353
354    case ACPI_TYPE_BUFFER:
355        Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
356        break;
357
358    default:
359        ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
360                ACPI_GET_OBJECT_TYPE (Operand0)));
361        Status = AE_AML_INTERNAL;
362    }
363
364    if (ACPI_FAILURE (Status))
365    {
366        goto Cleanup;
367    }
368
369    /*
370     * Both operands are now known to be the same object type
371     * (Both are Integer, String, or Buffer), and we can now perform the
372     * concatenation.
373     */
374
375    /*
376     * There are three cases to handle:
377     *
378     * 1) Two Integers concatenated to produce a new Buffer
379     * 2) Two Strings concatenated to produce a new String
380     * 3) Two Buffers concatenated to produce a new Buffer
381     */
382    switch (ACPI_GET_OBJECT_TYPE (Operand0))
383    {
384    case ACPI_TYPE_INTEGER:
385
386        /* Result of two Integers is a Buffer */
387        /* Need enough buffer space for two integers */
388
389        ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE)
390                            ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
391        if (!ReturnDesc)
392        {
393            Status = AE_NO_MEMORY;
394            goto Cleanup;
395        }
396
397        NewBuf = (char *) ReturnDesc->Buffer.Pointer;
398
399        /* Copy the first integer, LSB first */
400
401        ACPI_MEMCPY (NewBuf,
402                        &Operand0->Integer.Value,
403                        AcpiGbl_IntegerByteWidth);
404
405        /* Copy the second integer (LSB first) after the first */
406
407        ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth,
408                        &LocalOperand1->Integer.Value,
409                        AcpiGbl_IntegerByteWidth);
410        break;
411
412    case ACPI_TYPE_STRING:
413
414        /* Result of two Strings is a String */
415
416        NewLength = (ACPI_SIZE) Operand0->String.Length +
417                    (ACPI_SIZE) LocalOperand1->String.Length;
418        if (NewLength > ACPI_MAX_STRING_CONVERSION)
419        {
420            Status = AE_AML_STRING_LIMIT;
421            goto Cleanup;
422        }
423
424        ReturnDesc = AcpiUtCreateStringObject (NewLength);
425        if (!ReturnDesc)
426        {
427            Status = AE_NO_MEMORY;
428            goto Cleanup;
429        }
430
431        NewBuf = ReturnDesc->String.Pointer;
432
433        /* Concatenate the strings */
434
435        ACPI_STRCPY (NewBuf,
436                        Operand0->String.Pointer);
437        ACPI_STRCPY (NewBuf + Operand0->String.Length,
438                        LocalOperand1->String.Pointer);
439        break;
440
441    case ACPI_TYPE_BUFFER:
442
443        /* Result of two Buffers is a Buffer */
444
445        ReturnDesc = AcpiUtCreateBufferObject (
446                            (ACPI_SIZE) Operand0->Buffer.Length +
447                            (ACPI_SIZE) LocalOperand1->Buffer.Length);
448        if (!ReturnDesc)
449        {
450            Status = AE_NO_MEMORY;
451            goto Cleanup;
452        }
453
454        NewBuf = (char *) ReturnDesc->Buffer.Pointer;
455
456        /* Concatenate the buffers */
457
458        ACPI_MEMCPY (NewBuf,
459                        Operand0->Buffer.Pointer,
460                        Operand0->Buffer.Length);
461        ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length,
462                        LocalOperand1->Buffer.Pointer,
463                        LocalOperand1->Buffer.Length);
464        break;
465
466    default:
467
468        /* Invalid object type, should not happen here */
469
470        ACPI_REPORT_ERROR (("Concatenate - Invalid object type: %X\n",
471                ACPI_GET_OBJECT_TYPE (Operand0)));
472        Status =AE_AML_INTERNAL;
473        goto Cleanup;
474    }
475
476    *ActualReturnDesc = ReturnDesc;
477
478Cleanup:
479    if (LocalOperand1 != Operand1)
480    {
481        AcpiUtRemoveReference (LocalOperand1);
482    }
483    return_ACPI_STATUS (Status);
484}
485
486
487/*******************************************************************************
488 *
489 * FUNCTION:    AcpiExDoMathOp
490 *
491 * PARAMETERS:  Opcode              - AML opcode
492 *              Integer0            - Integer operand #0
493 *              Integer1            - Integer operand #1
494 *
495 * RETURN:      Integer result of the operation
496 *
497 * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
498 *              math functions here is to prevent a lot of pointer dereferencing
499 *              to obtain the operands.
500 *
501 ******************************************************************************/
502
503ACPI_INTEGER
504AcpiExDoMathOp (
505    UINT16                  Opcode,
506    ACPI_INTEGER            Integer0,
507    ACPI_INTEGER            Integer1)
508{
509
510    ACPI_FUNCTION_ENTRY ();
511
512
513    switch (Opcode)
514    {
515    case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
516
517        return (Integer0 + Integer1);
518
519
520    case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
521
522        return (Integer0 & Integer1);
523
524
525    case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
526
527        return (~(Integer0 & Integer1));
528
529
530    case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
531
532        return (Integer0 | Integer1);
533
534
535    case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
536
537        return (~(Integer0 | Integer1));
538
539
540    case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
541
542        return (Integer0 ^ Integer1);
543
544
545    case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
546
547        return (Integer0 * Integer1);
548
549
550    case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
551
552        return (Integer0 << Integer1);
553
554
555    case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
556
557        return (Integer0 >> Integer1);
558
559
560    case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
561
562        return (Integer0 - Integer1);
563
564    default:
565
566        return (0);
567    }
568}
569
570
571/*******************************************************************************
572 *
573 * FUNCTION:    AcpiExDoLogicalNumericOp
574 *
575 * PARAMETERS:  Opcode              - AML opcode
576 *              Integer0            - Integer operand #0
577 *              Integer1            - Integer operand #1
578 *              LogicalResult       - TRUE/FALSE result of the operation
579 *
580 * RETURN:      Status
581 *
582 * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
583 *              operators (LAnd and LOr), both operands must be integers.
584 *
585 *              Note: cleanest machine code seems to be produced by the code
586 *              below, rather than using statements of the form:
587 *                  Result = (Integer0 && Integer1);
588 *
589 ******************************************************************************/
590
591ACPI_STATUS
592AcpiExDoLogicalNumericOp (
593    UINT16                  Opcode,
594    ACPI_INTEGER            Integer0,
595    ACPI_INTEGER            Integer1,
596    BOOLEAN                 *LogicalResult)
597{
598    ACPI_STATUS             Status = AE_OK;
599    BOOLEAN                 LocalResult = FALSE;
600
601
602    ACPI_FUNCTION_TRACE ("ExDoLogicalNumericOp");
603
604
605    switch (Opcode)
606    {
607    case AML_LAND_OP:               /* LAnd (Integer0, Integer1) */
608
609        if (Integer0 && Integer1)
610        {
611            LocalResult = TRUE;
612        }
613        break;
614
615    case AML_LOR_OP:                /* LOr (Integer0, Integer1) */
616
617        if (Integer0 || Integer1)
618        {
619            LocalResult = TRUE;
620        }
621        break;
622
623    default:
624        Status = AE_AML_INTERNAL;
625        break;
626    }
627
628    /* Return the logical result and status */
629
630    *LogicalResult = LocalResult;
631    return_ACPI_STATUS (Status);
632}
633
634
635/*******************************************************************************
636 *
637 * FUNCTION:    AcpiExDoLogicalOp
638 *
639 * PARAMETERS:  Opcode              - AML opcode
640 *              Operand0            - operand #0
641 *              Operand1            - operand #1
642 *              LogicalResult       - TRUE/FALSE result of the operation
643 *
644 * RETURN:      Status
645 *
646 * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
647 *              functions here is to prevent a lot of pointer dereferencing
648 *              to obtain the operands and to simplify the generation of the
649 *              logical value. For the Numeric operators (LAnd and LOr), both
650 *              operands must be integers. For the other logical operators,
651 *              operands can be any combination of Integer/String/Buffer. The
652 *              first operand determines the type to which the second operand
653 *              will be converted.
654 *
655 *              Note: cleanest machine code seems to be produced by the code
656 *              below, rather than using statements of the form:
657 *                  Result = (Operand0 == Operand1);
658 *
659 ******************************************************************************/
660
661ACPI_STATUS
662AcpiExDoLogicalOp (
663    UINT16                  Opcode,
664    ACPI_OPERAND_OBJECT     *Operand0,
665    ACPI_OPERAND_OBJECT     *Operand1,
666    BOOLEAN                 *LogicalResult)
667{
668    ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
669    ACPI_INTEGER            Integer0;
670    ACPI_INTEGER            Integer1;
671    UINT32                  Length0;
672    UINT32                  Length1;
673    ACPI_STATUS             Status = AE_OK;
674    BOOLEAN                 LocalResult = FALSE;
675    int                     Compare;
676
677
678    ACPI_FUNCTION_TRACE ("ExDoLogicalOp");
679
680
681    /*
682     * Convert the second operand if necessary.  The first operand
683     * determines the type of the second operand, (See the Data Types
684     * section of the ACPI 3.0+ specification.)  Both object types are
685     * guaranteed to be either Integer/String/Buffer by the operand
686     * resolution mechanism.
687     */
688    switch (ACPI_GET_OBJECT_TYPE (Operand0))
689    {
690    case ACPI_TYPE_INTEGER:
691        Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
692        break;
693
694    case ACPI_TYPE_STRING:
695        Status = AcpiExConvertToString (Operand1, &LocalOperand1,
696                    ACPI_IMPLICIT_CONVERT_HEX);
697        break;
698
699    case ACPI_TYPE_BUFFER:
700        Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
701        break;
702
703    default:
704        Status = AE_AML_INTERNAL;
705        break;
706    }
707
708    if (ACPI_FAILURE (Status))
709    {
710        goto Cleanup;
711    }
712
713    /*
714     * Two cases: 1) Both Integers, 2) Both Strings or Buffers
715     */
716    if (ACPI_GET_OBJECT_TYPE (Operand0) == ACPI_TYPE_INTEGER)
717    {
718        /*
719         * 1) Both operands are of type integer
720         *    Note: LocalOperand1 may have changed above
721         */
722        Integer0 = Operand0->Integer.Value;
723        Integer1 = LocalOperand1->Integer.Value;
724
725        switch (Opcode)
726        {
727        case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
728
729            if (Integer0 == Integer1)
730            {
731                LocalResult = TRUE;
732            }
733            break;
734
735        case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
736
737            if (Integer0 > Integer1)
738            {
739                LocalResult = TRUE;
740            }
741            break;
742
743        case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
744
745            if (Integer0 < Integer1)
746            {
747                LocalResult = TRUE;
748            }
749            break;
750
751        default:
752            Status = AE_AML_INTERNAL;
753            break;
754        }
755    }
756    else
757    {
758        /*
759         * 2) Both operands are Strings or both are Buffers
760         *    Note: Code below takes advantage of common Buffer/String
761         *          object fields. LocalOperand1 may have changed above. Use
762         *          memcmp to handle nulls in buffers.
763         */
764        Length0 = Operand0->Buffer.Length;
765        Length1 = LocalOperand1->Buffer.Length;
766
767        /* Lexicographic compare: compare the data bytes */
768
769        Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer,
770                    LocalOperand1->Buffer.Pointer,
771                    (Length0 > Length1) ? Length1 : Length0);
772
773        switch (Opcode)
774        {
775        case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
776
777            /* Length and all bytes must be equal */
778
779            if ((Length0 == Length1) &&
780                (Compare == 0))
781            {
782                /* Length and all bytes match ==> TRUE */
783
784                LocalResult = TRUE;
785            }
786            break;
787
788        case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
789
790            if (Compare > 0)
791            {
792                LocalResult = TRUE;
793                goto Cleanup;   /* TRUE */
794            }
795            if (Compare < 0)
796            {
797                goto Cleanup;   /* FALSE */
798            }
799
800            /* Bytes match (to shortest length), compare lengths */
801
802            if (Length0 > Length1)
803            {
804                LocalResult = TRUE;
805            }
806            break;
807
808        case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
809
810            if (Compare > 0)
811            {
812                goto Cleanup;   /* FALSE */
813            }
814            if (Compare < 0)
815            {
816                LocalResult = TRUE;
817                goto Cleanup;   /* TRUE */
818            }
819
820            /* Bytes match (to shortest length), compare lengths */
821
822            if (Length0 < Length1)
823            {
824                LocalResult = TRUE;
825            }
826            break;
827
828        default:
829            Status = AE_AML_INTERNAL;
830            break;
831        }
832    }
833
834Cleanup:
835
836    /* New object was created if implicit conversion performed - delete */
837
838    if (LocalOperand1 != Operand1)
839    {
840        AcpiUtRemoveReference (LocalOperand1);
841    }
842
843    /* Return the logical result and status */
844
845    *LogicalResult = LocalResult;
846    return_ACPI_STATUS (Status);
847}
848
849
850