1 /******************************************************************************
   2  *
   3  * Module Name: nspredef - Validation of ACPI predefined methods and objects
   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 ACPI_CREATE_PREDEFINED_TABLE
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acnamesp.h"
  49 #include "acpredef.h"
  50 
  51 
  52 #define _COMPONENT          ACPI_NAMESPACE
  53         ACPI_MODULE_NAME    ("nspredef")
  54 
  55 
  56 /*******************************************************************************
  57  *
  58  * This module validates predefined ACPI objects that appear in the namespace,
  59  * at the time they are evaluated (via AcpiEvaluateObject). The purpose of this
  60  * validation is to detect problems with BIOS-exposed predefined ACPI objects
  61  * before the results are returned to the ACPI-related drivers.
  62  *
  63  * There are several areas that are validated:
  64  *
  65  *  1) The number of input arguments as defined by the method/object in the
  66  *     ASL is validated against the ACPI specification.
  67  *  2) The type of the return object (if any) is validated against the ACPI
  68  *     specification.
  69  *  3) For returned package objects, the count of package elements is
  70  *     validated, as well as the type of each package element. Nested
  71  *     packages are supported.
  72  *
  73  * For any problems found, a warning message is issued.
  74  *
  75  ******************************************************************************/
  76 
  77 
  78 /* Local prototypes */
  79 
  80 static ACPI_STATUS
  81 AcpiNsCheckReference (
  82     ACPI_EVALUATE_INFO          *Info,
  83     ACPI_OPERAND_OBJECT         *ReturnObject);
  84 
  85 static UINT32
  86 AcpiNsGetBitmappedType (
  87     ACPI_OPERAND_OBJECT         *ReturnObject);
  88 
  89 
  90 /*******************************************************************************
  91  *
  92  * FUNCTION:    AcpiNsCheckReturnValue
  93  *
  94  * PARAMETERS:  Node            - Namespace node for the method/object
  95  *              Info            - Method execution information block
  96  *              UserParamCount  - Number of parameters actually passed
  97  *              ReturnStatus    - Status from the object evaluation
  98  *              ReturnObjectPtr - Pointer to the object returned from the
  99  *                                evaluation of a method or object
 100  *
 101  * RETURN:      Status
 102  *
 103  * DESCRIPTION: Check the value returned from a predefined name.
 104  *
 105  ******************************************************************************/
 106 
 107 ACPI_STATUS
 108 AcpiNsCheckReturnValue (
 109     ACPI_NAMESPACE_NODE         *Node,
 110     ACPI_EVALUATE_INFO          *Info,
 111     UINT32                      UserParamCount,
 112     ACPI_STATUS                 ReturnStatus,
 113     ACPI_OPERAND_OBJECT         **ReturnObjectPtr)
 114 {
 115     ACPI_STATUS                 Status;
 116     const ACPI_PREDEFINED_INFO  *Predefined;
 117 
 118 
 119     /* If not a predefined name, we cannot validate the return object */
 120 
 121     Predefined = Info->Predefined;
 122     if (!Predefined)
 123     {
 124         return (AE_OK);
 125     }
 126 
 127     /*
 128      * If the method failed or did not actually return an object, we cannot
 129      * validate the return object
 130      */
 131     if ((ReturnStatus != AE_OK) &&
 132         (ReturnStatus != AE_CTRL_RETURN_VALUE))
 133     {
 134         return (AE_OK);
 135     }
 136 
 137     /*
 138      * Return value validation and possible repair.
 139      *
 140      * 1) Don't perform return value validation/repair if this feature
 141      * has been disabled via a global option.
 142      *
 143      * 2) We have a return value, but if one wasn't expected, just exit,
 144      * this is not a problem. For example, if the "Implicit Return"
 145      * feature is enabled, methods will always return a value.
 146      *
 147      * 3) If the return value can be of any type, then we cannot perform
 148      * any validation, just exit.
 149      */
 150     if (AcpiGbl_DisableAutoRepair ||
 151         (!Predefined->Info.ExpectedBtypes) ||
 152         (Predefined->Info.ExpectedBtypes == ACPI_RTYPE_ALL))
 153     {
 154         return (AE_OK);
 155     }
 156 
 157     /*
 158      * Check that the type of the main return object is what is expected
 159      * for this predefined name
 160      */
 161     Status = AcpiNsCheckObjectType (Info, ReturnObjectPtr,
 162         Predefined->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT);
 163     if (ACPI_FAILURE (Status))
 164     {
 165         goto Exit;
 166     }
 167 
 168     /*
 169      *
 170      * 4) If there is no return value and it is optional, just return
 171      * AE_OK (_WAK).
 172      */
 173     if (!(*ReturnObjectPtr))
 174     {
 175         goto Exit;
 176     }
 177 
 178     /*
 179      * For returned Package objects, check the type of all sub-objects.
 180      * Note: Package may have been newly created by call above.
 181      */
 182     if ((*ReturnObjectPtr)->Common.Type == ACPI_TYPE_PACKAGE)
 183     {
 184         Info->ParentPackage = *ReturnObjectPtr;
 185         Status = AcpiNsCheckPackage (Info, ReturnObjectPtr);
 186         if (ACPI_FAILURE (Status))
 187         {
 188             /* We might be able to fix some errors */
 189 
 190             if ((Status != AE_AML_OPERAND_TYPE) &&
 191                 (Status != AE_AML_OPERAND_VALUE))
 192             {
 193                 goto Exit;
 194             }
 195         }
 196     }
 197 
 198     /*
 199      * The return object was OK, or it was successfully repaired above.
 200      * Now make some additional checks such as verifying that package
 201      * objects are sorted correctly (if required) or buffer objects have
 202      * the correct data width (bytes vs. dwords). These repairs are
 203      * performed on a per-name basis, i.e., the code is specific to
 204      * particular predefined names.
 205      */
 206     Status = AcpiNsComplexRepairs (Info, Node, Status, ReturnObjectPtr);
 207 
 208 Exit:
 209     /*
 210      * If the object validation failed or if we successfully repaired one
 211      * or more objects, mark the parent node to suppress further warning
 212      * messages during the next evaluation of the same method/object.
 213      */
 214     if (ACPI_FAILURE (Status) ||
 215        (Info->ReturnFlags & ACPI_OBJECT_REPAIRED))
 216     {
 217         Node->Flags |= ANOBJ_EVALUATED;
 218     }
 219 
 220     return (Status);
 221 }
 222 
 223 
 224 /*******************************************************************************
 225  *
 226  * FUNCTION:    AcpiNsCheckObjectType
 227  *
 228  * PARAMETERS:  Info            - Method execution information block
 229  *              ReturnObjectPtr - Pointer to the object returned from the
 230  *                                evaluation of a method or object
 231  *              ExpectedBtypes  - Bitmap of expected return type(s)
 232  *              PackageIndex    - Index of object within parent package (if
 233  *                                applicable - ACPI_NOT_PACKAGE_ELEMENT
 234  *                                otherwise)
 235  *
 236  * RETURN:      Status
 237  *
 238  * DESCRIPTION: Check the type of the return object against the expected object
 239  *              type(s). Use of Btype allows multiple expected object types.
 240  *
 241  ******************************************************************************/
 242 
 243 ACPI_STATUS
 244 AcpiNsCheckObjectType (
 245     ACPI_EVALUATE_INFO          *Info,
 246     ACPI_OPERAND_OBJECT         **ReturnObjectPtr,
 247     UINT32                      ExpectedBtypes,
 248     UINT32                      PackageIndex)
 249 {
 250     ACPI_OPERAND_OBJECT         *ReturnObject = *ReturnObjectPtr;
 251     ACPI_STATUS                 Status = AE_OK;
 252     char                        TypeBuffer[48]; /* Room for 5 types */
 253 
 254 
 255     /* A Namespace node should not get here, but make sure */
 256 
 257     if (ReturnObject &&
 258         ACPI_GET_DESCRIPTOR_TYPE (ReturnObject) == ACPI_DESC_TYPE_NAMED)
 259     {
 260         ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 261             "Invalid return type - Found a Namespace node [%4.4s] type %s",
 262             ReturnObject->Node.Name.Ascii,
 263             AcpiUtGetTypeName (ReturnObject->Node.Type)));
 264         return (AE_AML_OPERAND_TYPE);
 265     }
 266 
 267     /*
 268      * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type.
 269      * The bitmapped type allows multiple possible return types.
 270      *
 271      * Note, the cases below must handle all of the possible types returned
 272      * from all of the predefined names (including elements of returned
 273      * packages)
 274      */
 275     Info->ReturnBtype = AcpiNsGetBitmappedType (ReturnObject);
 276     if (Info->ReturnBtype == ACPI_RTYPE_ANY)
 277     {
 278         /* Not one of the supported objects, must be incorrect */
 279         goto TypeErrorExit;
 280     }
 281 
 282     /* For reference objects, check that the reference type is correct */
 283 
 284     if ((Info->ReturnBtype & ExpectedBtypes) == ACPI_RTYPE_REFERENCE)
 285     {
 286         Status = AcpiNsCheckReference (Info, ReturnObject);
 287         return (Status);
 288     }
 289 
 290     /* Attempt simple repair of the returned object if necessary */
 291 
 292     Status = AcpiNsSimpleRepair (Info, ExpectedBtypes,
 293         PackageIndex, ReturnObjectPtr);
 294     if (ACPI_SUCCESS (Status))
 295     {
 296         return (AE_OK); /* Successful repair */
 297     }
 298 
 299 
 300 TypeErrorExit:
 301 
 302     /* Create a string with all expected types for this predefined object */
 303 
 304     AcpiUtGetExpectedReturnTypes (TypeBuffer, ExpectedBtypes);
 305 
 306     if (!ReturnObject)
 307     {
 308         ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 309             "Expected return object of type %s",
 310             TypeBuffer));
 311     }
 312     else if (PackageIndex == ACPI_NOT_PACKAGE_ELEMENT)
 313     {
 314         ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 315             "Return type mismatch - found %s, expected %s",
 316             AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer));
 317     }
 318     else
 319     {
 320         ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 321             "Return Package type mismatch at index %u - "
 322             "found %s, expected %s", PackageIndex,
 323             AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer));
 324     }
 325 
 326     return (AE_AML_OPERAND_TYPE);
 327 }
 328 
 329 
 330 /*******************************************************************************
 331  *
 332  * FUNCTION:    AcpiNsCheckReference
 333  *
 334  * PARAMETERS:  Info            - Method execution information block
 335  *              ReturnObject    - Object returned from the evaluation of a
 336  *                                method or object
 337  *
 338  * RETURN:      Status
 339  *
 340  * DESCRIPTION: Check a returned reference object for the correct reference
 341  *              type. The only reference type that can be returned from a
 342  *              predefined method is a named reference. All others are invalid.
 343  *
 344  ******************************************************************************/
 345 
 346 static ACPI_STATUS
 347 AcpiNsCheckReference (
 348     ACPI_EVALUATE_INFO          *Info,
 349     ACPI_OPERAND_OBJECT         *ReturnObject)
 350 {
 351 
 352     /*
 353      * Check the reference object for the correct reference type (opcode).
 354      * The only type of reference that can be converted to an ACPI_OBJECT is
 355      * a reference to a named object (reference class: NAME)
 356      */
 357     if (ReturnObject->Reference.Class == ACPI_REFCLASS_NAME)
 358     {
 359         return (AE_OK);
 360     }
 361 
 362     ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 363         "Return type mismatch - unexpected reference object type [%s] %2.2X",
 364         AcpiUtGetReferenceName (ReturnObject),
 365         ReturnObject->Reference.Class));
 366 
 367     return (AE_AML_OPERAND_TYPE);
 368 }
 369 
 370 
 371 /*******************************************************************************
 372  *
 373  * FUNCTION:    AcpiNsGetBitmappedType
 374  *
 375  * PARAMETERS:  ReturnObject    - Object returned from method/obj evaluation
 376  *
 377  * RETURN:      Object return type. ACPI_RTYPE_ANY indicates that the object
 378  *              type is not supported. ACPI_RTYPE_NONE indicates that no
 379  *              object was returned (ReturnObject is NULL).
 380  *
 381  * DESCRIPTION: Convert object type into a bitmapped object return type.
 382  *
 383  ******************************************************************************/
 384 
 385 static UINT32
 386 AcpiNsGetBitmappedType (
 387     ACPI_OPERAND_OBJECT         *ReturnObject)
 388 {
 389     UINT32                      ReturnBtype;
 390 
 391 
 392     if (!ReturnObject)
 393     {
 394         return (ACPI_RTYPE_NONE);
 395     }
 396 
 397     /* Map ACPI_OBJECT_TYPE to internal bitmapped type */
 398 
 399     switch (ReturnObject->Common.Type)
 400     {
 401     case ACPI_TYPE_INTEGER:
 402 
 403         ReturnBtype = ACPI_RTYPE_INTEGER;
 404         break;
 405 
 406     case ACPI_TYPE_BUFFER:
 407 
 408         ReturnBtype = ACPI_RTYPE_BUFFER;
 409         break;
 410 
 411     case ACPI_TYPE_STRING:
 412 
 413         ReturnBtype = ACPI_RTYPE_STRING;
 414         break;
 415 
 416     case ACPI_TYPE_PACKAGE:
 417 
 418         ReturnBtype = ACPI_RTYPE_PACKAGE;
 419         break;
 420 
 421     case ACPI_TYPE_LOCAL_REFERENCE:
 422 
 423         ReturnBtype = ACPI_RTYPE_REFERENCE;
 424         break;
 425 
 426     default:
 427 
 428         /* Not one of the supported objects, must be incorrect */
 429 
 430         ReturnBtype = ACPI_RTYPE_ANY;
 431         break;
 432     }
 433 
 434     return (ReturnBtype);
 435 }