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