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