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 }