1 /****************************************************************************** 2 * 3 * Module Name: nsrepair2 - Repair for objects returned by specific 4 * predefined methods 5 * 6 *****************************************************************************/ 7 8 /****************************************************************************** 9 * 10 * 1. Copyright Notice 11 * 12 * Some or all of this work - Copyright (c) 1999 - 2012, Intel Corp. 13 * All rights reserved. 14 * 15 * 2. License 16 * 17 * 2.1. This is your license from Intel Corp. under its intellectual property 18 * rights. You may have additional license terms from the party that provided 19 * you this software, covering your right to use that party's intellectual 20 * property rights. 21 * 22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 23 * copy of the source code appearing in this file ("Covered Code") an 24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 25 * base code distributed originally by Intel ("Original Intel Code") to copy, 26 * make derivatives, distribute, use and display any portion of the Covered 27 * Code in any form, with the right to sublicense such rights; and 28 * 29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 30 * license (with the right to sublicense), under only those claims of Intel 31 * patents that are infringed by the Original Intel Code, to make, use, sell, 32 * offer to sell, and import the Covered Code and derivative works thereof 33 * solely to the minimum extent necessary to exercise the above copyright 34 * license, and in no event shall the patent license extend to any additions 35 * to or modifications of the Original Intel Code. No other license or right 36 * is granted directly or by implication, estoppel or otherwise; 37 * 38 * The above copyright and patent license is granted only if the following 39 * conditions are met: 40 * 41 * 3. Conditions 42 * 43 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 44 * Redistribution of source code of any substantial portion of the Covered 45 * Code or modification with rights to further distribute source must include 46 * the above Copyright Notice, the above License, this list of Conditions, 47 * and the following Disclaimer and Export Compliance provision. In addition, 48 * Licensee must cause all Covered Code to which Licensee contributes to 49 * contain a file documenting the changes Licensee made to create that Covered 50 * Code and the date of any change. Licensee must include in that file the 51 * documentation of any changes made by any predecessor Licensee. Licensee 52 * must include a prominent statement that the modification is derived, 53 * directly or indirectly, from Original Intel Code. 54 * 55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 56 * Redistribution of source code of any substantial portion of the Covered 57 * Code or modification without rights to further distribute source must 58 * include the following Disclaimer and Export Compliance provision in the 59 * documentation and/or other materials provided with distribution. In 60 * addition, Licensee may not authorize further sublicense of source of any 61 * portion of the Covered Code, and must include terms to the effect that the 62 * license from Licensee to its licensee is limited to the intellectual 63 * property embodied in the software Licensee provides to its licensee, and 64 * not to intellectual property embodied in modifications its licensee may 65 * make. 66 * 67 * 3.3. Redistribution of Executable. Redistribution in executable form of any 68 * substantial portion of the Covered Code or modification must reproduce the 69 * above Copyright Notice, and the following Disclaimer and Export Compliance 70 * provision in the documentation and/or other materials provided with the 71 * distribution. 72 * 73 * 3.4. Intel retains all right, title, and interest in and to the Original 74 * Intel Code. 75 * 76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 77 * Intel shall be used in advertising or otherwise to promote the sale, use or 78 * other dealings in products derived from or relating to the Covered Code 79 * without prior written authorization from Intel. 80 * 81 * 4. Disclaimer and Export Compliance 82 * 83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 84 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 86 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 87 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 89 * PARTICULAR PURPOSE. 90 * 91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 98 * LIMITED REMEDY. 99 * 100 * 4.3. Licensee shall not export, either directly or indirectly, any of this 101 * software or system incorporating such software without first obtaining any 102 * required license or other approval from the U. S. Department of Commerce or 103 * any other agency or department of the United States Government. In the 104 * event Licensee exports any such software from the United States or 105 * re-exports any such software from a foreign destination, Licensee shall 106 * ensure that the distribution and export/re-export of the software is in 107 * compliance with all laws, regulations, orders, or other restrictions of the 108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 109 * any of its subsidiaries will export/re-export any technical data, process, 110 * software, or service, directly or indirectly, to any country for which the 111 * United States government or any agency thereof requires an export license, 112 * other governmental approval, or letter of assurance, without first obtaining 113 * such license, approval or letter. 114 * 115 *****************************************************************************/ 116 117 #define __NSREPAIR2_C__ 118 119 #include "acpi.h" 120 #include "accommon.h" 121 #include "acnamesp.h" 122 123 #define _COMPONENT ACPI_NAMESPACE 124 ACPI_MODULE_NAME ("nsrepair2") 125 126 127 /* 128 * Information structure and handler for ACPI predefined names that can 129 * be repaired on a per-name basis. 130 */ 131 typedef 132 ACPI_STATUS (*ACPI_REPAIR_FUNCTION) ( 133 ACPI_PREDEFINED_DATA *Data, 134 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 135 136 typedef struct acpi_repair_info 137 { 138 char Name[ACPI_NAME_SIZE]; 139 ACPI_REPAIR_FUNCTION RepairFunction; 140 141 } ACPI_REPAIR_INFO; 142 143 144 /* Local prototypes */ 145 146 static const ACPI_REPAIR_INFO * 147 AcpiNsMatchRepairableName ( 148 ACPI_NAMESPACE_NODE *Node); 149 150 static ACPI_STATUS 151 AcpiNsRepair_ALR ( 152 ACPI_PREDEFINED_DATA *Data, 153 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 154 155 static ACPI_STATUS 156 AcpiNsRepair_CID ( 157 ACPI_PREDEFINED_DATA *Data, 158 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 159 160 static ACPI_STATUS 161 AcpiNsRepair_FDE ( 162 ACPI_PREDEFINED_DATA *Data, 163 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 164 165 static ACPI_STATUS 166 AcpiNsRepair_HID ( 167 ACPI_PREDEFINED_DATA *Data, 168 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 169 170 static ACPI_STATUS 171 AcpiNsRepair_PSS ( 172 ACPI_PREDEFINED_DATA *Data, 173 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 174 175 static ACPI_STATUS 176 AcpiNsRepair_TSS ( 177 ACPI_PREDEFINED_DATA *Data, 178 ACPI_OPERAND_OBJECT **ReturnObjectPtr); 179 180 static ACPI_STATUS 181 AcpiNsCheckSortedList ( 182 ACPI_PREDEFINED_DATA *Data, 183 ACPI_OPERAND_OBJECT *ReturnObject, 184 UINT32 ExpectedCount, 185 UINT32 SortIndex, 186 UINT8 SortDirection, 187 char *SortKeyName); 188 189 static void 190 AcpiNsSortList ( 191 ACPI_OPERAND_OBJECT **Elements, 192 UINT32 Count, 193 UINT32 Index, 194 UINT8 SortDirection); 195 196 /* Values for SortDirection above */ 197 198 #define ACPI_SORT_ASCENDING 0 199 #define ACPI_SORT_DESCENDING 1 200 201 202 /* 203 * This table contains the names of the predefined methods for which we can 204 * perform more complex repairs. 205 * 206 * As necessary: 207 * 208 * _ALR: Sort the list ascending by AmbientIlluminance 209 * _CID: Strings: uppercase all, remove any leading asterisk 210 * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs 211 * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs 212 * _HID: Strings: uppercase all, remove any leading asterisk 213 * _PSS: Sort the list descending by Power 214 * _TSS: Sort the list descending by Power 215 * 216 * Names that must be packages, but cannot be sorted: 217 * 218 * _BCL: Values are tied to the Package index where they appear, and cannot 219 * be moved or sorted. These index values are used for _BQC and _BCM. 220 * However, we can fix the case where a buffer is returned, by converting 221 * it to a Package of integers. 222 */ 223 static const ACPI_REPAIR_INFO AcpiNsRepairableNames[] = 224 { 225 {"_ALR", AcpiNsRepair_ALR}, 226 {"_CID", AcpiNsRepair_CID}, 227 {"_FDE", AcpiNsRepair_FDE}, 228 {"_GTM", AcpiNsRepair_FDE}, /* _GTM has same repair as _FDE */ 229 {"_HID", AcpiNsRepair_HID}, 230 {"_PSS", AcpiNsRepair_PSS}, 231 {"_TSS", AcpiNsRepair_TSS}, 232 {{0,0,0,0}, NULL} /* Table terminator */ 233 }; 234 235 236 #define ACPI_FDE_FIELD_COUNT 5 237 #define ACPI_FDE_BYTE_BUFFER_SIZE 5 238 #define ACPI_FDE_DWORD_BUFFER_SIZE (ACPI_FDE_FIELD_COUNT * sizeof (UINT32)) 239 240 241 /****************************************************************************** 242 * 243 * FUNCTION: AcpiNsComplexRepairs 244 * 245 * PARAMETERS: Data - Pointer to validation data structure 246 * Node - Namespace node for the method/object 247 * ValidateStatus - Original status of earlier validation 248 * ReturnObjectPtr - Pointer to the object returned from the 249 * evaluation of a method or object 250 * 251 * RETURN: Status. AE_OK if repair was successful. If name is not 252 * matched, ValidateStatus is returned. 253 * 254 * DESCRIPTION: Attempt to repair/convert a return object of a type that was 255 * not expected. 256 * 257 *****************************************************************************/ 258 259 ACPI_STATUS 260 AcpiNsComplexRepairs ( 261 ACPI_PREDEFINED_DATA *Data, 262 ACPI_NAMESPACE_NODE *Node, 263 ACPI_STATUS ValidateStatus, 264 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 265 { 266 const ACPI_REPAIR_INFO *Predefined; 267 ACPI_STATUS Status; 268 269 270 /* Check if this name is in the list of repairable names */ 271 272 Predefined = AcpiNsMatchRepairableName (Node); 273 if (!Predefined) 274 { 275 return (ValidateStatus); 276 } 277 278 Status = Predefined->RepairFunction (Data, ReturnObjectPtr); 279 return (Status); 280 } 281 282 283 /****************************************************************************** 284 * 285 * FUNCTION: AcpiNsMatchRepairableName 286 * 287 * PARAMETERS: Node - Namespace node for the method/object 288 * 289 * RETURN: Pointer to entry in repair table. NULL indicates not found. 290 * 291 * DESCRIPTION: Check an object name against the repairable object list. 292 * 293 *****************************************************************************/ 294 295 static const ACPI_REPAIR_INFO * 296 AcpiNsMatchRepairableName ( 297 ACPI_NAMESPACE_NODE *Node) 298 { 299 const ACPI_REPAIR_INFO *ThisName; 300 301 302 /* Search info table for a repairable predefined method/object name */ 303 304 ThisName = AcpiNsRepairableNames; 305 while (ThisName->RepairFunction) 306 { 307 if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name)) 308 { 309 return (ThisName); 310 } 311 ThisName++; 312 } 313 314 return (NULL); /* Not found */ 315 } 316 317 318 /****************************************************************************** 319 * 320 * FUNCTION: AcpiNsRepair_ALR 321 * 322 * PARAMETERS: Data - Pointer to validation data structure 323 * ReturnObjectPtr - Pointer to the object returned from the 324 * evaluation of a method or object 325 * 326 * RETURN: Status. AE_OK if object is OK or was repaired successfully 327 * 328 * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list 329 * ascending by the ambient illuminance values. 330 * 331 *****************************************************************************/ 332 333 static ACPI_STATUS 334 AcpiNsRepair_ALR ( 335 ACPI_PREDEFINED_DATA *Data, 336 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 337 { 338 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 339 ACPI_STATUS Status; 340 341 342 Status = AcpiNsCheckSortedList (Data, ReturnObject, 2, 1, 343 ACPI_SORT_ASCENDING, "AmbientIlluminance"); 344 345 return (Status); 346 } 347 348 349 /****************************************************************************** 350 * 351 * FUNCTION: AcpiNsRepair_FDE 352 * 353 * PARAMETERS: Data - Pointer to validation data structure 354 * ReturnObjectPtr - Pointer to the object returned from the 355 * evaluation of a method or object 356 * 357 * RETURN: Status. AE_OK if object is OK or was repaired successfully 358 * 359 * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return 360 * value is a Buffer of 5 DWORDs. This function repairs a common 361 * problem where the return value is a Buffer of BYTEs, not 362 * DWORDs. 363 * 364 *****************************************************************************/ 365 366 static ACPI_STATUS 367 AcpiNsRepair_FDE ( 368 ACPI_PREDEFINED_DATA *Data, 369 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 370 { 371 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 372 ACPI_OPERAND_OBJECT *BufferObject; 373 UINT8 *ByteBuffer; 374 UINT32 *DwordBuffer; 375 UINT32 i; 376 377 378 ACPI_FUNCTION_NAME (NsRepair_FDE); 379 380 381 switch (ReturnObject->Common.Type) 382 { 383 case ACPI_TYPE_BUFFER: 384 385 /* This is the expected type. Length should be (at least) 5 DWORDs */ 386 387 if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE) 388 { 389 return (AE_OK); 390 } 391 392 /* We can only repair if we have exactly 5 BYTEs */ 393 394 if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE) 395 { 396 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 397 "Incorrect return buffer length %u, expected %u", 398 ReturnObject->Buffer.Length, ACPI_FDE_DWORD_BUFFER_SIZE)); 399 400 return (AE_AML_OPERAND_TYPE); 401 } 402 403 /* Create the new (larger) buffer object */ 404 405 BufferObject = AcpiUtCreateBufferObject (ACPI_FDE_DWORD_BUFFER_SIZE); 406 if (!BufferObject) 407 { 408 return (AE_NO_MEMORY); 409 } 410 411 /* Expand each byte to a DWORD */ 412 413 ByteBuffer = ReturnObject->Buffer.Pointer; 414 DwordBuffer = ACPI_CAST_PTR (UINT32, BufferObject->Buffer.Pointer); 415 416 for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) 417 { 418 *DwordBuffer = (UINT32) *ByteBuffer; 419 DwordBuffer++; 420 ByteBuffer++; 421 } 422 423 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 424 "%s Expanded Byte Buffer to expected DWord Buffer\n", 425 Data->Pathname)); 426 break; 427 428 default: 429 return (AE_AML_OPERAND_TYPE); 430 } 431 432 /* Delete the original return object, return the new buffer object */ 433 434 AcpiUtRemoveReference (ReturnObject); 435 *ReturnObjectPtr = BufferObject; 436 437 Data->Flags |= ACPI_OBJECT_REPAIRED; 438 return (AE_OK); 439 } 440 441 442 /****************************************************************************** 443 * 444 * FUNCTION: AcpiNsRepair_CID 445 * 446 * PARAMETERS: Data - Pointer to validation data structure 447 * ReturnObjectPtr - Pointer to the object returned from the 448 * evaluation of a method or object 449 * 450 * RETURN: Status. AE_OK if object is OK or was repaired successfully 451 * 452 * DESCRIPTION: Repair for the _CID object. If a string, ensure that all 453 * letters are uppercase and that there is no leading asterisk. 454 * If a Package, ensure same for all string elements. 455 * 456 *****************************************************************************/ 457 458 static ACPI_STATUS 459 AcpiNsRepair_CID ( 460 ACPI_PREDEFINED_DATA *Data, 461 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 462 { 463 ACPI_STATUS Status; 464 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 465 ACPI_OPERAND_OBJECT **ElementPtr; 466 ACPI_OPERAND_OBJECT *OriginalElement; 467 UINT16 OriginalRefCount; 468 UINT32 i; 469 470 471 /* Check for _CID as a simple string */ 472 473 if (ReturnObject->Common.Type == ACPI_TYPE_STRING) 474 { 475 Status = AcpiNsRepair_HID (Data, ReturnObjectPtr); 476 return (Status); 477 } 478 479 /* Exit if not a Package */ 480 481 if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) 482 { 483 return (AE_OK); 484 } 485 486 /* Examine each element of the _CID package */ 487 488 ElementPtr = ReturnObject->Package.Elements; 489 for (i = 0; i < ReturnObject->Package.Count; i++) 490 { 491 OriginalElement = *ElementPtr; 492 OriginalRefCount = OriginalElement->Common.ReferenceCount; 493 494 Status = AcpiNsRepair_HID (Data, ElementPtr); 495 if (ACPI_FAILURE (Status)) 496 { 497 return (Status); 498 } 499 500 /* Take care with reference counts */ 501 502 if (OriginalElement != *ElementPtr) 503 { 504 /* Element was replaced */ 505 506 (*ElementPtr)->Common.ReferenceCount = 507 OriginalRefCount; 508 509 AcpiUtRemoveReference (OriginalElement); 510 } 511 512 ElementPtr++; 513 } 514 515 return (AE_OK); 516 } 517 518 519 /****************************************************************************** 520 * 521 * FUNCTION: AcpiNsRepair_HID 522 * 523 * PARAMETERS: Data - Pointer to validation data structure 524 * ReturnObjectPtr - Pointer to the object returned from the 525 * evaluation of a method or object 526 * 527 * RETURN: Status. AE_OK if object is OK or was repaired successfully 528 * 529 * DESCRIPTION: Repair for the _HID object. If a string, ensure that all 530 * letters are uppercase and that there is no leading asterisk. 531 * 532 *****************************************************************************/ 533 534 static ACPI_STATUS 535 AcpiNsRepair_HID ( 536 ACPI_PREDEFINED_DATA *Data, 537 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 538 { 539 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 540 ACPI_OPERAND_OBJECT *NewString; 541 char *Source; 542 char *Dest; 543 544 545 ACPI_FUNCTION_NAME (NsRepair_HID); 546 547 548 /* We only care about string _HID objects (not integers) */ 549 550 if (ReturnObject->Common.Type != ACPI_TYPE_STRING) 551 { 552 return (AE_OK); 553 } 554 555 if (ReturnObject->String.Length == 0) 556 { 557 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 558 "Invalid zero-length _HID or _CID string")); 559 560 /* Return AE_OK anyway, let driver handle it */ 561 562 Data->Flags |= ACPI_OBJECT_REPAIRED; 563 return (AE_OK); 564 } 565 566 /* It is simplest to always create a new string object */ 567 568 NewString = AcpiUtCreateStringObject (ReturnObject->String.Length); 569 if (!NewString) 570 { 571 return (AE_NO_MEMORY); 572 } 573 574 /* 575 * Remove a leading asterisk if present. For some unknown reason, there 576 * are many machines in the field that contains IDs like this. 577 * 578 * Examples: "*PNP0C03", "*ACPI0003" 579 */ 580 Source = ReturnObject->String.Pointer; 581 if (*Source == '*') 582 { 583 Source++; 584 NewString->String.Length--; 585 586 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 587 "%s: Removed invalid leading asterisk\n", Data->Pathname)); 588 } 589 590 /* 591 * Copy and uppercase the string. From the ACPI 5.0 specification: 592 * 593 * A valid PNP ID must be of the form "AAA####" where A is an uppercase 594 * letter and # is a hex digit. A valid ACPI ID must be of the form 595 * "NNNN####" where N is an uppercase letter or decimal digit, and 596 * # is a hex digit. 597 */ 598 for (Dest = NewString->String.Pointer; *Source; Dest++, Source++) 599 { 600 *Dest = (char) ACPI_TOUPPER (*Source); 601 } 602 603 AcpiUtRemoveReference (ReturnObject); 604 *ReturnObjectPtr = NewString; 605 return (AE_OK); 606 } 607 608 609 /****************************************************************************** 610 * 611 * FUNCTION: AcpiNsRepair_TSS 612 * 613 * PARAMETERS: Data - Pointer to validation data structure 614 * ReturnObjectPtr - Pointer to the object returned from the 615 * evaluation of a method or object 616 * 617 * RETURN: Status. AE_OK if object is OK or was repaired successfully 618 * 619 * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list 620 * descending by the power dissipation values. 621 * 622 *****************************************************************************/ 623 624 static ACPI_STATUS 625 AcpiNsRepair_TSS ( 626 ACPI_PREDEFINED_DATA *Data, 627 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 628 { 629 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 630 ACPI_STATUS Status; 631 ACPI_NAMESPACE_NODE *Node; 632 633 634 /* 635 * We can only sort the _TSS return package if there is no _PSS in the 636 * same scope. This is because if _PSS is present, the ACPI specification 637 * dictates that the _TSS Power Dissipation field is to be ignored, and 638 * therefore some BIOSs leave garbage values in the _TSS Power field(s). 639 * In this case, it is best to just return the _TSS package as-is. 640 * (May, 2011) 641 */ 642 Status = AcpiNsGetNode (Data->Node, "^_PSS", ACPI_NS_NO_UPSEARCH, &Node); 643 if (ACPI_SUCCESS (Status)) 644 { 645 return (AE_OK); 646 } 647 648 Status = AcpiNsCheckSortedList (Data, ReturnObject, 5, 1, 649 ACPI_SORT_DESCENDING, "PowerDissipation"); 650 651 return (Status); 652 } 653 654 655 /****************************************************************************** 656 * 657 * FUNCTION: AcpiNsRepair_PSS 658 * 659 * PARAMETERS: Data - Pointer to validation data structure 660 * ReturnObjectPtr - Pointer to the object returned from the 661 * evaluation of a method or object 662 * 663 * RETURN: Status. AE_OK if object is OK or was repaired successfully 664 * 665 * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list 666 * by the CPU frequencies. Check that the power dissipation values 667 * are all proportional to CPU frequency (i.e., sorting by 668 * frequency should be the same as sorting by power.) 669 * 670 *****************************************************************************/ 671 672 static ACPI_STATUS 673 AcpiNsRepair_PSS ( 674 ACPI_PREDEFINED_DATA *Data, 675 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 676 { 677 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 678 ACPI_OPERAND_OBJECT **OuterElements; 679 UINT32 OuterElementCount; 680 ACPI_OPERAND_OBJECT **Elements; 681 ACPI_OPERAND_OBJECT *ObjDesc; 682 UINT32 PreviousValue; 683 ACPI_STATUS Status; 684 UINT32 i; 685 686 687 /* 688 * Entries (sub-packages) in the _PSS Package must be sorted by power 689 * dissipation, in descending order. If it appears that the list is 690 * incorrectly sorted, sort it. We sort by CpuFrequency, since this 691 * should be proportional to the power. 692 */ 693 Status =AcpiNsCheckSortedList (Data, ReturnObject, 6, 0, 694 ACPI_SORT_DESCENDING, "CpuFrequency"); 695 if (ACPI_FAILURE (Status)) 696 { 697 return (Status); 698 } 699 700 /* 701 * We now know the list is correctly sorted by CPU frequency. Check if 702 * the power dissipation values are proportional. 703 */ 704 PreviousValue = ACPI_UINT32_MAX; 705 OuterElements = ReturnObject->Package.Elements; 706 OuterElementCount = ReturnObject->Package.Count; 707 708 for (i = 0; i < OuterElementCount; i++) 709 { 710 Elements = (*OuterElements)->Package.Elements; 711 ObjDesc = Elements[1]; /* Index1 = PowerDissipation */ 712 713 if ((UINT32) ObjDesc->Integer.Value > PreviousValue) 714 { 715 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 716 "SubPackage[%u,%u] - suspicious power dissipation values", 717 i-1, i)); 718 } 719 720 PreviousValue = (UINT32) ObjDesc->Integer.Value; 721 OuterElements++; 722 } 723 724 return (AE_OK); 725 } 726 727 728 /****************************************************************************** 729 * 730 * FUNCTION: AcpiNsCheckSortedList 731 * 732 * PARAMETERS: Data - Pointer to validation data structure 733 * ReturnObject - Pointer to the top-level returned object 734 * ExpectedCount - Minimum length of each sub-package 735 * SortIndex - Sub-package entry to sort on 736 * SortDirection - Ascending or descending 737 * SortKeyName - Name of the SortIndex field 738 * 739 * RETURN: Status. AE_OK if the list is valid and is sorted correctly or 740 * has been repaired by sorting the list. 741 * 742 * DESCRIPTION: Check if the package list is valid and sorted correctly by the 743 * SortIndex. If not, then sort the list. 744 * 745 *****************************************************************************/ 746 747 static ACPI_STATUS 748 AcpiNsCheckSortedList ( 749 ACPI_PREDEFINED_DATA *Data, 750 ACPI_OPERAND_OBJECT *ReturnObject, 751 UINT32 ExpectedCount, 752 UINT32 SortIndex, 753 UINT8 SortDirection, 754 char *SortKeyName) 755 { 756 UINT32 OuterElementCount; 757 ACPI_OPERAND_OBJECT **OuterElements; 758 ACPI_OPERAND_OBJECT **Elements; 759 ACPI_OPERAND_OBJECT *ObjDesc; 760 UINT32 i; 761 UINT32 PreviousValue; 762 763 764 ACPI_FUNCTION_NAME (NsCheckSortedList); 765 766 767 /* The top-level object must be a package */ 768 769 if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) 770 { 771 return (AE_AML_OPERAND_TYPE); 772 } 773 774 /* 775 * NOTE: assumes list of sub-packages contains no NULL elements. 776 * Any NULL elements should have been removed by earlier call 777 * to AcpiNsRemoveNullElements. 778 */ 779 OuterElements = ReturnObject->Package.Elements; 780 OuterElementCount = ReturnObject->Package.Count; 781 if (!OuterElementCount) 782 { 783 return (AE_AML_PACKAGE_LIMIT); 784 } 785 786 PreviousValue = 0; 787 if (SortDirection == ACPI_SORT_DESCENDING) 788 { 789 PreviousValue = ACPI_UINT32_MAX; 790 } 791 792 /* Examine each subpackage */ 793 794 for (i = 0; i < OuterElementCount; i++) 795 { 796 /* Each element of the top-level package must also be a package */ 797 798 if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE) 799 { 800 return (AE_AML_OPERAND_TYPE); 801 } 802 803 /* Each sub-package must have the minimum length */ 804 805 if ((*OuterElements)->Package.Count < ExpectedCount) 806 { 807 return (AE_AML_PACKAGE_LIMIT); 808 } 809 810 Elements = (*OuterElements)->Package.Elements; 811 ObjDesc = Elements[SortIndex]; 812 813 if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) 814 { 815 return (AE_AML_OPERAND_TYPE); 816 } 817 818 /* 819 * The list must be sorted in the specified order. If we detect a 820 * discrepancy, sort the entire list. 821 */ 822 if (((SortDirection == ACPI_SORT_ASCENDING) && 823 (ObjDesc->Integer.Value < PreviousValue)) || 824 ((SortDirection == ACPI_SORT_DESCENDING) && 825 (ObjDesc->Integer.Value > PreviousValue))) 826 { 827 AcpiNsSortList (ReturnObject->Package.Elements, 828 OuterElementCount, SortIndex, SortDirection); 829 830 Data->Flags |= ACPI_OBJECT_REPAIRED; 831 832 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 833 "%s: Repaired unsorted list - now sorted by %s\n", 834 Data->Pathname, SortKeyName)); 835 return (AE_OK); 836 } 837 838 PreviousValue = (UINT32) ObjDesc->Integer.Value; 839 OuterElements++; 840 } 841 842 return (AE_OK); 843 } 844 845 846 /****************************************************************************** 847 * 848 * FUNCTION: AcpiNsSortList 849 * 850 * PARAMETERS: Elements - Package object element list 851 * Count - Element count for above 852 * Index - Sort by which package element 853 * SortDirection - Ascending or Descending sort 854 * 855 * RETURN: None 856 * 857 * DESCRIPTION: Sort the objects that are in a package element list. 858 * 859 * NOTE: Assumes that all NULL elements have been removed from the package, 860 * and that all elements have been verified to be of type Integer. 861 * 862 *****************************************************************************/ 863 864 static void 865 AcpiNsSortList ( 866 ACPI_OPERAND_OBJECT **Elements, 867 UINT32 Count, 868 UINT32 Index, 869 UINT8 SortDirection) 870 { 871 ACPI_OPERAND_OBJECT *ObjDesc1; 872 ACPI_OPERAND_OBJECT *ObjDesc2; 873 ACPI_OPERAND_OBJECT *TempObj; 874 UINT32 i; 875 UINT32 j; 876 877 878 /* Simple bubble sort */ 879 880 for (i = 1; i < Count; i++) 881 { 882 for (j = (Count - 1); j >= i; j--) 883 { 884 ObjDesc1 = Elements[j-1]->Package.Elements[Index]; 885 ObjDesc2 = Elements[j]->Package.Elements[Index]; 886 887 if (((SortDirection == ACPI_SORT_ASCENDING) && 888 (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) || 889 890 ((SortDirection == ACPI_SORT_DESCENDING) && 891 (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value))) 892 { 893 TempObj = Elements[j-1]; 894 Elements[j-1] = Elements[j]; 895 Elements[j] = TempObj; 896 } 897 } 898 } 899 } 900