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