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 - 2021, 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 ElementPtr++; 571 } 572 573 return_ACPI_STATUS (AE_OK); 574 } 575 576 577 /****************************************************************************** 578 * 579 * FUNCTION: AcpiNsRepair_CST 580 * 581 * PARAMETERS: Info - Method execution information block 582 * ReturnObjectPtr - Pointer to the object returned from the 583 * evaluation of a method or object 584 * 585 * RETURN: Status. AE_OK if object is OK or was repaired successfully 586 * 587 * DESCRIPTION: Repair for the _CST object: 588 * 1. Sort the list ascending by C state type 589 * 2. Ensure type cannot be zero 590 * 3. A subpackage count of zero means _CST is meaningless 591 * 4. Count must match the number of C state subpackages 592 * 593 *****************************************************************************/ 594 595 static ACPI_STATUS 596 AcpiNsRepair_CST ( 597 ACPI_EVALUATE_INFO *Info, 598 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 599 { 600 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 601 ACPI_OPERAND_OBJECT **OuterElements; 602 UINT32 OuterElementCount; 603 ACPI_OPERAND_OBJECT *ObjDesc; 604 ACPI_STATUS Status; 605 BOOLEAN Removing; 606 UINT32 i; 607 608 609 ACPI_FUNCTION_NAME (NsRepair_CST); 610 611 612 /* 613 * Check if the C-state type values are proportional. 614 */ 615 OuterElementCount = ReturnObject->Package.Count - 1; 616 i = 0; 617 while (i < OuterElementCount) 618 { 619 OuterElements = &ReturnObject->Package.Elements[i + 1]; 620 Removing = FALSE; 621 622 if ((*OuterElements)->Package.Count == 0) 623 { 624 ACPI_WARN_PREDEFINED ((AE_INFO, 625 Info->FullPathname, Info->NodeFlags, 626 "SubPackage[%u] - removing entry due to zero count", i)); 627 Removing = TRUE; 628 goto RemoveElement; 629 } 630 631 ObjDesc = (*OuterElements)->Package.Elements[1]; /* Index1 = Type */ 632 if ((UINT32) ObjDesc->Integer.Value == 0) 633 { 634 ACPI_WARN_PREDEFINED ((AE_INFO, 635 Info->FullPathname, Info->NodeFlags, 636 "SubPackage[%u] - removing entry due to invalid Type(0)", i)); 637 Removing = TRUE; 638 } 639 640 RemoveElement: 641 if (Removing) 642 { 643 AcpiNsRemoveElement (ReturnObject, i + 1); 644 OuterElementCount--; 645 } 646 else 647 { 648 i++; 649 } 650 } 651 652 /* Update top-level package count, Type "Integer" checked elsewhere */ 653 654 ObjDesc = ReturnObject->Package.Elements[0]; 655 ObjDesc->Integer.Value = OuterElementCount; 656 657 /* 658 * Entries (subpackages) in the _CST Package must be sorted by the 659 * C-state type, in ascending order. 660 */ 661 Status = AcpiNsCheckSortedList (Info, ReturnObject, 1, 4, 1, 662 ACPI_SORT_ASCENDING, "C-State Type"); 663 if (ACPI_FAILURE (Status)) 664 { 665 return (Status); 666 } 667 668 return (AE_OK); 669 } 670 671 672 /****************************************************************************** 673 * 674 * FUNCTION: AcpiNsRepair_HID 675 * 676 * PARAMETERS: Info - Method execution information block 677 * ReturnObjectPtr - Pointer to the object returned from the 678 * evaluation of a method or object 679 * 680 * RETURN: Status. AE_OK if object is OK or was repaired successfully 681 * 682 * DESCRIPTION: Repair for the _HID object. If a string, ensure that all 683 * letters are uppercase and that there is no leading asterisk. 684 * 685 *****************************************************************************/ 686 687 static ACPI_STATUS 688 AcpiNsRepair_HID ( 689 ACPI_EVALUATE_INFO *Info, 690 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 691 { 692 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 693 char *Dest; 694 char *Source; 695 696 697 ACPI_FUNCTION_NAME (NsRepair_HID); 698 699 700 /* We only care about string _HID objects (not integers) */ 701 702 if (ReturnObject->Common.Type != ACPI_TYPE_STRING) 703 { 704 return_ACPI_STATUS (AE_OK); 705 } 706 707 if (ReturnObject->String.Length == 0) 708 { 709 ACPI_WARN_PREDEFINED ((AE_INFO, 710 Info->FullPathname, Info->NodeFlags, 711 "Invalid zero-length _HID or _CID string")); 712 713 /* Return AE_OK anyway, let driver handle it */ 714 715 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 716 return_ACPI_STATUS (AE_OK); 717 } 718 719 /* 720 * Remove a leading asterisk if present. For some unknown reason, there 721 * are many machines in the field that contains IDs like this. 722 * 723 * Examples: "*PNP0C03", "*ACPI0003" 724 */ 725 Source = ReturnObject->String.Pointer; 726 if (*Source == '*') 727 { 728 Source++; 729 ReturnObject->String.Length--; 730 731 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 732 "%s: Removed invalid leading asterisk\n", Info->FullPathname)); 733 } 734 735 /* 736 * Copy and uppercase the string. From the ACPI 5.0 specification: 737 * 738 * A valid PNP ID must be of the form "AAA####" where A is an uppercase 739 * letter and # is a hex digit. A valid ACPI ID must be of the form 740 * "NNNN####" where N is an uppercase letter or decimal digit, and 741 * # is a hex digit. 742 */ 743 for (Dest = ReturnObject->String.Pointer; *Source; Dest++, Source++) 744 { 745 *Dest = (char) toupper ((int) *Source); 746 } 747 ReturnObject->String.Pointer[ReturnObject->String.Length] = 0; 748 749 return_ACPI_STATUS (AE_OK); 750 } 751 752 753 /****************************************************************************** 754 * 755 * FUNCTION: AcpiNsRepair_PRT 756 * 757 * PARAMETERS: Info - Method execution information block 758 * ReturnObjectPtr - Pointer to the object returned from the 759 * evaluation of a method or object 760 * 761 * RETURN: Status. AE_OK if object is OK or was repaired successfully 762 * 763 * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed 764 * SourceName and SourceIndex field, a common BIOS bug. 765 * 766 *****************************************************************************/ 767 768 static ACPI_STATUS 769 AcpiNsRepair_PRT ( 770 ACPI_EVALUATE_INFO *Info, 771 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 772 { 773 ACPI_OPERAND_OBJECT *PackageObject = *ReturnObjectPtr; 774 ACPI_OPERAND_OBJECT **TopObjectList; 775 ACPI_OPERAND_OBJECT **SubObjectList; 776 ACPI_OPERAND_OBJECT *ObjDesc; 777 ACPI_OPERAND_OBJECT *SubPackage; 778 UINT32 ElementCount; 779 UINT32 Index; 780 781 782 /* Each element in the _PRT package is a subpackage */ 783 784 TopObjectList = PackageObject->Package.Elements; 785 ElementCount = PackageObject->Package.Count; 786 787 /* Examine each subpackage */ 788 789 for (Index = 0; Index < ElementCount; Index++, TopObjectList++) 790 { 791 SubPackage = *TopObjectList; 792 SubObjectList = SubPackage->Package.Elements; 793 794 /* Check for minimum required element count */ 795 796 if (SubPackage->Package.Count < 4) 797 { 798 continue; 799 } 800 801 /* 802 * If the BIOS has erroneously reversed the _PRT SourceName (index 2) 803 * and the SourceIndex (index 3), fix it. _PRT is important enough to 804 * workaround this BIOS error. This also provides compatibility with 805 * other ACPI implementations. 806 */ 807 ObjDesc = SubObjectList[3]; 808 if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)) 809 { 810 SubObjectList[3] = SubObjectList[2]; 811 SubObjectList[2] = ObjDesc; 812 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 813 814 ACPI_WARN_PREDEFINED ((AE_INFO, 815 Info->FullPathname, Info->NodeFlags, 816 "PRT[%X]: Fixed reversed SourceName and SourceIndex", 817 Index)); 818 } 819 } 820 821 return (AE_OK); 822 } 823 824 825 /****************************************************************************** 826 * 827 * FUNCTION: AcpiNsRepair_PSS 828 * 829 * PARAMETERS: Info - Method execution information block 830 * ReturnObjectPtr - Pointer to the object returned from the 831 * evaluation of a method or object 832 * 833 * RETURN: Status. AE_OK if object is OK or was repaired successfully 834 * 835 * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list 836 * by the CPU frequencies. Check that the power dissipation values 837 * are all proportional to CPU frequency (i.e., sorting by 838 * frequency should be the same as sorting by power.) 839 * 840 *****************************************************************************/ 841 842 static ACPI_STATUS 843 AcpiNsRepair_PSS ( 844 ACPI_EVALUATE_INFO *Info, 845 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 846 { 847 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 848 ACPI_OPERAND_OBJECT **OuterElements; 849 UINT32 OuterElementCount; 850 ACPI_OPERAND_OBJECT **Elements; 851 ACPI_OPERAND_OBJECT *ObjDesc; 852 UINT32 PreviousValue; 853 ACPI_STATUS Status; 854 UINT32 i; 855 856 857 /* 858 * Entries (subpackages) in the _PSS Package must be sorted by power 859 * dissipation, in descending order. If it appears that the list is 860 * incorrectly sorted, sort it. We sort by CpuFrequency, since this 861 * should be proportional to the power. 862 */ 863 Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 6, 0, 864 ACPI_SORT_DESCENDING, "CpuFrequency"); 865 if (ACPI_FAILURE (Status)) 866 { 867 return (Status); 868 } 869 870 /* 871 * We now know the list is correctly sorted by CPU frequency. Check if 872 * the power dissipation values are proportional. 873 */ 874 PreviousValue = ACPI_UINT32_MAX; 875 OuterElements = ReturnObject->Package.Elements; 876 OuterElementCount = ReturnObject->Package.Count; 877 878 for (i = 0; i < OuterElementCount; i++) 879 { 880 Elements = (*OuterElements)->Package.Elements; 881 ObjDesc = Elements[1]; /* Index1 = PowerDissipation */ 882 883 if ((UINT32) ObjDesc->Integer.Value > PreviousValue) 884 { 885 ACPI_WARN_PREDEFINED ((AE_INFO, 886 Info->FullPathname, Info->NodeFlags, 887 "SubPackage[%u,%u] - suspicious power dissipation values", 888 i-1, i)); 889 } 890 891 PreviousValue = (UINT32) ObjDesc->Integer.Value; 892 OuterElements++; 893 } 894 895 return (AE_OK); 896 } 897 898 899 /****************************************************************************** 900 * 901 * FUNCTION: AcpiNsRepair_TSS 902 * 903 * PARAMETERS: Info - Method execution information block 904 * ReturnObjectPtr - Pointer to the object returned from the 905 * evaluation of a method or object 906 * 907 * RETURN: Status. AE_OK if object is OK or was repaired successfully 908 * 909 * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list 910 * descending by the power dissipation values. 911 * 912 *****************************************************************************/ 913 914 static ACPI_STATUS 915 AcpiNsRepair_TSS ( 916 ACPI_EVALUATE_INFO *Info, 917 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 918 { 919 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 920 ACPI_STATUS Status; 921 ACPI_NAMESPACE_NODE *Node; 922 923 924 /* 925 * We can only sort the _TSS return package if there is no _PSS in the 926 * same scope. This is because if _PSS is present, the ACPI specification 927 * dictates that the _TSS Power Dissipation field is to be ignored, and 928 * therefore some BIOSs leave garbage values in the _TSS Power field(s). 929 * In this case, it is best to just return the _TSS package as-is. 930 * (May, 2011) 931 */ 932 Status = AcpiNsGetNode (Info->Node, "^_PSS", 933 ACPI_NS_NO_UPSEARCH, &Node); 934 if (ACPI_SUCCESS (Status)) 935 { 936 return (AE_OK); 937 } 938 939 Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 5, 1, 940 ACPI_SORT_DESCENDING, "PowerDissipation"); 941 942 return (Status); 943 } 944 945 946 /****************************************************************************** 947 * 948 * FUNCTION: AcpiNsCheckSortedList 949 * 950 * PARAMETERS: Info - Method execution information block 951 * ReturnObject - Pointer to the top-level returned object 952 * StartIndex - Index of the first subpackage 953 * ExpectedCount - Minimum length of each subpackage 954 * SortIndex - Subpackage entry to sort on 955 * SortDirection - Ascending or descending 956 * SortKeyName - Name of the SortIndex field 957 * 958 * RETURN: Status. AE_OK if the list is valid and is sorted correctly or 959 * has been repaired by sorting the list. 960 * 961 * DESCRIPTION: Check if the package list is valid and sorted correctly by the 962 * SortIndex. If not, then sort the list. 963 * 964 *****************************************************************************/ 965 966 static ACPI_STATUS 967 AcpiNsCheckSortedList ( 968 ACPI_EVALUATE_INFO *Info, 969 ACPI_OPERAND_OBJECT *ReturnObject, 970 UINT32 StartIndex, 971 UINT32 ExpectedCount, 972 UINT32 SortIndex, 973 UINT8 SortDirection, 974 char *SortKeyName) 975 { 976 UINT32 OuterElementCount; 977 ACPI_OPERAND_OBJECT **OuterElements; 978 ACPI_OPERAND_OBJECT **Elements; 979 ACPI_OPERAND_OBJECT *ObjDesc; 980 UINT32 i; 981 UINT32 PreviousValue; 982 983 984 ACPI_FUNCTION_NAME (NsCheckSortedList); 985 986 987 /* The top-level object must be a package */ 988 989 if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) 990 { 991 return (AE_AML_OPERAND_TYPE); 992 } 993 994 /* 995 * NOTE: assumes list of subpackages contains no NULL elements. 996 * Any NULL elements should have been removed by earlier call 997 * to AcpiNsRemoveNullElements. 998 */ 999 OuterElementCount = ReturnObject->Package.Count; 1000 if (!OuterElementCount || StartIndex >= OuterElementCount) 1001 { 1002 return (AE_AML_PACKAGE_LIMIT); 1003 } 1004 1005 OuterElements = &ReturnObject->Package.Elements[StartIndex]; 1006 OuterElementCount -= StartIndex; 1007 1008 PreviousValue = 0; 1009 if (SortDirection == ACPI_SORT_DESCENDING) 1010 { 1011 PreviousValue = ACPI_UINT32_MAX; 1012 } 1013 1014 /* Examine each subpackage */ 1015 1016 for (i = 0; i < OuterElementCount; i++) 1017 { 1018 /* Each element of the top-level package must also be a package */ 1019 1020 if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE) 1021 { 1022 return (AE_AML_OPERAND_TYPE); 1023 } 1024 1025 /* Each subpackage must have the minimum length */ 1026 1027 if ((*OuterElements)->Package.Count < ExpectedCount) 1028 { 1029 return (AE_AML_PACKAGE_LIMIT); 1030 } 1031 1032 Elements = (*OuterElements)->Package.Elements; 1033 ObjDesc = Elements[SortIndex]; 1034 1035 if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) 1036 { 1037 return (AE_AML_OPERAND_TYPE); 1038 } 1039 1040 /* 1041 * The list must be sorted in the specified order. If we detect a 1042 * discrepancy, sort the entire list. 1043 */ 1044 if (((SortDirection == ACPI_SORT_ASCENDING) && 1045 (ObjDesc->Integer.Value < PreviousValue)) || 1046 ((SortDirection == ACPI_SORT_DESCENDING) && 1047 (ObjDesc->Integer.Value > PreviousValue))) 1048 { 1049 AcpiNsSortList (&ReturnObject->Package.Elements[StartIndex], 1050 OuterElementCount, SortIndex, SortDirection); 1051 1052 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 1053 1054 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 1055 "%s: Repaired unsorted list - now sorted by %s\n", 1056 Info->FullPathname, SortKeyName)); 1057 return (AE_OK); 1058 } 1059 1060 PreviousValue = (UINT32) ObjDesc->Integer.Value; 1061 OuterElements++; 1062 } 1063 1064 return (AE_OK); 1065 } 1066 1067 1068 /****************************************************************************** 1069 * 1070 * FUNCTION: AcpiNsSortList 1071 * 1072 * PARAMETERS: Elements - Package object element list 1073 * Count - Element count for above 1074 * Index - Sort by which package element 1075 * SortDirection - Ascending or Descending sort 1076 * 1077 * RETURN: None 1078 * 1079 * DESCRIPTION: Sort the objects that are in a package element list. 1080 * 1081 * NOTE: Assumes that all NULL elements have been removed from the package, 1082 * and that all elements have been verified to be of type Integer. 1083 * 1084 *****************************************************************************/ 1085 1086 static void 1087 AcpiNsSortList ( 1088 ACPI_OPERAND_OBJECT **Elements, 1089 UINT32 Count, 1090 UINT32 Index, 1091 UINT8 SortDirection) 1092 { 1093 ACPI_OPERAND_OBJECT *ObjDesc1; 1094 ACPI_OPERAND_OBJECT *ObjDesc2; 1095 ACPI_OPERAND_OBJECT *TempObj; 1096 UINT32 i; 1097 UINT32 j; 1098 1099 1100 /* Simple bubble sort */ 1101 1102 for (i = 1; i < Count; i++) 1103 { 1104 for (j = (Count - 1); j >= i; j--) 1105 { 1106 ObjDesc1 = Elements[j-1]->Package.Elements[Index]; 1107 ObjDesc2 = Elements[j]->Package.Elements[Index]; 1108 1109 if (((SortDirection == ACPI_SORT_ASCENDING) && 1110 (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) || 1111 1112 ((SortDirection == ACPI_SORT_DESCENDING) && 1113 (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value))) 1114 { 1115 TempObj = Elements[j-1]; 1116 Elements[j-1] = Elements[j]; 1117 Elements[j] = TempObj; 1118 } 1119 } 1120 } 1121 } 1122 1123 1124 /****************************************************************************** 1125 * 1126 * FUNCTION: AcpiNsRemoveElement 1127 * 1128 * PARAMETERS: ObjDesc - Package object element list 1129 * Index - Index of element to remove 1130 * 1131 * RETURN: None 1132 * 1133 * DESCRIPTION: Remove the requested element of a package and delete it. 1134 * 1135 *****************************************************************************/ 1136 1137 static void 1138 AcpiNsRemoveElement ( 1139 ACPI_OPERAND_OBJECT *ObjDesc, 1140 UINT32 Index) 1141 { 1142 ACPI_OPERAND_OBJECT **Source; 1143 ACPI_OPERAND_OBJECT **Dest; 1144 UINT32 Count; 1145 UINT32 NewCount; 1146 UINT32 i; 1147 1148 1149 ACPI_FUNCTION_NAME (NsRemoveElement); 1150 1151 1152 Count = ObjDesc->Package.Count; 1153 NewCount = Count - 1; 1154 1155 Source = ObjDesc->Package.Elements; 1156 Dest = Source; 1157 1158 /* Examine all elements of the package object, remove matched index */ 1159 1160 for (i = 0; i < Count; i++) 1161 { 1162 if (i == Index) 1163 { 1164 AcpiUtRemoveReference (*Source); /* Remove one ref for being in pkg */ 1165 AcpiUtRemoveReference (*Source); 1166 } 1167 else 1168 { 1169 *Dest = *Source; 1170 Dest++; 1171 } 1172 1173 Source++; 1174 } 1175 1176 /* NULL terminate list and update the package count */ 1177 1178 *Dest = NULL; 1179 ObjDesc->Package.Count = NewCount; 1180 } 1181