nspredef.c revision 1.1.1.3
1/****************************************************************************** 2 * 3 * Module Name: nspredef - Validation of ACPI predefined methods and objects 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2011, 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 "acpi.h" 47#include "accommon.h" 48#include "acnamesp.h" 49#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 80static ACPI_STATUS 81AcpiNsCheckPackage ( 82 ACPI_PREDEFINED_DATA *Data, 83 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 84 85static ACPI_STATUS 86AcpiNsCheckPackageList ( 87 ACPI_PREDEFINED_DATA *Data, 88 const ACPI_PREDEFINED_INFO *Package, 89 ACPI_OPERAND_OBJECT **Elements, 90 UINT32 Count); 91 92static ACPI_STATUS 93AcpiNsCheckPackageElements ( 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 102static ACPI_STATUS 103AcpiNsCheckObjectType ( 104 ACPI_PREDEFINED_DATA *Data, 105 ACPI_OPERAND_OBJECT **ReturnObjectPtr, 106 UINT32 ExpectedBtypes, 107 UINT32 PackageIndex); 108 109static ACPI_STATUS 110AcpiNsCheckReference ( 111 ACPI_PREDEFINED_DATA *Data, 112 ACPI_OPERAND_OBJECT *ReturnObject); 113 114static void 115AcpiNsGetExpectedTypes ( 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 */ 123static 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 149ACPI_STATUS 150AcpiNsCheckPredefinedNames ( 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 285Exit: 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 297Cleanup: 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 320void 321AcpiNsCheckParameterCount ( 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 411const ACPI_PREDEFINED_INFO * 412AcpiNsCheckForPredefinedName ( 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 466static ACPI_STATUS 467AcpiNsCheckPackage ( 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 669 /* 670 * These types all return a single Package that consists of a 671 * variable number of sub-Packages. 672 * 673 * First, ensure that the first element is a sub-Package. If not, 674 * the BIOS may have incorrectly returned the object as a single 675 * package instead of a Package of Packages (a common error if 676 * there is only one entry). We may be able to repair this by 677 * wrapping the returned Package with a new outer Package. 678 */ 679 if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE)) 680 { 681 /* Create the new outer package and populate it */ 682 683 Status = AcpiNsRepairPackageList (Data, ReturnObjectPtr); 684 if (ACPI_FAILURE (Status)) 685 { 686 return (Status); 687 } 688 689 /* Update locals to point to the new package (of 1 element) */ 690 691 ReturnObject = *ReturnObjectPtr; 692 Elements = ReturnObject->Package.Elements; 693 Count = 1; 694 } 695 696 /* Examine the sub-packages */ 697 698 Status = AcpiNsCheckPackageList (Data, Package, Elements, Count); 699 break; 700 701 702 default: 703 704 /* Should not get here if predefined info table is correct */ 705 706 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 707 "Invalid internal return type in table entry: %X", 708 Package->RetInfo.Type)); 709 710 return (AE_AML_INTERNAL); 711 } 712 713 return (Status); 714 715 716PackageTooSmall: 717 718 /* Error exit for the case with an incorrect package count */ 719 720 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 721 "Return Package is too small - found %u elements, expected %u", 722 Count, ExpectedCount)); 723 724 return (AE_AML_OPERAND_VALUE); 725} 726 727 728/******************************************************************************* 729 * 730 * FUNCTION: AcpiNsCheckPackageList 731 * 732 * PARAMETERS: Data - Pointer to validation data structure 733 * Package - Pointer to package-specific info for method 734 * Elements - Element list of parent package. All elements 735 * of this list should be of type Package. 736 * Count - Count of subpackages 737 * 738 * RETURN: Status 739 * 740 * DESCRIPTION: Examine a list of subpackages 741 * 742 ******************************************************************************/ 743 744static ACPI_STATUS 745AcpiNsCheckPackageList ( 746 ACPI_PREDEFINED_DATA *Data, 747 const ACPI_PREDEFINED_INFO *Package, 748 ACPI_OPERAND_OBJECT **Elements, 749 UINT32 Count) 750{ 751 ACPI_OPERAND_OBJECT *SubPackage; 752 ACPI_OPERAND_OBJECT **SubElements; 753 ACPI_STATUS Status; 754 UINT32 ExpectedCount; 755 UINT32 i; 756 UINT32 j; 757 758 759 /* 760 * Validate each sub-Package in the parent Package 761 * 762 * NOTE: assumes list of sub-packages contains no NULL elements. 763 * Any NULL elements should have been removed by earlier call 764 * to AcpiNsRemoveNullElements. 765 */ 766 for (i = 0; i < Count; i++) 767 { 768 SubPackage = *Elements; 769 SubElements = SubPackage->Package.Elements; 770 Data->ParentPackage = SubPackage; 771 772 /* Each sub-object must be of type Package */ 773 774 Status = AcpiNsCheckObjectType (Data, &SubPackage, 775 ACPI_RTYPE_PACKAGE, i); 776 if (ACPI_FAILURE (Status)) 777 { 778 return (Status); 779 } 780 781 /* Examine the different types of expected sub-packages */ 782 783 Data->ParentPackage = SubPackage; 784 switch (Package->RetInfo.Type) 785 { 786 case ACPI_PTYPE2: 787 case ACPI_PTYPE2_PKG_COUNT: 788 case ACPI_PTYPE2_REV_FIXED: 789 790 /* Each subpackage has a fixed number of elements */ 791 792 ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 793 if (SubPackage->Package.Count < ExpectedCount) 794 { 795 goto PackageTooSmall; 796 } 797 798 Status = AcpiNsCheckPackageElements (Data, SubElements, 799 Package->RetInfo.ObjectType1, 800 Package->RetInfo.Count1, 801 Package->RetInfo.ObjectType2, 802 Package->RetInfo.Count2, 0); 803 if (ACPI_FAILURE (Status)) 804 { 805 return (Status); 806 } 807 break; 808 809 810 case ACPI_PTYPE2_FIXED: 811 812 /* Each sub-package has a fixed length */ 813 814 ExpectedCount = Package->RetInfo2.Count; 815 if (SubPackage->Package.Count < ExpectedCount) 816 { 817 goto PackageTooSmall; 818 } 819 820 /* Check the type of each sub-package element */ 821 822 for (j = 0; j < ExpectedCount; j++) 823 { 824 Status = AcpiNsCheckObjectType (Data, &SubElements[j], 825 Package->RetInfo2.ObjectType[j], j); 826 if (ACPI_FAILURE (Status)) 827 { 828 return (Status); 829 } 830 } 831 break; 832 833 834 case ACPI_PTYPE2_MIN: 835 836 /* Each sub-package has a variable but minimum length */ 837 838 ExpectedCount = Package->RetInfo.Count1; 839 if (SubPackage->Package.Count < ExpectedCount) 840 { 841 goto PackageTooSmall; 842 } 843 844 /* Check the type of each sub-package element */ 845 846 Status = AcpiNsCheckPackageElements (Data, SubElements, 847 Package->RetInfo.ObjectType1, 848 SubPackage->Package.Count, 0, 0, 0); 849 if (ACPI_FAILURE (Status)) 850 { 851 return (Status); 852 } 853 break; 854 855 856 case ACPI_PTYPE2_COUNT: 857 858 /* 859 * First element is the (Integer) count of elements, including 860 * the count field (the ACPI name is NumElements) 861 */ 862 Status = AcpiNsCheckObjectType (Data, SubElements, 863 ACPI_RTYPE_INTEGER, 0); 864 if (ACPI_FAILURE (Status)) 865 { 866 return (Status); 867 } 868 869 /* 870 * Make sure package is large enough for the Count and is 871 * is as large as the minimum size 872 */ 873 ExpectedCount = (UINT32) (*SubElements)->Integer.Value; 874 if (SubPackage->Package.Count < ExpectedCount) 875 { 876 goto PackageTooSmall; 877 } 878 if (SubPackage->Package.Count < Package->RetInfo.Count1) 879 { 880 ExpectedCount = Package->RetInfo.Count1; 881 goto PackageTooSmall; 882 } 883 if (ExpectedCount == 0) 884 { 885 /* 886 * Either the NumEntries element was originally zero or it was 887 * a NULL element and repaired to an Integer of value zero. 888 * In either case, repair it by setting NumEntries to be the 889 * actual size of the subpackage. 890 */ 891 ExpectedCount = SubPackage->Package.Count; 892 (*SubElements)->Integer.Value = ExpectedCount; 893 } 894 895 /* Check the type of each sub-package element */ 896 897 Status = AcpiNsCheckPackageElements (Data, (SubElements + 1), 898 Package->RetInfo.ObjectType1, 899 (ExpectedCount - 1), 0, 0, 1); 900 if (ACPI_FAILURE (Status)) 901 { 902 return (Status); 903 } 904 break; 905 906 907 default: /* Should not get here, type was validated by caller */ 908 909 return (AE_AML_INTERNAL); 910 } 911 912 Elements++; 913 } 914 915 return (AE_OK); 916 917 918PackageTooSmall: 919 920 /* The sub-package count was smaller than required */ 921 922 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 923 "Return Sub-Package[%u] is too small - found %u elements, expected %u", 924 i, SubPackage->Package.Count, ExpectedCount)); 925 926 return (AE_AML_OPERAND_VALUE); 927} 928 929 930/******************************************************************************* 931 * 932 * FUNCTION: AcpiNsCheckPackageElements 933 * 934 * PARAMETERS: Data - Pointer to validation data structure 935 * Elements - Pointer to the package elements array 936 * Type1 - Object type for first group 937 * Count1 - Count for first group 938 * Type2 - Object type for second group 939 * Count2 - Count for second group 940 * StartIndex - Start of the first group of elements 941 * 942 * RETURN: Status 943 * 944 * DESCRIPTION: Check that all elements of a package are of the correct object 945 * type. Supports up to two groups of different object types. 946 * 947 ******************************************************************************/ 948 949static ACPI_STATUS 950AcpiNsCheckPackageElements ( 951 ACPI_PREDEFINED_DATA *Data, 952 ACPI_OPERAND_OBJECT **Elements, 953 UINT8 Type1, 954 UINT32 Count1, 955 UINT8 Type2, 956 UINT32 Count2, 957 UINT32 StartIndex) 958{ 959 ACPI_OPERAND_OBJECT **ThisElement = Elements; 960 ACPI_STATUS Status; 961 UINT32 i; 962 963 964 /* 965 * Up to two groups of package elements are supported by the data 966 * structure. All elements in each group must be of the same type. 967 * The second group can have a count of zero. 968 */ 969 for (i = 0; i < Count1; i++) 970 { 971 Status = AcpiNsCheckObjectType (Data, ThisElement, 972 Type1, i + StartIndex); 973 if (ACPI_FAILURE (Status)) 974 { 975 return (Status); 976 } 977 ThisElement++; 978 } 979 980 for (i = 0; i < Count2; i++) 981 { 982 Status = AcpiNsCheckObjectType (Data, ThisElement, 983 Type2, (i + Count1 + StartIndex)); 984 if (ACPI_FAILURE (Status)) 985 { 986 return (Status); 987 } 988 ThisElement++; 989 } 990 991 return (AE_OK); 992} 993 994 995/******************************************************************************* 996 * 997 * FUNCTION: AcpiNsCheckObjectType 998 * 999 * PARAMETERS: Data - Pointer to validation data structure 1000 * ReturnObjectPtr - Pointer to the object returned from the 1001 * evaluation of a method or object 1002 * ExpectedBtypes - Bitmap of expected return type(s) 1003 * PackageIndex - Index of object within parent package (if 1004 * applicable - ACPI_NOT_PACKAGE_ELEMENT 1005 * otherwise) 1006 * 1007 * RETURN: Status 1008 * 1009 * DESCRIPTION: Check the type of the return object against the expected object 1010 * type(s). Use of Btype allows multiple expected object types. 1011 * 1012 ******************************************************************************/ 1013 1014static ACPI_STATUS 1015AcpiNsCheckObjectType ( 1016 ACPI_PREDEFINED_DATA *Data, 1017 ACPI_OPERAND_OBJECT **ReturnObjectPtr, 1018 UINT32 ExpectedBtypes, 1019 UINT32 PackageIndex) 1020{ 1021 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 1022 ACPI_STATUS Status = AE_OK; 1023 UINT32 ReturnBtype; 1024 char TypeBuffer[48]; /* Room for 5 types */ 1025 1026 1027 /* 1028 * If we get a NULL ReturnObject here, it is a NULL package element. 1029 * Since all extraneous NULL package elements were removed earlier by a 1030 * call to AcpiNsRemoveNullElements, this is an unexpected NULL element. 1031 * We will attempt to repair it. 1032 */ 1033 if (!ReturnObject) 1034 { 1035 Status = AcpiNsRepairNullElement (Data, ExpectedBtypes, 1036 PackageIndex, ReturnObjectPtr); 1037 if (ACPI_SUCCESS (Status)) 1038 { 1039 return (AE_OK); /* Repair was successful */ 1040 } 1041 goto TypeErrorExit; 1042 } 1043 1044 /* A Namespace node should not get here, but make sure */ 1045 1046 if (ACPI_GET_DESCRIPTOR_TYPE (ReturnObject) == ACPI_DESC_TYPE_NAMED) 1047 { 1048 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 1049 "Invalid return type - Found a Namespace node [%4.4s] type %s", 1050 ReturnObject->Node.Name.Ascii, 1051 AcpiUtGetTypeName (ReturnObject->Node.Type))); 1052 return (AE_AML_OPERAND_TYPE); 1053 } 1054 1055 /* 1056 * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type. 1057 * The bitmapped type allows multiple possible return types. 1058 * 1059 * Note, the cases below must handle all of the possible types returned 1060 * from all of the predefined names (including elements of returned 1061 * packages) 1062 */ 1063 switch (ReturnObject->Common.Type) 1064 { 1065 case ACPI_TYPE_INTEGER: 1066 ReturnBtype = ACPI_RTYPE_INTEGER; 1067 break; 1068 1069 case ACPI_TYPE_BUFFER: 1070 ReturnBtype = ACPI_RTYPE_BUFFER; 1071 break; 1072 1073 case ACPI_TYPE_STRING: 1074 ReturnBtype = ACPI_RTYPE_STRING; 1075 break; 1076 1077 case ACPI_TYPE_PACKAGE: 1078 ReturnBtype = ACPI_RTYPE_PACKAGE; 1079 break; 1080 1081 case ACPI_TYPE_LOCAL_REFERENCE: 1082 ReturnBtype = ACPI_RTYPE_REFERENCE; 1083 break; 1084 1085 default: 1086 /* Not one of the supported objects, must be incorrect */ 1087 1088 goto TypeErrorExit; 1089 } 1090 1091 /* Is the object one of the expected types? */ 1092 1093 if (ReturnBtype & ExpectedBtypes) 1094 { 1095 /* For reference objects, check that the reference type is correct */ 1096 1097 if (ReturnObject->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) 1098 { 1099 Status = AcpiNsCheckReference (Data, ReturnObject); 1100 } 1101 1102 return (Status); 1103 } 1104 1105 /* Type mismatch -- attempt repair of the returned object */ 1106 1107 Status = AcpiNsRepairObject (Data, ExpectedBtypes, 1108 PackageIndex, ReturnObjectPtr); 1109 if (ACPI_SUCCESS (Status)) 1110 { 1111 return (AE_OK); /* Repair was successful */ 1112 } 1113 1114 1115TypeErrorExit: 1116 1117 /* Create a string with all expected types for this predefined object */ 1118 1119 AcpiNsGetExpectedTypes (TypeBuffer, ExpectedBtypes); 1120 1121 if (PackageIndex == ACPI_NOT_PACKAGE_ELEMENT) 1122 { 1123 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 1124 "Return type mismatch - found %s, expected %s", 1125 AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer)); 1126 } 1127 else 1128 { 1129 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 1130 "Return Package type mismatch at index %u - " 1131 "found %s, expected %s", PackageIndex, 1132 AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer)); 1133 } 1134 1135 return (AE_AML_OPERAND_TYPE); 1136} 1137 1138 1139/******************************************************************************* 1140 * 1141 * FUNCTION: AcpiNsCheckReference 1142 * 1143 * PARAMETERS: Data - Pointer to validation data structure 1144 * ReturnObject - Object returned from the evaluation of a 1145 * method or object 1146 * 1147 * RETURN: Status 1148 * 1149 * DESCRIPTION: Check a returned reference object for the correct reference 1150 * type. The only reference type that can be returned from a 1151 * predefined method is a named reference. All others are invalid. 1152 * 1153 ******************************************************************************/ 1154 1155static ACPI_STATUS 1156AcpiNsCheckReference ( 1157 ACPI_PREDEFINED_DATA *Data, 1158 ACPI_OPERAND_OBJECT *ReturnObject) 1159{ 1160 1161 /* 1162 * Check the reference object for the correct reference type (opcode). 1163 * The only type of reference that can be converted to an ACPI_OBJECT is 1164 * a reference to a named object (reference class: NAME) 1165 */ 1166 if (ReturnObject->Reference.Class == ACPI_REFCLASS_NAME) 1167 { 1168 return (AE_OK); 1169 } 1170 1171 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 1172 "Return type mismatch - unexpected reference object type [%s] %2.2X", 1173 AcpiUtGetReferenceName (ReturnObject), 1174 ReturnObject->Reference.Class)); 1175 1176 return (AE_AML_OPERAND_TYPE); 1177} 1178 1179 1180/******************************************************************************* 1181 * 1182 * FUNCTION: AcpiNsGetExpectedTypes 1183 * 1184 * PARAMETERS: Buffer - Pointer to where the string is returned 1185 * ExpectedBtypes - Bitmap of expected return type(s) 1186 * 1187 * RETURN: Buffer is populated with type names. 1188 * 1189 * DESCRIPTION: Translate the expected types bitmap into a string of ascii 1190 * names of expected types, for use in warning messages. 1191 * 1192 ******************************************************************************/ 1193 1194static void 1195AcpiNsGetExpectedTypes ( 1196 char *Buffer, 1197 UINT32 ExpectedBtypes) 1198{ 1199 UINT32 ThisRtype; 1200 UINT32 i; 1201 UINT32 j; 1202 1203 1204 j = 1; 1205 Buffer[0] = 0; 1206 ThisRtype = ACPI_RTYPE_INTEGER; 1207 1208 for (i = 0; i < ACPI_NUM_RTYPES; i++) 1209 { 1210 /* If one of the expected types, concatenate the name of this type */ 1211 1212 if (ExpectedBtypes & ThisRtype) 1213 { 1214 ACPI_STRCAT (Buffer, &AcpiRtypeNames[i][j]); 1215 j = 0; /* Use name separator from now on */ 1216 } 1217 ThisRtype <<= 1; /* Next Rtype */ 1218 } 1219} 1220