1 /******************************************************************************
   2  *
   3  * Module Name: exoparg6 - AML execution - opcodes with 6 arguments
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 #define __EXOPARG6_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acinterp.h"
  49 #include "acparser.h"
  50 #include "amlcode.h"
  51 
  52 
  53 #define _COMPONENT          ACPI_EXECUTER
  54         ACPI_MODULE_NAME    ("exoparg6")
  55 
  56 
  57 /*!
  58  * Naming convention for AML interpreter execution routines.
  59  *
  60  * The routines that begin execution of AML opcodes are named with a common
  61  * convention based upon the number of arguments, the number of target operands,
  62  * and whether or not a value is returned:
  63  *
  64  *      AcpiExOpcode_xA_yT_zR
  65  *
  66  * Where:
  67  *
  68  * xA - ARGUMENTS:    The number of arguments (input operands) that are
  69  *                    required for this opcode type (1 through 6 args).
  70  * yT - TARGETS:      The number of targets (output operands) that are required
  71  *                    for this opcode type (0, 1, or 2 targets).
  72  * zR - RETURN VALUE: Indicates whether this opcode type returns a value
  73  *                    as the function return (0 or 1).
  74  *
  75  * The AcpiExOpcode* functions are called via the Dispatcher component with
  76  * fully resolved operands.
  77 !*/
  78 
  79 /* Local prototypes */
  80 
  81 static BOOLEAN
  82 AcpiExDoMatch (
  83     UINT32                  MatchOp,
  84     ACPI_OPERAND_OBJECT     *PackageObj,
  85     ACPI_OPERAND_OBJECT     *MatchObj);
  86 
  87 
  88 /*******************************************************************************
  89  *
  90  * FUNCTION:    AcpiExDoMatch
  91  *
  92  * PARAMETERS:  MatchOp         - The AML match operand
  93  *              PackageObj      - Object from the target package
  94  *              MatchObj        - Object to be matched
  95  *
  96  * RETURN:      TRUE if the match is successful, FALSE otherwise
  97  *
  98  * DESCRIPTION: Implements the low-level match for the ASL Match operator.
  99  *              Package elements will be implicitly converted to the type of
 100  *              the match object (Integer/Buffer/String).
 101  *
 102  ******************************************************************************/
 103 
 104 static BOOLEAN
 105 AcpiExDoMatch (
 106     UINT32                  MatchOp,
 107     ACPI_OPERAND_OBJECT     *PackageObj,
 108     ACPI_OPERAND_OBJECT     *MatchObj)
 109 {
 110     BOOLEAN                 LogicalResult = TRUE;
 111     ACPI_STATUS             Status;
 112 
 113 
 114     /*
 115      * Note: Since the PackageObj/MatchObj ordering is opposite to that of
 116      * the standard logical operators, we have to reverse them when we call
 117      * DoLogicalOp in order to make the implicit conversion rules work
 118      * correctly. However, this means we have to flip the entire equation
 119      * also. A bit ugly perhaps, but overall, better than fussing the
 120      * parameters around at runtime, over and over again.
 121      *
 122      * Below, P[i] refers to the package element, M refers to the Match object.
 123      */
 124     switch (MatchOp)
 125     {
 126     case MATCH_MTR:
 127 
 128         /* Always true */
 129 
 130         break;
 131 
 132     case MATCH_MEQ:
 133         /*
 134          * True if equal: (P[i] == M)
 135          * Change to:     (M == P[i])
 136          */
 137         Status = AcpiExDoLogicalOp (AML_LEQUAL_OP, MatchObj, PackageObj,
 138                     &LogicalResult);
 139         if (ACPI_FAILURE (Status))
 140         {
 141             return (FALSE);
 142         }
 143         break;
 144 
 145     case MATCH_MLE:
 146         /*
 147          * True if less than or equal: (P[i] <= M) (P[i] NotGreater than M)
 148          * Change to:                  (M >= P[i]) (M NotLess than P[i])
 149          */
 150         Status = AcpiExDoLogicalOp (AML_LLESS_OP, MatchObj, PackageObj,
 151                     &LogicalResult);
 152         if (ACPI_FAILURE (Status))
 153         {
 154             return (FALSE);
 155         }
 156         LogicalResult = (BOOLEAN) !LogicalResult;
 157         break;
 158 
 159     case MATCH_MLT:
 160         /*
 161          * True if less than: (P[i] < M)
 162          * Change to:         (M > P[i])
 163          */
 164         Status = AcpiExDoLogicalOp (AML_LGREATER_OP, MatchObj, PackageObj,
 165                     &LogicalResult);
 166         if (ACPI_FAILURE (Status))
 167         {
 168             return (FALSE);
 169         }
 170         break;
 171 
 172     case MATCH_MGE:
 173         /*
 174          * True if greater than or equal: (P[i] >= M) (P[i] NotLess than M)
 175          * Change to:                     (M <= P[i]) (M NotGreater than P[i])
 176          */
 177         Status = AcpiExDoLogicalOp (AML_LGREATER_OP, MatchObj, PackageObj,
 178                     &LogicalResult);
 179         if (ACPI_FAILURE (Status))
 180         {
 181             return (FALSE);
 182         }
 183         LogicalResult = (BOOLEAN)!LogicalResult;
 184         break;
 185 
 186     case MATCH_MGT:
 187         /*
 188          * True if greater than: (P[i] > M)
 189          * Change to:            (M < P[i])
 190          */
 191         Status = AcpiExDoLogicalOp (AML_LLESS_OP, MatchObj, PackageObj,
 192                     &LogicalResult);
 193         if (ACPI_FAILURE (Status))
 194         {
 195             return (FALSE);
 196         }
 197         break;
 198 
 199     default:
 200 
 201         /* Undefined */
 202 
 203         return (FALSE);
 204     }
 205 
 206     return (LogicalResult);
 207 }
 208 
 209 
 210 /*******************************************************************************
 211  *
 212  * FUNCTION:    AcpiExOpcode_6A_0T_1R
 213  *
 214  * PARAMETERS:  WalkState           - Current walk state
 215  *
 216  * RETURN:      Status
 217  *
 218  * DESCRIPTION: Execute opcode with 6 arguments, no target, and a return value
 219  *
 220  ******************************************************************************/
 221 
 222 ACPI_STATUS
 223 AcpiExOpcode_6A_0T_1R (
 224     ACPI_WALK_STATE         *WalkState)
 225 {
 226     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
 227     ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
 228     ACPI_STATUS             Status = AE_OK;
 229     UINT64                  Index;
 230     ACPI_OPERAND_OBJECT     *ThisElement;
 231 
 232 
 233     ACPI_FUNCTION_TRACE_STR (ExOpcode_6A_0T_1R,
 234         AcpiPsGetOpcodeName (WalkState->Opcode));
 235 
 236 
 237     switch (WalkState->Opcode)
 238     {
 239     case AML_MATCH_OP:
 240         /*
 241          * Match (SearchPkg[0], MatchOp1[1], MatchObj1[2],
 242          *                      MatchOp2[3], MatchObj2[4], StartIndex[5])
 243          */
 244 
 245         /* Validate both Match Term Operators (MTR, MEQ, etc.) */
 246 
 247         if ((Operand[1]->Integer.Value > MAX_MATCH_OPERATOR) ||
 248             (Operand[3]->Integer.Value > MAX_MATCH_OPERATOR))
 249         {
 250             ACPI_ERROR ((AE_INFO, "Match operator out of range"));
 251             Status = AE_AML_OPERAND_VALUE;
 252             goto Cleanup;
 253         }
 254 
 255         /* Get the package StartIndex, validate against the package length */
 256 
 257         Index = Operand[5]->Integer.Value;
 258         if (Index >= Operand[0]->Package.Count)
 259         {
 260             ACPI_ERROR ((AE_INFO,
 261                 "Index (0x%8.8X%8.8X) beyond package end (0x%X)",
 262                 ACPI_FORMAT_UINT64 (Index), Operand[0]->Package.Count));
 263             Status = AE_AML_PACKAGE_LIMIT;
 264             goto Cleanup;
 265         }
 266 
 267         /* Create an integer for the return value */
 268         /* Default return value is ACPI_UINT64_MAX if no match found */
 269 
 270         ReturnDesc = AcpiUtCreateIntegerObject (ACPI_UINT64_MAX);
 271         if (!ReturnDesc)
 272         {
 273             Status = AE_NO_MEMORY;
 274             goto Cleanup;
 275 
 276         }
 277 
 278         /*
 279          * Examine each element until a match is found. Both match conditions
 280          * must be satisfied for a match to occur. Within the loop,
 281          * "continue" signifies that the current element does not match
 282          * and the next should be examined.
 283          *
 284          * Upon finding a match, the loop will terminate via "break" at
 285          * the bottom. If it terminates "normally", MatchValue will be
 286          * ACPI_UINT64_MAX (Ones) (its initial value) indicating that no
 287          * match was found.
 288          */
 289         for ( ; Index < Operand[0]->Package.Count; Index++)
 290         {
 291             /* Get the current package element */
 292 
 293             ThisElement = Operand[0]->Package.Elements[Index];
 294 
 295             /* Treat any uninitialized (NULL) elements as non-matching */
 296 
 297             if (!ThisElement)
 298             {
 299                 continue;
 300             }
 301 
 302             /*
 303              * Both match conditions must be satisfied. Execution of a continue
 304              * (proceed to next iteration of enclosing for loop) signifies a
 305              * non-match.
 306              */
 307             if (!AcpiExDoMatch ((UINT32) Operand[1]->Integer.Value,
 308                                 ThisElement, Operand[2]))
 309             {
 310                 continue;
 311             }
 312 
 313             if (!AcpiExDoMatch ((UINT32) Operand[3]->Integer.Value,
 314                                 ThisElement, Operand[4]))
 315             {
 316                 continue;
 317             }
 318 
 319             /* Match found: Index is the return value */
 320 
 321             ReturnDesc->Integer.Value = Index;
 322             break;
 323         }
 324         break;
 325 
 326     case AML_LOAD_TABLE_OP:
 327 
 328         Status = AcpiExLoadTableOp (WalkState, &ReturnDesc);
 329         break;
 330 
 331     default:
 332 
 333         ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
 334             WalkState->Opcode));
 335         Status = AE_AML_BAD_OPCODE;
 336         goto Cleanup;
 337     }
 338 
 339 
 340 Cleanup:
 341 
 342     /* Delete return object on error */
 343 
 344     if (ACPI_FAILURE (Status))
 345     {
 346         AcpiUtRemoveReference (ReturnDesc);
 347     }
 348 
 349     /* Save return object on success */
 350 
 351     else
 352     {
 353         WalkState->ResultObj = ReturnDesc;
 354     }
 355 
 356     return_ACPI_STATUS (Status);
 357 }