1 /****************************************************************************** 2 * 3 * Module Name: nspredef - Validation of ACPI predefined methods and objects 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, 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 #define ACPI_CREATE_PREDEFINED_TABLE 45 46 #include <contrib/dev/acpica/include/acpi.h> 47 #include <contrib/dev/acpica/include/accommon.h> 48 #include <contrib/dev/acpica/include/acnamesp.h> 49 #include <contrib/dev/acpica/include/acpredef.h> 50 51 52 #define _COMPONENT ACPI_NAMESPACE 53 ACPI_MODULE_NAME ("nspredef") 54 55 56 /******************************************************************************* 57 * 58 * This module validates predefined ACPI objects that appear in the namespace, 59 * at the time they are evaluated (via AcpiEvaluateObject). The purpose of this 60 * validation is to detect problems with BIOS-exposed predefined ACPI objects 61 * before the results are returned to the ACPI-related drivers. 62 * 63 * There are several areas that are validated: 64 * 65 * 1) The number of input arguments as defined by the method/object in the 66 * ASL is validated against the ACPI specification. 67 * 2) The type of the return object (if any) is validated against the ACPI 68 * specification. 69 * 3) For returned package objects, the count of package elements is 70 * validated, as well as the type of each package element. Nested 71 * packages are supported. 72 * 73 * For any problems found, a warning message is issued. 74 * 75 ******************************************************************************/ 76 77 78 /* Local prototypes */ 79 80 static ACPI_STATUS 81 AcpiNsCheckPackage ( 82 ACPI_PREDEFINED_DATA *Data, 83 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 84 85 static ACPI_STATUS 86 AcpiNsCheckPackageList ( 87 ACPI_PREDEFINED_DATA *Data, 88 const ACPI_PREDEFINED_INFO *Package, 89 ACPI_OPERAND_OBJECT **Elements, 90 UINT32 Count); 91 92 static ACPI_STATUS 93 AcpiNsCheckPackageElements ( 94 ACPI_PREDEFINED_DATA *Data, 95 ACPI_OPERAND_OBJECT **Elements, 96 UINT8 Type1, 97 UINT32 Count1, 98 UINT8 Type2, 99 UINT32 Count2, 100 UINT32 StartIndex); 101 102 static ACPI_STATUS 103 AcpiNsCheckObjectType ( 104 ACPI_PREDEFINED_DATA *Data, 105 ACPI_OPERAND_OBJECT **ReturnObjectPtr, 106 UINT32 ExpectedBtypes, 107 UINT32 PackageIndex); 108 109 static ACPI_STATUS 110 AcpiNsCheckReference ( 111 ACPI_PREDEFINED_DATA *Data, 112 ACPI_OPERAND_OBJECT *ReturnObject); 113 114 static void 115 AcpiNsGetExpectedTypes ( 116 char *Buffer, 117 UINT32 ExpectedBtypes); 118 119 /* 120 * Names for the types that can be returned by the predefined objects. 121 * Used for warning messages. Must be in the same order as the ACPI_RTYPEs 122 */ 123 static const char *AcpiRtypeNames[] = 124 { 125 "/Integer", 126 "/String", 127 "/Buffer", 128 "/Package", 129 "/Reference", 130 }; 131 132 133 /******************************************************************************* 134 * 135 * FUNCTION: AcpiNsCheckPredefinedNames 136 * 137 * PARAMETERS: Node - Namespace node for the method/object 138 * UserParamCount - Number of parameters actually passed 139 * ReturnStatus - Status from the object evaluation 140 * ReturnObjectPtr - Pointer to the object returned from the 141 * evaluation of a method or object 142 * 143 * RETURN: Status 144 * 145 * DESCRIPTION: Check an ACPI name for a match in the predefined name list. 146 * 147 ******************************************************************************/ 148 149 ACPI_STATUS 150 AcpiNsCheckPredefinedNames ( 151 ACPI_NAMESPACE_NODE *Node, 152 UINT32 UserParamCount, 153 ACPI_STATUS ReturnStatus, 154 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 155 { 156 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 157 ACPI_STATUS Status = AE_OK; 158 const ACPI_PREDEFINED_INFO *Predefined; 159 char *Pathname; 160 ACPI_PREDEFINED_DATA *Data; 161 162 163 /* Match the name for this method/object against the predefined list */ 164 165 Predefined = AcpiNsCheckForPredefinedName (Node); 166 167 /* Get the full pathname to the object, for use in warning messages */ 168 169 Pathname = AcpiNsGetExternalPathname (Node); 170 if (!Pathname) 171 { 172 return (AE_OK); /* Could not get pathname, ignore */ 173 } 174 175 /* 176 * Check that the parameter count for this method matches the ASL 177 * definition. For predefined names, ensure that both the caller and 178 * the method itself are in accordance with the ACPI specification. 179 */ 180 AcpiNsCheckParameterCount (Pathname, Node, UserParamCount, Predefined); 181 182 /* If not a predefined name, we cannot validate the return object */ 183 184 if (!Predefined) 185 { 186 goto Cleanup; 187 } 188 189 /* 190 * If the method failed or did not actually return an object, we cannot 191 * validate the return object 192 */ 193 if ((ReturnStatus != AE_OK) && (ReturnStatus != AE_CTRL_RETURN_VALUE)) 194 { 195 goto Cleanup; 196 } 197 198 /* 199 * If there is no return value, check if we require a return value for 200 * this predefined name. Either one return value is expected, or none, 201 * for both methods and other objects. 202 * 203 * Exit now if there is no return object. Warning if one was expected. 204 */ 205 if (!ReturnObject) 206 { 207 if ((Predefined->Info.ExpectedBtypes) && 208 (!(Predefined->Info.ExpectedBtypes & ACPI_RTYPE_NONE))) 209 { 210 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 211 "Missing expected return value")); 212 213 Status = AE_AML_NO_RETURN_VALUE; 214 } 215 goto Cleanup; 216 } 217 218 /* 219 * Return value validation and possible repair. 220 * 221 * 1) Don't perform return value validation/repair if this feature 222 * has been disabled via a global option. 223 * 224 * 2) We have a return value, but if one wasn't expected, just exit, 225 * this is not a problem. For example, if the "Implicit Return" 226 * feature is enabled, methods will always return a value. 227 * 228 * 3) If the return value can be of any type, then we cannot perform 229 * any validation, just exit. 230 */ 231 if (AcpiGbl_DisableAutoRepair || 232 (!Predefined->Info.ExpectedBtypes) || 233 (Predefined->Info.ExpectedBtypes == ACPI_RTYPE_ALL)) 234 { 235 goto Cleanup; 236 } 237 238 /* Create the parameter data block for object validation */ 239 240 Data = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PREDEFINED_DATA)); 241 if (!Data) 242 { 243 goto Cleanup; 244 } 245 Data->Predefined = Predefined; 246 Data->Node = Node; 247 Data->NodeFlags = Node->Flags; 248 Data->Pathname = Pathname; 249 250 /* 251 * Check that the type of the main return object is what is expected 252 * for this predefined name 253 */ 254 Status = AcpiNsCheckObjectType (Data, ReturnObjectPtr, 255 Predefined->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT); 256 if (ACPI_FAILURE (Status)) 257 { 258 goto Exit; 259 } 260 261 /* 262 * For returned Package objects, check the type of all sub-objects. 263 * Note: Package may have been newly created by call above. 264 */ 265 if ((*ReturnObjectPtr)->Common.Type == ACPI_TYPE_PACKAGE) 266 { 267 Data->ParentPackage = *ReturnObjectPtr; 268 Status = AcpiNsCheckPackage (Data, ReturnObjectPtr); 269 if (ACPI_FAILURE (Status)) 270 { 271 goto Exit; 272 } 273 } 274 275 /* 276 * The return object was OK, or it was successfully repaired above. 277 * Now make some additional checks such as verifying that package 278 * objects are sorted correctly (if required) or buffer objects have 279 * the correct data width (bytes vs. dwords). These repairs are 280 * performed on a per-name basis, i.e., the code is specific to 281 * particular predefined names. 282 */ 283 Status = AcpiNsComplexRepairs (Data, Node, Status, ReturnObjectPtr); 284 285 Exit: 286 /* 287 * If the object validation failed or if we successfully repaired one 288 * or more objects, mark the parent node to suppress further warning 289 * messages during the next evaluation of the same method/object. 290 */ 291 if (ACPI_FAILURE (Status) || (Data->Flags & ACPI_OBJECT_REPAIRED)) 292 { 293 Node->Flags |= ANOBJ_EVALUATED; 294 } 295 ACPI_FREE (Data); 296 297 Cleanup: 298 ACPI_FREE (Pathname); 299 return (Status); 300 } 301 302 303 /******************************************************************************* 304 * 305 * FUNCTION: AcpiNsCheckParameterCount 306 * 307 * PARAMETERS: Pathname - Full pathname to the node (for error msgs) 308 * Node - Namespace node for the method/object 309 * UserParamCount - Number of args passed in by the caller 310 * Predefined - Pointer to entry in predefined name table 311 * 312 * RETURN: None 313 * 314 * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a 315 * predefined name is what is expected (i.e., what is defined in 316 * the ACPI specification for this predefined name.) 317 * 318 ******************************************************************************/ 319 320 void 321 AcpiNsCheckParameterCount ( 322 char *Pathname, 323 ACPI_NAMESPACE_NODE *Node, 324 UINT32 UserParamCount, 325 const ACPI_PREDEFINED_INFO *Predefined) 326 { 327 UINT32 ParamCount; 328 UINT32 RequiredParamsCurrent; 329 UINT32 RequiredParamsOld; 330 331 332 /* Methods have 0-7 parameters. All other types have zero. */ 333 334 ParamCount = 0; 335 if (Node->Type == ACPI_TYPE_METHOD) 336 { 337 ParamCount = Node->Object->Method.ParamCount; 338 } 339 340 if (!Predefined) 341 { 342 /* 343 * Check the parameter count for non-predefined methods/objects. 344 * 345 * Warning if too few or too many arguments have been passed by the 346 * caller. An incorrect number of arguments may not cause the method 347 * to fail. However, the method will fail if there are too few 348 * arguments and the method attempts to use one of the missing ones. 349 */ 350 if (UserParamCount < ParamCount) 351 { 352 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 353 "Insufficient arguments - needs %u, found %u", 354 ParamCount, UserParamCount)); 355 } 356 else if (UserParamCount > ParamCount) 357 { 358 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 359 "Excess arguments - needs %u, found %u", 360 ParamCount, UserParamCount)); 361 } 362 return; 363 } 364 365 /* 366 * Validate the user-supplied parameter count. 367 * Allow two different legal argument counts (_SCP, etc.) 368 */ 369 RequiredParamsCurrent = Predefined->Info.ParamCount & 0x0F; 370 RequiredParamsOld = Predefined->Info.ParamCount >> 4; 371 372 if (UserParamCount != ACPI_UINT32_MAX) 373 { 374 if ((UserParamCount != RequiredParamsCurrent) && 375 (UserParamCount != RequiredParamsOld)) 376 { 377 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 378 "Parameter count mismatch - " 379 "caller passed %u, ACPI requires %u", 380 UserParamCount, RequiredParamsCurrent)); 381 } 382 } 383 384 /* 385 * Check that the ASL-defined parameter count is what is expected for 386 * this predefined name (parameter count as defined by the ACPI 387 * specification) 388 */ 389 if ((ParamCount != RequiredParamsCurrent) && 390 (ParamCount != RequiredParamsOld)) 391 { 392 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, Node->Flags, 393 "Parameter count mismatch - ASL declared %u, ACPI requires %u", 394 ParamCount, RequiredParamsCurrent)); 395 } 396 } 397 398 399 /******************************************************************************* 400 * 401 * FUNCTION: AcpiNsCheckForPredefinedName 402 * 403 * PARAMETERS: Node - Namespace node for the method/object 404 * 405 * RETURN: Pointer to entry in predefined table. NULL indicates not found. 406 * 407 * DESCRIPTION: Check an object name against the predefined object list. 408 * 409 ******************************************************************************/ 410 411 const ACPI_PREDEFINED_INFO * 412 AcpiNsCheckForPredefinedName ( 413 ACPI_NAMESPACE_NODE *Node) 414 { 415 const ACPI_PREDEFINED_INFO *ThisName; 416 417 418 /* Quick check for a predefined name, first character must be underscore */ 419 420 if (Node->Name.Ascii[0] != '_') 421 { 422 return (NULL); 423 } 424 425 /* Search info table for a predefined method/object name */ 426 427 ThisName = PredefinedNames; 428 while (ThisName->Info.Name[0]) 429 { 430 if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Info.Name)) 431 { 432 return (ThisName); 433 } 434 435 /* 436 * Skip next entry in the table if this name returns a Package 437 * (next entry contains the package info) 438 */ 439 if (ThisName->Info.ExpectedBtypes & ACPI_RTYPE_PACKAGE) 440 { 441 ThisName++; 442 } 443 444 ThisName++; 445 } 446 447 return (NULL); /* Not found */ 448 } 449 450 451 /******************************************************************************* 452 * 453 * FUNCTION: AcpiNsCheckPackage 454 * 455 * PARAMETERS: Data - Pointer to validation data structure 456 * ReturnObjectPtr - Pointer to the object returned from the 457 * evaluation of a method or object 458 * 459 * RETURN: Status 460 * 461 * DESCRIPTION: Check a returned package object for the correct count and 462 * correct type of all sub-objects. 463 * 464 ******************************************************************************/ 465 466 static ACPI_STATUS 467 AcpiNsCheckPackage ( 468 ACPI_PREDEFINED_DATA *Data, 469 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 470 { 471 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 472 const ACPI_PREDEFINED_INFO *Package; 473 ACPI_OPERAND_OBJECT **Elements; 474 ACPI_STATUS Status = AE_OK; 475 UINT32 ExpectedCount; 476 UINT32 Count; 477 UINT32 i; 478 479 480 ACPI_FUNCTION_NAME (NsCheckPackage); 481 482 483 /* The package info for this name is in the next table entry */ 484 485 Package = Data->Predefined + 1; 486 487 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 488 "%s Validating return Package of Type %X, Count %X\n", 489 Data->Pathname, Package->RetInfo.Type, ReturnObject->Package.Count)); 490 491 /* 492 * For variable-length Packages, we can safely remove all embedded 493 * and trailing NULL package elements 494 */ 495 AcpiNsRemoveNullElements (Data, Package->RetInfo.Type, ReturnObject); 496 497 /* Extract package count and elements array */ 498 499 Elements = ReturnObject->Package.Elements; 500 Count = ReturnObject->Package.Count; 501 502 /* The package must have at least one element, else invalid */ 503 504 if (!Count) 505 { 506 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 507 "Return Package has no elements (empty)")); 508 509 return (AE_AML_OPERAND_VALUE); 510 } 511 512 /* 513 * Decode the type of the expected package contents 514 * 515 * PTYPE1 packages contain no subpackages 516 * PTYPE2 packages contain sub-packages 517 */ 518 switch (Package->RetInfo.Type) 519 { 520 case ACPI_PTYPE1_FIXED: 521 522 /* 523 * The package count is fixed and there are no sub-packages 524 * 525 * If package is too small, exit. 526 * If package is larger than expected, issue warning but continue 527 */ 528 ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 529 if (Count < ExpectedCount) 530 { 531 goto PackageTooSmall; 532 } 533 else if (Count > ExpectedCount) 534 { 535 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 536 "%s: Return Package is larger than needed - " 537 "found %u, expected %u\n", 538 Data->Pathname, Count, ExpectedCount)); 539 } 540 541 /* Validate all elements of the returned package */ 542 543 Status = AcpiNsCheckPackageElements (Data, Elements, 544 Package->RetInfo.ObjectType1, Package->RetInfo.Count1, 545 Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0); 546 break; 547 548 549 case ACPI_PTYPE1_VAR: 550 551 /* 552 * The package count is variable, there are no sub-packages, and all 553 * elements must be of the same type 554 */ 555 for (i = 0; i < Count; i++) 556 { 557 Status = AcpiNsCheckObjectType (Data, Elements, 558 Package->RetInfo.ObjectType1, i); 559 if (ACPI_FAILURE (Status)) 560 { 561 return (Status); 562 } 563 Elements++; 564 } 565 break; 566 567 568 case ACPI_PTYPE1_OPTION: 569 570 /* 571 * The package count is variable, there are no sub-packages. There are 572 * a fixed number of required elements, and a variable number of 573 * optional elements. 574 * 575 * Check if package is at least as large as the minimum required 576 */ 577 ExpectedCount = Package->RetInfo3.Count; 578 if (Count < ExpectedCount) 579 { 580 goto PackageTooSmall; 581 } 582 583 /* Variable number of sub-objects */ 584 585 for (i = 0; i < Count; i++) 586 { 587 if (i < Package->RetInfo3.Count) 588 { 589 /* These are the required package elements (0, 1, or 2) */ 590 591 Status = AcpiNsCheckObjectType (Data, Elements, 592 Package->RetInfo3.ObjectType[i], i); 593 if (ACPI_FAILURE (Status)) 594 { 595 return (Status); 596 } 597 } 598 else 599 { 600 /* These are the optional package elements */ 601 602 Status = AcpiNsCheckObjectType (Data, Elements, 603 Package->RetInfo3.TailObjectType, i); 604 if (ACPI_FAILURE (Status)) 605 { 606 return (Status); 607 } 608 } 609 Elements++; 610 } 611 break; 612 613 614 case ACPI_PTYPE2_REV_FIXED: 615 616 /* First element is the (Integer) revision */ 617 618 Status = AcpiNsCheckObjectType (Data, Elements, 619 ACPI_RTYPE_INTEGER, 0); 620 if (ACPI_FAILURE (Status)) 621 { 622 return (Status); 623 } 624 625 Elements++; 626 Count--; 627 628 /* Examine the sub-packages */ 629 630 Status = AcpiNsCheckPackageList (Data, Package, Elements, Count); 631 break; 632 633 634 case ACPI_PTYPE2_PKG_COUNT: 635 636 /* First element is the (Integer) count of sub-packages to follow */ 637 638 Status = AcpiNsCheckObjectType (Data, Elements, 639 ACPI_RTYPE_INTEGER, 0); 640 if (ACPI_FAILURE (Status)) 641 { 642 return (Status); 643 } 644 645 /* 646 * Count cannot be larger than the parent package length, but allow it 647 * to be smaller. The >= accounts for the Integer above. 648 */ 649 ExpectedCount = (UINT32) (*Elements)->Integer.Value; 650 if (ExpectedCount >= Count) 651 { 652 goto PackageTooSmall; 653 } 654 655 Count = ExpectedCount; 656 Elements++; 657 658 /* Examine the sub-packages */ 659 660 Status = AcpiNsCheckPackageList (Data, Package, Elements, Count); 661 break; 662 663 664 case ACPI_PTYPE2: 665 case ACPI_PTYPE2_FIXED: 666 case ACPI_PTYPE2_MIN: 667 case ACPI_PTYPE2_COUNT: 668 case ACPI_PTYPE2_FIX_VAR: 669 670 /* 671 * These types all return a single Package that consists of a 672 * variable number of sub-Packages. 673 * 674 * First, ensure that the first element is a sub-Package. If not, 675 * the BIOS may have incorrectly returned the object as a single 676 * package instead of a Package of Packages (a common error if 677 * there is only one entry). We may be able to repair this by 678 * wrapping the returned Package with a new outer Package. 679 */ 680 if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE)) 681 { 682 /* Create the new outer package and populate it */ 683 684 Status = AcpiNsWrapWithPackage (Data, ReturnObject, ReturnObjectPtr); 685 if (ACPI_FAILURE (Status)) 686 { 687 return (Status); 688 } 689 690 /* Update locals to point to the new package (of 1 element) */ 691 692 ReturnObject = *ReturnObjectPtr; 693 Elements = ReturnObject->Package.Elements; 694 Count = 1; 695 } 696 697 /* Examine the sub-packages */ 698 699 Status = AcpiNsCheckPackageList (Data, Package, Elements, Count); 700 break; 701 702 703 default: 704 705 /* Should not get here if predefined info table is correct */ 706 707 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 708 "Invalid internal return type in table entry: %X", 709 Package->RetInfo.Type)); 710 711 return (AE_AML_INTERNAL); 712 } 713 714 return (Status); 715 716 717 PackageTooSmall: 718 719 /* Error exit for the case with an incorrect package count */ 720 721 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 722 "Return Package is too small - found %u elements, expected %u", 723 Count, ExpectedCount)); 724 725 return (AE_AML_OPERAND_VALUE); 726 } 727 728 729 /******************************************************************************* 730 * 731 * FUNCTION: AcpiNsCheckPackageList 732 * 733 * PARAMETERS: Data - Pointer to validation data structure 734 * Package - Pointer to package-specific info for method 735 * Elements - Element list of parent package. All elements 736 * of this list should be of type Package. 737 * Count - Count of subpackages 738 * 739 * RETURN: Status 740 * 741 * DESCRIPTION: Examine a list of subpackages 742 * 743 ******************************************************************************/ 744 745 static ACPI_STATUS 746 AcpiNsCheckPackageList ( 747 ACPI_PREDEFINED_DATA *Data, 748 const ACPI_PREDEFINED_INFO *Package, 749 ACPI_OPERAND_OBJECT **Elements, 750 UINT32 Count) 751 { 752 ACPI_OPERAND_OBJECT *SubPackage; 753 ACPI_OPERAND_OBJECT **SubElements; 754 ACPI_STATUS Status; 755 UINT32 ExpectedCount; 756 UINT32 i; 757 UINT32 j; 758 759 760 /* 761 * Validate each sub-Package in the parent Package 762 * 763 * NOTE: assumes list of sub-packages contains no NULL elements. 764 * Any NULL elements should have been removed by earlier call 765 * to AcpiNsRemoveNullElements. 766 */ 767 for (i = 0; i < Count; i++) 768 { 769 SubPackage = *Elements; 770 SubElements = SubPackage->Package.Elements; 771 Data->ParentPackage = SubPackage; 772 773 /* Each sub-object must be of type Package */ 774 775 Status = AcpiNsCheckObjectType (Data, &SubPackage, 776 ACPI_RTYPE_PACKAGE, i); 777 if (ACPI_FAILURE (Status)) 778 { 779 return (Status); 780 } 781 782 /* Examine the different types of expected sub-packages */ 783 784 Data->ParentPackage = SubPackage; 785 switch (Package->RetInfo.Type) 786 { 787 case ACPI_PTYPE2: 788 case ACPI_PTYPE2_PKG_COUNT: 789 case ACPI_PTYPE2_REV_FIXED: 790 791 /* Each subpackage has a fixed number of elements */ 792 793 ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 794 if (SubPackage->Package.Count < ExpectedCount) 795 { 796 goto PackageTooSmall; 797 } 798 799 Status = AcpiNsCheckPackageElements (Data, SubElements, 800 Package->RetInfo.ObjectType1, 801 Package->RetInfo.Count1, 802 Package->RetInfo.ObjectType2, 803 Package->RetInfo.Count2, 0); 804 if (ACPI_FAILURE (Status)) 805 { 806 return (Status); 807 } 808 break; 809 810 811 case ACPI_PTYPE2_FIX_VAR: 812 /* 813 * Each subpackage has a fixed number of elements and an 814 * optional element 815 */ 816 ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 817 if (SubPackage->Package.Count < ExpectedCount) 818 { 819 goto PackageTooSmall; 820 } 821 822 Status = AcpiNsCheckPackageElements (Data, SubElements, 823 Package->RetInfo.ObjectType1, 824 Package->RetInfo.Count1, 825 Package->RetInfo.ObjectType2, 826 SubPackage->Package.Count - Package->RetInfo.Count1, 0); 827 if (ACPI_FAILURE (Status)) 828 { 829 return (Status); 830 } 831 break; 832 833 834 case ACPI_PTYPE2_FIXED: 835 836 /* Each sub-package has a fixed length */ 837 838 ExpectedCount = Package->RetInfo2.Count; 839 if (SubPackage->Package.Count < ExpectedCount) 840 { 841 goto PackageTooSmall; 842 } 843 844 /* Check the type of each sub-package element */ 845 846 for (j = 0; j < ExpectedCount; j++) 847 { 848 Status = AcpiNsCheckObjectType (Data, &SubElements[j], 849 Package->RetInfo2.ObjectType[j], j); 850 if (ACPI_FAILURE (Status)) 851 { 852 return (Status); 853 } 854 } 855 break; 856 857 858 case ACPI_PTYPE2_MIN: 859 860 /* Each sub-package has a variable but minimum length */ 861 862 ExpectedCount = Package->RetInfo.Count1; 863 if (SubPackage->Package.Count < ExpectedCount) 864 { 865 goto PackageTooSmall; 866 } 867 868 /* Check the type of each sub-package element */ 869 870 Status = AcpiNsCheckPackageElements (Data, SubElements, 871 Package->RetInfo.ObjectType1, 872 SubPackage->Package.Count, 0, 0, 0); 873 if (ACPI_FAILURE (Status)) 874 { 875 return (Status); 876 } 877 break; 878 879 880 case ACPI_PTYPE2_COUNT: 881 882 /* 883 * First element is the (Integer) count of elements, including 884 * the count field (the ACPI name is NumElements) 885 */ 886 Status = AcpiNsCheckObjectType (Data, SubElements, 887 ACPI_RTYPE_INTEGER, 0); 888 if (ACPI_FAILURE (Status)) 889 { 890 return (Status); 891 } 892 893 /* 894 * Make sure package is large enough for the Count and is 895 * is as large as the minimum size 896 */ 897 ExpectedCount = (UINT32) (*SubElements)->Integer.Value; 898 if (SubPackage->Package.Count < ExpectedCount) 899 { 900 goto PackageTooSmall; 901 } 902 if (SubPackage->Package.Count < Package->RetInfo.Count1) 903 { 904 ExpectedCount = Package->RetInfo.Count1; 905 goto PackageTooSmall; 906 } 907 if (ExpectedCount == 0) 908 { 909 /* 910 * Either the NumEntries element was originally zero or it was 911 * a NULL element and repaired to an Integer of value zero. 912 * In either case, repair it by setting NumEntries to be the 913 * actual size of the subpackage. 914 */ 915 ExpectedCount = SubPackage->Package.Count; 916 (*SubElements)->Integer.Value = ExpectedCount; 917 } 918 919 /* Check the type of each sub-package element */ 920 921 Status = AcpiNsCheckPackageElements (Data, (SubElements + 1), 922 Package->RetInfo.ObjectType1, 923 (ExpectedCount - 1), 0, 0, 1); 924 if (ACPI_FAILURE (Status)) 925 { 926 return (Status); 927 } 928 break; 929 930 931 default: /* Should not get here, type was validated by caller */ 932 933 return (AE_AML_INTERNAL); 934 } 935 936 Elements++; 937 } 938 939 return (AE_OK); 940 941 942 PackageTooSmall: 943 944 /* The sub-package count was smaller than required */ 945 946 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 947 "Return Sub-Package[%u] is too small - found %u elements, expected %u", 948 i, SubPackage->Package.Count, ExpectedCount)); 949 950 return (AE_AML_OPERAND_VALUE); 951 } 952 953 954 /******************************************************************************* 955 * 956 * FUNCTION: AcpiNsCheckPackageElements 957 * 958 * PARAMETERS: Data - Pointer to validation data structure 959 * Elements - Pointer to the package elements array 960 * Type1 - Object type for first group 961 * Count1 - Count for first group 962 * Type2 - Object type for second group 963 * Count2 - Count for second group 964 * StartIndex - Start of the first group of elements 965 * 966 * RETURN: Status 967 * 968 * DESCRIPTION: Check that all elements of a package are of the correct object 969 * type. Supports up to two groups of different object types. 970 * 971 ******************************************************************************/ 972 973 static ACPI_STATUS 974 AcpiNsCheckPackageElements ( 975 ACPI_PREDEFINED_DATA *Data, 976 ACPI_OPERAND_OBJECT **Elements, 977 UINT8 Type1, 978 UINT32 Count1, 979 UINT8 Type2, 980 UINT32 Count2, 981 UINT32 StartIndex) 982 { 983 ACPI_OPERAND_OBJECT **ThisElement = Elements; 984 ACPI_STATUS Status; 985 UINT32 i; 986 987 988 /* 989 * Up to two groups of package elements are supported by the data 990 * structure. All elements in each group must be of the same type. 991 * The second group can have a count of zero. 992 */ 993 for (i = 0; i < Count1; i++) 994 { 995 Status = AcpiNsCheckObjectType (Data, ThisElement, 996 Type1, i + StartIndex); 997 if (ACPI_FAILURE (Status)) 998 { 999 return (Status); 1000 } 1001 ThisElement++; 1002 } 1003 1004 for (i = 0; i < Count2; i++) 1005 { 1006 Status = AcpiNsCheckObjectType (Data, ThisElement, 1007 Type2, (i + Count1 + StartIndex)); 1008 if (ACPI_FAILURE (Status)) 1009 { 1010 return (Status); 1011 } 1012 ThisElement++; 1013 } 1014 1015 return (AE_OK); 1016 } 1017 1018 1019 /******************************************************************************* 1020 * 1021 * FUNCTION: AcpiNsCheckObjectType 1022 * 1023 * PARAMETERS: Data - Pointer to validation data structure 1024 * ReturnObjectPtr - Pointer to the object returned from the 1025 * evaluation of a method or object 1026 * ExpectedBtypes - Bitmap of expected return type(s) 1027 * PackageIndex - Index of object within parent package (if 1028 * applicable - ACPI_NOT_PACKAGE_ELEMENT 1029 * otherwise) 1030 * 1031 * RETURN: Status 1032 * 1033 * DESCRIPTION: Check the type of the return object against the expected object 1034 * type(s). Use of Btype allows multiple expected object types. 1035 * 1036 ******************************************************************************/ 1037 1038 static ACPI_STATUS 1039 AcpiNsCheckObjectType ( 1040 ACPI_PREDEFINED_DATA *Data, 1041 ACPI_OPERAND_OBJECT **ReturnObjectPtr, 1042 UINT32 ExpectedBtypes, 1043 UINT32 PackageIndex) 1044 { 1045 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 1046 ACPI_STATUS Status = AE_OK; 1047 UINT32 ReturnBtype; 1048 char TypeBuffer[48]; /* Room for 5 types */ 1049 1050 1051 /* 1052 * If we get a NULL ReturnObject here, it is a NULL package element. 1053 * Since all extraneous NULL package elements were removed earlier by a 1054 * call to AcpiNsRemoveNullElements, this is an unexpected NULL element. 1055 * We will attempt to repair it. 1056 */ 1057 if (!ReturnObject) 1058 { 1059 Status = AcpiNsRepairNullElement (Data, ExpectedBtypes, 1060 PackageIndex, ReturnObjectPtr); 1061 if (ACPI_SUCCESS (Status)) 1062 { 1063 return (AE_OK); /* Repair was successful */ 1064 } 1065 goto TypeErrorExit; 1066 } 1067 1068 /* A Namespace node should not get here, but make sure */ 1069 1070 if (ACPI_GET_DESCRIPTOR_TYPE (ReturnObject) == ACPI_DESC_TYPE_NAMED) 1071 { 1072 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 1073 "Invalid return type - Found a Namespace node [%4.4s] type %s", 1074 ReturnObject->Node.Name.Ascii, 1075 AcpiUtGetTypeName (ReturnObject->Node.Type))); 1076 return (AE_AML_OPERAND_TYPE); 1077 } 1078 1079 /* 1080 * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type. 1081 * The bitmapped type allows multiple possible return types. 1082 * 1083 * Note, the cases below must handle all of the possible types returned 1084 * from all of the predefined names (including elements of returned 1085 * packages) 1086 */ 1087 switch (ReturnObject->Common.Type) 1088 { 1089 case ACPI_TYPE_INTEGER: 1090 ReturnBtype = ACPI_RTYPE_INTEGER; 1091 break; 1092 1093 case ACPI_TYPE_BUFFER: 1094 ReturnBtype = ACPI_RTYPE_BUFFER; 1095 break; 1096 1097 case ACPI_TYPE_STRING: 1098 ReturnBtype = ACPI_RTYPE_STRING; 1099 break; 1100 1101 case ACPI_TYPE_PACKAGE: 1102 ReturnBtype = ACPI_RTYPE_PACKAGE; 1103 break; 1104 1105 case ACPI_TYPE_LOCAL_REFERENCE: 1106 ReturnBtype = ACPI_RTYPE_REFERENCE; 1107 break; 1108 1109 default: 1110 /* Not one of the supported objects, must be incorrect */ 1111 1112 goto TypeErrorExit; 1113 } 1114 1115 /* Is the object one of the expected types? */ 1116 1117 if (ReturnBtype & ExpectedBtypes) 1118 { 1119 /* For reference objects, check that the reference type is correct */ 1120 1121 if (ReturnObject->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) 1122 { 1123 Status = AcpiNsCheckReference (Data, ReturnObject); 1124 } 1125 1126 return (Status); 1127 } 1128 1129 /* Type mismatch -- attempt repair of the returned object */ 1130 1131 Status = AcpiNsRepairObject (Data, ExpectedBtypes, 1132 PackageIndex, ReturnObjectPtr); 1133 if (ACPI_SUCCESS (Status)) 1134 { 1135 return (AE_OK); /* Repair was successful */ 1136 } 1137 1138 1139 TypeErrorExit: 1140 1141 /* Create a string with all expected types for this predefined object */ 1142 1143 AcpiNsGetExpectedTypes (TypeBuffer, ExpectedBtypes); 1144 1145 if (PackageIndex == ACPI_NOT_PACKAGE_ELEMENT) 1146 { 1147 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 1148 "Return type mismatch - found %s, expected %s", 1149 AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer)); 1150 } 1151 else 1152 { 1153 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 1154 "Return Package type mismatch at index %u - " 1155 "found %s, expected %s", PackageIndex, 1156 AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer)); 1157 } 1158 1159 return (AE_AML_OPERAND_TYPE); 1160 } 1161 1162 1163 /******************************************************************************* 1164 * 1165 * FUNCTION: AcpiNsCheckReference 1166 * 1167 * PARAMETERS: Data - Pointer to validation data structure 1168 * ReturnObject - Object returned from the evaluation of a 1169 * method or object 1170 * 1171 * RETURN: Status 1172 * 1173 * DESCRIPTION: Check a returned reference object for the correct reference 1174 * type. The only reference type that can be returned from a 1175 * predefined method is a named reference. All others are invalid. 1176 * 1177 ******************************************************************************/ 1178 1179 static ACPI_STATUS 1180 AcpiNsCheckReference ( 1181 ACPI_PREDEFINED_DATA *Data, 1182 ACPI_OPERAND_OBJECT *ReturnObject) 1183 { 1184 1185 /* 1186 * Check the reference object for the correct reference type (opcode). 1187 * The only type of reference that can be converted to an ACPI_OBJECT is 1188 * a reference to a named object (reference class: NAME) 1189 */ 1190 if (ReturnObject->Reference.Class == ACPI_REFCLASS_NAME) 1191 { 1192 return (AE_OK); 1193 } 1194 1195 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 1196 "Return type mismatch - unexpected reference object type [%s] %2.2X", 1197 AcpiUtGetReferenceName (ReturnObject), 1198 ReturnObject->Reference.Class)); 1199 1200 return (AE_AML_OPERAND_TYPE); 1201 } 1202 1203 1204 /******************************************************************************* 1205 * 1206 * FUNCTION: AcpiNsGetExpectedTypes 1207 * 1208 * PARAMETERS: Buffer - Pointer to where the string is returned 1209 * ExpectedBtypes - Bitmap of expected return type(s) 1210 * 1211 * RETURN: Buffer is populated with type names. 1212 * 1213 * DESCRIPTION: Translate the expected types bitmap into a string of ascii 1214 * names of expected types, for use in warning messages. 1215 * 1216 ******************************************************************************/ 1217 1218 static void 1219 AcpiNsGetExpectedTypes ( 1220 char *Buffer, 1221 UINT32 ExpectedBtypes) 1222 { 1223 UINT32 ThisRtype; 1224 UINT32 i; 1225 UINT32 j; 1226 1227 1228 j = 1; 1229 Buffer[0] = 0; 1230 ThisRtype = ACPI_RTYPE_INTEGER; 1231 1232 for (i = 0; i < ACPI_NUM_RTYPES; i++) 1233 { 1234 /* If one of the expected types, concatenate the name of this type */ 1235 1236 if (ExpectedBtypes & ThisRtype) 1237 { 1238 ACPI_STRCAT (Buffer, &AcpiRtypeNames[i][j]); 1239 j = 0; /* Use name separator from now on */ 1240 } 1241 ThisRtype <<= 1; /* Next Rtype */ 1242 } 1243 } 1244