1 /******************************************************************************
   2  *
   3  * Module Name: nsprepkg - Validation of package objects for predefined names
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2013, 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 #include "acpi.h"
  45 #include "accommon.h"
  46 #include "acnamesp.h"
  47 #include "acpredef.h"
  48 
  49 
  50 #define _COMPONENT          ACPI_NAMESPACE
  51         ACPI_MODULE_NAME    ("nsprepkg")
  52 
  53 
  54 /* Local prototypes */
  55 
  56 static ACPI_STATUS
  57 AcpiNsCheckPackageList (
  58     ACPI_EVALUATE_INFO          *Info,
  59     const ACPI_PREDEFINED_INFO  *Package,
  60     ACPI_OPERAND_OBJECT         **Elements,
  61     UINT32                      Count);
  62 
  63 static ACPI_STATUS
  64 AcpiNsCheckPackageElements (
  65     ACPI_EVALUATE_INFO          *Info,
  66     ACPI_OPERAND_OBJECT         **Elements,
  67     UINT8                       Type1,
  68     UINT32                      Count1,
  69     UINT8                       Type2,
  70     UINT32                      Count2,
  71     UINT32                      StartIndex);
  72 
  73 
  74 /*******************************************************************************
  75  *
  76  * FUNCTION:    AcpiNsCheckPackage
  77  *
  78  * PARAMETERS:  Info                - Method execution information block
  79  *              ReturnObjectPtr     - Pointer to the object returned from the
  80  *                                    evaluation of a method or object
  81  *
  82  * RETURN:      Status
  83  *
  84  * DESCRIPTION: Check a returned package object for the correct count and
  85  *              correct type of all sub-objects.
  86  *
  87  ******************************************************************************/
  88 
  89 ACPI_STATUS
  90 AcpiNsCheckPackage (
  91     ACPI_EVALUATE_INFO          *Info,
  92     ACPI_OPERAND_OBJECT         **ReturnObjectPtr)
  93 {
  94     ACPI_OPERAND_OBJECT         *ReturnObject = *ReturnObjectPtr;
  95     const ACPI_PREDEFINED_INFO  *Package;
  96     ACPI_OPERAND_OBJECT         **Elements;
  97     ACPI_STATUS                 Status = AE_OK;
  98     UINT32                      ExpectedCount;
  99     UINT32                      Count;
 100     UINT32                      i;
 101 
 102 
 103     ACPI_FUNCTION_NAME (NsCheckPackage);
 104 
 105 
 106     /* The package info for this name is in the next table entry */
 107 
 108     Package = Info->Predefined + 1;
 109 
 110     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
 111         "%s Validating return Package of Type %X, Count %X\n",
 112         Info->FullPathname, Package->RetInfo.Type,
 113         ReturnObject->Package.Count));
 114 
 115     /*
 116      * For variable-length Packages, we can safely remove all embedded
 117      * and trailing NULL package elements
 118      */
 119     AcpiNsRemoveNullElements (Info, Package->RetInfo.Type, ReturnObject);
 120 
 121     /* Extract package count and elements array */
 122 
 123     Elements = ReturnObject->Package.Elements;
 124     Count = ReturnObject->Package.Count;
 125 
 126     /*
 127      * Most packages must have at least one element. The only exception
 128      * is the variable-length package (ACPI_PTYPE1_VAR).
 129      */
 130     if (!Count)
 131     {
 132         if (Package->RetInfo.Type == ACPI_PTYPE1_VAR)
 133         {
 134             return (AE_OK);
 135         }
 136 
 137         ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 138             "Return Package has no elements (empty)"));
 139 
 140         return (AE_AML_OPERAND_VALUE);
 141     }
 142 
 143     /*
 144      * Decode the type of the expected package contents
 145      *
 146      * PTYPE1 packages contain no subpackages
 147      * PTYPE2 packages contain sub-packages
 148      */
 149     switch (Package->RetInfo.Type)
 150     {
 151     case ACPI_PTYPE1_FIXED:
 152         /*
 153          * The package count is fixed and there are no sub-packages
 154          *
 155          * If package is too small, exit.
 156          * If package is larger than expected, issue warning but continue
 157          */
 158         ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
 159         if (Count < ExpectedCount)
 160         {
 161             goto PackageTooSmall;
 162         }
 163         else if (Count > ExpectedCount)
 164         {
 165             ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
 166                 "%s: Return Package is larger than needed - "
 167                 "found %u, expected %u\n",
 168                 Info->FullPathname, Count, ExpectedCount));
 169         }
 170 
 171         /* Validate all elements of the returned package */
 172 
 173         Status = AcpiNsCheckPackageElements (Info, Elements,
 174                     Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
 175                     Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0);
 176         break;
 177 
 178     case ACPI_PTYPE1_VAR:
 179         /*
 180          * The package count is variable, there are no sub-packages, and all
 181          * elements must be of the same type
 182          */
 183         for (i = 0; i < Count; i++)
 184         {
 185             Status = AcpiNsCheckObjectType (Info, Elements,
 186                         Package->RetInfo.ObjectType1, i);
 187             if (ACPI_FAILURE (Status))
 188             {
 189                 return (Status);
 190             }
 191             Elements++;
 192         }
 193         break;
 194 
 195     case ACPI_PTYPE1_OPTION:
 196         /*
 197          * The package count is variable, there are no sub-packages. There are
 198          * a fixed number of required elements, and a variable number of
 199          * optional elements.
 200          *
 201          * Check if package is at least as large as the minimum required
 202          */
 203         ExpectedCount = Package->RetInfo3.Count;
 204         if (Count < ExpectedCount)
 205         {
 206             goto PackageTooSmall;
 207         }
 208 
 209         /* Variable number of sub-objects */
 210 
 211         for (i = 0; i < Count; i++)
 212         {
 213             if (i < Package->RetInfo3.Count)
 214             {
 215                 /* These are the required package elements (0, 1, or 2) */
 216 
 217                 Status = AcpiNsCheckObjectType (Info, Elements,
 218                             Package->RetInfo3.ObjectType[i], i);
 219                 if (ACPI_FAILURE (Status))
 220                 {
 221                     return (Status);
 222                 }
 223             }
 224             else
 225             {
 226                 /* These are the optional package elements */
 227 
 228                 Status = AcpiNsCheckObjectType (Info, Elements,
 229                             Package->RetInfo3.TailObjectType, i);
 230                 if (ACPI_FAILURE (Status))
 231                 {
 232                     return (Status);
 233                 }
 234             }
 235             Elements++;
 236         }
 237         break;
 238 
 239     case ACPI_PTYPE2_REV_FIXED:
 240 
 241         /* First element is the (Integer) revision */
 242 
 243         Status = AcpiNsCheckObjectType (Info, Elements,
 244                     ACPI_RTYPE_INTEGER, 0);
 245         if (ACPI_FAILURE (Status))
 246         {
 247             return (Status);
 248         }
 249 
 250         Elements++;
 251         Count--;
 252 
 253         /* Examine the sub-packages */
 254 
 255         Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
 256         break;
 257 
 258     case ACPI_PTYPE2_PKG_COUNT:
 259 
 260         /* First element is the (Integer) count of sub-packages to follow */
 261 
 262         Status = AcpiNsCheckObjectType (Info, Elements,
 263                     ACPI_RTYPE_INTEGER, 0);
 264         if (ACPI_FAILURE (Status))
 265         {
 266             return (Status);
 267         }
 268 
 269         /*
 270          * Count cannot be larger than the parent package length, but allow it
 271          * to be smaller. The >= accounts for the Integer above.
 272          */
 273         ExpectedCount = (UINT32) (*Elements)->Integer.Value;
 274         if (ExpectedCount >= Count)
 275         {
 276             goto PackageTooSmall;
 277         }
 278 
 279         Count = ExpectedCount;
 280         Elements++;
 281 
 282         /* Examine the sub-packages */
 283 
 284         Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
 285         break;
 286 
 287     case ACPI_PTYPE2:
 288     case ACPI_PTYPE2_FIXED:
 289     case ACPI_PTYPE2_MIN:
 290     case ACPI_PTYPE2_COUNT:
 291     case ACPI_PTYPE2_FIX_VAR:
 292         /*
 293          * These types all return a single Package that consists of a
 294          * variable number of sub-Packages.
 295          *
 296          * First, ensure that the first element is a sub-Package. If not,
 297          * the BIOS may have incorrectly returned the object as a single
 298          * package instead of a Package of Packages (a common error if
 299          * there is only one entry). We may be able to repair this by
 300          * wrapping the returned Package with a new outer Package.
 301          */
 302         if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE))
 303         {
 304             /* Create the new outer package and populate it */
 305 
 306             Status = AcpiNsWrapWithPackage (Info, ReturnObject, ReturnObjectPtr);
 307             if (ACPI_FAILURE (Status))
 308             {
 309                 return (Status);
 310             }
 311 
 312             /* Update locals to point to the new package (of 1 element) */
 313 
 314             ReturnObject = *ReturnObjectPtr;
 315             Elements = ReturnObject->Package.Elements;
 316             Count = 1;
 317         }
 318 
 319         /* Examine the sub-packages */
 320 
 321         Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
 322         break;
 323 
 324     default:
 325 
 326         /* Should not get here if predefined info table is correct */
 327 
 328         ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 329             "Invalid internal return type in table entry: %X",
 330             Package->RetInfo.Type));
 331 
 332         return (AE_AML_INTERNAL);
 333     }
 334 
 335     return (Status);
 336 
 337 
 338 PackageTooSmall:
 339 
 340     /* Error exit for the case with an incorrect package count */
 341 
 342     ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 343         "Return Package is too small - found %u elements, expected %u",
 344         Count, ExpectedCount));
 345 
 346     return (AE_AML_OPERAND_VALUE);
 347 }
 348 
 349 
 350 /*******************************************************************************
 351  *
 352  * FUNCTION:    AcpiNsCheckPackageList
 353  *
 354  * PARAMETERS:  Info            - Method execution information block
 355  *              Package         - Pointer to package-specific info for method
 356  *              Elements        - Element list of parent package. All elements
 357  *                                of this list should be of type Package.
 358  *              Count           - Count of subpackages
 359  *
 360  * RETURN:      Status
 361  *
 362  * DESCRIPTION: Examine a list of subpackages
 363  *
 364  ******************************************************************************/
 365 
 366 static ACPI_STATUS
 367 AcpiNsCheckPackageList (
 368     ACPI_EVALUATE_INFO          *Info,
 369     const ACPI_PREDEFINED_INFO  *Package,
 370     ACPI_OPERAND_OBJECT         **Elements,
 371     UINT32                      Count)
 372 {
 373     ACPI_OPERAND_OBJECT         *SubPackage;
 374     ACPI_OPERAND_OBJECT         **SubElements;
 375     ACPI_STATUS                 Status;
 376     UINT32                      ExpectedCount;
 377     UINT32                      i;
 378     UINT32                      j;
 379 
 380 
 381     /*
 382      * Validate each sub-Package in the parent Package
 383      *
 384      * NOTE: assumes list of sub-packages contains no NULL elements.
 385      * Any NULL elements should have been removed by earlier call
 386      * to AcpiNsRemoveNullElements.
 387      */
 388     for (i = 0; i < Count; i++)
 389     {
 390         SubPackage = *Elements;
 391         SubElements = SubPackage->Package.Elements;
 392         Info->ParentPackage = SubPackage;
 393 
 394         /* Each sub-object must be of type Package */
 395 
 396         Status = AcpiNsCheckObjectType (Info, &SubPackage,
 397                     ACPI_RTYPE_PACKAGE, i);
 398         if (ACPI_FAILURE (Status))
 399         {
 400             return (Status);
 401         }
 402 
 403         /* Examine the different types of expected sub-packages */
 404 
 405         Info->ParentPackage = SubPackage;
 406         switch (Package->RetInfo.Type)
 407         {
 408         case ACPI_PTYPE2:
 409         case ACPI_PTYPE2_PKG_COUNT:
 410         case ACPI_PTYPE2_REV_FIXED:
 411 
 412             /* Each subpackage has a fixed number of elements */
 413 
 414             ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
 415             if (SubPackage->Package.Count < ExpectedCount)
 416             {
 417                 goto PackageTooSmall;
 418             }
 419 
 420             Status = AcpiNsCheckPackageElements (Info, SubElements,
 421                         Package->RetInfo.ObjectType1,
 422                         Package->RetInfo.Count1,
 423                         Package->RetInfo.ObjectType2,
 424                         Package->RetInfo.Count2, 0);
 425             if (ACPI_FAILURE (Status))
 426             {
 427                 return (Status);
 428             }
 429             break;
 430 
 431         case ACPI_PTYPE2_FIX_VAR:
 432             /*
 433              * Each subpackage has a fixed number of elements and an
 434              * optional element
 435              */
 436             ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
 437             if (SubPackage->Package.Count < ExpectedCount)
 438             {
 439                 goto PackageTooSmall;
 440             }
 441 
 442             Status = AcpiNsCheckPackageElements (Info, SubElements,
 443                         Package->RetInfo.ObjectType1,
 444                         Package->RetInfo.Count1,
 445                         Package->RetInfo.ObjectType2,
 446                         SubPackage->Package.Count - Package->RetInfo.Count1, 0);
 447             if (ACPI_FAILURE (Status))
 448             {
 449                 return (Status);
 450             }
 451             break;
 452 
 453         case ACPI_PTYPE2_FIXED:
 454 
 455             /* Each sub-package has a fixed length */
 456 
 457             ExpectedCount = Package->RetInfo2.Count;
 458             if (SubPackage->Package.Count < ExpectedCount)
 459             {
 460                 goto PackageTooSmall;
 461             }
 462 
 463             /* Check the type of each sub-package element */
 464 
 465             for (j = 0; j < ExpectedCount; j++)
 466             {
 467                 Status = AcpiNsCheckObjectType (Info, &SubElements[j],
 468                             Package->RetInfo2.ObjectType[j], j);
 469                 if (ACPI_FAILURE (Status))
 470                 {
 471                     return (Status);
 472                 }
 473             }
 474             break;
 475 
 476         case ACPI_PTYPE2_MIN:
 477 
 478             /* Each sub-package has a variable but minimum length */
 479 
 480             ExpectedCount = Package->RetInfo.Count1;
 481             if (SubPackage->Package.Count < ExpectedCount)
 482             {
 483                 goto PackageTooSmall;
 484             }
 485 
 486             /* Check the type of each sub-package element */
 487 
 488             Status = AcpiNsCheckPackageElements (Info, SubElements,
 489                         Package->RetInfo.ObjectType1,
 490                         SubPackage->Package.Count, 0, 0, 0);
 491             if (ACPI_FAILURE (Status))
 492             {
 493                 return (Status);
 494             }
 495             break;
 496 
 497         case ACPI_PTYPE2_COUNT:
 498             /*
 499              * First element is the (Integer) count of elements, including
 500              * the count field (the ACPI name is NumElements)
 501              */
 502             Status = AcpiNsCheckObjectType (Info, SubElements,
 503                         ACPI_RTYPE_INTEGER, 0);
 504             if (ACPI_FAILURE (Status))
 505             {
 506                 return (Status);
 507             }
 508 
 509             /*
 510              * Make sure package is large enough for the Count and is
 511              * is as large as the minimum size
 512              */
 513             ExpectedCount = (UINT32) (*SubElements)->Integer.Value;
 514             if (SubPackage->Package.Count < ExpectedCount)
 515             {
 516                 goto PackageTooSmall;
 517             }
 518             if (SubPackage->Package.Count < Package->RetInfo.Count1)
 519             {
 520                 ExpectedCount = Package->RetInfo.Count1;
 521                 goto PackageTooSmall;
 522             }
 523             if (ExpectedCount == 0)
 524             {
 525                 /*
 526                  * Either the NumEntries element was originally zero or it was
 527                  * a NULL element and repaired to an Integer of value zero.
 528                  * In either case, repair it by setting NumEntries to be the
 529                  * actual size of the subpackage.
 530                  */
 531                 ExpectedCount = SubPackage->Package.Count;
 532                 (*SubElements)->Integer.Value = ExpectedCount;
 533             }
 534 
 535             /* Check the type of each sub-package element */
 536 
 537             Status = AcpiNsCheckPackageElements (Info, (SubElements + 1),
 538                         Package->RetInfo.ObjectType1,
 539                         (ExpectedCount - 1), 0, 0, 1);
 540             if (ACPI_FAILURE (Status))
 541             {
 542                 return (Status);
 543             }
 544             break;
 545 
 546         default: /* Should not get here, type was validated by caller */
 547 
 548             return (AE_AML_INTERNAL);
 549         }
 550 
 551         Elements++;
 552     }
 553 
 554     return (AE_OK);
 555 
 556 
 557 PackageTooSmall:
 558 
 559     /* The sub-package count was smaller than required */
 560 
 561     ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 562         "Return Sub-Package[%u] is too small - found %u elements, expected %u",
 563         i, SubPackage->Package.Count, ExpectedCount));
 564 
 565     return (AE_AML_OPERAND_VALUE);
 566 }
 567 
 568 
 569 /*******************************************************************************
 570  *
 571  * FUNCTION:    AcpiNsCheckPackageElements
 572  *
 573  * PARAMETERS:  Info            - Method execution information block
 574  *              Elements        - Pointer to the package elements array
 575  *              Type1           - Object type for first group
 576  *              Count1          - Count for first group
 577  *              Type2           - Object type for second group
 578  *              Count2          - Count for second group
 579  *              StartIndex      - Start of the first group of elements
 580  *
 581  * RETURN:      Status
 582  *
 583  * DESCRIPTION: Check that all elements of a package are of the correct object
 584  *              type. Supports up to two groups of different object types.
 585  *
 586  ******************************************************************************/
 587 
 588 static ACPI_STATUS
 589 AcpiNsCheckPackageElements (
 590     ACPI_EVALUATE_INFO          *Info,
 591     ACPI_OPERAND_OBJECT         **Elements,
 592     UINT8                       Type1,
 593     UINT32                      Count1,
 594     UINT8                       Type2,
 595     UINT32                      Count2,
 596     UINT32                      StartIndex)
 597 {
 598     ACPI_OPERAND_OBJECT         **ThisElement = Elements;
 599     ACPI_STATUS                 Status;
 600     UINT32                      i;
 601 
 602 
 603     /*
 604      * Up to two groups of package elements are supported by the data
 605      * structure. All elements in each group must be of the same type.
 606      * The second group can have a count of zero.
 607      */
 608     for (i = 0; i < Count1; i++)
 609     {
 610         Status = AcpiNsCheckObjectType (Info, ThisElement,
 611                     Type1, i + StartIndex);
 612         if (ACPI_FAILURE (Status))
 613         {
 614             return (Status);
 615         }
 616         ThisElement++;
 617     }
 618 
 619     for (i = 0; i < Count2; i++)
 620     {
 621         Status = AcpiNsCheckObjectType (Info, ThisElement,
 622                     Type2, (i + Count1 + StartIndex));
 623         if (ACPI_FAILURE (Status))
 624         {
 625             return (Status);
 626         }
 627         ThisElement++;
 628     }
 629 
 630     return (AE_OK);
 631 }