1 /****************************************************************************** 2 * 3 * Module Name: nsprepkg - Validation of package objects for predefined names 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 "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 subpackages 148 */ 149 switch (Package->RetInfo.Type) 150 { 151 case ACPI_PTYPE1_FIXED: 152 /* 153 * The package count is fixed and there are no subpackages 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 subpackages, 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 subpackages. 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 ( 244 Info, Elements, ACPI_RTYPE_INTEGER, 0); 245 if (ACPI_FAILURE (Status)) 246 { 247 return (Status); 248 } 249 250 Elements++; 251 Count--; 252 253 /* Examine the subpackages */ 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 subpackages to follow */ 261 262 Status = AcpiNsCheckObjectType ( 263 Info, Elements, 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 subpackages */ 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 subpackages. 295 * 296 * First, ensure that the first element is a subpackage. 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 ( 307 Info, ReturnObject, ReturnObjectPtr); 308 if (ACPI_FAILURE (Status)) 309 { 310 return (Status); 311 } 312 313 /* Update locals to point to the new package (of 1 element) */ 314 315 ReturnObject = *ReturnObjectPtr; 316 Elements = ReturnObject->Package.Elements; 317 Count = 1; 318 } 319 320 /* Examine the subpackages */ 321 322 Status = AcpiNsCheckPackageList (Info, Package, Elements, Count); 323 break; 324 325 case ACPI_PTYPE2_VAR_VAR: 326 /* 327 * Returns a variable list of packages, each with a variable list 328 * of objects. 329 */ 330 break; 331 332 case ACPI_PTYPE2_UUID_PAIR: 333 334 /* The package must contain pairs of (UUID + type) */ 335 336 if (Count & 1) 337 { 338 ExpectedCount = Count + 1; 339 goto PackageTooSmall; 340 } 341 342 while (Count > 0) 343 { 344 Status = AcpiNsCheckObjectType(Info, Elements, 345 Package->RetInfo.ObjectType1, 0); 346 if (ACPI_FAILURE(Status)) 347 { 348 return (Status); 349 } 350 351 /* Validate length of the UUID buffer */ 352 353 if ((*Elements)->Buffer.Length != 16) 354 { 355 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, 356 Info->NodeFlags, "Invalid length for UUID Buffer")); 357 return (AE_AML_OPERAND_VALUE); 358 } 359 360 Status = AcpiNsCheckObjectType(Info, Elements + 1, 361 Package->RetInfo.ObjectType2, 0); 362 if (ACPI_FAILURE(Status)) 363 { 364 return (Status); 365 } 366 367 Elements += 2; 368 Count -= 2; 369 } 370 break; 371 372 default: 373 374 /* Should not get here if predefined info table is correct */ 375 376 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, 377 "Invalid internal return type in table entry: %X", 378 Package->RetInfo.Type)); 379 380 return (AE_AML_INTERNAL); 381 } 382 383 return (Status); 384 385 386 PackageTooSmall: 387 388 /* Error exit for the case with an incorrect package count */ 389 390 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, 391 "Return Package is too small - found %u elements, expected %u", 392 Count, ExpectedCount)); 393 394 return (AE_AML_OPERAND_VALUE); 395 } 396 397 398 /******************************************************************************* 399 * 400 * FUNCTION: AcpiNsCheckPackageList 401 * 402 * PARAMETERS: Info - Method execution information block 403 * Package - Pointer to package-specific info for method 404 * Elements - Element list of parent package. All elements 405 * of this list should be of type Package. 406 * Count - Count of subpackages 407 * 408 * RETURN: Status 409 * 410 * DESCRIPTION: Examine a list of subpackages 411 * 412 ******************************************************************************/ 413 414 static ACPI_STATUS 415 AcpiNsCheckPackageList ( 416 ACPI_EVALUATE_INFO *Info, 417 const ACPI_PREDEFINED_INFO *Package, 418 ACPI_OPERAND_OBJECT **Elements, 419 UINT32 Count) 420 { 421 ACPI_OPERAND_OBJECT *SubPackage; 422 ACPI_OPERAND_OBJECT **SubElements; 423 ACPI_STATUS Status; 424 UINT32 ExpectedCount; 425 UINT32 i; 426 UINT32 j; 427 428 429 /* 430 * Validate each subpackage in the parent Package 431 * 432 * NOTE: assumes list of subpackages contains no NULL elements. 433 * Any NULL elements should have been removed by earlier call 434 * to AcpiNsRemoveNullElements. 435 */ 436 for (i = 0; i < Count; i++) 437 { 438 SubPackage = *Elements; 439 SubElements = SubPackage->Package.Elements; 440 Info->ParentPackage = SubPackage; 441 442 /* Each sub-object must be of type Package */ 443 444 Status = AcpiNsCheckObjectType (Info, &SubPackage, 445 ACPI_RTYPE_PACKAGE, i); 446 if (ACPI_FAILURE (Status)) 447 { 448 return (Status); 449 } 450 451 /* Examine the different types of expected subpackages */ 452 453 Info->ParentPackage = SubPackage; 454 switch (Package->RetInfo.Type) 455 { 456 case ACPI_PTYPE2: 457 case ACPI_PTYPE2_PKG_COUNT: 458 case ACPI_PTYPE2_REV_FIXED: 459 460 /* Each subpackage has a fixed number of elements */ 461 462 ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 463 if (SubPackage->Package.Count < ExpectedCount) 464 { 465 goto PackageTooSmall; 466 } 467 468 Status = AcpiNsCheckPackageElements (Info, SubElements, 469 Package->RetInfo.ObjectType1, 470 Package->RetInfo.Count1, 471 Package->RetInfo.ObjectType2, 472 Package->RetInfo.Count2, 0); 473 if (ACPI_FAILURE (Status)) 474 { 475 return (Status); 476 } 477 break; 478 479 case ACPI_PTYPE2_FIX_VAR: 480 /* 481 * Each subpackage has a fixed number of elements and an 482 * optional element 483 */ 484 ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 485 if (SubPackage->Package.Count < ExpectedCount) 486 { 487 goto PackageTooSmall; 488 } 489 490 Status = AcpiNsCheckPackageElements (Info, SubElements, 491 Package->RetInfo.ObjectType1, 492 Package->RetInfo.Count1, 493 Package->RetInfo.ObjectType2, 494 SubPackage->Package.Count - Package->RetInfo.Count1, 0); 495 if (ACPI_FAILURE (Status)) 496 { 497 return (Status); 498 } 499 break; 500 501 case ACPI_PTYPE2_VAR_VAR: 502 /* 503 * Each subpackage has a fixed or variable number of elements 504 */ 505 break; 506 507 case ACPI_PTYPE2_FIXED: 508 509 /* Each subpackage has a fixed length */ 510 511 ExpectedCount = Package->RetInfo2.Count; 512 if (SubPackage->Package.Count < ExpectedCount) 513 { 514 goto PackageTooSmall; 515 } 516 517 /* Check the type of each subpackage element */ 518 519 for (j = 0; j < ExpectedCount; j++) 520 { 521 Status = AcpiNsCheckObjectType (Info, &SubElements[j], 522 Package->RetInfo2.ObjectType[j], j); 523 if (ACPI_FAILURE (Status)) 524 { 525 return (Status); 526 } 527 } 528 break; 529 530 case ACPI_PTYPE2_MIN: 531 532 /* Each subpackage has a variable but minimum length */ 533 534 ExpectedCount = Package->RetInfo.Count1; 535 if (SubPackage->Package.Count < ExpectedCount) 536 { 537 goto PackageTooSmall; 538 } 539 540 /* Check the type of each subpackage element */ 541 542 Status = AcpiNsCheckPackageElements (Info, SubElements, 543 Package->RetInfo.ObjectType1, 544 SubPackage->Package.Count, 0, 0, 0); 545 if (ACPI_FAILURE (Status)) 546 { 547 return (Status); 548 } 549 break; 550 551 case ACPI_PTYPE2_COUNT: 552 /* 553 * First element is the (Integer) count of elements, including 554 * the count field (the ACPI name is NumElements) 555 */ 556 Status = AcpiNsCheckObjectType (Info, SubElements, 557 ACPI_RTYPE_INTEGER, 0); 558 if (ACPI_FAILURE (Status)) 559 { 560 return (Status); 561 } 562 563 /* 564 * Make sure package is large enough for the Count and is 565 * is as large as the minimum size 566 */ 567 ExpectedCount = (UINT32) (*SubElements)->Integer.Value; 568 if (SubPackage->Package.Count < ExpectedCount) 569 { 570 goto PackageTooSmall; 571 } 572 if (SubPackage->Package.Count < Package->RetInfo.Count1) 573 { 574 ExpectedCount = Package->RetInfo.Count1; 575 goto PackageTooSmall; 576 } 577 if (ExpectedCount == 0) 578 { 579 /* 580 * Either the NumEntries element was originally zero or it was 581 * a NULL element and repaired to an Integer of value zero. 582 * In either case, repair it by setting NumEntries to be the 583 * actual size of the subpackage. 584 */ 585 ExpectedCount = SubPackage->Package.Count; 586 (*SubElements)->Integer.Value = ExpectedCount; 587 } 588 589 /* Check the type of each subpackage element */ 590 591 Status = AcpiNsCheckPackageElements (Info, (SubElements + 1), 592 Package->RetInfo.ObjectType1, 593 (ExpectedCount - 1), 0, 0, 1); 594 if (ACPI_FAILURE (Status)) 595 { 596 return (Status); 597 } 598 break; 599 600 default: /* Should not get here, type was validated by caller */ 601 602 return (AE_AML_INTERNAL); 603 } 604 605 Elements++; 606 } 607 608 return (AE_OK); 609 610 611 PackageTooSmall: 612 613 /* The subpackage count was smaller than required */ 614 615 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, 616 "Return SubPackage[%u] is too small - found %u elements, expected %u", 617 i, SubPackage->Package.Count, ExpectedCount)); 618 619 return (AE_AML_OPERAND_VALUE); 620 } 621 622 623 /******************************************************************************* 624 * 625 * FUNCTION: AcpiNsCheckPackageElements 626 * 627 * PARAMETERS: Info - Method execution information block 628 * Elements - Pointer to the package elements array 629 * Type1 - Object type for first group 630 * Count1 - Count for first group 631 * Type2 - Object type for second group 632 * Count2 - Count for second group 633 * StartIndex - Start of the first group of elements 634 * 635 * RETURN: Status 636 * 637 * DESCRIPTION: Check that all elements of a package are of the correct object 638 * type. Supports up to two groups of different object types. 639 * 640 ******************************************************************************/ 641 642 static ACPI_STATUS 643 AcpiNsCheckPackageElements ( 644 ACPI_EVALUATE_INFO *Info, 645 ACPI_OPERAND_OBJECT **Elements, 646 UINT8 Type1, 647 UINT32 Count1, 648 UINT8 Type2, 649 UINT32 Count2, 650 UINT32 StartIndex) 651 { 652 ACPI_OPERAND_OBJECT **ThisElement = Elements; 653 ACPI_STATUS Status; 654 UINT32 i; 655 656 657 /* 658 * Up to two groups of package elements are supported by the data 659 * structure. All elements in each group must be of the same type. 660 * The second group can have a count of zero. 661 */ 662 for (i = 0; i < Count1; i++) 663 { 664 Status = AcpiNsCheckObjectType (Info, ThisElement, 665 Type1, i + StartIndex); 666 if (ACPI_FAILURE (Status)) 667 { 668 return (Status); 669 } 670 ThisElement++; 671 } 672 673 for (i = 0; i < Count2; i++) 674 { 675 Status = AcpiNsCheckObjectType (Info, ThisElement, 676 Type2, (i + Count1 + StartIndex)); 677 if (ACPI_FAILURE (Status)) 678 { 679 return (Status); 680 } 681 ThisElement++; 682 } 683 684 return (AE_OK); 685 } 686