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