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, "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 559 560 Status = AcpiNsCheckSortedList (Data, ReturnObject, 5, 1, 561 ACPI_SORT_DESCENDING, "PowerDissipation"); 562 563 return (Status); 564 } 565 566 567 /****************************************************************************** 568 * 569 * FUNCTION: AcpiNsRepair_PSS 570 * 571 * PARAMETERS: Data - Pointer to validation data structure 572 * ReturnObjectPtr - Pointer to the object returned from the 573 * evaluation of a method or object 574 * 575 * RETURN: Status. AE_OK if object is OK or was repaired successfully 576 * 577 * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list 578 * by the CPU frequencies. Check that the power dissipation values 579 * are all proportional to CPU frequency (i.e., sorting by 580 * frequency should be the same as sorting by power.) 581 * 582 *****************************************************************************/ 583 584 static ACPI_STATUS 585 AcpiNsRepair_PSS ( 586 ACPI_PREDEFINED_DATA *Data, 587 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 588 { 589 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 590 ACPI_OPERAND_OBJECT **OuterElements; 591 UINT32 OuterElementCount; 592 ACPI_OPERAND_OBJECT **Elements; 593 ACPI_OPERAND_OBJECT *ObjDesc; 594 UINT32 PreviousValue; 595 ACPI_STATUS Status; 596 UINT32 i; 597 598 599 /* 600 * Entries (sub-packages) in the _PSS Package must be sorted by power 601 * dissipation, in descending order. If it appears that the list is 602 * incorrectly sorted, sort it. We sort by CpuFrequency, since this 603 * should be proportional to the power. 604 */ 605 Status =AcpiNsCheckSortedList (Data, ReturnObject, 6, 0, 606 ACPI_SORT_DESCENDING, "CpuFrequency"); 607 if (ACPI_FAILURE (Status)) 608 { 609 return (Status); 610 } 611 612 /* 613 * We now know the list is correctly sorted by CPU frequency. Check if 614 * the power dissipation values are proportional. 615 */ 616 PreviousValue = ACPI_UINT32_MAX; 617 OuterElements = ReturnObject->Package.Elements; 618 OuterElementCount = ReturnObject->Package.Count; 619 620 for (i = 0; i < OuterElementCount; i++) 621 { 622 Elements = (*OuterElements)->Package.Elements; 623 ObjDesc = Elements[1]; /* Index1 = PowerDissipation */ 624 625 if ((UINT32) ObjDesc->Integer.Value > PreviousValue) 626 { 627 ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, 628 "SubPackage[%u,%u] - suspicious power dissipation values", 629 i-1, i)); 630 } 631 632 PreviousValue = (UINT32) ObjDesc->Integer.Value; 633 OuterElements++; 634 } 635 636 return (AE_OK); 637 } 638 639 640 /****************************************************************************** 641 * 642 * FUNCTION: AcpiNsCheckSortedList 643 * 644 * PARAMETERS: Data - Pointer to validation data structure 645 * ReturnObject - Pointer to the top-level returned object 646 * ExpectedCount - Minimum length of each sub-package 647 * SortIndex - Sub-package entry to sort on 648 * SortDirection - Ascending or descending 649 * SortKeyName - Name of the SortIndex field 650 * 651 * RETURN: Status. AE_OK if the list is valid and is sorted correctly or 652 * has been repaired by sorting the list. 653 * 654 * DESCRIPTION: Check if the package list is valid and sorted correctly by the 655 * SortIndex. If not, then sort the list. 656 * 657 *****************************************************************************/ 658 659 static ACPI_STATUS 660 AcpiNsCheckSortedList ( 661 ACPI_PREDEFINED_DATA *Data, 662 ACPI_OPERAND_OBJECT *ReturnObject, 663 UINT32 ExpectedCount, 664 UINT32 SortIndex, 665 UINT8 SortDirection, 666 char *SortKeyName) 667 { 668 UINT32 OuterElementCount; 669 ACPI_OPERAND_OBJECT **OuterElements; 670 ACPI_OPERAND_OBJECT **Elements; 671 ACPI_OPERAND_OBJECT *ObjDesc; 672 UINT32 i; 673 UINT32 PreviousValue; 674 675 676 ACPI_FUNCTION_NAME (NsCheckSortedList); 677 678 679 /* The top-level object must be a package */ 680 681 if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) 682 { 683 return (AE_AML_OPERAND_TYPE); 684 } 685 686 /* 687 * NOTE: assumes list of sub-packages contains no NULL elements. 688 * Any NULL elements should have been removed by earlier call 689 * to AcpiNsRemoveNullElements. 690 */ 691 OuterElements = ReturnObject->Package.Elements; 692 OuterElementCount = ReturnObject->Package.Count; 693 if (!OuterElementCount) 694 { 695 return (AE_AML_PACKAGE_LIMIT); 696 } 697 698 PreviousValue = 0; 699 if (SortDirection == ACPI_SORT_DESCENDING) 700 { 701 PreviousValue = ACPI_UINT32_MAX; 702 } 703 704 /* Examine each subpackage */ 705 706 for (i = 0; i < OuterElementCount; i++) 707 { 708 /* Each element of the top-level package must also be a package */ 709 710 if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE) 711 { 712 return (AE_AML_OPERAND_TYPE); 713 } 714 715 /* Each sub-package must have the minimum length */ 716 717 if ((*OuterElements)->Package.Count < ExpectedCount) 718 { 719 return (AE_AML_PACKAGE_LIMIT); 720 } 721 722 Elements = (*OuterElements)->Package.Elements; 723 ObjDesc = Elements[SortIndex]; 724 725 if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) 726 { 727 return (AE_AML_OPERAND_TYPE); 728 } 729 730 /* 731 * The list must be sorted in the specified order. If we detect a 732 * discrepancy, sort the entire list. 733 */ 734 if (((SortDirection == ACPI_SORT_ASCENDING) && 735 (ObjDesc->Integer.Value < PreviousValue)) || 736 ((SortDirection == ACPI_SORT_DESCENDING) && 737 (ObjDesc->Integer.Value > PreviousValue))) 738 { 739 AcpiNsSortList (ReturnObject->Package.Elements, 740 OuterElementCount, SortIndex, SortDirection); 741 742 Data->Flags |= ACPI_OBJECT_REPAIRED; 743 744 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 745 "%s: Repaired unsorted list - now sorted by %s\n", 746 Data->Pathname, SortKeyName)); 747 return (AE_OK); 748 } 749 750 PreviousValue = (UINT32) ObjDesc->Integer.Value; 751 OuterElements++; 752 } 753 754 return (AE_OK); 755 } 756 757 758 /****************************************************************************** 759 * 760 * FUNCTION: AcpiNsSortList 761 * 762 * PARAMETERS: Elements - Package object element list 763 * Count - Element count for above 764 * Index - Sort by which package element 765 * SortDirection - Ascending or Descending sort 766 * 767 * RETURN: None 768 * 769 * DESCRIPTION: Sort the objects that are in a package element list. 770 * 771 * NOTE: Assumes that all NULL elements have been removed from the package, 772 * and that all elements have been verified to be of type Integer. 773 * 774 *****************************************************************************/ 775 776 static void 777 AcpiNsSortList ( 778 ACPI_OPERAND_OBJECT **Elements, 779 UINT32 Count, 780 UINT32 Index, 781 UINT8 SortDirection) 782 { 783 ACPI_OPERAND_OBJECT *ObjDesc1; 784 ACPI_OPERAND_OBJECT *ObjDesc2; 785 ACPI_OPERAND_OBJECT *TempObj; 786 UINT32 i; 787 UINT32 j; 788 789 790 /* Simple bubble sort */ 791 792 for (i = 1; i < Count; i++) 793 { 794 for (j = (Count - 1); j >= i; j--) 795 { 796 ObjDesc1 = Elements[j-1]->Package.Elements[Index]; 797 ObjDesc2 = Elements[j]->Package.Elements[Index]; 798 799 if (((SortDirection == ACPI_SORT_ASCENDING) && 800 (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) || 801 802 ((SortDirection == ACPI_SORT_DESCENDING) && 803 (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value))) 804 { 805 TempObj = Elements[j-1]; 806 Elements[j-1] = Elements[j]; 807 Elements[j] = TempObj; 808 } 809 } 810 } 811 }