exmisc.c revision 193249
1
2/******************************************************************************
3 *
4 * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
5 *              $Revision: 1.144 $
6 *
7 *****************************************************************************/
8
9/******************************************************************************
10 *
11 * 1. Copyright Notice
12 *
13 * Some or all of this work - Copyright (c) 1999 - 2007, 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#include <contrib/dev/acpica/amlresrc.h>
125
126
127#define _COMPONENT          ACPI_EXECUTER
128        ACPI_MODULE_NAME    ("exmisc")
129
130
131/*******************************************************************************
132 *
133 * FUNCTION:    AcpiExGetObjectReference
134 *
135 * PARAMETERS:  ObjDesc             - Create a reference to this object
136 *              ReturnDesc          - Where to store the reference
137 *              WalkState           - Current state
138 *
139 * RETURN:      Status
140 *
141 * DESCRIPTION: Obtain and return a "reference" to the target object
142 *              Common code for the RefOfOp and the CondRefOfOp.
143 *
144 ******************************************************************************/
145
146ACPI_STATUS
147AcpiExGetObjectReference (
148    ACPI_OPERAND_OBJECT     *ObjDesc,
149    ACPI_OPERAND_OBJECT     **ReturnDesc,
150    ACPI_WALK_STATE         *WalkState)
151{
152    ACPI_OPERAND_OBJECT     *ReferenceObj;
153    ACPI_OPERAND_OBJECT     *ReferencedObj;
154
155
156    ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
157
158
159    *ReturnDesc = NULL;
160
161    switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
162    {
163    case ACPI_DESC_TYPE_OPERAND:
164
165        if (ACPI_GET_OBJECT_TYPE (ObjDesc) != ACPI_TYPE_LOCAL_REFERENCE)
166        {
167            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
168        }
169
170        /*
171         * Must be a reference to a Local or Arg
172         */
173        switch (ObjDesc->Reference.Opcode)
174        {
175        case AML_LOCAL_OP:
176        case AML_ARG_OP:
177        case AML_DEBUG_OP:
178
179            /* The referenced object is the pseudo-node for the local/arg */
180
181            ReferencedObj = ObjDesc->Reference.Object;
182            break;
183
184        default:
185
186            ACPI_ERROR ((AE_INFO, "Unknown Reference opcode %X",
187                ObjDesc->Reference.Opcode));
188            return_ACPI_STATUS (AE_AML_INTERNAL);
189        }
190        break;
191
192
193    case ACPI_DESC_TYPE_NAMED:
194
195        /*
196         * A named reference that has already been resolved to a Node
197         */
198        ReferencedObj = ObjDesc;
199        break;
200
201
202    default:
203
204        ACPI_ERROR ((AE_INFO, "Invalid descriptor type %X",
205            ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
206        return_ACPI_STATUS (AE_TYPE);
207    }
208
209
210    /* Create a new reference object */
211
212    ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
213    if (!ReferenceObj)
214    {
215        return_ACPI_STATUS (AE_NO_MEMORY);
216    }
217
218    ReferenceObj->Reference.Opcode = AML_REF_OF_OP;
219    ReferenceObj->Reference.Object = ReferencedObj;
220    *ReturnDesc = ReferenceObj;
221
222    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
223        "Object %p Type [%s], returning Reference %p\n",
224        ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
225
226    return_ACPI_STATUS (AE_OK);
227}
228
229
230/*******************************************************************************
231 *
232 * FUNCTION:    AcpiExConcatTemplate
233 *
234 * PARAMETERS:  Operand0            - First source object
235 *              Operand1            - Second source object
236 *              ActualReturnDesc    - Where to place the return object
237 *              WalkState           - Current walk state
238 *
239 * RETURN:      Status
240 *
241 * DESCRIPTION: Concatenate two resource templates
242 *
243 ******************************************************************************/
244
245ACPI_STATUS
246AcpiExConcatTemplate (
247    ACPI_OPERAND_OBJECT     *Operand0,
248    ACPI_OPERAND_OBJECT     *Operand1,
249    ACPI_OPERAND_OBJECT     **ActualReturnDesc,
250    ACPI_WALK_STATE         *WalkState)
251{
252    ACPI_STATUS             Status;
253    ACPI_OPERAND_OBJECT     *ReturnDesc;
254    UINT8                   *NewBuf;
255    UINT8                   *EndTag;
256    ACPI_SIZE               Length0;
257    ACPI_SIZE               Length1;
258    ACPI_SIZE               NewLength;
259
260
261    ACPI_FUNCTION_TRACE (ExConcatTemplate);
262
263
264    /*
265     * Find the EndTag descriptor in each resource template.
266     * Note1: returned pointers point TO the EndTag, not past it.
267     * Note2: zero-length buffers are allowed; treated like one EndTag
268     */
269
270    /* Get the length of the first resource template */
271
272    Status = AcpiUtGetResourceEndTag (Operand0, &EndTag);
273    if (ACPI_FAILURE (Status))
274    {
275        return_ACPI_STATUS (Status);
276    }
277
278    Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer);
279
280    /* Get the length of the second resource template */
281
282    Status = AcpiUtGetResourceEndTag (Operand1, &EndTag);
283    if (ACPI_FAILURE (Status))
284    {
285        return_ACPI_STATUS (Status);
286    }
287
288    Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer);
289
290    /* Combine both lengths, minimum size will be 2 for EndTag */
291
292    NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG);
293
294    /* Create a new buffer object for the result (with one EndTag) */
295
296    ReturnDesc = AcpiUtCreateBufferObject (NewLength);
297    if (!ReturnDesc)
298    {
299        return_ACPI_STATUS (AE_NO_MEMORY);
300    }
301
302    /*
303     * Copy the templates to the new buffer, 0 first, then 1 follows. One
304     * EndTag descriptor is copied from Operand1.
305     */
306    NewBuf = ReturnDesc->Buffer.Pointer;
307    ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length0);
308    ACPI_MEMCPY (NewBuf + Length0, Operand1->Buffer.Pointer, Length1);
309
310    /* Insert EndTag and set the checksum to zero, means "ignore checksum" */
311
312    NewBuf[NewLength - 1] = 0;
313    NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
314
315    /* Return the completed resource template */
316
317    *ActualReturnDesc = ReturnDesc;
318    return_ACPI_STATUS (AE_OK);
319}
320
321
322/*******************************************************************************
323 *
324 * FUNCTION:    AcpiExDoConcatenate
325 *
326 * PARAMETERS:  Operand0            - First source object
327 *              Operand1            - Second source object
328 *              ActualReturnDesc    - Where to place the return object
329 *              WalkState           - Current walk state
330 *
331 * RETURN:      Status
332 *
333 * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
334 *
335 ******************************************************************************/
336
337ACPI_STATUS
338AcpiExDoConcatenate (
339    ACPI_OPERAND_OBJECT     *Operand0,
340    ACPI_OPERAND_OBJECT     *Operand1,
341    ACPI_OPERAND_OBJECT     **ActualReturnDesc,
342    ACPI_WALK_STATE         *WalkState)
343{
344    ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
345    ACPI_OPERAND_OBJECT     *ReturnDesc;
346    char                    *NewBuf;
347    ACPI_STATUS             Status;
348
349
350    ACPI_FUNCTION_TRACE (ExDoConcatenate);
351
352
353    /*
354     * Convert the second operand if necessary.  The first operand
355     * determines the type of the second operand, (See the Data Types
356     * section of the ACPI specification.)  Both object types are
357     * guaranteed to be either Integer/String/Buffer by the operand
358     * resolution mechanism.
359     */
360    switch (ACPI_GET_OBJECT_TYPE (Operand0))
361    {
362    case ACPI_TYPE_INTEGER:
363        Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
364        break;
365
366    case ACPI_TYPE_STRING:
367        Status = AcpiExConvertToString (Operand1, &LocalOperand1,
368                    ACPI_IMPLICIT_CONVERT_HEX);
369        break;
370
371    case ACPI_TYPE_BUFFER:
372        Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
373        break;
374
375    default:
376        ACPI_ERROR ((AE_INFO, "Invalid object type: %X",
377            ACPI_GET_OBJECT_TYPE (Operand0)));
378        Status = AE_AML_INTERNAL;
379    }
380
381    if (ACPI_FAILURE (Status))
382    {
383        goto Cleanup;
384    }
385
386    /*
387     * Both operands are now known to be the same object type
388     * (Both are Integer, String, or Buffer), and we can now perform the
389     * concatenation.
390     */
391
392    /*
393     * There are three cases to handle:
394     *
395     * 1) Two Integers concatenated to produce a new Buffer
396     * 2) Two Strings concatenated to produce a new String
397     * 3) Two Buffers concatenated to produce a new Buffer
398     */
399    switch (ACPI_GET_OBJECT_TYPE (Operand0))
400    {
401    case ACPI_TYPE_INTEGER:
402
403        /* Result of two Integers is a Buffer */
404        /* Need enough buffer space for two integers */
405
406        ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE)
407                            ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
408        if (!ReturnDesc)
409        {
410            Status = AE_NO_MEMORY;
411            goto Cleanup;
412        }
413
414        NewBuf = (char *) ReturnDesc->Buffer.Pointer;
415
416        /* Copy the first integer, LSB first */
417
418        ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value,
419                        AcpiGbl_IntegerByteWidth);
420
421        /* Copy the second integer (LSB first) after the first */
422
423        ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth,
424                        &LocalOperand1->Integer.Value,
425                        AcpiGbl_IntegerByteWidth);
426        break;
427
428    case ACPI_TYPE_STRING:
429
430        /* Result of two Strings is a String */
431
432        ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE)
433                        (Operand0->String.Length +
434                        LocalOperand1->String.Length));
435        if (!ReturnDesc)
436        {
437            Status = AE_NO_MEMORY;
438            goto Cleanup;
439        }
440
441        NewBuf = ReturnDesc->String.Pointer;
442
443        /* Concatenate the strings */
444
445        ACPI_STRCPY (NewBuf, Operand0->String.Pointer);
446        ACPI_STRCPY (NewBuf + Operand0->String.Length,
447                        LocalOperand1->String.Pointer);
448        break;
449
450    case ACPI_TYPE_BUFFER:
451
452        /* Result of two Buffers is a Buffer */
453
454        ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE)
455                        (Operand0->Buffer.Length +
456                        LocalOperand1->Buffer.Length));
457        if (!ReturnDesc)
458        {
459            Status = AE_NO_MEMORY;
460            goto Cleanup;
461        }
462
463        NewBuf = (char *) ReturnDesc->Buffer.Pointer;
464
465        /* Concatenate the buffers */
466
467        ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer,
468                        Operand0->Buffer.Length);
469        ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length,
470                        LocalOperand1->Buffer.Pointer,
471                        LocalOperand1->Buffer.Length);
472        break;
473
474    default:
475
476        /* Invalid object type, should not happen here */
477
478        ACPI_ERROR ((AE_INFO, "Invalid object type: %X",
479            ACPI_GET_OBJECT_TYPE (Operand0)));
480        Status =AE_AML_INTERNAL;
481        goto Cleanup;
482    }
483
484    *ActualReturnDesc = ReturnDesc;
485
486Cleanup:
487    if (LocalOperand1 != Operand1)
488    {
489        AcpiUtRemoveReference (LocalOperand1);
490    }
491    return_ACPI_STATUS (Status);
492}
493
494
495/*******************************************************************************
496 *
497 * FUNCTION:    AcpiExDoMathOp
498 *
499 * PARAMETERS:  Opcode              - AML opcode
500 *              Integer0            - Integer operand #0
501 *              Integer1            - Integer operand #1
502 *
503 * RETURN:      Integer result of the operation
504 *
505 * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
506 *              math functions here is to prevent a lot of pointer dereferencing
507 *              to obtain the operands.
508 *
509 ******************************************************************************/
510
511ACPI_INTEGER
512AcpiExDoMathOp (
513    UINT16                  Opcode,
514    ACPI_INTEGER            Integer0,
515    ACPI_INTEGER            Integer1)
516{
517
518    ACPI_FUNCTION_ENTRY ();
519
520
521    switch (Opcode)
522    {
523    case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
524
525        return (Integer0 + Integer1);
526
527
528    case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
529
530        return (Integer0 & Integer1);
531
532
533    case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
534
535        return (~(Integer0 & Integer1));
536
537
538    case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
539
540        return (Integer0 | Integer1);
541
542
543    case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
544
545        return (~(Integer0 | Integer1));
546
547
548    case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
549
550        return (Integer0 ^ Integer1);
551
552
553    case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
554
555        return (Integer0 * Integer1);
556
557
558    case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
559
560        /*
561         * We need to check if the shiftcount is larger than the integer bit
562         * width since the behavior of this is not well-defined in the C language.
563         */
564        if (Integer1 >= AcpiGbl_IntegerBitWidth)
565        {
566            return (0);
567        }
568        return (Integer0 << Integer1);
569
570
571    case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
572
573        /*
574         * We need to check if the shiftcount is larger than the integer bit
575         * width since the behavior of this is not well-defined in the C language.
576         */
577        if (Integer1 >= AcpiGbl_IntegerBitWidth)
578        {
579            return (0);
580        }
581        return (Integer0 >> Integer1);
582
583
584    case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
585
586        return (Integer0 - Integer1);
587
588    default:
589
590        return (0);
591    }
592}
593
594
595/*******************************************************************************
596 *
597 * FUNCTION:    AcpiExDoLogicalNumericOp
598 *
599 * PARAMETERS:  Opcode              - AML opcode
600 *              Integer0            - Integer operand #0
601 *              Integer1            - Integer operand #1
602 *              LogicalResult       - TRUE/FALSE result of the operation
603 *
604 * RETURN:      Status
605 *
606 * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
607 *              operators (LAnd and LOr), both operands must be integers.
608 *
609 *              Note: cleanest machine code seems to be produced by the code
610 *              below, rather than using statements of the form:
611 *                  Result = (Integer0 && Integer1);
612 *
613 ******************************************************************************/
614
615ACPI_STATUS
616AcpiExDoLogicalNumericOp (
617    UINT16                  Opcode,
618    ACPI_INTEGER            Integer0,
619    ACPI_INTEGER            Integer1,
620    BOOLEAN                 *LogicalResult)
621{
622    ACPI_STATUS             Status = AE_OK;
623    BOOLEAN                 LocalResult = FALSE;
624
625
626    ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
627
628
629    switch (Opcode)
630    {
631    case AML_LAND_OP:               /* LAnd (Integer0, Integer1) */
632
633        if (Integer0 && Integer1)
634        {
635            LocalResult = TRUE;
636        }
637        break;
638
639    case AML_LOR_OP:                /* LOr (Integer0, Integer1) */
640
641        if (Integer0 || Integer1)
642        {
643            LocalResult = TRUE;
644        }
645        break;
646
647    default:
648        Status = AE_AML_INTERNAL;
649        break;
650    }
651
652    /* Return the logical result and status */
653
654    *LogicalResult = LocalResult;
655    return_ACPI_STATUS (Status);
656}
657
658
659/*******************************************************************************
660 *
661 * FUNCTION:    AcpiExDoLogicalOp
662 *
663 * PARAMETERS:  Opcode              - AML opcode
664 *              Operand0            - operand #0
665 *              Operand1            - operand #1
666 *              LogicalResult       - TRUE/FALSE result of the operation
667 *
668 * RETURN:      Status
669 *
670 * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
671 *              functions here is to prevent a lot of pointer dereferencing
672 *              to obtain the operands and to simplify the generation of the
673 *              logical value. For the Numeric operators (LAnd and LOr), both
674 *              operands must be integers. For the other logical operators,
675 *              operands can be any combination of Integer/String/Buffer. The
676 *              first operand determines the type to which the second operand
677 *              will be converted.
678 *
679 *              Note: cleanest machine code seems to be produced by the code
680 *              below, rather than using statements of the form:
681 *                  Result = (Operand0 == Operand1);
682 *
683 ******************************************************************************/
684
685ACPI_STATUS
686AcpiExDoLogicalOp (
687    UINT16                  Opcode,
688    ACPI_OPERAND_OBJECT     *Operand0,
689    ACPI_OPERAND_OBJECT     *Operand1,
690    BOOLEAN                 *LogicalResult)
691{
692    ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
693    ACPI_INTEGER            Integer0;
694    ACPI_INTEGER            Integer1;
695    UINT32                  Length0;
696    UINT32                  Length1;
697    ACPI_STATUS             Status = AE_OK;
698    BOOLEAN                 LocalResult = FALSE;
699    int                     Compare;
700
701
702    ACPI_FUNCTION_TRACE (ExDoLogicalOp);
703
704
705    /*
706     * Convert the second operand if necessary.  The first operand
707     * determines the type of the second operand, (See the Data Types
708     * section of the ACPI 3.0+ specification.)  Both object types are
709     * guaranteed to be either Integer/String/Buffer by the operand
710     * resolution mechanism.
711     */
712    switch (ACPI_GET_OBJECT_TYPE (Operand0))
713    {
714    case ACPI_TYPE_INTEGER:
715        Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
716        break;
717
718    case ACPI_TYPE_STRING:
719        Status = AcpiExConvertToString (Operand1, &LocalOperand1,
720                    ACPI_IMPLICIT_CONVERT_HEX);
721        break;
722
723    case ACPI_TYPE_BUFFER:
724        Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
725        break;
726
727    default:
728        Status = AE_AML_INTERNAL;
729        break;
730    }
731
732    if (ACPI_FAILURE (Status))
733    {
734        goto Cleanup;
735    }
736
737    /*
738     * Two cases: 1) Both Integers, 2) Both Strings or Buffers
739     */
740    if (ACPI_GET_OBJECT_TYPE (Operand0) == ACPI_TYPE_INTEGER)
741    {
742        /*
743         * 1) Both operands are of type integer
744         *    Note: LocalOperand1 may have changed above
745         */
746        Integer0 = Operand0->Integer.Value;
747        Integer1 = LocalOperand1->Integer.Value;
748
749        switch (Opcode)
750        {
751        case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
752
753            if (Integer0 == Integer1)
754            {
755                LocalResult = TRUE;
756            }
757            break;
758
759        case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
760
761            if (Integer0 > Integer1)
762            {
763                LocalResult = TRUE;
764            }
765            break;
766
767        case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
768
769            if (Integer0 < Integer1)
770            {
771                LocalResult = TRUE;
772            }
773            break;
774
775        default:
776            Status = AE_AML_INTERNAL;
777            break;
778        }
779    }
780    else
781    {
782        /*
783         * 2) Both operands are Strings or both are Buffers
784         *    Note: Code below takes advantage of common Buffer/String
785         *          object fields. LocalOperand1 may have changed above. Use
786         *          memcmp to handle nulls in buffers.
787         */
788        Length0 = Operand0->Buffer.Length;
789        Length1 = LocalOperand1->Buffer.Length;
790
791        /* Lexicographic compare: compare the data bytes */
792
793        Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer,
794                    LocalOperand1->Buffer.Pointer,
795                    (Length0 > Length1) ? Length1 : Length0);
796
797        switch (Opcode)
798        {
799        case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
800
801            /* Length and all bytes must be equal */
802
803            if ((Length0 == Length1) &&
804                (Compare == 0))
805            {
806                /* Length and all bytes match ==> TRUE */
807
808                LocalResult = TRUE;
809            }
810            break;
811
812        case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
813
814            if (Compare > 0)
815            {
816                LocalResult = TRUE;
817                goto Cleanup;   /* TRUE */
818            }
819            if (Compare < 0)
820            {
821                goto Cleanup;   /* FALSE */
822            }
823
824            /* Bytes match (to shortest length), compare lengths */
825
826            if (Length0 > Length1)
827            {
828                LocalResult = TRUE;
829            }
830            break;
831
832        case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
833
834            if (Compare > 0)
835            {
836                goto Cleanup;   /* FALSE */
837            }
838            if (Compare < 0)
839            {
840                LocalResult = TRUE;
841                goto Cleanup;   /* TRUE */
842            }
843
844            /* Bytes match (to shortest length), compare lengths */
845
846            if (Length0 < Length1)
847            {
848                LocalResult = TRUE;
849            }
850            break;
851
852        default:
853            Status = AE_AML_INTERNAL;
854            break;
855        }
856    }
857
858Cleanup:
859
860    /* New object was created if implicit conversion performed - delete */
861
862    if (LocalOperand1 != Operand1)
863    {
864        AcpiUtRemoveReference (LocalOperand1);
865    }
866
867    /* Return the logical result and status */
868
869    *LogicalResult = LocalResult;
870    return_ACPI_STATUS (Status);
871}
872
873
874