1 /****************************************************************************** 2 * 3 * Module Name: aslprepkg - support for ACPI predefined name package objects 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 <contrib/dev/acpica/compiler/aslcompiler.h> 45 #include "aslcompiler.y.h" 46 #include <contrib/dev/acpica/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 subpackages 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 subpackages, 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 subpackages. 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 subpackages */ 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 subpackages 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 subpackages */ 287 288 ApCheckPackageList (Predefined->Info.Name, Op, 289 Package, 1, Count); 290 break; 291 292 case ACPI_PTYPE2_UUID_PAIR: 293 294 /* The package contains a variable list of UUID Buffer/Package pairs */ 295 296 /* The length of the package must be even */ 297 298 if (Count & 1) 299 { 300 sprintf (MsgBuffer, "%4.4s: Package length, %d, must be even.", 301 Predefined->Info.Name, Count); 302 303 AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, 304 ParentOp->Asl.Child, MsgBuffer); 305 } 306 307 /* Validate the alternating types */ 308 309 for (i = 0; i < Count; ++i) 310 { 311 if (i & 1) 312 { 313 ApCheckObjectType (Predefined->Info.Name, Op, 314 Package->RetInfo.ObjectType2, i); 315 } 316 else 317 { 318 ApCheckObjectType (Predefined->Info.Name, Op, 319 Package->RetInfo.ObjectType1, i); 320 } 321 322 Op = Op->Asl.Next; 323 } 324 325 break; 326 327 case ACPI_PTYPE2: 328 case ACPI_PTYPE2_FIXED: 329 case ACPI_PTYPE2_MIN: 330 case ACPI_PTYPE2_COUNT: 331 case ACPI_PTYPE2_FIX_VAR: 332 /* 333 * These types all return a single Package that consists of a 334 * variable number of subpackages. 335 */ 336 337 /* Examine the subpackages */ 338 339 ApCheckPackageList (Predefined->Info.Name, Op, 340 Package, 0, Count); 341 break; 342 343 default: 344 return; 345 } 346 347 return; 348 349 PackageTooSmall: 350 ApPackageTooSmall (Predefined->Info.Name, ParentOp, 351 Count, ExpectedCount); 352 } 353 354 355 /******************************************************************************* 356 * 357 * FUNCTION: ApCheckPackageElements 358 * 359 * PARAMETERS: PredefinedName - Name of the predefined object 360 * Op - Parser op for the package 361 * Type1 - Object type for first group 362 * Count1 - Count for first group 363 * Type2 - Object type for second group 364 * Count2 - Count for second group 365 * 366 * RETURN: None 367 * 368 * DESCRIPTION: Validate all elements of a package. Works with packages that 369 * are defined to contain up to two groups of different object 370 * types. 371 * 372 ******************************************************************************/ 373 374 static void 375 ApCheckPackageElements ( 376 const char *PredefinedName, 377 ACPI_PARSE_OBJECT *Op, 378 UINT8 Type1, 379 UINT32 Count1, 380 UINT8 Type2, 381 UINT32 Count2) 382 { 383 UINT32 i; 384 385 386 /* 387 * Up to two groups of package elements are supported by the data 388 * structure. All elements in each group must be of the same type. 389 * The second group can have a count of zero. 390 * 391 * Aborts check upon a NULL package element, as this means (at compile 392 * time) that the remainder of the package elements are also NULL 393 * (This is the only way to create NULL package elements.) 394 */ 395 for (i = 0; (i < Count1) && Op; i++) 396 { 397 ApCheckObjectType (PredefinedName, Op, Type1, i); 398 Op = Op->Asl.Next; 399 } 400 401 for (i = 0; (i < Count2) && Op; i++) 402 { 403 ApCheckObjectType (PredefinedName, Op, Type2, (i + Count1)); 404 Op = Op->Asl.Next; 405 } 406 } 407 408 409 /******************************************************************************* 410 * 411 * FUNCTION: ApCheckPackageList 412 * 413 * PARAMETERS: PredefinedName - Name of the predefined object 414 * ParentOp - Parser op of the parent package 415 * Package - Package info for this predefined name 416 * StartIndex - Index in parent package where list begins 417 * ParentCount - Element count of parent package 418 * 419 * RETURN: None 420 * 421 * DESCRIPTION: Validate the individual package elements for a predefined name. 422 * Handles the cases where the predefined name is defined as a 423 * Package of Packages (subpackages). These are the types: 424 * 425 * ACPI_PTYPE2 426 * ACPI_PTYPE2_FIXED 427 * ACPI_PTYPE2_MIN 428 * ACPI_PTYPE2_COUNT 429 * ACPI_PTYPE2_FIX_VAR 430 * 431 ******************************************************************************/ 432 433 static void 434 ApCheckPackageList ( 435 const char *PredefinedName, 436 ACPI_PARSE_OBJECT *ParentOp, 437 const ACPI_PREDEFINED_INFO *Package, 438 UINT32 StartIndex, 439 UINT32 ParentCount) 440 { 441 ACPI_PARSE_OBJECT *SubPackageOp = ParentOp; 442 ACPI_PARSE_OBJECT *Op; 443 ACPI_STATUS Status; 444 UINT32 Count; 445 UINT32 ExpectedCount; 446 UINT32 i; 447 UINT32 j; 448 449 450 /* 451 * Validate each subpackage in the parent Package 452 * 453 * Note: We ignore NULL package elements on the assumption that 454 * they will be initialized by the BIOS or other ASL code. 455 */ 456 for (i = 0; (i < ParentCount) && SubPackageOp; i++) 457 { 458 /* Each object in the list must be of type Package */ 459 460 Status = ApCheckObjectType (PredefinedName, SubPackageOp, 461 ACPI_RTYPE_PACKAGE, i + StartIndex); 462 if (ACPI_FAILURE (Status)) 463 { 464 goto NextSubpackage; 465 } 466 467 /* Examine the different types of expected subpackages */ 468 469 Op = SubPackageOp->Asl.Child; 470 471 /* First child is the package length */ 472 473 Count = (UINT32) Op->Asl.Value.Integer; 474 Op = Op->Asl.Next; 475 476 /* The subpackage must have at least one element */ 477 478 if (!Count) 479 { 480 ApZeroLengthPackage (PredefinedName, SubPackageOp); 481 goto NextSubpackage; 482 } 483 484 /* 485 * Decode the package type. 486 * PTYPE2 indicates that a "package of packages" is expected for 487 * this name. The various flavors of PTYPE2 indicate the number 488 * and format of the subpackages. 489 */ 490 switch (Package->RetInfo.Type) 491 { 492 case ACPI_PTYPE2: 493 case ACPI_PTYPE2_PKG_COUNT: 494 case ACPI_PTYPE2_REV_FIXED: 495 496 /* Each subpackage has a fixed number of elements */ 497 498 ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 499 if (Count < ExpectedCount) 500 { 501 ApPackageTooSmall (PredefinedName, SubPackageOp, 502 Count, ExpectedCount); 503 break; 504 } 505 if (Count > ExpectedCount) 506 { 507 ApPackageTooLarge (PredefinedName, SubPackageOp, 508 Count, ExpectedCount); 509 break; 510 } 511 512 ApCheckPackageElements (PredefinedName, Op, 513 Package->RetInfo.ObjectType1, Package->RetInfo.Count1, 514 Package->RetInfo.ObjectType2, Package->RetInfo.Count2); 515 break; 516 517 case ACPI_PTYPE2_FIX_VAR: 518 /* 519 * Each subpackage has a fixed number of elements and an 520 * optional element 521 */ 522 ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 523 if (Count < ExpectedCount) 524 { 525 ApPackageTooSmall (PredefinedName, SubPackageOp, 526 Count, ExpectedCount); 527 break; 528 } 529 530 ApCheckPackageElements (PredefinedName, Op, 531 Package->RetInfo.ObjectType1, Package->RetInfo.Count1, 532 Package->RetInfo.ObjectType2, 533 Count - Package->RetInfo.Count1); 534 break; 535 536 case ACPI_PTYPE2_FIXED: 537 538 /* Each subpackage has a fixed length */ 539 540 ExpectedCount = Package->RetInfo2.Count; 541 if (Count < ExpectedCount) 542 { 543 ApPackageTooSmall (PredefinedName, SubPackageOp, 544 Count, ExpectedCount); 545 break; 546 } 547 if (Count > ExpectedCount) 548 { 549 ApPackageTooLarge (PredefinedName, SubPackageOp, 550 Count, ExpectedCount); 551 break; 552 } 553 554 /* Check each object/type combination */ 555 556 for (j = 0; j < ExpectedCount; j++) 557 { 558 ApCheckObjectType (PredefinedName, Op, 559 Package->RetInfo2.ObjectType[j], j); 560 561 Op = Op->Asl.Next; 562 } 563 break; 564 565 case ACPI_PTYPE2_MIN: 566 567 /* Each subpackage has a variable but minimum length */ 568 569 ExpectedCount = Package->RetInfo.Count1; 570 if (Count < ExpectedCount) 571 { 572 ApPackageTooSmall (PredefinedName, SubPackageOp, 573 Count, ExpectedCount); 574 break; 575 } 576 577 /* Check the type of each subpackage element */ 578 579 ApCheckPackageElements (PredefinedName, Op, 580 Package->RetInfo.ObjectType1, Count, 0, 0); 581 break; 582 583 case ACPI_PTYPE2_COUNT: 584 /* 585 * First element is the (Integer) count of elements, including 586 * the count field (the ACPI name is NumElements) 587 */ 588 Status = ApCheckObjectType (PredefinedName, Op, 589 ACPI_RTYPE_INTEGER, 0); 590 591 /* We must have an integer count from above (otherwise, use Count) */ 592 593 if (ACPI_SUCCESS (Status)) 594 { 595 /* 596 * Make sure package is large enough for the Count and is 597 * is as large as the minimum size 598 */ 599 ExpectedCount = (UINT32) Op->Asl.Value.Integer; 600 601 if (Count < ExpectedCount) 602 { 603 ApPackageTooSmall (PredefinedName, SubPackageOp, 604 Count, ExpectedCount); 605 break; 606 } 607 else if (Count > ExpectedCount) 608 { 609 ApPackageTooLarge (PredefinedName, SubPackageOp, 610 Count, ExpectedCount); 611 } 612 613 /* Some names of this type have a minimum length */ 614 615 if (Count < Package->RetInfo.Count1) 616 { 617 ExpectedCount = Package->RetInfo.Count1; 618 ApPackageTooSmall (PredefinedName, SubPackageOp, 619 Count, ExpectedCount); 620 break; 621 } 622 623 Count = ExpectedCount; 624 } 625 626 /* Check the type of each subpackage element */ 627 628 Op = Op->Asl.Next; 629 ApCheckPackageElements (PredefinedName, Op, 630 Package->RetInfo.ObjectType1, (Count - 1), 0, 0); 631 break; 632 633 default: 634 break; 635 } 636 637 NextSubpackage: 638 SubPackageOp = SubPackageOp->Asl.Next; 639 } 640 } 641 642 643 /******************************************************************************* 644 * 645 * FUNCTION: ApPackageTooSmall 646 * 647 * PARAMETERS: PredefinedName - Name of the predefined object 648 * Op - Current parser op 649 * Count - Actual package element count 650 * ExpectedCount - Expected package element count 651 * 652 * RETURN: None 653 * 654 * DESCRIPTION: Issue error message for a package that is smaller than 655 * required. 656 * 657 ******************************************************************************/ 658 659 static void 660 ApPackageTooSmall ( 661 const char *PredefinedName, 662 ACPI_PARSE_OBJECT *Op, 663 UINT32 Count, 664 UINT32 ExpectedCount) 665 { 666 667 sprintf (MsgBuffer, "%s: length %u, required minimum is %u", 668 PredefinedName, Count, ExpectedCount); 669 670 AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); 671 } 672 673 674 /******************************************************************************* 675 * 676 * FUNCTION: ApZeroLengthPackage 677 * 678 * PARAMETERS: PredefinedName - Name of the predefined object 679 * Op - Current parser op 680 * 681 * RETURN: None 682 * 683 * DESCRIPTION: Issue error message for a zero-length package (a package that 684 * is required to have a non-zero length). Variable length 685 * packages seem to be allowed to have zero length, however. 686 * Even if not allowed, BIOS code does it. 687 * 688 ******************************************************************************/ 689 690 static void 691 ApZeroLengthPackage ( 692 const char *PredefinedName, 693 ACPI_PARSE_OBJECT *Op) 694 { 695 696 sprintf (MsgBuffer, "%s: length is zero", PredefinedName); 697 698 AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); 699 } 700 701 702 /******************************************************************************* 703 * 704 * FUNCTION: ApPackageTooLarge 705 * 706 * PARAMETERS: PredefinedName - Name of the predefined object 707 * Op - Current parser op 708 * Count - Actual package element count 709 * ExpectedCount - Expected package element count 710 * 711 * RETURN: None 712 * 713 * DESCRIPTION: Issue a remark for a package that is larger than expected. 714 * 715 ******************************************************************************/ 716 717 static void 718 ApPackageTooLarge ( 719 const char *PredefinedName, 720 ACPI_PARSE_OBJECT *Op, 721 UINT32 Count, 722 UINT32 ExpectedCount) 723 { 724 725 sprintf (MsgBuffer, "%s: length is %u, only %u required", 726 PredefinedName, Count, ExpectedCount); 727 728 AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); 729 } 730