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