1 /******************************************************************************
   2  *
   3  * Module Name: uteval - Object evaluation
   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 __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->RelativePathname = 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 
 140         ReturnBtype = ACPI_BTYPE_INTEGER;
 141         break;
 142 
 143     case ACPI_TYPE_BUFFER:
 144 
 145         ReturnBtype = ACPI_BTYPE_BUFFER;
 146         break;
 147 
 148     case ACPI_TYPE_STRING:
 149 
 150         ReturnBtype = ACPI_BTYPE_STRING;
 151         break;
 152 
 153     case ACPI_TYPE_PACKAGE:
 154 
 155         ReturnBtype = ACPI_BTYPE_PACKAGE;
 156         break;
 157 
 158     default:
 159 
 160         ReturnBtype = 0;
 161         break;
 162     }
 163 
 164     if ((AcpiGbl_EnableInterpreterSlack) &&
 165         (!ExpectedReturnBtypes))
 166     {
 167         /*
 168          * We received a return object, but one was not expected. This can
 169          * happen frequently if the "implicit return" feature is enabled.
 170          * Just delete the return object and return AE_OK.
 171          */
 172         AcpiUtRemoveReference (Info->ReturnObject);
 173         goto Cleanup;
 174     }
 175 
 176     /* Is the return object one of the expected types? */
 177 
 178     if (!(ExpectedReturnBtypes & ReturnBtype))
 179     {
 180         ACPI_ERROR_METHOD ("Return object type is incorrect",
 181             PrefixNode, Path, AE_TYPE);
 182 
 183         ACPI_ERROR ((AE_INFO,
 184             "Type returned from %s was incorrect: %s, expected Btypes: 0x%X",
 185             Path, AcpiUtGetObjectTypeName (Info->ReturnObject),
 186             ExpectedReturnBtypes));
 187 
 188         /* On error exit, we must delete the return object */
 189 
 190         AcpiUtRemoveReference (Info->ReturnObject);
 191         Status = AE_TYPE;
 192         goto Cleanup;
 193     }
 194 
 195     /* Object type is OK, return it */
 196 
 197     *ReturnDesc = Info->ReturnObject;
 198 
 199 Cleanup:
 200     ACPI_FREE (Info);
 201     return_ACPI_STATUS (Status);
 202 }
 203 
 204 
 205 /*******************************************************************************
 206  *
 207  * FUNCTION:    AcpiUtEvaluateNumericObject
 208  *
 209  * PARAMETERS:  ObjectName          - Object name to be evaluated
 210  *              DeviceNode          - Node for the device
 211  *              Value               - Where the value is returned
 212  *
 213  * RETURN:      Status
 214  *
 215  * DESCRIPTION: Evaluates a numeric namespace object for a selected device
 216  *              and stores result in *Value.
 217  *
 218  *              NOTE: Internal function, no parameter validation
 219  *
 220  ******************************************************************************/
 221 
 222 ACPI_STATUS
 223 AcpiUtEvaluateNumericObject (
 224     char                    *ObjectName,
 225     ACPI_NAMESPACE_NODE     *DeviceNode,
 226     UINT64                  *Value)
 227 {
 228     ACPI_OPERAND_OBJECT     *ObjDesc;
 229     ACPI_STATUS             Status;
 230 
 231 
 232     ACPI_FUNCTION_TRACE (UtEvaluateNumericObject);
 233 
 234 
 235     Status = AcpiUtEvaluateObject (DeviceNode, ObjectName,
 236                 ACPI_BTYPE_INTEGER, &ObjDesc);
 237     if (ACPI_FAILURE (Status))
 238     {
 239         return_ACPI_STATUS (Status);
 240     }
 241 
 242     /* Get the returned Integer */
 243 
 244     *Value = ObjDesc->Integer.Value;
 245 
 246     /* On exit, we must delete the return object */
 247 
 248     AcpiUtRemoveReference (ObjDesc);
 249     return_ACPI_STATUS (Status);
 250 }
 251 
 252 
 253 /*******************************************************************************
 254  *
 255  * FUNCTION:    AcpiUtExecute_STA
 256  *
 257  * PARAMETERS:  DeviceNode          - Node for the device
 258  *              Flags               - Where the status flags are returned
 259  *
 260  * RETURN:      Status
 261  *
 262  * DESCRIPTION: Executes _STA for selected device and stores results in
 263  *              *Flags. If _STA does not exist, then the device is assumed
 264  *              to be present/functional/enabled (as per the ACPI spec).
 265  *
 266  *              NOTE: Internal function, no parameter validation
 267  *
 268  ******************************************************************************/
 269 
 270 ACPI_STATUS
 271 AcpiUtExecute_STA (
 272     ACPI_NAMESPACE_NODE     *DeviceNode,
 273     UINT32                  *Flags)
 274 {
 275     ACPI_OPERAND_OBJECT     *ObjDesc;
 276     ACPI_STATUS             Status;
 277 
 278 
 279     ACPI_FUNCTION_TRACE (UtExecute_STA);
 280 
 281 
 282     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__STA,
 283                 ACPI_BTYPE_INTEGER, &ObjDesc);
 284     if (ACPI_FAILURE (Status))
 285     {
 286         if (AE_NOT_FOUND == Status)
 287         {
 288             /*
 289              * if _STA does not exist, then (as per the ACPI specification),
 290              * the returned flags will indicate that the device is present,
 291              * functional, and enabled.
 292              */
 293             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 294                 "_STA on %4.4s was not found, assuming device is present\n",
 295                 AcpiUtGetNodeName (DeviceNode)));
 296 
 297             *Flags = ACPI_UINT32_MAX;
 298             Status = AE_OK;
 299         }
 300 
 301         return_ACPI_STATUS (Status);
 302     }
 303 
 304     /* Extract the status flags */
 305 
 306     *Flags = (UINT32) ObjDesc->Integer.Value;
 307 
 308     /* On exit, we must delete the return object */
 309 
 310     AcpiUtRemoveReference (ObjDesc);
 311     return_ACPI_STATUS (Status);
 312 }
 313 
 314 
 315 /*******************************************************************************
 316  *
 317  * FUNCTION:    AcpiUtExecutePowerMethods
 318  *
 319  * PARAMETERS:  DeviceNode          - Node for the device
 320  *              MethodNames         - Array of power method names
 321  *              MethodCount         - Number of methods to execute
 322  *              OutValues           - Where the power method values are returned
 323  *
 324  * RETURN:      Status, OutValues
 325  *
 326  * DESCRIPTION: Executes the specified power methods for the device and returns
 327  *              the result(s).
 328  *
 329  *              NOTE: Internal function, no parameter validation
 330  *
 331  ******************************************************************************/
 332 
 333 ACPI_STATUS
 334 AcpiUtExecutePowerMethods (
 335     ACPI_NAMESPACE_NODE     *DeviceNode,
 336     const char              **MethodNames,
 337     UINT8                   MethodCount,
 338     UINT8                   *OutValues)
 339 {
 340     ACPI_OPERAND_OBJECT     *ObjDesc;
 341     ACPI_STATUS             Status;
 342     ACPI_STATUS             FinalStatus = AE_NOT_FOUND;
 343     UINT32                  i;
 344 
 345 
 346     ACPI_FUNCTION_TRACE (UtExecutePowerMethods);
 347 
 348 
 349     for (i = 0; i < MethodCount; i++)
 350     {
 351         /*
 352          * Execute the power method (_SxD or _SxW). The only allowable
 353          * return type is an Integer.
 354          */
 355         Status = AcpiUtEvaluateObject (DeviceNode,
 356                     ACPI_CAST_PTR (char, MethodNames[i]),
 357                     ACPI_BTYPE_INTEGER, &ObjDesc);
 358         if (ACPI_SUCCESS (Status))
 359         {
 360             OutValues[i] = (UINT8) ObjDesc->Integer.Value;
 361 
 362             /* Delete the return object */
 363 
 364             AcpiUtRemoveReference (ObjDesc);
 365             FinalStatus = AE_OK;            /* At least one value is valid */
 366             continue;
 367         }
 368 
 369         OutValues[i] = ACPI_UINT8_MAX;
 370         if (Status == AE_NOT_FOUND)
 371         {
 372             continue; /* Ignore if not found */
 373         }
 374 
 375         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Failed %s on Device %4.4s, %s\n",
 376             ACPI_CAST_PTR (char, MethodNames[i]),
 377             AcpiUtGetNodeName (DeviceNode), AcpiFormatException (Status)));
 378     }
 379 
 380     return_ACPI_STATUS (FinalStatus);
 381 }