1 /******************************************************************************
   2  *
   3  * Module Name: aslprepkg - support for ACPI predefined name package 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 #include "aslcompiler.h"
  45 #include "aslcompiler.y.h"
  46 #include "acpredef.h"
  47 
  48 
  49 #define _COMPONENT          ACPI_COMPILER
  50         ACPI_MODULE_NAME    ("aslprepkg")
  51 
  52 
  53 /* Local prototypes */
  54 
  55 static void
  56 ApCheckPackageElements (
  57     const char                  *PredefinedName,
  58     ACPI_PARSE_OBJECT           *Op,
  59     UINT8                       Type1,
  60     UINT32                      Count1,
  61     UINT8                       Type2,
  62     UINT32                      Count2);
  63 
  64 static void
  65 ApCheckPackageList (
  66     const char                  *PredefinedName,
  67     ACPI_PARSE_OBJECT           *ParentOp,
  68     const ACPI_PREDEFINED_INFO  *Package,
  69     UINT32                      StartIndex,
  70     UINT32                      Count);
  71 
  72 static void
  73 ApPackageTooSmall (
  74     const char                  *PredefinedName,
  75     ACPI_PARSE_OBJECT           *Op,
  76     UINT32                      Count,
  77     UINT32                      ExpectedCount);
  78 
  79 static void
  80 ApZeroLengthPackage (
  81     const char                  *PredefinedName,
  82     ACPI_PARSE_OBJECT           *Op);
  83 
  84 static void
  85 ApPackageTooLarge (
  86     const char                  *PredefinedName,
  87     ACPI_PARSE_OBJECT           *Op,
  88     UINT32                      Count,
  89     UINT32                      ExpectedCount);
  90 
  91 
  92 /*******************************************************************************
  93  *
  94  * FUNCTION:    ApCheckPackage
  95  *
  96  * PARAMETERS:  ParentOp            - Parser op for the package
  97  *              Predefined          - Pointer to package-specific info for
  98  *                                    the method
  99  *
 100  * RETURN:      None
 101  *
 102  * DESCRIPTION: Top-level validation for predefined name return package
 103  *              objects.
 104  *
 105  ******************************************************************************/
 106 
 107 void
 108 ApCheckPackage (
 109     ACPI_PARSE_OBJECT           *ParentOp,
 110     const ACPI_PREDEFINED_INFO  *Predefined)
 111 {
 112     ACPI_PARSE_OBJECT           *Op;
 113     const ACPI_PREDEFINED_INFO  *Package;
 114     ACPI_STATUS                 Status;
 115     UINT32                      ExpectedCount;
 116     UINT32                      Count;
 117     UINT32                      i;
 118 
 119 
 120     /* The package info for this name is in the next table entry */
 121 
 122     Package = Predefined + 1;
 123 
 124     /* First child is the package length */
 125 
 126     Op = ParentOp->Asl.Child;
 127     Count = (UINT32) Op->Asl.Value.Integer;
 128 
 129     /*
 130      * Many of the variable-length top-level packages are allowed to simply
 131      * have zero elements. This allows the BIOS to tell the host that even
 132      * though the predefined name/method exists, the feature is not supported.
 133      * Other package types require one or more elements. In any case, there
 134      * is no need to continue validation.
 135      */
 136     if (!Count)
 137     {
 138         switch (Package->RetInfo.Type)
 139         {
 140         case ACPI_PTYPE1_FIXED:
 141         case ACPI_PTYPE1_OPTION:
 142         case ACPI_PTYPE2_PKG_COUNT:
 143         case ACPI_PTYPE2_REV_FIXED:
 144 
 145             ApZeroLengthPackage (Predefined->Info.Name, ParentOp);
 146             break;
 147 
 148         case ACPI_PTYPE1_VAR:
 149         case ACPI_PTYPE2:
 150         case ACPI_PTYPE2_COUNT:
 151         case ACPI_PTYPE2_FIXED:
 152         case ACPI_PTYPE2_MIN:
 153         case ACPI_PTYPE2_FIX_VAR:
 154         default:
 155 
 156             break;
 157         }
 158 
 159         return;
 160     }
 161 
 162     /* Get the first element of the package */
 163 
 164     Op = Op->Asl.Next;
 165 
 166     /* Decode the package type */
 167 
 168     switch (Package->RetInfo.Type)
 169     {
 170     case ACPI_PTYPE1_FIXED:
 171         /*
 172          * The package count is fixed and there are no sub-packages
 173          *
 174          * If package is too small, exit.
 175          * If package is larger than expected, issue warning but continue
 176          */
 177         ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
 178         if (Count < ExpectedCount)
 179         {
 180             goto PackageTooSmall;
 181         }
 182         else if (Count > ExpectedCount)
 183         {
 184             ApPackageTooLarge (Predefined->Info.Name, ParentOp,
 185                 Count, ExpectedCount);
 186         }
 187 
 188         /* Validate all elements of the package */
 189 
 190         ApCheckPackageElements (Predefined->Info.Name, Op,
 191             Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
 192             Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
 193         break;
 194 
 195     case ACPI_PTYPE1_VAR:
 196         /*
 197          * The package count is variable, there are no sub-packages,
 198          * and all elements must be of the same type
 199          */
 200         for (i = 0; i < Count; i++)
 201         {
 202             ApCheckObjectType (Predefined->Info.Name, Op,
 203                 Package->RetInfo.ObjectType1, i);
 204             Op = Op->Asl.Next;
 205         }
 206         break;
 207 
 208     case ACPI_PTYPE1_OPTION:
 209         /*
 210          * The package count is variable, there are no sub-packages.
 211          * There are a fixed number of required elements, and a variable
 212          * number of optional elements.
 213          *
 214          * Check if package is at least as large as the minimum required
 215          */
 216         ExpectedCount = Package->RetInfo3.Count;
 217         if (Count < ExpectedCount)
 218         {
 219             goto PackageTooSmall;
 220         }
 221 
 222         /* Variable number of sub-objects */
 223 
 224         for (i = 0; i < Count; i++)
 225         {
 226             if (i < Package->RetInfo3.Count)
 227             {
 228                 /* These are the required package elements (0, 1, or 2) */
 229 
 230                 ApCheckObjectType (Predefined->Info.Name, Op,
 231                     Package->RetInfo3.ObjectType[i], i);
 232             }
 233             else
 234             {
 235                 /* These are the optional package elements */
 236 
 237                 ApCheckObjectType (Predefined->Info.Name, Op,
 238                     Package->RetInfo3.TailObjectType, i);
 239             }
 240             Op = Op->Asl.Next;
 241         }
 242         break;
 243 
 244     case ACPI_PTYPE2_REV_FIXED:
 245 
 246         /* First element is the (Integer) revision */
 247 
 248         ApCheckObjectType (Predefined->Info.Name, Op,
 249             ACPI_RTYPE_INTEGER, 0);
 250 
 251         Op = Op->Asl.Next;
 252         Count--;
 253 
 254         /* Examine the sub-packages */
 255 
 256         ApCheckPackageList (Predefined->Info.Name, Op,
 257             Package, 1, Count);
 258         break;
 259 
 260     case ACPI_PTYPE2_PKG_COUNT:
 261 
 262         /* First element is the (Integer) count of sub-packages to follow */
 263 
 264         Status = ApCheckObjectType (Predefined->Info.Name, Op,
 265             ACPI_RTYPE_INTEGER, 0);
 266 
 267         /* We must have an integer count from above (otherwise, use Count) */
 268 
 269         if (ACPI_SUCCESS (Status))
 270         {
 271             /*
 272              * Count cannot be larger than the parent package length, but
 273              * allow it to be smaller. The >= accounts for the Integer above.
 274              */
 275             ExpectedCount = (UINT32) Op->Asl.Value.Integer;
 276             if (ExpectedCount >= Count)
 277             {
 278                 goto PackageTooSmall;
 279             }
 280 
 281             Count = ExpectedCount;
 282         }
 283 
 284         Op = Op->Asl.Next;
 285 
 286         /* Examine the sub-packages */
 287 
 288         ApCheckPackageList (Predefined->Info.Name, Op,
 289             Package, 1, Count);
 290         break;
 291 
 292     case ACPI_PTYPE2:
 293     case ACPI_PTYPE2_FIXED:
 294     case ACPI_PTYPE2_MIN:
 295     case ACPI_PTYPE2_COUNT:
 296     case ACPI_PTYPE2_FIX_VAR:
 297         /*
 298          * These types all return a single Package that consists of a
 299          * variable number of sub-Packages.
 300          */
 301 
 302         /* Examine the sub-packages */
 303 
 304         ApCheckPackageList (Predefined->Info.Name, Op,
 305             Package, 0, Count);
 306         break;
 307 
 308     default:
 309         return;
 310     }
 311 
 312     return;
 313 
 314 PackageTooSmall:
 315     ApPackageTooSmall (Predefined->Info.Name, ParentOp,
 316         Count, ExpectedCount);
 317 }
 318 
 319 
 320 /*******************************************************************************
 321  *
 322  * FUNCTION:    ApCheckPackageElements
 323  *
 324  * PARAMETERS:  PredefinedName      - Name of the predefined object
 325  *              Op                  - Parser op for the package
 326  *              Type1               - Object type for first group
 327  *              Count1              - Count for first group
 328  *              Type2               - Object type for second group
 329  *              Count2              - Count for second group
 330  *
 331  * RETURN:      None
 332  *
 333  * DESCRIPTION: Validate all elements of a package. Works with packages that
 334  *              are defined to contain up to two groups of different object
 335  *              types.
 336  *
 337  ******************************************************************************/
 338 
 339 static void
 340 ApCheckPackageElements (
 341     const char              *PredefinedName,
 342     ACPI_PARSE_OBJECT       *Op,
 343     UINT8                   Type1,
 344     UINT32                  Count1,
 345     UINT8                   Type2,
 346     UINT32                  Count2)
 347 {
 348     UINT32                  i;
 349 
 350 
 351     /*
 352      * Up to two groups of package elements are supported by the data
 353      * structure. All elements in each group must be of the same type.
 354      * The second group can have a count of zero.
 355      *
 356      * Aborts check upon a NULL package element, as this means (at compile
 357      * time) that the remainder of the package elements are also NULL
 358      * (This is the only way to create NULL package elements.)
 359      */
 360     for (i = 0; (i < Count1) && Op; i++)
 361     {
 362         ApCheckObjectType (PredefinedName, Op, Type1, i);
 363         Op = Op->Asl.Next;
 364     }
 365 
 366     for (i = 0; (i < Count2) && Op; i++)
 367     {
 368         ApCheckObjectType (PredefinedName, Op, Type2, (i + Count1));
 369         Op = Op->Asl.Next;
 370     }
 371 }
 372 
 373 
 374 /*******************************************************************************
 375  *
 376  * FUNCTION:    ApCheckPackageList
 377  *
 378  * PARAMETERS:  PredefinedName      - Name of the predefined object
 379  *              ParentOp            - Parser op of the parent package
 380  *              Package             - Package info for this predefined name
 381  *              StartIndex          - Index in parent package where list begins
 382  *              ParentCount         - Element count of parent package
 383  *
 384  * RETURN:      None
 385  *
 386  * DESCRIPTION: Validate the individual package elements for a predefined name.
 387  *              Handles the cases where the predefined name is defined as a
 388  *              Package of Packages (subpackages). These are the types:
 389  *
 390  *              ACPI_PTYPE2
 391  *              ACPI_PTYPE2_FIXED
 392  *              ACPI_PTYPE2_MIN
 393  *              ACPI_PTYPE2_COUNT
 394  *              ACPI_PTYPE2_FIX_VAR
 395  *
 396  ******************************************************************************/
 397 
 398 static void
 399 ApCheckPackageList (
 400     const char                  *PredefinedName,
 401     ACPI_PARSE_OBJECT           *ParentOp,
 402     const ACPI_PREDEFINED_INFO  *Package,
 403     UINT32                      StartIndex,
 404     UINT32                      ParentCount)
 405 {
 406     ACPI_PARSE_OBJECT           *SubPackageOp = ParentOp;
 407     ACPI_PARSE_OBJECT           *Op;
 408     ACPI_STATUS                 Status;
 409     UINT32                      Count;
 410     UINT32                      ExpectedCount;
 411     UINT32                      i;
 412     UINT32                      j;
 413 
 414 
 415     /*
 416      * Validate each subpackage in the parent Package
 417      *
 418      * Note: We ignore NULL package elements on the assumption that
 419      * they will be initialized by the BIOS or other ASL code.
 420      */
 421     for (i = 0; (i < ParentCount) && SubPackageOp; i++)
 422     {
 423         /* Each object in the list must be of type Package */
 424 
 425         Status = ApCheckObjectType (PredefinedName, SubPackageOp,
 426             ACPI_RTYPE_PACKAGE, i + StartIndex);
 427         if (ACPI_FAILURE (Status))
 428         {
 429             goto NextSubpackage;
 430         }
 431 
 432         /* Examine the different types of expected subpackages */
 433 
 434         Op = SubPackageOp->Asl.Child;
 435 
 436         /* First child is the package length */
 437 
 438         Count = (UINT32) Op->Asl.Value.Integer;
 439         Op = Op->Asl.Next;
 440 
 441         /* The subpackage must have at least one element */
 442 
 443         if (!Count)
 444         {
 445             ApZeroLengthPackage (PredefinedName, SubPackageOp);
 446             goto NextSubpackage;
 447         }
 448 
 449         /*
 450          * Decode the package type.
 451          * PTYPE2 indicates that a "package of packages" is expected for
 452          * this name. The various flavors of PTYPE2 indicate the number
 453          * and format of the subpackages.
 454          */
 455         switch (Package->RetInfo.Type)
 456         {
 457         case ACPI_PTYPE2:
 458         case ACPI_PTYPE2_PKG_COUNT:
 459         case ACPI_PTYPE2_REV_FIXED:
 460 
 461             /* Each subpackage has a fixed number of elements */
 462 
 463             ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
 464             if (Count < ExpectedCount)
 465             {
 466                 ApPackageTooSmall (PredefinedName, SubPackageOp,
 467                     Count, ExpectedCount);
 468                 break;
 469             }
 470 
 471             ApCheckPackageElements (PredefinedName, Op,
 472                 Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
 473                 Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
 474             break;
 475 
 476         case ACPI_PTYPE2_FIX_VAR:
 477             /*
 478              * Each subpackage has a fixed number of elements and an
 479              * optional element
 480              */
 481             ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
 482             if (Count < ExpectedCount)
 483             {
 484                 ApPackageTooSmall (PredefinedName, SubPackageOp,
 485                     Count, ExpectedCount);
 486                 break;
 487             }
 488 
 489             ApCheckPackageElements (PredefinedName, Op,
 490                 Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
 491                 Package->RetInfo.ObjectType2,
 492                 Count - Package->RetInfo.Count1);
 493             break;
 494 
 495         case ACPI_PTYPE2_FIXED:
 496 
 497             /* Each sub-package has a fixed length */
 498 
 499             ExpectedCount = Package->RetInfo2.Count;
 500             if (Count < ExpectedCount)
 501             {
 502                 ApPackageTooSmall (PredefinedName, SubPackageOp,
 503                     Count, ExpectedCount);
 504                 break;
 505             }
 506 
 507             /* Check each object/type combination */
 508 
 509             for (j = 0; j < ExpectedCount; j++)
 510             {
 511                 ApCheckObjectType (PredefinedName, Op,
 512                     Package->RetInfo2.ObjectType[j], j);
 513 
 514                 Op = Op->Asl.Next;
 515             }
 516             break;
 517 
 518         case ACPI_PTYPE2_MIN:
 519 
 520             /* Each sub-package has a variable but minimum length */
 521 
 522             ExpectedCount = Package->RetInfo.Count1;
 523             if (Count < ExpectedCount)
 524             {
 525                 ApPackageTooSmall (PredefinedName, SubPackageOp,
 526                     Count, ExpectedCount);
 527                 break;
 528             }
 529 
 530             /* Check the type of each sub-package element */
 531 
 532             ApCheckPackageElements (PredefinedName, Op,
 533                 Package->RetInfo.ObjectType1, Count, 0, 0);
 534             break;
 535 
 536         case ACPI_PTYPE2_COUNT:
 537             /*
 538              * First element is the (Integer) count of elements, including
 539              * the count field (the ACPI name is NumElements)
 540              */
 541             Status = ApCheckObjectType (PredefinedName, Op,
 542                 ACPI_RTYPE_INTEGER, 0);
 543 
 544             /* We must have an integer count from above (otherwise, use Count) */
 545 
 546             if (ACPI_SUCCESS (Status))
 547             {
 548                 /*
 549                  * Make sure package is large enough for the Count and is
 550                  * is as large as the minimum size
 551                  */
 552                 ExpectedCount = (UINT32) Op->Asl.Value.Integer;
 553 
 554                 if (Count < ExpectedCount)
 555                 {
 556                     ApPackageTooSmall (PredefinedName, SubPackageOp,
 557                         Count, ExpectedCount);
 558                     break;
 559                 }
 560                 else if (Count > ExpectedCount)
 561                 {
 562                     ApPackageTooLarge (PredefinedName, SubPackageOp,
 563                         Count, ExpectedCount);
 564                 }
 565 
 566                 /* Some names of this type have a minimum length */
 567 
 568                 if (Count < Package->RetInfo.Count1)
 569                 {
 570                     ExpectedCount = Package->RetInfo.Count1;
 571                     ApPackageTooSmall (PredefinedName, SubPackageOp,
 572                         Count, ExpectedCount);
 573                     break;
 574                 }
 575 
 576                 Count = ExpectedCount;
 577             }
 578 
 579             /* Check the type of each sub-package element */
 580 
 581             Op = Op->Asl.Next;
 582             ApCheckPackageElements (PredefinedName, Op,
 583                 Package->RetInfo.ObjectType1, (Count - 1), 0, 0);
 584             break;
 585 
 586         default:
 587             break;
 588         }
 589 
 590 NextSubpackage:
 591         SubPackageOp = SubPackageOp->Asl.Next;
 592     }
 593 }
 594 
 595 
 596 /*******************************************************************************
 597  *
 598  * FUNCTION:    ApPackageTooSmall
 599  *
 600  * PARAMETERS:  PredefinedName      - Name of the predefined object
 601  *              Op                  - Current parser op
 602  *              Count               - Actual package element count
 603  *              ExpectedCount       - Expected package element count
 604  *
 605  * RETURN:      None
 606  *
 607  * DESCRIPTION: Issue error message for a package that is smaller than
 608  *              required.
 609  *
 610  ******************************************************************************/
 611 
 612 static void
 613 ApPackageTooSmall (
 614     const char                  *PredefinedName,
 615     ACPI_PARSE_OBJECT           *Op,
 616     UINT32                      Count,
 617     UINT32                      ExpectedCount)
 618 {
 619 
 620     sprintf (MsgBuffer, "%s: length %u, required minimum is %u",
 621         PredefinedName, Count, ExpectedCount);
 622 
 623     AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
 624 }
 625 
 626 
 627 /*******************************************************************************
 628  *
 629  * FUNCTION:    ApZeroLengthPackage
 630  *
 631  * PARAMETERS:  PredefinedName      - Name of the predefined object
 632  *              Op                  - Current parser op
 633  *
 634  * RETURN:      None
 635  *
 636  * DESCRIPTION: Issue error message for a zero-length package (a package that
 637  *              is required to have a non-zero length). Variable length
 638  *              packages seem to be allowed to have zero length, however.
 639  *              Even if not allowed, BIOS code does it.
 640  *
 641  ******************************************************************************/
 642 
 643 static void
 644 ApZeroLengthPackage (
 645     const char                  *PredefinedName,
 646     ACPI_PARSE_OBJECT           *Op)
 647 {
 648 
 649     sprintf (MsgBuffer, "%s: length is zero", PredefinedName);
 650 
 651     AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
 652 }
 653 
 654 
 655 /*******************************************************************************
 656  *
 657  * FUNCTION:    ApPackageTooLarge
 658  *
 659  * PARAMETERS:  PredefinedName      - Name of the predefined object
 660  *              Op                  - Current parser op
 661  *              Count               - Actual package element count
 662  *              ExpectedCount       - Expected package element count
 663  *
 664  * RETURN:      None
 665  *
 666  * DESCRIPTION: Issue a remark for a package that is larger than expected.
 667  *
 668  ******************************************************************************/
 669 
 670 static void
 671 ApPackageTooLarge (
 672     const char                  *PredefinedName,
 673     ACPI_PARSE_OBJECT           *Op,
 674     UINT32                      Count,
 675     UINT32                      ExpectedCount)
 676 {
 677 
 678     sprintf (MsgBuffer, "%s: length is %u, only %u required",
 679         PredefinedName, Count, ExpectedCount);
 680 
 681     AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
 682 }