1 /******************************************************************************
   2  *
   3  * Module Name: uteval - Object evaluation
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2011, 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 __UTEVAL_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acnamesp.h"
  49 
  50 
  51 #define _COMPONENT          ACPI_UTILITIES
  52         ACPI_MODULE_NAME    ("uteval")
  53 
  54 
  55 /*******************************************************************************
  56  *
  57  * FUNCTION:    AcpiUtEvaluateObject
  58  *
  59  * PARAMETERS:  PrefixNode          - Starting node
  60  *              Path                - Path to object from starting node
  61  *              ExpectedReturnTypes - Bitmap of allowed return types
  62  *              ReturnDesc          - Where a return value is stored
  63  *
  64  * RETURN:      Status
  65  *
  66  * DESCRIPTION: Evaluates a namespace object and verifies the type of the
  67  *              return object. Common code that simplifies accessing objects
  68  *              that have required return objects of fixed types.
  69  *
  70  *              NOTE: Internal function, no parameter validation
  71  *
  72  ******************************************************************************/
  73 
  74 ACPI_STATUS
  75 AcpiUtEvaluateObject (
  76     ACPI_NAMESPACE_NODE     *PrefixNode,
  77     char                    *Path,
  78     UINT32                  ExpectedReturnBtypes,
  79     ACPI_OPERAND_OBJECT     **ReturnDesc)
  80 {
  81     ACPI_EVALUATE_INFO      *Info;
  82     ACPI_STATUS             Status;
  83     UINT32                  ReturnBtype;
  84 
  85 
  86     ACPI_FUNCTION_TRACE (UtEvaluateObject);
  87 
  88 
  89     /* Allocate the evaluation information block */
  90 
  91     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
  92     if (!Info)
  93     {
  94         return_ACPI_STATUS (AE_NO_MEMORY);
  95     }
  96 
  97     Info->PrefixNode = PrefixNode;
  98     Info->Pathname = Path;
  99 
 100     /* Evaluate the object/method */
 101 
 102     Status = AcpiNsEvaluate (Info);
 103     if (ACPI_FAILURE (Status))
 104     {
 105         if (Status == AE_NOT_FOUND)
 106         {
 107             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n",
 108                 AcpiUtGetNodeName (PrefixNode), Path));
 109         }
 110         else
 111         {
 112             ACPI_ERROR_METHOD ("Method execution failed",
 113                 PrefixNode, Path, Status);
 114         }
 115 
 116         goto Cleanup;
 117     }
 118 
 119     /* Did we get a return object? */
 120 
 121     if (!Info->ReturnObject)
 122     {
 123         if (ExpectedReturnBtypes)
 124         {
 125             ACPI_ERROR_METHOD ("No object was returned from",
 126                 PrefixNode, Path, AE_NOT_EXIST);
 127 
 128             Status = AE_NOT_EXIST;
 129         }
 130 
 131         goto Cleanup;
 132     }
 133 
 134     /* Map the return object type to the bitmapped type */
 135 
 136     switch ((Info->ReturnObject)->Common.Type)
 137     {
 138     case ACPI_TYPE_INTEGER:
 139         ReturnBtype = ACPI_BTYPE_INTEGER;
 140         break;
 141 
 142     case ACPI_TYPE_BUFFER:
 143         ReturnBtype = ACPI_BTYPE_BUFFER;
 144         break;
 145 
 146     case ACPI_TYPE_STRING:
 147         ReturnBtype = ACPI_BTYPE_STRING;
 148         break;
 149 
 150     case ACPI_TYPE_PACKAGE:
 151         ReturnBtype = ACPI_BTYPE_PACKAGE;
 152         break;
 153 
 154     default:
 155         ReturnBtype = 0;
 156         break;
 157     }
 158 
 159     if ((AcpiGbl_EnableInterpreterSlack) &&
 160         (!ExpectedReturnBtypes))
 161     {
 162         /*
 163          * We received a return object, but one was not expected. This can
 164          * happen frequently if the "implicit return" feature is enabled.
 165          * Just delete the return object and return AE_OK.
 166          */
 167         AcpiUtRemoveReference (Info->ReturnObject);
 168         goto Cleanup;
 169     }
 170 
 171     /* Is the return object one of the expected types? */
 172 
 173     if (!(ExpectedReturnBtypes & ReturnBtype))
 174     {
 175         ACPI_ERROR_METHOD ("Return object type is incorrect",
 176             PrefixNode, Path, AE_TYPE);
 177 
 178         ACPI_ERROR ((AE_INFO,
 179             "Type returned from %s was incorrect: %s, expected Btypes: 0x%X",
 180             Path, AcpiUtGetObjectTypeName (Info->ReturnObject),
 181             ExpectedReturnBtypes));
 182 
 183         /* On error exit, we must delete the return object */
 184 
 185         AcpiUtRemoveReference (Info->ReturnObject);
 186         Status = AE_TYPE;
 187         goto Cleanup;
 188     }
 189 
 190     /* Object type is OK, return it */
 191 
 192     *ReturnDesc = Info->ReturnObject;
 193 
 194 Cleanup:
 195     ACPI_FREE (Info);
 196     return_ACPI_STATUS (Status);
 197 }
 198 
 199 
 200 /*******************************************************************************
 201  *
 202  * FUNCTION:    AcpiUtEvaluateNumericObject
 203  *
 204  * PARAMETERS:  ObjectName          - Object name to be evaluated
 205  *              DeviceNode          - Node for the device
 206  *              Value               - Where the value is returned
 207  *
 208  * RETURN:      Status
 209  *
 210  * DESCRIPTION: Evaluates a numeric namespace object for a selected device
 211  *              and stores result in *Value.
 212  *
 213  *              NOTE: Internal function, no parameter validation
 214  *
 215  ******************************************************************************/
 216 
 217 ACPI_STATUS
 218 AcpiUtEvaluateNumericObject (
 219     char                    *ObjectName,
 220     ACPI_NAMESPACE_NODE     *DeviceNode,
 221     UINT64                  *Value)
 222 {
 223     ACPI_OPERAND_OBJECT     *ObjDesc;
 224     ACPI_STATUS             Status;
 225 
 226 
 227     ACPI_FUNCTION_TRACE (UtEvaluateNumericObject);
 228 
 229 
 230     Status = AcpiUtEvaluateObject (DeviceNode, ObjectName,
 231                 ACPI_BTYPE_INTEGER, &ObjDesc);
 232     if (ACPI_FAILURE (Status))
 233     {
 234         return_ACPI_STATUS (Status);
 235     }
 236 
 237     /* Get the returned Integer */
 238 
 239     *Value = ObjDesc->Integer.Value;
 240 
 241     /* On exit, we must delete the return object */
 242 
 243     AcpiUtRemoveReference (ObjDesc);
 244     return_ACPI_STATUS (Status);
 245 }
 246 
 247 
 248 /*******************************************************************************
 249  *
 250  * FUNCTION:    AcpiUtExecute_STA
 251  *
 252  * PARAMETERS:  DeviceNode          - Node for the device
 253  *              Flags               - Where the status flags are returned
 254  *
 255  * RETURN:      Status
 256  *
 257  * DESCRIPTION: Executes _STA for selected device and stores results in
 258  *              *Flags.
 259  *
 260  *              NOTE: Internal function, no parameter validation
 261  *
 262  ******************************************************************************/
 263 
 264 ACPI_STATUS
 265 AcpiUtExecute_STA (
 266     ACPI_NAMESPACE_NODE     *DeviceNode,
 267     UINT32                  *Flags)
 268 {
 269     ACPI_OPERAND_OBJECT     *ObjDesc;
 270     ACPI_STATUS             Status;
 271 
 272 
 273     ACPI_FUNCTION_TRACE (UtExecute_STA);
 274 
 275 
 276     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__STA,
 277                 ACPI_BTYPE_INTEGER, &ObjDesc);
 278     if (ACPI_FAILURE (Status))
 279     {
 280         if (AE_NOT_FOUND == Status)
 281         {
 282             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 283                 "_STA on %4.4s was not found, assuming device is present\n",
 284                 AcpiUtGetNodeName (DeviceNode)));
 285 
 286             *Flags = ACPI_UINT32_MAX;
 287             Status = AE_OK;
 288         }
 289 
 290         return_ACPI_STATUS (Status);
 291     }
 292 
 293     /* Extract the status flags */
 294 
 295     *Flags = (UINT32) ObjDesc->Integer.Value;
 296 
 297     /* On exit, we must delete the return object */
 298 
 299     AcpiUtRemoveReference (ObjDesc);
 300     return_ACPI_STATUS (Status);
 301 }
 302 
 303 
 304 /*******************************************************************************
 305  *
 306  * FUNCTION:    AcpiUtExecutePowerMethods
 307  *
 308  * PARAMETERS:  DeviceNode          - Node for the device
 309  *              MethodNames         - Array of power method names
 310  *              MethodCount         - Number of methods to execute
 311  *              OutValues           - Where the power method values are returned
 312  *
 313  * RETURN:      Status, OutValues
 314  *
 315  * DESCRIPTION: Executes the specified power methods for the device and returns
 316  *              the result(s).
 317  *
 318  *              NOTE: Internal function, no parameter validation
 319  *
 320  ******************************************************************************/
 321 
 322 ACPI_STATUS
 323 AcpiUtExecutePowerMethods (
 324     ACPI_NAMESPACE_NODE     *DeviceNode,
 325     const char              **MethodNames,
 326     UINT8                   MethodCount,
 327     UINT8                   *OutValues)
 328 {
 329     ACPI_OPERAND_OBJECT     *ObjDesc;
 330     ACPI_STATUS             Status;
 331     ACPI_STATUS             FinalStatus = AE_NOT_FOUND;
 332     UINT32                  i;
 333 
 334 
 335     ACPI_FUNCTION_TRACE (UtExecutePowerMethods);
 336 
 337 
 338     for (i = 0; i < MethodCount; i++)
 339     {
 340         /*
 341          * Execute the power method (_SxD or _SxW). The only allowable
 342          * return type is an Integer.
 343          */
 344         Status = AcpiUtEvaluateObject (DeviceNode,
 345                     ACPI_CAST_PTR (char, MethodNames[i]),
 346                     ACPI_BTYPE_INTEGER, &ObjDesc);
 347         if (ACPI_SUCCESS (Status))
 348         {
 349             OutValues[i] = (UINT8) ObjDesc->Integer.Value;
 350 
 351             /* Delete the return object */
 352 
 353             AcpiUtRemoveReference (ObjDesc);
 354             FinalStatus = AE_OK;            /* At least one value is valid */
 355             continue;
 356         }
 357 
 358         OutValues[i] = ACPI_UINT8_MAX;
 359         if (Status == AE_NOT_FOUND)
 360         {
 361             continue; /* Ignore if not found */
 362         }
 363 
 364         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Failed %s on Device %4.4s, %s\n",
 365             ACPI_CAST_PTR (char, MethodNames[i]),
 366             AcpiUtGetNodeName (DeviceNode), AcpiFormatException (Status)));
 367     }
 368 
 369     return_ACPI_STATUS (FinalStatus);
 370 }