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