1 /****************************************************************************** 2 * 3 * Module Name: nsrepair2 - Repair for objects returned by specific 4 * predefined methods 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2014, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #define __NSREPAIR2_C__ 46 47 #include "acpi.h" 48 #include "accommon.h" 49 #include "acnamesp.h" 50 51 #define _COMPONENT ACPI_NAMESPACE 52 ACPI_MODULE_NAME ("nsrepair2") 53 54 55 /* 56 * Information structure and handler for ACPI predefined names that can 57 * be repaired on a per-name basis. 58 */ 59 typedef 60 ACPI_STATUS (*ACPI_REPAIR_FUNCTION) ( 61 ACPI_EVALUATE_INFO *Info, 62 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 63 64 typedef struct acpi_repair_info 65 { 66 char Name[ACPI_NAME_SIZE]; 67 ACPI_REPAIR_FUNCTION RepairFunction; 68 69 } ACPI_REPAIR_INFO; 70 71 72 /* Local prototypes */ 73 74 static const ACPI_REPAIR_INFO * 75 AcpiNsMatchComplexRepair ( 76 ACPI_NAMESPACE_NODE *Node); 77 78 static ACPI_STATUS 79 AcpiNsRepair_ALR ( 80 ACPI_EVALUATE_INFO *Info, 81 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 82 83 static ACPI_STATUS 84 AcpiNsRepair_CID ( 85 ACPI_EVALUATE_INFO *Info, 86 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 87 88 static ACPI_STATUS 89 AcpiNsRepair_CST ( 90 ACPI_EVALUATE_INFO *Info, 91 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 92 93 static ACPI_STATUS 94 AcpiNsRepair_FDE ( 95 ACPI_EVALUATE_INFO *Info, 96 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 97 98 static ACPI_STATUS 99 AcpiNsRepair_HID ( 100 ACPI_EVALUATE_INFO *Info, 101 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 102 103 static ACPI_STATUS 104 AcpiNsRepair_PRT ( 105 ACPI_EVALUATE_INFO *Info, 106 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 107 108 static ACPI_STATUS 109 AcpiNsRepair_PSS ( 110 ACPI_EVALUATE_INFO *Info, 111 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 112 113 static ACPI_STATUS 114 AcpiNsRepair_TSS ( 115 ACPI_EVALUATE_INFO *Info, 116 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 117 118 static ACPI_STATUS 119 AcpiNsCheckSortedList ( 120 ACPI_EVALUATE_INFO *Info, 121 ACPI_OPERAND_OBJECT *ReturnObject, 122 UINT32 StartIndex, 123 UINT32 ExpectedCount, 124 UINT32 SortIndex, 125 UINT8 SortDirection, 126 char *SortKeyName); 127 128 /* Values for SortDirection above */ 129 130 #define ACPI_SORT_ASCENDING 0 131 #define ACPI_SORT_DESCENDING 1 132 133 static void 134 AcpiNsRemoveElement ( 135 ACPI_OPERAND_OBJECT *ObjDesc, 136 UINT32 Index); 137 138 static void 139 AcpiNsSortList ( 140 ACPI_OPERAND_OBJECT **Elements, 141 UINT32 Count, 142 UINT32 Index, 143 UINT8 SortDirection); 144 145 146 /* 147 * This table contains the names of the predefined methods for which we can 148 * perform more complex repairs. 149 * 150 * As necessary: 151 * 152 * _ALR: Sort the list ascending by AmbientIlluminance 153 * _CID: Strings: uppercase all, remove any leading asterisk 154 * _CST: Sort the list ascending by C state type 155 * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs 156 * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs 157 * _HID: Strings: uppercase all, remove any leading asterisk 158 * _PRT: Fix reversed SourceName and SourceIndex 159 * _PSS: Sort the list descending by Power 160 * _TSS: Sort the list descending by Power 161 * 162 * Names that must be packages, but cannot be sorted: 163 * 164 * _BCL: Values are tied to the Package index where they appear, and cannot 165 * be moved or sorted. These index values are used for _BQC and _BCM. 166 * However, we can fix the case where a buffer is returned, by converting 167 * it to a Package of integers. 168 */ 169 static const ACPI_REPAIR_INFO AcpiNsRepairableNames[] = 170 { 171 {"_ALR", AcpiNsRepair_ALR}, 172 {"_CID", AcpiNsRepair_CID}, 173 {"_CST", AcpiNsRepair_CST}, 174 {"_FDE", AcpiNsRepair_FDE}, 175 {"_GTM", AcpiNsRepair_FDE}, /* _GTM has same repair as _FDE */ 176 {"_HID", AcpiNsRepair_HID}, 177 {"_PRT", AcpiNsRepair_PRT}, 178 {"_PSS", AcpiNsRepair_PSS}, 179 {"_TSS", AcpiNsRepair_TSS}, 180 {{0,0,0,0}, NULL} /* Table terminator */ 181 }; 182 183 184 #define ACPI_FDE_FIELD_COUNT 5 185 #define ACPI_FDE_BYTE_BUFFER_SIZE 5 186 #define ACPI_FDE_DWORD_BUFFER_SIZE (ACPI_FDE_FIELD_COUNT * sizeof (UINT32)) 187 188 189 /****************************************************************************** 190 * 191 * FUNCTION: AcpiNsComplexRepairs 192 * 193 * PARAMETERS: Info - Method execution information block 194 * Node - Namespace node for the method/object 195 * ValidateStatus - Original status of earlier validation 196 * ReturnObjectPtr - Pointer to the object returned from the 197 * evaluation of a method or object 198 * 199 * RETURN: Status. AE_OK if repair was successful. If name is not 200 * matched, ValidateStatus is returned. 201 * 202 * DESCRIPTION: Attempt to repair/convert a return object of a type that was 203 * not expected. 204 * 205 *****************************************************************************/ 206 207 ACPI_STATUS 208 AcpiNsComplexRepairs ( 209 ACPI_EVALUATE_INFO *Info, 210 ACPI_NAMESPACE_NODE *Node, 211 ACPI_STATUS ValidateStatus, 212 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 213 { 214 const ACPI_REPAIR_INFO *Predefined; 215 ACPI_STATUS Status; 216 217 218 /* Check if this name is in the list of repairable names */ 219 220 Predefined = AcpiNsMatchComplexRepair (Node); 221 if (!Predefined) 222 { 223 return (ValidateStatus); 224 } 225 226 Status = Predefined->RepairFunction (Info, ReturnObjectPtr); 227 return (Status); 228 } 229 230 231 /****************************************************************************** 232 * 233 * FUNCTION: AcpiNsMatchComplexRepair 234 * 235 * PARAMETERS: Node - Namespace node for the method/object 236 * 237 * RETURN: Pointer to entry in repair table. NULL indicates not found. 238 * 239 * DESCRIPTION: Check an object name against the repairable object list. 240 * 241 *****************************************************************************/ 242 243 static const ACPI_REPAIR_INFO * 244 AcpiNsMatchComplexRepair ( 245 ACPI_NAMESPACE_NODE *Node) 246 { 247 const ACPI_REPAIR_INFO *ThisName; 248 249 250 /* Search info table for a repairable predefined method/object name */ 251 252 ThisName = AcpiNsRepairableNames; 253 while (ThisName->RepairFunction) 254 { 255 if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name)) 256 { 257 return (ThisName); 258 } 259 ThisName++; 260 } 261 262 return (NULL); /* Not found */ 263 } 264 265 266 /****************************************************************************** 267 * 268 * FUNCTION: AcpiNsRepair_ALR 269 * 270 * PARAMETERS: Info - Method execution information block 271 * ReturnObjectPtr - Pointer to the object returned from the 272 * evaluation of a method or object 273 * 274 * RETURN: Status. AE_OK if object is OK or was repaired successfully 275 * 276 * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list 277 * ascending by the ambient illuminance values. 278 * 279 *****************************************************************************/ 280 281 static ACPI_STATUS 282 AcpiNsRepair_ALR ( 283 ACPI_EVALUATE_INFO *Info, 284 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 285 { 286 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 287 ACPI_STATUS Status; 288 289 290 Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 2, 1, 291 ACPI_SORT_ASCENDING, "AmbientIlluminance"); 292 293 return (Status); 294 } 295 296 297 /****************************************************************************** 298 * 299 * FUNCTION: AcpiNsRepair_FDE 300 * 301 * PARAMETERS: Info - Method execution information block 302 * ReturnObjectPtr - Pointer to the object returned from the 303 * evaluation of a method or object 304 * 305 * RETURN: Status. AE_OK if object is OK or was repaired successfully 306 * 307 * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return 308 * value is a Buffer of 5 DWORDs. This function repairs a common 309 * problem where the return value is a Buffer of BYTEs, not 310 * DWORDs. 311 * 312 *****************************************************************************/ 313 314 static ACPI_STATUS 315 AcpiNsRepair_FDE ( 316 ACPI_EVALUATE_INFO *Info, 317 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 318 { 319 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 320 ACPI_OPERAND_OBJECT *BufferObject; 321 UINT8 *ByteBuffer; 322 UINT32 *DwordBuffer; 323 UINT32 i; 324 325 326 ACPI_FUNCTION_NAME (NsRepair_FDE); 327 328 329 switch (ReturnObject->Common.Type) 330 { 331 case ACPI_TYPE_BUFFER: 332 333 /* This is the expected type. Length should be (at least) 5 DWORDs */ 334 335 if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE) 336 { 337 return (AE_OK); 338 } 339 340 /* We can only repair if we have exactly 5 BYTEs */ 341 342 if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE) 343 { 344 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, 345 "Incorrect return buffer length %u, expected %u", 346 ReturnObject->Buffer.Length, ACPI_FDE_DWORD_BUFFER_SIZE)); 347 348 return (AE_AML_OPERAND_TYPE); 349 } 350 351 /* Create the new (larger) buffer object */ 352 353 BufferObject = AcpiUtCreateBufferObject (ACPI_FDE_DWORD_BUFFER_SIZE); 354 if (!BufferObject) 355 { 356 return (AE_NO_MEMORY); 357 } 358 359 /* Expand each byte to a DWORD */ 360 361 ByteBuffer = ReturnObject->Buffer.Pointer; 362 DwordBuffer = ACPI_CAST_PTR (UINT32, BufferObject->Buffer.Pointer); 363 364 for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) 365 { 366 *DwordBuffer = (UINT32) *ByteBuffer; 367 DwordBuffer++; 368 ByteBuffer++; 369 } 370 371 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 372 "%s Expanded Byte Buffer to expected DWord Buffer\n", 373 Info->FullPathname)); 374 break; 375 376 default: 377 378 return (AE_AML_OPERAND_TYPE); 379 } 380 381 /* Delete the original return object, return the new buffer object */ 382 383 AcpiUtRemoveReference (ReturnObject); 384 *ReturnObjectPtr = BufferObject; 385 386 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 387 return (AE_OK); 388 } 389 390 391 /****************************************************************************** 392 * 393 * FUNCTION: AcpiNsRepair_CID 394 * 395 * PARAMETERS: Info - Method execution information block 396 * ReturnObjectPtr - Pointer to the object returned from the 397 * evaluation of a method or object 398 * 399 * RETURN: Status. AE_OK if object is OK or was repaired successfully 400 * 401 * DESCRIPTION: Repair for the _CID object. If a string, ensure that all 402 * letters are uppercase and that there is no leading asterisk. 403 * If a Package, ensure same for all string elements. 404 * 405 *****************************************************************************/ 406 407 static ACPI_STATUS 408 AcpiNsRepair_CID ( 409 ACPI_EVALUATE_INFO *Info, 410 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 411 { 412 ACPI_STATUS Status; 413 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 414 ACPI_OPERAND_OBJECT **ElementPtr; 415 ACPI_OPERAND_OBJECT *OriginalElement; 416 UINT16 OriginalRefCount; 417 UINT32 i; 418 419 420 /* Check for _CID as a simple string */ 421 422 if (ReturnObject->Common.Type == ACPI_TYPE_STRING) 423 { 424 Status = AcpiNsRepair_HID (Info, ReturnObjectPtr); 425 return (Status); 426 } 427 428 /* Exit if not a Package */ 429 430 if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) 431 { 432 return (AE_OK); 433 } 434 435 /* Examine each element of the _CID package */ 436 437 ElementPtr = ReturnObject->Package.Elements; 438 for (i = 0; i < ReturnObject->Package.Count; i++) 439 { 440 OriginalElement = *ElementPtr; 441 OriginalRefCount = OriginalElement->Common.ReferenceCount; 442 443 Status = AcpiNsRepair_HID (Info, ElementPtr); 444 if (ACPI_FAILURE (Status)) 445 { 446 return (Status); 447 } 448 449 /* Take care with reference counts */ 450 451 if (OriginalElement != *ElementPtr) 452 { 453 /* Element was replaced */ 454 455 (*ElementPtr)->Common.ReferenceCount = 456 OriginalRefCount; 457 458 AcpiUtRemoveReference (OriginalElement); 459 } 460 461 ElementPtr++; 462 } 463 464 return (AE_OK); 465 } 466 467 468 /****************************************************************************** 469 * 470 * FUNCTION: AcpiNsRepair_CST 471 * 472 * PARAMETERS: Info - Method execution information block 473 * ReturnObjectPtr - Pointer to the object returned from the 474 * evaluation of a method or object 475 * 476 * RETURN: Status. AE_OK if object is OK or was repaired successfully 477 * 478 * DESCRIPTION: Repair for the _CST object: 479 * 1. Sort the list ascending by C state type 480 * 2. Ensure type cannot be zero 481 * 3. A sub-package count of zero means _CST is meaningless 482 * 4. Count must match the number of C state sub-packages 483 * 484 *****************************************************************************/ 485 486 static ACPI_STATUS 487 AcpiNsRepair_CST ( 488 ACPI_EVALUATE_INFO *Info, 489 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 490 { 491 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 492 ACPI_OPERAND_OBJECT **OuterElements; 493 UINT32 OuterElementCount; 494 ACPI_OPERAND_OBJECT *ObjDesc; 495 ACPI_STATUS Status; 496 BOOLEAN Removing; 497 UINT32 i; 498 499 500 ACPI_FUNCTION_NAME (NsRepair_CST); 501 502 503 /* 504 * Check if the C-state type values are proportional. 505 */ 506 OuterElementCount = ReturnObject->Package.Count - 1; 507 i = 0; 508 while (i < OuterElementCount) 509 { 510 OuterElements = &ReturnObject->Package.Elements[i + 1]; 511 Removing = FALSE; 512 513 if ((*OuterElements)->Package.Count == 0) 514 { 515 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, 516 "SubPackage[%u] - removing entry due to zero count", i)); 517 Removing = TRUE; 518 goto RemoveElement; 519 } 520 521 ObjDesc = (*OuterElements)->Package.Elements[1]; /* Index1 = Type */ 522 if ((UINT32) ObjDesc->Integer.Value == 0) 523 { 524 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, 525 "SubPackage[%u] - removing entry due to invalid Type(0)", i)); 526 Removing = TRUE; 527 } 528 529 RemoveElement: 530 if (Removing) 531 { 532 AcpiNsRemoveElement (ReturnObject, i + 1); 533 OuterElementCount--; 534 } 535 else 536 { 537 i++; 538 } 539 } 540 541 /* Update top-level package count, Type "Integer" checked elsewhere */ 542 543 ObjDesc = ReturnObject->Package.Elements[0]; 544 ObjDesc->Integer.Value = OuterElementCount; 545 546 /* 547 * Entries (subpackages) in the _CST Package must be sorted by the 548 * C-state type, in ascending order. 549 */ 550 Status = AcpiNsCheckSortedList (Info, ReturnObject, 1, 4, 1, 551 ACPI_SORT_ASCENDING, "C-State Type"); 552 if (ACPI_FAILURE (Status)) 553 { 554 return (Status); 555 } 556 557 return (AE_OK); 558 } 559 560 561 /****************************************************************************** 562 * 563 * FUNCTION: AcpiNsRepair_HID 564 * 565 * PARAMETERS: Info - Method execution information block 566 * ReturnObjectPtr - Pointer to the object returned from the 567 * evaluation of a method or object 568 * 569 * RETURN: Status. AE_OK if object is OK or was repaired successfully 570 * 571 * DESCRIPTION: Repair for the _HID object. If a string, ensure that all 572 * letters are uppercase and that there is no leading asterisk. 573 * 574 *****************************************************************************/ 575 576 static ACPI_STATUS 577 AcpiNsRepair_HID ( 578 ACPI_EVALUATE_INFO *Info, 579 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 580 { 581 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 582 ACPI_OPERAND_OBJECT *NewString; 583 char *Source; 584 char *Dest; 585 586 587 ACPI_FUNCTION_NAME (NsRepair_HID); 588 589 590 /* We only care about string _HID objects (not integers) */ 591 592 if (ReturnObject->Common.Type != ACPI_TYPE_STRING) 593 { 594 return (AE_OK); 595 } 596 597 if (ReturnObject->String.Length == 0) 598 { 599 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, 600 "Invalid zero-length _HID or _CID string")); 601 602 /* Return AE_OK anyway, let driver handle it */ 603 604 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 605 return (AE_OK); 606 } 607 608 /* It is simplest to always create a new string object */ 609 610 NewString = AcpiUtCreateStringObject (ReturnObject->String.Length); 611 if (!NewString) 612 { 613 return (AE_NO_MEMORY); 614 } 615 616 /* 617 * Remove a leading asterisk if present. For some unknown reason, there 618 * are many machines in the field that contains IDs like this. 619 * 620 * Examples: "*PNP0C03", "*ACPI0003" 621 */ 622 Source = ReturnObject->String.Pointer; 623 if (*Source == '*') 624 { 625 Source++; 626 NewString->String.Length--; 627 628 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 629 "%s: Removed invalid leading asterisk\n", Info->FullPathname)); 630 } 631 632 /* 633 * Copy and uppercase the string. From the ACPI 5.0 specification: 634 * 635 * A valid PNP ID must be of the form "AAA####" where A is an uppercase 636 * letter and # is a hex digit. A valid ACPI ID must be of the form 637 * "NNNN####" where N is an uppercase letter or decimal digit, and 638 * # is a hex digit. 639 */ 640 for (Dest = NewString->String.Pointer; *Source; Dest++, Source++) 641 { 642 *Dest = (char) ACPI_TOUPPER (*Source); 643 } 644 645 AcpiUtRemoveReference (ReturnObject); 646 *ReturnObjectPtr = NewString; 647 return (AE_OK); 648 } 649 650 651 /****************************************************************************** 652 * 653 * FUNCTION: AcpiNsRepair_PRT 654 * 655 * PARAMETERS: Info - Method execution information block 656 * ReturnObjectPtr - Pointer to the object returned from the 657 * evaluation of a method or object 658 * 659 * RETURN: Status. AE_OK if object is OK or was repaired successfully 660 * 661 * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed 662 * SourceName and SourceIndex field, a common BIOS bug. 663 * 664 *****************************************************************************/ 665 666 static ACPI_STATUS 667 AcpiNsRepair_PRT ( 668 ACPI_EVALUATE_INFO *Info, 669 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 670 { 671 ACPI_OPERAND_OBJECT *PackageObject = *ReturnObjectPtr; 672 ACPI_OPERAND_OBJECT **TopObjectList; 673 ACPI_OPERAND_OBJECT **SubObjectList; 674 ACPI_OPERAND_OBJECT *ObjDesc; 675 UINT32 ElementCount; 676 UINT32 Index; 677 678 679 /* Each element in the _PRT package is a subpackage */ 680 681 TopObjectList = PackageObject->Package.Elements; 682 ElementCount = PackageObject->Package.Count; 683 684 for (Index = 0; Index < ElementCount; Index++) 685 { 686 SubObjectList = (*TopObjectList)->Package.Elements; 687 688 /* 689 * If the BIOS has erroneously reversed the _PRT SourceName (index 2) 690 * and the SourceIndex (index 3), fix it. _PRT is important enough to 691 * workaround this BIOS error. This also provides compatibility with 692 * other ACPI implementations. 693 */ 694 ObjDesc = SubObjectList[3]; 695 if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)) 696 { 697 SubObjectList[3] = SubObjectList[2]; 698 SubObjectList[2] = ObjDesc; 699 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 700 701 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, 702 "PRT[%X]: Fixed reversed SourceName and SourceIndex", 703 Index)); 704 } 705 706 /* Point to the next ACPI_OPERAND_OBJECT in the top level package */ 707 708 TopObjectList++; 709 } 710 711 return (AE_OK); 712 } 713 714 715 /****************************************************************************** 716 * 717 * FUNCTION: AcpiNsRepair_PSS 718 * 719 * PARAMETERS: Info - Method execution information block 720 * ReturnObjectPtr - Pointer to the object returned from the 721 * evaluation of a method or object 722 * 723 * RETURN: Status. AE_OK if object is OK or was repaired successfully 724 * 725 * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list 726 * by the CPU frequencies. Check that the power dissipation values 727 * are all proportional to CPU frequency (i.e., sorting by 728 * frequency should be the same as sorting by power.) 729 * 730 *****************************************************************************/ 731 732 static ACPI_STATUS 733 AcpiNsRepair_PSS ( 734 ACPI_EVALUATE_INFO *Info, 735 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 736 { 737 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 738 ACPI_OPERAND_OBJECT **OuterElements; 739 UINT32 OuterElementCount; 740 ACPI_OPERAND_OBJECT **Elements; 741 ACPI_OPERAND_OBJECT *ObjDesc; 742 UINT32 PreviousValue; 743 ACPI_STATUS Status; 744 UINT32 i; 745 746 747 /* 748 * Entries (sub-packages) in the _PSS Package must be sorted by power 749 * dissipation, in descending order. If it appears that the list is 750 * incorrectly sorted, sort it. We sort by CpuFrequency, since this 751 * should be proportional to the power. 752 */ 753 Status =AcpiNsCheckSortedList (Info, ReturnObject, 0, 6, 0, 754 ACPI_SORT_DESCENDING, "CpuFrequency"); 755 if (ACPI_FAILURE (Status)) 756 { 757 return (Status); 758 } 759 760 /* 761 * We now know the list is correctly sorted by CPU frequency. Check if 762 * the power dissipation values are proportional. 763 */ 764 PreviousValue = ACPI_UINT32_MAX; 765 OuterElements = ReturnObject->Package.Elements; 766 OuterElementCount = ReturnObject->Package.Count; 767 768 for (i = 0; i < OuterElementCount; i++) 769 { 770 Elements = (*OuterElements)->Package.Elements; 771 ObjDesc = Elements[1]; /* Index1 = PowerDissipation */ 772 773 if ((UINT32) ObjDesc->Integer.Value > PreviousValue) 774 { 775 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, 776 "SubPackage[%u,%u] - suspicious power dissipation values", 777 i-1, i)); 778 } 779 780 PreviousValue = (UINT32) ObjDesc->Integer.Value; 781 OuterElements++; 782 } 783 784 return (AE_OK); 785 } 786 787 788 /****************************************************************************** 789 * 790 * FUNCTION: AcpiNsRepair_TSS 791 * 792 * PARAMETERS: Info - Method execution information block 793 * ReturnObjectPtr - Pointer to the object returned from the 794 * evaluation of a method or object 795 * 796 * RETURN: Status. AE_OK if object is OK or was repaired successfully 797 * 798 * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list 799 * descending by the power dissipation values. 800 * 801 *****************************************************************************/ 802 803 static ACPI_STATUS 804 AcpiNsRepair_TSS ( 805 ACPI_EVALUATE_INFO *Info, 806 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 807 { 808 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 809 ACPI_STATUS Status; 810 ACPI_NAMESPACE_NODE *Node; 811 812 813 /* 814 * We can only sort the _TSS return package if there is no _PSS in the 815 * same scope. This is because if _PSS is present, the ACPI specification 816 * dictates that the _TSS Power Dissipation field is to be ignored, and 817 * therefore some BIOSs leave garbage values in the _TSS Power field(s). 818 * In this case, it is best to just return the _TSS package as-is. 819 * (May, 2011) 820 */ 821 Status = AcpiNsGetNode (Info->Node, "^_PSS", 822 ACPI_NS_NO_UPSEARCH, &Node); 823 if (ACPI_SUCCESS (Status)) 824 { 825 return (AE_OK); 826 } 827 828 Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 5, 1, 829 ACPI_SORT_DESCENDING, "PowerDissipation"); 830 831 return (Status); 832 } 833 834 835 /****************************************************************************** 836 * 837 * FUNCTION: AcpiNsCheckSortedList 838 * 839 * PARAMETERS: Info - Method execution information block 840 * ReturnObject - Pointer to the top-level returned object 841 * StartIndex - Index of the first sub-package 842 * ExpectedCount - Minimum length of each sub-package 843 * SortIndex - Sub-package entry to sort on 844 * SortDirection - Ascending or descending 845 * SortKeyName - Name of the SortIndex field 846 * 847 * RETURN: Status. AE_OK if the list is valid and is sorted correctly or 848 * has been repaired by sorting the list. 849 * 850 * DESCRIPTION: Check if the package list is valid and sorted correctly by the 851 * SortIndex. If not, then sort the list. 852 * 853 *****************************************************************************/ 854 855 static ACPI_STATUS 856 AcpiNsCheckSortedList ( 857 ACPI_EVALUATE_INFO *Info, 858 ACPI_OPERAND_OBJECT *ReturnObject, 859 UINT32 StartIndex, 860 UINT32 ExpectedCount, 861 UINT32 SortIndex, 862 UINT8 SortDirection, 863 char *SortKeyName) 864 { 865 UINT32 OuterElementCount; 866 ACPI_OPERAND_OBJECT **OuterElements; 867 ACPI_OPERAND_OBJECT **Elements; 868 ACPI_OPERAND_OBJECT *ObjDesc; 869 UINT32 i; 870 UINT32 PreviousValue; 871 872 873 ACPI_FUNCTION_NAME (NsCheckSortedList); 874 875 876 /* The top-level object must be a package */ 877 878 if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) 879 { 880 return (AE_AML_OPERAND_TYPE); 881 } 882 883 /* 884 * NOTE: assumes list of sub-packages contains no NULL elements. 885 * Any NULL elements should have been removed by earlier call 886 * to AcpiNsRemoveNullElements. 887 */ 888 OuterElementCount = ReturnObject->Package.Count; 889 if (!OuterElementCount || StartIndex >= OuterElementCount) 890 { 891 return (AE_AML_PACKAGE_LIMIT); 892 } 893 894 OuterElements = &ReturnObject->Package.Elements[StartIndex]; 895 OuterElementCount -= StartIndex; 896 897 PreviousValue = 0; 898 if (SortDirection == ACPI_SORT_DESCENDING) 899 { 900 PreviousValue = ACPI_UINT32_MAX; 901 } 902 903 /* Examine each subpackage */ 904 905 for (i = 0; i < OuterElementCount; i++) 906 { 907 /* Each element of the top-level package must also be a package */ 908 909 if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE) 910 { 911 return (AE_AML_OPERAND_TYPE); 912 } 913 914 /* Each sub-package must have the minimum length */ 915 916 if ((*OuterElements)->Package.Count < ExpectedCount) 917 { 918 return (AE_AML_PACKAGE_LIMIT); 919 } 920 921 Elements = (*OuterElements)->Package.Elements; 922 ObjDesc = Elements[SortIndex]; 923 924 if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) 925 { 926 return (AE_AML_OPERAND_TYPE); 927 } 928 929 /* 930 * The list must be sorted in the specified order. If we detect a 931 * discrepancy, sort the entire list. 932 */ 933 if (((SortDirection == ACPI_SORT_ASCENDING) && 934 (ObjDesc->Integer.Value < PreviousValue)) || 935 ((SortDirection == ACPI_SORT_DESCENDING) && 936 (ObjDesc->Integer.Value > PreviousValue))) 937 { 938 AcpiNsSortList (&ReturnObject->Package.Elements[StartIndex], 939 OuterElementCount, SortIndex, SortDirection); 940 941 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 942 943 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 944 "%s: Repaired unsorted list - now sorted by %s\n", 945 Info->FullPathname, SortKeyName)); 946 return (AE_OK); 947 } 948 949 PreviousValue = (UINT32) ObjDesc->Integer.Value; 950 OuterElements++; 951 } 952 953 return (AE_OK); 954 } 955 956 957 /****************************************************************************** 958 * 959 * FUNCTION: AcpiNsSortList 960 * 961 * PARAMETERS: Elements - Package object element list 962 * Count - Element count for above 963 * Index - Sort by which package element 964 * SortDirection - Ascending or Descending sort 965 * 966 * RETURN: None 967 * 968 * DESCRIPTION: Sort the objects that are in a package element list. 969 * 970 * NOTE: Assumes that all NULL elements have been removed from the package, 971 * and that all elements have been verified to be of type Integer. 972 * 973 *****************************************************************************/ 974 975 static void 976 AcpiNsSortList ( 977 ACPI_OPERAND_OBJECT **Elements, 978 UINT32 Count, 979 UINT32 Index, 980 UINT8 SortDirection) 981 { 982 ACPI_OPERAND_OBJECT *ObjDesc1; 983 ACPI_OPERAND_OBJECT *ObjDesc2; 984 ACPI_OPERAND_OBJECT *TempObj; 985 UINT32 i; 986 UINT32 j; 987 988 989 /* Simple bubble sort */ 990 991 for (i = 1; i < Count; i++) 992 { 993 for (j = (Count - 1); j >= i; j--) 994 { 995 ObjDesc1 = Elements[j-1]->Package.Elements[Index]; 996 ObjDesc2 = Elements[j]->Package.Elements[Index]; 997 998 if (((SortDirection == ACPI_SORT_ASCENDING) && 999 (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) || 1000 1001 ((SortDirection == ACPI_SORT_DESCENDING) && 1002 (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value))) 1003 { 1004 TempObj = Elements[j-1]; 1005 Elements[j-1] = Elements[j]; 1006 Elements[j] = TempObj; 1007 } 1008 } 1009 } 1010 } 1011 1012 1013 /****************************************************************************** 1014 * 1015 * FUNCTION: AcpiNsRemoveElement 1016 * 1017 * PARAMETERS: ObjDesc - Package object element list 1018 * Index - Index of element to remove 1019 * 1020 * RETURN: None 1021 * 1022 * DESCRIPTION: Remove the requested element of a package and delete it. 1023 * 1024 *****************************************************************************/ 1025 1026 static void 1027 AcpiNsRemoveElement ( 1028 ACPI_OPERAND_OBJECT *ObjDesc, 1029 UINT32 Index) 1030 { 1031 ACPI_OPERAND_OBJECT **Source; 1032 ACPI_OPERAND_OBJECT **Dest; 1033 UINT32 Count; 1034 UINT32 NewCount; 1035 UINT32 i; 1036 1037 1038 ACPI_FUNCTION_NAME (NsRemoveElement); 1039 1040 1041 Count = ObjDesc->Package.Count; 1042 NewCount = Count - 1; 1043 1044 Source = ObjDesc->Package.Elements; 1045 Dest = Source; 1046 1047 /* Examine all elements of the package object, remove matched index */ 1048 1049 for (i = 0; i < Count; i++) 1050 { 1051 if (i == Index) 1052 { 1053 AcpiUtRemoveReference (*Source); /* Remove one ref for being in pkg */ 1054 AcpiUtRemoveReference (*Source); 1055 } 1056 else 1057 { 1058 *Dest = *Source; 1059 Dest++; 1060 } 1061 Source++; 1062 } 1063 1064 /* NULL terminate list and update the package count */ 1065 1066 *Dest = NULL; 1067 ObjDesc->Package.Count = NewCount; 1068 }