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