Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/acpica/exmisc.c need to be fixed.

0001 
0002 /******************************************************************************
0003  *
0004  * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
0005  *
0006  *****************************************************************************/
0007 
0008 /******************************************************************************
0009  *
0010  * 1. Copyright Notice
0011  *
0012  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
0013  * All rights reserved.
0014  *
0015  * 2. License
0016  *
0017  * 2.1. This is your license from Intel Corp. under its intellectual property
0018  * rights.  You may have additional license terms from the party that provided
0019  * you this software, covering your right to use that party's intellectual
0020  * property rights.
0021  *
0022  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0023  * copy of the source code appearing in this file ("Covered Code") an
0024  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0025  * base code distributed originally by Intel ("Original Intel Code") to copy,
0026  * make derivatives, distribute, use and display any portion of the Covered
0027  * Code in any form, with the right to sublicense such rights; and
0028  *
0029  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0030  * license (with the right to sublicense), under only those claims of Intel
0031  * patents that are infringed by the Original Intel Code, to make, use, sell,
0032  * offer to sell, and import the Covered Code and derivative works thereof
0033  * solely to the minimum extent necessary to exercise the above copyright
0034  * license, and in no event shall the patent license extend to any additions
0035  * to or modifications of the Original Intel Code.  No other license or right
0036  * is granted directly or by implication, estoppel or otherwise;
0037  *
0038  * The above copyright and patent license is granted only if the following
0039  * conditions are met:
0040  *
0041  * 3. Conditions
0042  *
0043  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0044  * Redistribution of source code of any substantial portion of the Covered
0045  * Code or modification with rights to further distribute source must include
0046  * the above Copyright Notice, the above License, this list of Conditions,
0047  * and the following Disclaimer and Export Compliance provision.  In addition,
0048  * Licensee must cause all Covered Code to which Licensee contributes to
0049  * contain a file documenting the changes Licensee made to create that Covered
0050  * Code and the date of any change.  Licensee must include in that file the
0051  * documentation of any changes made by any predecessor Licensee.  Licensee
0052  * must include a prominent statement that the modification is derived,
0053  * directly or indirectly, from Original Intel Code.
0054  *
0055  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0056  * Redistribution of source code of any substantial portion of the Covered
0057  * Code or modification without rights to further distribute source must
0058  * include the following Disclaimer and Export Compliance provision in the
0059  * documentation and/or other materials provided with distribution.  In
0060  * addition, Licensee may not authorize further sublicense of source of any
0061  * portion of the Covered Code, and must include terms to the effect that the
0062  * license from Licensee to its licensee is limited to the intellectual
0063  * property embodied in the software Licensee provides to its licensee, and
0064  * not to intellectual property embodied in modifications its licensee may
0065  * make.
0066  *
0067  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0068  * substantial portion of the Covered Code or modification must reproduce the
0069  * above Copyright Notice, and the following Disclaimer and Export Compliance
0070  * provision in the documentation and/or other materials provided with the
0071  * distribution.
0072  *
0073  * 3.4. Intel retains all right, title, and interest in and to the Original
0074  * Intel Code.
0075  *
0076  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0077  * Intel shall be used in advertising or otherwise to promote the sale, use or
0078  * other dealings in products derived from or relating to the Covered Code
0079  * without prior written authorization from Intel.
0080  *
0081  * 4. Disclaimer and Export Compliance
0082  *
0083  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0084  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0085  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
0086  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
0087 
0088  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
0089  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0090  * PARTICULAR PURPOSE.
0091  *
0092  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0093  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0094  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0095  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0096  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0097  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
0098  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0099  * LIMITED REMEDY.
0100  *
0101  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0102  * software or system incorporating such software without first obtaining any
0103  * required license or other approval from the U. S. Department of Commerce or
0104  * any other agency or department of the United States Government.  In the
0105  * event Licensee exports any such software from the United States or
0106  * re-exports any such software from a foreign destination, Licensee shall
0107  * ensure that the distribution and export/re-export of the software is in
0108  * compliance with all laws, regulations, orders, or other restrictions of the
0109  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0110  * any of its subsidiaries will export/re-export any technical data, process,
0111  * software, or service, directly or indirectly, to any country for which the
0112  * United States government or any agency thereof requires an export license,
0113  * other governmental approval, or letter of assurance, without first obtaining
0114  * such license, approval or letter.
0115  *
0116  *****************************************************************************/
0117 
0118 #define __EXMISC_C__
0119 
0120 #include "acpi.h"
0121 #include "accommon.h"
0122 #include "acinterp.h"
0123 #include "amlcode.h"
0124 #include "amlresrc.h"
0125 
0126 
0127 #define _COMPONENT          ACPI_EXECUTER
0128         ACPI_MODULE_NAME    ("exmisc")
0129 
0130 
0131 /*******************************************************************************
0132  *
0133  * FUNCTION:    AcpiExGetObjectReference
0134  *
0135  * PARAMETERS:  ObjDesc             - Create a reference to this object
0136  *              ReturnDesc          - Where to store the reference
0137  *              WalkState           - Current state
0138  *
0139  * RETURN:      Status
0140  *
0141  * DESCRIPTION: Obtain and return a "reference" to the target object
0142  *              Common code for the RefOfOp and the CondRefOfOp.
0143  *
0144  ******************************************************************************/
0145 
0146 ACPI_STATUS
0147 AcpiExGetObjectReference (
0148     ACPI_OPERAND_OBJECT     *ObjDesc,
0149     ACPI_OPERAND_OBJECT     **ReturnDesc,
0150     ACPI_WALK_STATE         *WalkState)
0151 {
0152     ACPI_OPERAND_OBJECT     *ReferenceObj;
0153     ACPI_OPERAND_OBJECT     *ReferencedObj;
0154 
0155 
0156     ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
0157 
0158 
0159     *ReturnDesc = NULL;
0160 
0161     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
0162     {
0163     case ACPI_DESC_TYPE_OPERAND:
0164 
0165         if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
0166         {
0167             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
0168         }
0169 
0170         /*
0171          * Must be a reference to a Local or Arg
0172          */
0173         switch (ObjDesc->Reference.Class)
0174         {
0175         case ACPI_REFCLASS_LOCAL:
0176         case ACPI_REFCLASS_ARG:
0177         case ACPI_REFCLASS_DEBUG:
0178 
0179             /* The referenced object is the pseudo-node for the local/arg */
0180 
0181             ReferencedObj = ObjDesc->Reference.Object;
0182             break;
0183 
0184         default:
0185 
0186             ACPI_ERROR ((AE_INFO, "Unknown Reference Class %2.2X",
0187                 ObjDesc->Reference.Class));
0188             return_ACPI_STATUS (AE_AML_INTERNAL);
0189         }
0190         break;
0191 
0192 
0193     case ACPI_DESC_TYPE_NAMED:
0194 
0195         /*
0196          * A named reference that has already been resolved to a Node
0197          */
0198         ReferencedObj = ObjDesc;
0199         break;
0200 
0201 
0202     default:
0203 
0204         ACPI_ERROR ((AE_INFO, "Invalid descriptor type %X",
0205             ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
0206         return_ACPI_STATUS (AE_TYPE);
0207     }
0208 
0209 
0210     /* Create a new reference object */
0211 
0212     ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
0213     if (!ReferenceObj)
0214     {
0215         return_ACPI_STATUS (AE_NO_MEMORY);
0216     }
0217 
0218     ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
0219     ReferenceObj->Reference.Object = ReferencedObj;
0220     *ReturnDesc = ReferenceObj;
0221 
0222     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
0223         "Object %p Type [%s], returning Reference %p\n",
0224         ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
0225 
0226     return_ACPI_STATUS (AE_OK);
0227 }
0228 
0229 
0230 /*******************************************************************************
0231  *
0232  * FUNCTION:    AcpiExConcatTemplate
0233  *
0234  * PARAMETERS:  Operand0            - First source object
0235  *              Operand1            - Second source object
0236  *              ActualReturnDesc    - Where to place the return object
0237  *              WalkState           - Current walk state
0238  *
0239  * RETURN:      Status
0240  *
0241  * DESCRIPTION: Concatenate two resource templates
0242  *
0243  ******************************************************************************/
0244 
0245 ACPI_STATUS
0246 AcpiExConcatTemplate (
0247     ACPI_OPERAND_OBJECT     *Operand0,
0248     ACPI_OPERAND_OBJECT     *Operand1,
0249     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
0250     ACPI_WALK_STATE         *WalkState)
0251 {
0252     ACPI_STATUS             Status;
0253     ACPI_OPERAND_OBJECT     *ReturnDesc;
0254     UINT8                   *NewBuf;
0255     UINT8                   *EndTag;
0256     ACPI_SIZE               Length0;
0257     ACPI_SIZE               Length1;
0258     ACPI_SIZE               NewLength;
0259 
0260 
0261     ACPI_FUNCTION_TRACE (ExConcatTemplate);
0262 
0263 
0264     /*
0265      * Find the EndTag descriptor in each resource template.
0266      * Note1: returned pointers point TO the EndTag, not past it.
0267      * Note2: zero-length buffers are allowed; treated like one EndTag
0268      */
0269 
0270     /* Get the length of the first resource template */
0271 
0272     Status = AcpiUtGetResourceEndTag (Operand0, &EndTag);
0273     if (ACPI_FAILURE (Status))
0274     {
0275         return_ACPI_STATUS (Status);
0276     }
0277 
0278     Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer);
0279 
0280     /* Get the length of the second resource template */
0281 
0282     Status = AcpiUtGetResourceEndTag (Operand1, &EndTag);
0283     if (ACPI_FAILURE (Status))
0284     {
0285         return_ACPI_STATUS (Status);
0286     }
0287 
0288     Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer);
0289 
0290     /* Combine both lengths, minimum size will be 2 for EndTag */
0291 
0292     NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG);
0293 
0294     /* Create a new buffer object for the result (with one EndTag) */
0295 
0296     ReturnDesc = AcpiUtCreateBufferObject (NewLength);
0297     if (!ReturnDesc)
0298     {
0299         return_ACPI_STATUS (AE_NO_MEMORY);
0300     }
0301 
0302     /*
0303      * Copy the templates to the new buffer, 0 first, then 1 follows. One
0304      * EndTag descriptor is copied from Operand1.
0305      */
0306     NewBuf = ReturnDesc->Buffer.Pointer;
0307     ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length0);
0308     ACPI_MEMCPY (NewBuf + Length0, Operand1->Buffer.Pointer, Length1);
0309 
0310     /* Insert EndTag and set the checksum to zero, means "ignore checksum" */
0311 
0312     NewBuf[NewLength - 1] = 0;
0313     NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
0314 
0315     /* Return the completed resource template */
0316 
0317     *ActualReturnDesc = ReturnDesc;
0318     return_ACPI_STATUS (AE_OK);
0319 }
0320 
0321 
0322 /*******************************************************************************
0323  *
0324  * FUNCTION:    AcpiExDoConcatenate
0325  *
0326  * PARAMETERS:  Operand0            - First source object
0327  *              Operand1            - Second source object
0328  *              ActualReturnDesc    - Where to place the return object
0329  *              WalkState           - Current walk state
0330  *
0331  * RETURN:      Status
0332  *
0333  * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
0334  *
0335  ******************************************************************************/
0336 
0337 ACPI_STATUS
0338 AcpiExDoConcatenate (
0339     ACPI_OPERAND_OBJECT     *Operand0,
0340     ACPI_OPERAND_OBJECT     *Operand1,
0341     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
0342     ACPI_WALK_STATE         *WalkState)
0343 {
0344     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
0345     ACPI_OPERAND_OBJECT     *ReturnDesc;
0346     char                    *NewBuf;
0347     ACPI_STATUS             Status;
0348 
0349 
0350     ACPI_FUNCTION_TRACE (ExDoConcatenate);
0351 
0352 
0353     /*
0354      * Convert the second operand if necessary.  The first operand
0355      * determines the type of the second operand, (See the Data Types
0356      * section of the ACPI specification.)  Both object types are
0357      * guaranteed to be either Integer/String/Buffer by the operand
0358      * resolution mechanism.
0359      */
0360     switch (Operand0->Common.Type)
0361     {
0362     case ACPI_TYPE_INTEGER:
0363         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
0364         break;
0365 
0366     case ACPI_TYPE_STRING:
0367         Status = AcpiExConvertToString (Operand1, &LocalOperand1,
0368                     ACPI_IMPLICIT_CONVERT_HEX);
0369         break;
0370 
0371     case ACPI_TYPE_BUFFER:
0372         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
0373         break;
0374 
0375     default:
0376         ACPI_ERROR ((AE_INFO, "Invalid object type: %X",
0377             Operand0->Common.Type));
0378         Status = AE_AML_INTERNAL;
0379     }
0380 
0381     if (ACPI_FAILURE (Status))
0382     {
0383         goto Cleanup;
0384     }
0385 
0386     /*
0387      * Both operands are now known to be the same object type
0388      * (Both are Integer, String, or Buffer), and we can now perform the
0389      * concatenation.
0390      */
0391 
0392     /*
0393      * There are three cases to handle:
0394      *
0395      * 1) Two Integers concatenated to produce a new Buffer
0396      * 2) Two Strings concatenated to produce a new String
0397      * 3) Two Buffers concatenated to produce a new Buffer
0398      */
0399     switch (Operand0->Common.Type)
0400     {
0401     case ACPI_TYPE_INTEGER:
0402 
0403         /* Result of two Integers is a Buffer */
0404         /* Need enough buffer space for two integers */
0405 
0406         ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE)
0407                             ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
0408         if (!ReturnDesc)
0409         {
0410             Status = AE_NO_MEMORY;
0411             goto Cleanup;
0412         }
0413 
0414         NewBuf = (char *) ReturnDesc->Buffer.Pointer;
0415 
0416         /* Copy the first integer, LSB first */
0417 
0418         ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value,
0419                         AcpiGbl_IntegerByteWidth);
0420 
0421         /* Copy the second integer (LSB first) after the first */
0422 
0423         ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth,
0424                         &LocalOperand1->Integer.Value,
0425                         AcpiGbl_IntegerByteWidth);
0426         break;
0427 
0428     case ACPI_TYPE_STRING:
0429 
0430         /* Result of two Strings is a String */
0431 
0432         ReturnDesc = AcpiUtCreateStringObject (
0433                         ((ACPI_SIZE) Operand0->String.Length +
0434                         LocalOperand1->String.Length));
0435         if (!ReturnDesc)
0436         {
0437             Status = AE_NO_MEMORY;
0438             goto Cleanup;
0439         }
0440 
0441         NewBuf = ReturnDesc->String.Pointer;
0442 
0443         /* Concatenate the strings */
0444 
0445         ACPI_STRCPY (NewBuf, Operand0->String.Pointer);
0446         ACPI_STRCPY (NewBuf + Operand0->String.Length,
0447                         LocalOperand1->String.Pointer);
0448         break;
0449 
0450     case ACPI_TYPE_BUFFER:
0451 
0452         /* Result of two Buffers is a Buffer */
0453 
0454         ReturnDesc = AcpiUtCreateBufferObject (
0455                         ((ACPI_SIZE) Operand0->Buffer.Length +
0456                         LocalOperand1->Buffer.Length));
0457         if (!ReturnDesc)
0458         {
0459             Status = AE_NO_MEMORY;
0460             goto Cleanup;
0461         }
0462 
0463         NewBuf = (char *) ReturnDesc->Buffer.Pointer;
0464 
0465         /* Concatenate the buffers */
0466 
0467         ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer,
0468                         Operand0->Buffer.Length);
0469         ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length,
0470                         LocalOperand1->Buffer.Pointer,
0471                         LocalOperand1->Buffer.Length);
0472         break;
0473 
0474     default:
0475 
0476         /* Invalid object type, should not happen here */
0477 
0478         ACPI_ERROR ((AE_INFO, "Invalid object type: %X",
0479             Operand0->Common.Type));
0480         Status =AE_AML_INTERNAL;
0481         goto Cleanup;
0482     }
0483 
0484     *ActualReturnDesc = ReturnDesc;
0485 
0486 Cleanup:
0487     if (LocalOperand1 != Operand1)
0488     {
0489         AcpiUtRemoveReference (LocalOperand1);
0490     }
0491     return_ACPI_STATUS (Status);
0492 }
0493 
0494 
0495 /*******************************************************************************
0496  *
0497  * FUNCTION:    AcpiExDoMathOp
0498  *
0499  * PARAMETERS:  Opcode              - AML opcode
0500  *              Integer0            - Integer operand #0
0501  *              Integer1            - Integer operand #1
0502  *
0503  * RETURN:      Integer result of the operation
0504  *
0505  * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
0506  *              math functions here is to prevent a lot of pointer dereferencing
0507  *              to obtain the operands.
0508  *
0509  ******************************************************************************/
0510 
0511 ACPI_INTEGER
0512 AcpiExDoMathOp (
0513     UINT16                  Opcode,
0514     ACPI_INTEGER            Integer0,
0515     ACPI_INTEGER            Integer1)
0516 {
0517 
0518     ACPI_FUNCTION_ENTRY ();
0519 
0520 
0521     switch (Opcode)
0522     {
0523     case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
0524 
0525         return (Integer0 + Integer1);
0526 
0527 
0528     case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
0529 
0530         return (Integer0 & Integer1);
0531 
0532 
0533     case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
0534 
0535         return (~(Integer0 & Integer1));
0536 
0537 
0538     case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
0539 
0540         return (Integer0 | Integer1);
0541 
0542 
0543     case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
0544 
0545         return (~(Integer0 | Integer1));
0546 
0547 
0548     case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
0549 
0550         return (Integer0 ^ Integer1);
0551 
0552 
0553     case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
0554 
0555         return (Integer0 * Integer1);
0556 
0557 
0558     case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
0559 
0560         /*
0561          * We need to check if the shiftcount is larger than the integer bit
0562          * width since the behavior of this is not well-defined in the C language.
0563          */
0564         if (Integer1 >= AcpiGbl_IntegerBitWidth)
0565         {
0566             return (0);
0567         }
0568         return (Integer0 << Integer1);
0569 
0570 
0571     case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
0572 
0573         /*
0574          * We need to check if the shiftcount is larger than the integer bit
0575          * width since the behavior of this is not well-defined in the C language.
0576          */
0577         if (Integer1 >= AcpiGbl_IntegerBitWidth)
0578         {
0579             return (0);
0580         }
0581         return (Integer0 >> Integer1);
0582 
0583 
0584     case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
0585 
0586         return (Integer0 - Integer1);
0587 
0588     default:
0589 
0590         return (0);
0591     }
0592 }
0593 
0594 
0595 /*******************************************************************************
0596  *
0597  * FUNCTION:    AcpiExDoLogicalNumericOp
0598  *
0599  * PARAMETERS:  Opcode              - AML opcode
0600  *              Integer0            - Integer operand #0
0601  *              Integer1            - Integer operand #1
0602  *              LogicalResult       - TRUE/FALSE result of the operation
0603  *
0604  * RETURN:      Status
0605  *
0606  * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
0607  *              operators (LAnd and LOr), both operands must be integers.
0608  *
0609  *              Note: cleanest machine code seems to be produced by the code
0610  *              below, rather than using statements of the form:
0611  *                  Result = (Integer0 && Integer1);
0612  *
0613  ******************************************************************************/
0614 
0615 ACPI_STATUS
0616 AcpiExDoLogicalNumericOp (
0617     UINT16                  Opcode,
0618     ACPI_INTEGER            Integer0,
0619     ACPI_INTEGER            Integer1,
0620     BOOLEAN                 *LogicalResult)
0621 {
0622     ACPI_STATUS             Status = AE_OK;
0623     BOOLEAN                 LocalResult = FALSE;
0624 
0625 
0626     ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
0627 
0628 
0629     switch (Opcode)
0630     {
0631     case AML_LAND_OP:               /* LAnd (Integer0, Integer1) */
0632 
0633         if (Integer0 && Integer1)
0634         {
0635             LocalResult = TRUE;
0636         }
0637         break;
0638 
0639     case AML_LOR_OP:                /* LOr (Integer0, Integer1) */
0640 
0641         if (Integer0 || Integer1)
0642         {
0643             LocalResult = TRUE;
0644         }
0645         break;
0646 
0647     default:
0648         Status = AE_AML_INTERNAL;
0649         break;
0650     }
0651 
0652     /* Return the logical result and status */
0653 
0654     *LogicalResult = LocalResult;
0655     return_ACPI_STATUS (Status);
0656 }
0657 
0658 
0659 /*******************************************************************************
0660  *
0661  * FUNCTION:    AcpiExDoLogicalOp
0662  *
0663  * PARAMETERS:  Opcode              - AML opcode
0664  *              Operand0            - operand #0
0665  *              Operand1            - operand #1
0666  *              LogicalResult       - TRUE/FALSE result of the operation
0667  *
0668  * RETURN:      Status
0669  *
0670  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
0671  *              functions here is to prevent a lot of pointer dereferencing
0672  *              to obtain the operands and to simplify the generation of the
0673  *              logical value. For the Numeric operators (LAnd and LOr), both
0674  *              operands must be integers. For the other logical operators,
0675  *              operands can be any combination of Integer/String/Buffer. The
0676  *              first operand determines the type to which the second operand
0677  *              will be converted.
0678  *
0679  *              Note: cleanest machine code seems to be produced by the code
0680  *              below, rather than using statements of the form:
0681  *                  Result = (Operand0 == Operand1);
0682  *
0683  ******************************************************************************/
0684 
0685 ACPI_STATUS
0686 AcpiExDoLogicalOp (
0687     UINT16                  Opcode,
0688     ACPI_OPERAND_OBJECT     *Operand0,
0689     ACPI_OPERAND_OBJECT     *Operand1,
0690     BOOLEAN                 *LogicalResult)
0691 {
0692     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
0693     ACPI_INTEGER            Integer0;
0694     ACPI_INTEGER            Integer1;
0695     UINT32                  Length0;
0696     UINT32                  Length1;
0697     ACPI_STATUS             Status = AE_OK;
0698     BOOLEAN                 LocalResult = FALSE;
0699     int                     Compare;
0700 
0701 
0702     ACPI_FUNCTION_TRACE (ExDoLogicalOp);
0703 
0704 
0705     /*
0706      * Convert the second operand if necessary.  The first operand
0707      * determines the type of the second operand, (See the Data Types
0708      * section of the ACPI 3.0+ specification.)  Both object types are
0709      * guaranteed to be either Integer/String/Buffer by the operand
0710      * resolution mechanism.
0711      */
0712     switch (Operand0->Common.Type)
0713     {
0714     case ACPI_TYPE_INTEGER:
0715         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
0716         break;
0717 
0718     case ACPI_TYPE_STRING:
0719         Status = AcpiExConvertToString (Operand1, &LocalOperand1,
0720                     ACPI_IMPLICIT_CONVERT_HEX);
0721         break;
0722 
0723     case ACPI_TYPE_BUFFER:
0724         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
0725         break;
0726 
0727     default:
0728         Status = AE_AML_INTERNAL;
0729         break;
0730     }
0731 
0732     if (ACPI_FAILURE (Status))
0733     {
0734         goto Cleanup;
0735     }
0736 
0737     /*
0738      * Two cases: 1) Both Integers, 2) Both Strings or Buffers
0739      */
0740     if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
0741     {
0742         /*
0743          * 1) Both operands are of type integer
0744          *    Note: LocalOperand1 may have changed above
0745          */
0746         Integer0 = Operand0->Integer.Value;
0747         Integer1 = LocalOperand1->Integer.Value;
0748 
0749         switch (Opcode)
0750         {
0751         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
0752 
0753             if (Integer0 == Integer1)
0754             {
0755                 LocalResult = TRUE;
0756             }
0757             break;
0758 
0759         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
0760 
0761             if (Integer0 > Integer1)
0762             {
0763                 LocalResult = TRUE;
0764             }
0765             break;
0766 
0767         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
0768 
0769             if (Integer0 < Integer1)
0770             {
0771                 LocalResult = TRUE;
0772             }
0773             break;
0774 
0775         default:
0776             Status = AE_AML_INTERNAL;
0777             break;
0778         }
0779     }
0780     else
0781     {
0782         /*
0783          * 2) Both operands are Strings or both are Buffers
0784          *    Note: Code below takes advantage of common Buffer/String
0785          *          object fields. LocalOperand1 may have changed above. Use
0786          *          memcmp to handle nulls in buffers.
0787          */
0788         Length0 = Operand0->Buffer.Length;
0789         Length1 = LocalOperand1->Buffer.Length;
0790 
0791         /* Lexicographic compare: compare the data bytes */
0792 
0793         Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer,
0794                     LocalOperand1->Buffer.Pointer,
0795                     (Length0 > Length1) ? Length1 : Length0);
0796 
0797         switch (Opcode)
0798         {
0799         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
0800 
0801             /* Length and all bytes must be equal */
0802 
0803             if ((Length0 == Length1) &&
0804                 (Compare == 0))
0805             {
0806                 /* Length and all bytes match ==> TRUE */
0807 
0808                 LocalResult = TRUE;
0809             }
0810             break;
0811 
0812         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
0813 
0814             if (Compare > 0)
0815             {
0816                 LocalResult = TRUE;
0817                 goto Cleanup;   /* TRUE */
0818             }
0819             if (Compare < 0)
0820             {
0821                 goto Cleanup;   /* FALSE */
0822             }
0823 
0824             /* Bytes match (to shortest length), compare lengths */
0825 
0826             if (Length0 > Length1)
0827             {
0828                 LocalResult = TRUE;
0829             }
0830             break;
0831 
0832         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
0833 
0834             if (Compare > 0)
0835             {
0836                 goto Cleanup;   /* FALSE */
0837             }
0838             if (Compare < 0)
0839             {
0840                 LocalResult = TRUE;
0841                 goto Cleanup;   /* TRUE */
0842             }
0843 
0844             /* Bytes match (to shortest length), compare lengths */
0845 
0846             if (Length0 < Length1)
0847             {
0848                 LocalResult = TRUE;
0849             }
0850             break;
0851 
0852         default:
0853             Status = AE_AML_INTERNAL;
0854             break;
0855         }
0856     }
0857 
0858 Cleanup:
0859 
0860     /* New object was created if implicit conversion performed - delete */
0861 
0862     if (LocalOperand1 != Operand1)
0863     {
0864         AcpiUtRemoveReference (LocalOperand1);
0865     }
0866 
0867     /* Return the logical result and status */
0868 
0869     *LogicalResult = LocalResult;
0870     return_ACPI_STATUS (Status);
0871 }
0872 
0873