Home | History | Annotate | Line # | Download | only in namespace
nsrepair2.c revision 1.20
      1 /******************************************************************************
      2  *
      3  * Module Name: nsrepair2 - Repair for objects returned by specific
      4  *                          predefined methods
      5  *
      6  *****************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 #include "acpi.h"
     46 #include "accommon.h"
     47 #include "acnamesp.h"
     48 
     49 #define _COMPONENT          ACPI_NAMESPACE
     50         ACPI_MODULE_NAME    ("nsrepair2")
     51 
     52 
     53 /*
     54  * Information structure and handler for ACPI predefined names that can
     55  * be repaired on a per-name basis.
     56  */
     57 typedef
     58 ACPI_STATUS (*ACPI_REPAIR_FUNCTION) (
     59     ACPI_EVALUATE_INFO      *Info,
     60     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
     61 
     62 typedef struct acpi_repair_info
     63 {
     64     char                    Name[ACPI_NAMESEG_SIZE];
     65     ACPI_REPAIR_FUNCTION    RepairFunction;
     66 
     67 } ACPI_REPAIR_INFO;
     68 
     69 
     70 /* Local prototypes */
     71 
     72 static const ACPI_REPAIR_INFO *
     73 AcpiNsMatchComplexRepair (
     74     ACPI_NAMESPACE_NODE     *Node);
     75 
     76 static ACPI_STATUS
     77 AcpiNsRepair_ALR (
     78     ACPI_EVALUATE_INFO      *Info,
     79     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
     80 
     81 static ACPI_STATUS
     82 AcpiNsRepair_CID (
     83     ACPI_EVALUATE_INFO      *Info,
     84     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
     85 
     86 static ACPI_STATUS
     87 AcpiNsRepair_CST (
     88     ACPI_EVALUATE_INFO      *Info,
     89     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
     90 
     91 static ACPI_STATUS
     92 AcpiNsRepair_FDE (
     93     ACPI_EVALUATE_INFO      *Info,
     94     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
     95 
     96 static ACPI_STATUS
     97 AcpiNsRepair_HID (
     98     ACPI_EVALUATE_INFO      *Info,
     99     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
    100 
    101 static ACPI_STATUS
    102 AcpiNsRepair_PRT (
    103     ACPI_EVALUATE_INFO      *Info,
    104     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
    105 
    106 static ACPI_STATUS
    107 AcpiNsRepair_PSS (
    108     ACPI_EVALUATE_INFO      *Info,
    109     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
    110 
    111 static ACPI_STATUS
    112 AcpiNsRepair_TSS (
    113     ACPI_EVALUATE_INFO      *Info,
    114     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
    115 
    116 static ACPI_STATUS
    117 AcpiNsCheckSortedList (
    118     ACPI_EVALUATE_INFO      *Info,
    119     ACPI_OPERAND_OBJECT     *ReturnObject,
    120     UINT32                  StartIndex,
    121     UINT32                  ExpectedCount,
    122     UINT32                  SortIndex,
    123     UINT8                   SortDirection,
    124     const char              *SortKeyName);
    125 
    126 /* Values for SortDirection above */
    127 
    128 #define ACPI_SORT_ASCENDING     0
    129 #define ACPI_SORT_DESCENDING    1
    130 
    131 static void
    132 AcpiNsRemoveElement (
    133     ACPI_OPERAND_OBJECT     *ObjDesc,
    134     UINT32                  Index);
    135 
    136 static void
    137 AcpiNsSortList (
    138     ACPI_OPERAND_OBJECT     **Elements,
    139     UINT32                  Count,
    140     UINT32                  Index,
    141     UINT8                   SortDirection);
    142 
    143 
    144 /*
    145  * This table contains the names of the predefined methods for which we can
    146  * perform more complex repairs.
    147  *
    148  * As necessary:
    149  *
    150  * _ALR: Sort the list ascending by AmbientIlluminance
    151  * _CID: Strings: uppercase all, remove any leading asterisk
    152  * _CST: Sort the list ascending by C state type
    153  * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
    154  * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
    155  * _HID: Strings: uppercase all, remove any leading asterisk
    156  * _PRT: Fix reversed SourceName and SourceIndex
    157  * _PSS: Sort the list descending by Power
    158  * _TSS: Sort the list descending by Power
    159  *
    160  * Names that must be packages, but cannot be sorted:
    161  *
    162  * _BCL: Values are tied to the Package index where they appear, and cannot
    163  * be moved or sorted. These index values are used for _BQC and _BCM.
    164  * However, we can fix the case where a buffer is returned, by converting
    165  * it to a Package of integers.
    166  */
    167 static const ACPI_REPAIR_INFO       AcpiNsRepairableNames[] =
    168 {
    169     {"_ALR", AcpiNsRepair_ALR},
    170     {"_CID", AcpiNsRepair_CID},
    171     {"_CST", AcpiNsRepair_CST},
    172     {"_FDE", AcpiNsRepair_FDE},
    173     {"_GTM", AcpiNsRepair_FDE},     /* _GTM has same repair as _FDE */
    174     {"_HID", AcpiNsRepair_HID},
    175     {"_PRT", AcpiNsRepair_PRT},
    176     {"_PSS", AcpiNsRepair_PSS},
    177     {"_TSS", AcpiNsRepair_TSS},
    178     {{0,0,0,0}, NULL}               /* Table terminator */
    179 };
    180 
    181 
    182 #define ACPI_FDE_FIELD_COUNT        5
    183 #define ACPI_FDE_BYTE_BUFFER_SIZE   5
    184 #define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * (UINT32) sizeof (UINT32))
    185 
    186 
    187 /******************************************************************************
    188  *
    189  * FUNCTION:    AcpiNsComplexRepairs
    190  *
    191  * PARAMETERS:  Info                - Method execution information block
    192  *              Node                - Namespace node for the method/object
    193  *              ValidateStatus      - Original status of earlier validation
    194  *              ReturnObjectPtr     - Pointer to the object returned from the
    195  *                                    evaluation of a method or object
    196  *
    197  * RETURN:      Status. AE_OK if repair was successful. If name is not
    198  *              matched, ValidateStatus is returned.
    199  *
    200  * DESCRIPTION: Attempt to repair/convert a return object of a type that was
    201  *              not expected.
    202  *
    203  *****************************************************************************/
    204 
    205 ACPI_STATUS
    206 AcpiNsComplexRepairs (
    207     ACPI_EVALUATE_INFO      *Info,
    208     ACPI_NAMESPACE_NODE     *Node,
    209     ACPI_STATUS             ValidateStatus,
    210     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    211 {
    212     const ACPI_REPAIR_INFO  *Predefined;
    213     ACPI_STATUS             Status;
    214 
    215 
    216     ACPI_FUNCTION_TRACE (NsComplexRepairs);
    217 
    218     /* Check if this name is in the list of repairable names */
    219 
    220     Predefined = AcpiNsMatchComplexRepair (Node);
    221     if (!Predefined)
    222     {
    223         return_ACPI_STATUS (ValidateStatus);
    224     }
    225 
    226     Status = Predefined->RepairFunction (Info, ReturnObjectPtr);
    227     return_ACPI_STATUS (Status);
    228 }
    229 
    230 
    231 /******************************************************************************
    232  *
    233  * FUNCTION:    AcpiNsMatchComplexRepair
    234  *
    235  * PARAMETERS:  Node                - Namespace node for the method/object
    236  *
    237  * RETURN:      Pointer to entry in repair table. NULL indicates not found.
    238  *
    239  * DESCRIPTION: Check an object name against the repairable object list.
    240  *
    241  *****************************************************************************/
    242 
    243 static const ACPI_REPAIR_INFO *
    244 AcpiNsMatchComplexRepair (
    245     ACPI_NAMESPACE_NODE     *Node)
    246 {
    247     const ACPI_REPAIR_INFO  *ThisName;
    248 
    249 
    250     /* Search info table for a repairable predefined method/object name */
    251 
    252     ThisName = AcpiNsRepairableNames;
    253     while (ThisName->RepairFunction)
    254     {
    255         if (ACPI_COMPARE_NAMESEG (Node->Name.Ascii, ThisName->Name))
    256         {
    257             return (ThisName);
    258         }
    259 
    260         ThisName++;
    261     }
    262 
    263     return (NULL); /* Not found */
    264 }
    265 
    266 
    267 /******************************************************************************
    268  *
    269  * FUNCTION:    AcpiNsRepair_ALR
    270  *
    271  * PARAMETERS:  Info                - Method execution information block
    272  *              ReturnObjectPtr     - Pointer to the object returned from the
    273  *                                    evaluation of a method or object
    274  *
    275  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
    276  *
    277  * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
    278  *              ascending by the ambient illuminance values.
    279  *
    280  *****************************************************************************/
    281 
    282 static ACPI_STATUS
    283 AcpiNsRepair_ALR (
    284     ACPI_EVALUATE_INFO      *Info,
    285     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    286 {
    287     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    288     ACPI_STATUS             Status;
    289 
    290 
    291     Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 2, 1,
    292         ACPI_SORT_ASCENDING, "AmbientIlluminance");
    293 
    294     return (Status);
    295 }
    296 
    297 
    298 /******************************************************************************
    299  *
    300  * FUNCTION:    AcpiNsRepair_FDE
    301  *
    302  * PARAMETERS:  Info                - Method execution information block
    303  *              ReturnObjectPtr     - Pointer to the object returned from the
    304  *                                    evaluation of a method or object
    305  *
    306  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
    307  *
    308  * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return
    309  *              value is a Buffer of 5 DWORDs. This function repairs a common
    310  *              problem where the return value is a Buffer of BYTEs, not
    311  *              DWORDs.
    312  *
    313  *****************************************************************************/
    314 
    315 static ACPI_STATUS
    316 AcpiNsRepair_FDE (
    317     ACPI_EVALUATE_INFO      *Info,
    318     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    319 {
    320     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    321     ACPI_OPERAND_OBJECT     *BufferObject;
    322     UINT8                   *ByteBuffer;
    323     UINT32                  *DwordBuffer;
    324     UINT32                  i;
    325 
    326 
    327     ACPI_FUNCTION_NAME (NsRepair_FDE);
    328 
    329 
    330     switch (ReturnObject->Common.Type)
    331     {
    332     case ACPI_TYPE_BUFFER:
    333 
    334         /* This is the expected type. Length should be (at least) 5 DWORDs */
    335 
    336         if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE)
    337         {
    338             return (AE_OK);
    339         }
    340 
    341         /* We can only repair if we have exactly 5 BYTEs */
    342 
    343         if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE)
    344         {
    345             ACPI_WARN_PREDEFINED ((AE_INFO,
    346                 Info->FullPathname, Info->NodeFlags,
    347                 "Incorrect return buffer length %u, expected %u",
    348                 ReturnObject->Buffer.Length, ACPI_FDE_DWORD_BUFFER_SIZE));
    349 
    350             return (AE_AML_OPERAND_TYPE);
    351         }
    352 
    353         /* Create the new (larger) buffer object */
    354 
    355         BufferObject = AcpiUtCreateBufferObject (
    356             ACPI_FDE_DWORD_BUFFER_SIZE);
    357         if (!BufferObject)
    358         {
    359             return (AE_NO_MEMORY);
    360         }
    361 
    362         /* Expand each byte to a DWORD */
    363 
    364         ByteBuffer = ReturnObject->Buffer.Pointer;
    365         DwordBuffer = ACPI_CAST_PTR (UINT32,
    366             BufferObject->Buffer.Pointer);
    367 
    368         for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++)
    369         {
    370             *DwordBuffer = (UINT32) *ByteBuffer;
    371             DwordBuffer++;
    372             ByteBuffer++;
    373         }
    374 
    375         ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    376             "%s Expanded Byte Buffer to expected DWord Buffer\n",
    377             Info->FullPathname));
    378         break;
    379 
    380     default:
    381 
    382         return (AE_AML_OPERAND_TYPE);
    383     }
    384 
    385     /* Delete the original return object, return the new buffer object */
    386 
    387     AcpiUtRemoveReference (ReturnObject);
    388     *ReturnObjectPtr = BufferObject;
    389 
    390     Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
    391     return (AE_OK);
    392 }
    393 
    394 
    395 /******************************************************************************
    396  *
    397  * FUNCTION:    AcpiNsRepair_CID
    398  *
    399  * PARAMETERS:  Info                - Method execution information block
    400  *              ReturnObjectPtr     - Pointer to the object returned from the
    401  *                                    evaluation of a method or object
    402  *
    403  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
    404  *
    405  * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
    406  *              letters are uppercase and that there is no leading asterisk.
    407  *              If a Package, ensure same for all string elements.
    408  *
    409  *****************************************************************************/
    410 
    411 static ACPI_STATUS
    412 AcpiNsRepair_CID (
    413     ACPI_EVALUATE_INFO      *Info,
    414     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    415 {
    416     ACPI_STATUS             Status;
    417     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    418     ACPI_OPERAND_OBJECT     **ElementPtr;
    419     ACPI_OPERAND_OBJECT     *OriginalElement;
    420     UINT16                  OriginalRefCount;
    421     UINT32                  i;
    422 
    423     ACPI_FUNCTION_TRACE (NsRepair_CID);
    424 
    425     /* Check for _CID as a simple string */
    426 
    427     if (ReturnObject->Common.Type == ACPI_TYPE_STRING)
    428     {
    429         Status = AcpiNsRepair_HID (Info, ReturnObjectPtr);
    430         return_ACPI_STATUS (Status);
    431     }
    432 
    433     /* Exit if not a Package */
    434 
    435     if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
    436     {
    437         return_ACPI_STATUS (AE_OK);
    438     }
    439 
    440     /* Examine each element of the _CID package */
    441 
    442     ElementPtr = ReturnObject->Package.Elements;
    443     for (i = 0; i < ReturnObject->Package.Count; i++)
    444     {
    445         OriginalElement = *ElementPtr;
    446         OriginalRefCount = OriginalElement->Common.ReferenceCount;
    447 
    448         Status = AcpiNsRepair_HID (Info, ElementPtr);
    449         if (ACPI_FAILURE (Status))
    450         {
    451             return_ACPI_STATUS (Status);
    452         }
    453 
    454         if (OriginalElement != *ElementPtr)
    455         {
    456             /* Update reference count of new object */
    457 
    458             (*ElementPtr)->Common.ReferenceCount =
    459                 OriginalRefCount;
    460         }
    461 
    462         ElementPtr++;
    463     }
    464 
    465     return_ACPI_STATUS (AE_OK);
    466 }
    467 
    468 
    469 /******************************************************************************
    470  *
    471  * FUNCTION:    AcpiNsRepair_CST
    472  *
    473  * PARAMETERS:  Info                - Method execution information block
    474  *              ReturnObjectPtr     - Pointer to the object returned from the
    475  *                                    evaluation of a method or object
    476  *
    477  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
    478  *
    479  * DESCRIPTION: Repair for the _CST object:
    480  *              1. Sort the list ascending by C state type
    481  *              2. Ensure type cannot be zero
    482  *              3. A subpackage count of zero means _CST is meaningless
    483  *              4. Count must match the number of C state subpackages
    484  *
    485  *****************************************************************************/
    486 
    487 static ACPI_STATUS
    488 AcpiNsRepair_CST (
    489     ACPI_EVALUATE_INFO      *Info,
    490     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    491 {
    492     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    493     ACPI_OPERAND_OBJECT     **OuterElements;
    494     UINT32                  OuterElementCount;
    495     ACPI_OPERAND_OBJECT     *ObjDesc;
    496     ACPI_STATUS             Status;
    497     BOOLEAN                 Removing;
    498     UINT32                  i;
    499 
    500 
    501     ACPI_FUNCTION_NAME (NsRepair_CST);
    502 
    503 
    504     /*
    505      * Check if the C-state type values are proportional.
    506      */
    507     OuterElementCount = ReturnObject->Package.Count - 1;
    508     i = 0;
    509     while (i < OuterElementCount)
    510     {
    511         OuterElements = &ReturnObject->Package.Elements[i + 1];
    512         Removing = FALSE;
    513 
    514         if ((*OuterElements)->Package.Count == 0)
    515         {
    516             ACPI_WARN_PREDEFINED ((AE_INFO,
    517                 Info->FullPathname, Info->NodeFlags,
    518                 "SubPackage[%u] - removing entry due to zero count", i));
    519             Removing = TRUE;
    520             goto RemoveElement;
    521         }
    522 
    523         ObjDesc = (*OuterElements)->Package.Elements[1]; /* Index1 = Type */
    524         if ((UINT32) ObjDesc->Integer.Value == 0)
    525         {
    526             ACPI_WARN_PREDEFINED ((AE_INFO,
    527                 Info->FullPathname, Info->NodeFlags,
    528                 "SubPackage[%u] - removing entry due to invalid Type(0)", i));
    529             Removing = TRUE;
    530         }
    531 
    532 RemoveElement:
    533         if (Removing)
    534         {
    535             AcpiNsRemoveElement (ReturnObject, i + 1);
    536             OuterElementCount--;
    537         }
    538         else
    539         {
    540             i++;
    541         }
    542     }
    543 
    544     /* Update top-level package count, Type "Integer" checked elsewhere */
    545 
    546     ObjDesc = ReturnObject->Package.Elements[0];
    547     ObjDesc->Integer.Value = OuterElementCount;
    548 
    549     /*
    550      * Entries (subpackages) in the _CST Package must be sorted by the
    551      * C-state type, in ascending order.
    552      */
    553     Status = AcpiNsCheckSortedList (Info, ReturnObject, 1, 4, 1,
    554         ACPI_SORT_ASCENDING, "C-State Type");
    555     if (ACPI_FAILURE (Status))
    556     {
    557         return (Status);
    558     }
    559 
    560     return (AE_OK);
    561 }
    562 
    563 
    564 /******************************************************************************
    565  *
    566  * FUNCTION:    AcpiNsRepair_HID
    567  *
    568  * PARAMETERS:  Info                - Method execution information block
    569  *              ReturnObjectPtr     - Pointer to the object returned from the
    570  *                                    evaluation of a method or object
    571  *
    572  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
    573  *
    574  * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
    575  *              letters are uppercase and that there is no leading asterisk.
    576  *
    577  *****************************************************************************/
    578 
    579 static ACPI_STATUS
    580 AcpiNsRepair_HID (
    581     ACPI_EVALUATE_INFO      *Info,
    582     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    583 {
    584     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    585     ACPI_OPERAND_OBJECT     *NewString;
    586     char                    *Source;
    587     char                    *Dest;
    588 
    589 
    590     ACPI_FUNCTION_TRACE (NsRepair_HID);
    591 
    592 
    593     /* We only care about string _HID objects (not integers) */
    594 
    595     if (ReturnObject->Common.Type != ACPI_TYPE_STRING)
    596     {
    597         return_ACPI_STATUS (AE_OK);
    598     }
    599 
    600     if (ReturnObject->String.Length == 0)
    601     {
    602         ACPI_WARN_PREDEFINED ((AE_INFO,
    603             Info->FullPathname, Info->NodeFlags,
    604             "Invalid zero-length _HID or _CID string"));
    605 
    606         /* Return AE_OK anyway, let driver handle it */
    607 
    608         Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
    609         return_ACPI_STATUS (AE_OK);
    610     }
    611 
    612     /* It is simplest to always create a new string object */
    613 
    614     NewString = AcpiUtCreateStringObject (ReturnObject->String.Length);
    615     if (!NewString)
    616     {
    617         return_ACPI_STATUS (AE_NO_MEMORY);
    618     }
    619 
    620     /*
    621      * Remove a leading asterisk if present. For some unknown reason, there
    622      * are many machines in the field that contains IDs like this.
    623      *
    624      * Examples: "*PNP0C03", "*ACPI0003"
    625      */
    626     Source = ReturnObject->String.Pointer;
    627     if (*Source == '*')
    628     {
    629         Source++;
    630         NewString->String.Length--;
    631 
    632         ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    633             "%s: Removed invalid leading asterisk\n", Info->FullPathname));
    634     }
    635 
    636     /*
    637      * Copy and uppercase the string. From the ACPI 5.0 specification:
    638      *
    639      * A valid PNP ID must be of the form "AAA####" where A is an uppercase
    640      * letter and # is a hex digit. A valid ACPI ID must be of the form
    641      * "NNNN####" where N is an uppercase letter or decimal digit, and
    642      * # is a hex digit.
    643      */
    644     for (Dest = NewString->String.Pointer; *Source; Dest++, Source++)
    645     {
    646         *Dest = (char) toupper ((int) *Source);
    647     }
    648 
    649     AcpiUtRemoveReference (ReturnObject);
    650     *ReturnObjectPtr = NewString;
    651     return_ACPI_STATUS (AE_OK);
    652 }
    653 
    654 
    655 /******************************************************************************
    656  *
    657  * FUNCTION:    AcpiNsRepair_PRT
    658  *
    659  * PARAMETERS:  Info                - Method execution information block
    660  *              ReturnObjectPtr     - Pointer to the object returned from the
    661  *                                    evaluation of a method or object
    662  *
    663  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
    664  *
    665  * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed
    666  *              SourceName and SourceIndex field, a common BIOS bug.
    667  *
    668  *****************************************************************************/
    669 
    670 static ACPI_STATUS
    671 AcpiNsRepair_PRT (
    672     ACPI_EVALUATE_INFO      *Info,
    673     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    674 {
    675     ACPI_OPERAND_OBJECT     *PackageObject = *ReturnObjectPtr;
    676     ACPI_OPERAND_OBJECT     **TopObjectList;
    677     ACPI_OPERAND_OBJECT     **SubObjectList;
    678     ACPI_OPERAND_OBJECT     *ObjDesc;
    679     ACPI_OPERAND_OBJECT     *SubPackage;
    680     UINT32                  ElementCount;
    681     UINT32                  Index;
    682 
    683 
    684     /* Each element in the _PRT package is a subpackage */
    685 
    686     TopObjectList = PackageObject->Package.Elements;
    687     ElementCount = PackageObject->Package.Count;
    688 
    689     /* Examine each subpackage */
    690 
    691     for (Index = 0; Index < ElementCount; Index++, TopObjectList++)
    692     {
    693         SubPackage = *TopObjectList;
    694         SubObjectList = SubPackage->Package.Elements;
    695 
    696         /* Check for minimum required element count */
    697 
    698         if (SubPackage->Package.Count < 4)
    699         {
    700             continue;
    701         }
    702 
    703         /*
    704          * If the BIOS has erroneously reversed the _PRT SourceName (index 2)
    705          * and the SourceIndex (index 3), fix it. _PRT is important enough to
    706          * workaround this BIOS error. This also provides compatibility with
    707          * other ACPI implementations.
    708          */
    709         ObjDesc = SubObjectList[3];
    710         if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
    711         {
    712             SubObjectList[3] = SubObjectList[2];
    713             SubObjectList[2] = ObjDesc;
    714             Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
    715 
    716             ACPI_WARN_PREDEFINED ((AE_INFO,
    717                 Info->FullPathname, Info->NodeFlags,
    718                 "PRT[%X]: Fixed reversed SourceName and SourceIndex",
    719                 Index));
    720         }
    721     }
    722 
    723     return (AE_OK);
    724 }
    725 
    726 
    727 /******************************************************************************
    728  *
    729  * FUNCTION:    AcpiNsRepair_PSS
    730  *
    731  * PARAMETERS:  Info                - Method execution information block
    732  *              ReturnObjectPtr     - Pointer to the object returned from the
    733  *                                    evaluation of a method or object
    734  *
    735  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
    736  *
    737  * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
    738  *              by the CPU frequencies. Check that the power dissipation values
    739  *              are all proportional to CPU frequency (i.e., sorting by
    740  *              frequency should be the same as sorting by power.)
    741  *
    742  *****************************************************************************/
    743 
    744 static ACPI_STATUS
    745 AcpiNsRepair_PSS (
    746     ACPI_EVALUATE_INFO      *Info,
    747     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    748 {
    749     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    750     ACPI_OPERAND_OBJECT     **OuterElements;
    751     UINT32                  OuterElementCount;
    752     ACPI_OPERAND_OBJECT     **Elements;
    753     ACPI_OPERAND_OBJECT     *ObjDesc;
    754     UINT32                  PreviousValue;
    755     ACPI_STATUS             Status;
    756     UINT32                  i;
    757 
    758 
    759     /*
    760      * Entries (subpackages) in the _PSS Package must be sorted by power
    761      * dissipation, in descending order. If it appears that the list is
    762      * incorrectly sorted, sort it. We sort by CpuFrequency, since this
    763      * should be proportional to the power.
    764      */
    765     Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 6, 0,
    766         ACPI_SORT_DESCENDING, "CpuFrequency");
    767     if (ACPI_FAILURE (Status))
    768     {
    769         return (Status);
    770     }
    771 
    772     /*
    773      * We now know the list is correctly sorted by CPU frequency. Check if
    774      * the power dissipation values are proportional.
    775      */
    776     PreviousValue = ACPI_UINT32_MAX;
    777     OuterElements = ReturnObject->Package.Elements;
    778     OuterElementCount = ReturnObject->Package.Count;
    779 
    780     for (i = 0; i < OuterElementCount; i++)
    781     {
    782         Elements = (*OuterElements)->Package.Elements;
    783         ObjDesc = Elements[1]; /* Index1 = PowerDissipation */
    784 
    785         if ((UINT32) ObjDesc->Integer.Value > PreviousValue)
    786         {
    787             ACPI_WARN_PREDEFINED ((AE_INFO,
    788                 Info->FullPathname, Info->NodeFlags,
    789                 "SubPackage[%u,%u] - suspicious power dissipation values",
    790                 i-1, i));
    791         }
    792 
    793         PreviousValue = (UINT32) ObjDesc->Integer.Value;
    794         OuterElements++;
    795     }
    796 
    797     return (AE_OK);
    798 }
    799 
    800 
    801 /******************************************************************************
    802  *
    803  * FUNCTION:    AcpiNsRepair_TSS
    804  *
    805  * PARAMETERS:  Info                - Method execution information block
    806  *              ReturnObjectPtr     - Pointer to the object returned from the
    807  *                                    evaluation of a method or object
    808  *
    809  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
    810  *
    811  * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
    812  *              descending by the power dissipation values.
    813  *
    814  *****************************************************************************/
    815 
    816 static ACPI_STATUS
    817 AcpiNsRepair_TSS (
    818     ACPI_EVALUATE_INFO      *Info,
    819     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    820 {
    821     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    822     ACPI_STATUS             Status;
    823     ACPI_NAMESPACE_NODE     *Node;
    824 
    825 
    826     /*
    827      * We can only sort the _TSS return package if there is no _PSS in the
    828      * same scope. This is because if _PSS is present, the ACPI specification
    829      * dictates that the _TSS Power Dissipation field is to be ignored, and
    830      * therefore some BIOSs leave garbage values in the _TSS Power field(s).
    831      * In this case, it is best to just return the _TSS package as-is.
    832      * (May, 2011)
    833      */
    834     Status = AcpiNsGetNode (Info->Node, "^_PSS",
    835         ACPI_NS_NO_UPSEARCH, &Node);
    836     if (ACPI_SUCCESS (Status))
    837     {
    838         return (AE_OK);
    839     }
    840 
    841     Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 5, 1,
    842         ACPI_SORT_DESCENDING, "PowerDissipation");
    843 
    844     return (Status);
    845 }
    846 
    847 
    848 /******************************************************************************
    849  *
    850  * FUNCTION:    AcpiNsCheckSortedList
    851  *
    852  * PARAMETERS:  Info                - Method execution information block
    853  *              ReturnObject        - Pointer to the top-level returned object
    854  *              StartIndex          - Index of the first subpackage
    855  *              ExpectedCount       - Minimum length of each subpackage
    856  *              SortIndex           - Subpackage entry to sort on
    857  *              SortDirection       - Ascending or descending
    858  *              SortKeyName         - Name of the SortIndex field
    859  *
    860  * RETURN:      Status. AE_OK if the list is valid and is sorted correctly or
    861  *              has been repaired by sorting the list.
    862  *
    863  * DESCRIPTION: Check if the package list is valid and sorted correctly by the
    864  *              SortIndex. If not, then sort the list.
    865  *
    866  *****************************************************************************/
    867 
    868 static ACPI_STATUS
    869 AcpiNsCheckSortedList (
    870     ACPI_EVALUATE_INFO      *Info,
    871     ACPI_OPERAND_OBJECT     *ReturnObject,
    872     UINT32                  StartIndex,
    873     UINT32                  ExpectedCount,
    874     UINT32                  SortIndex,
    875     UINT8                   SortDirection,
    876     const char              *SortKeyName)
    877 {
    878     UINT32                  OuterElementCount;
    879     ACPI_OPERAND_OBJECT     **OuterElements;
    880     ACPI_OPERAND_OBJECT     **Elements;
    881     ACPI_OPERAND_OBJECT     *ObjDesc;
    882     UINT32                  i;
    883     UINT32                  PreviousValue;
    884 
    885 
    886     ACPI_FUNCTION_NAME (NsCheckSortedList);
    887 
    888 
    889     /* The top-level object must be a package */
    890 
    891     if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
    892     {
    893         return (AE_AML_OPERAND_TYPE);
    894     }
    895 
    896     /*
    897      * NOTE: assumes list of subpackages contains no NULL elements.
    898      * Any NULL elements should have been removed by earlier call
    899      * to AcpiNsRemoveNullElements.
    900      */
    901     OuterElementCount = ReturnObject->Package.Count;
    902     if (!OuterElementCount || StartIndex >= OuterElementCount)
    903     {
    904         return (AE_AML_PACKAGE_LIMIT);
    905     }
    906 
    907     OuterElements = &ReturnObject->Package.Elements[StartIndex];
    908     OuterElementCount -= StartIndex;
    909 
    910     PreviousValue = 0;
    911     if (SortDirection == ACPI_SORT_DESCENDING)
    912     {
    913         PreviousValue = ACPI_UINT32_MAX;
    914     }
    915 
    916     /* Examine each subpackage */
    917 
    918     for (i = 0; i < OuterElementCount; i++)
    919     {
    920         /* Each element of the top-level package must also be a package */
    921 
    922         if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE)
    923         {
    924             return (AE_AML_OPERAND_TYPE);
    925         }
    926 
    927         /* Each subpackage must have the minimum length */
    928 
    929         if ((*OuterElements)->Package.Count < ExpectedCount)
    930         {
    931             return (AE_AML_PACKAGE_LIMIT);
    932         }
    933 
    934         Elements = (*OuterElements)->Package.Elements;
    935         ObjDesc = Elements[SortIndex];
    936 
    937         if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
    938         {
    939             return (AE_AML_OPERAND_TYPE);
    940         }
    941 
    942         /*
    943          * The list must be sorted in the specified order. If we detect a
    944          * discrepancy, sort the entire list.
    945          */
    946         if (((SortDirection == ACPI_SORT_ASCENDING) &&
    947                 (ObjDesc->Integer.Value < PreviousValue)) ||
    948             ((SortDirection == ACPI_SORT_DESCENDING) &&
    949                 (ObjDesc->Integer.Value > PreviousValue)))
    950         {
    951             AcpiNsSortList (&ReturnObject->Package.Elements[StartIndex],
    952                 OuterElementCount, SortIndex, SortDirection);
    953 
    954             Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
    955 
    956             ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    957                 "%s: Repaired unsorted list - now sorted by %s\n",
    958                 Info->FullPathname, SortKeyName));
    959             return (AE_OK);
    960         }
    961 
    962         PreviousValue = (UINT32) ObjDesc->Integer.Value;
    963         OuterElements++;
    964     }
    965 
    966     return (AE_OK);
    967 }
    968 
    969 
    970 /******************************************************************************
    971  *
    972  * FUNCTION:    AcpiNsSortList
    973  *
    974  * PARAMETERS:  Elements            - Package object element list
    975  *              Count               - Element count for above
    976  *              Index               - Sort by which package element
    977  *              SortDirection       - Ascending or Descending sort
    978  *
    979  * RETURN:      None
    980  *
    981  * DESCRIPTION: Sort the objects that are in a package element list.
    982  *
    983  * NOTE: Assumes that all NULL elements have been removed from the package,
    984  *       and that all elements have been verified to be of type Integer.
    985  *
    986  *****************************************************************************/
    987 
    988 static void
    989 AcpiNsSortList (
    990     ACPI_OPERAND_OBJECT     **Elements,
    991     UINT32                  Count,
    992     UINT32                  Index,
    993     UINT8                   SortDirection)
    994 {
    995     ACPI_OPERAND_OBJECT     *ObjDesc1;
    996     ACPI_OPERAND_OBJECT     *ObjDesc2;
    997     ACPI_OPERAND_OBJECT     *TempObj;
    998     UINT32                  i;
    999     UINT32                  j;
   1000 
   1001 
   1002     /* Simple bubble sort */
   1003 
   1004     for (i = 1; i < Count; i++)
   1005     {
   1006         for (j = (Count - 1); j >= i; j--)
   1007         {
   1008             ObjDesc1 = Elements[j-1]->Package.Elements[Index];
   1009             ObjDesc2 = Elements[j]->Package.Elements[Index];
   1010 
   1011             if (((SortDirection == ACPI_SORT_ASCENDING) &&
   1012                     (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) ||
   1013 
   1014                 ((SortDirection == ACPI_SORT_DESCENDING) &&
   1015                     (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value)))
   1016             {
   1017                 TempObj = Elements[j-1];
   1018                 Elements[j-1] = Elements[j];
   1019                 Elements[j] = TempObj;
   1020             }
   1021         }
   1022     }
   1023 }
   1024 
   1025 
   1026 /******************************************************************************
   1027  *
   1028  * FUNCTION:    AcpiNsRemoveElement
   1029  *
   1030  * PARAMETERS:  ObjDesc             - Package object element list
   1031  *              Index               - Index of element to remove
   1032  *
   1033  * RETURN:      None
   1034  *
   1035  * DESCRIPTION: Remove the requested element of a package and delete it.
   1036  *
   1037  *****************************************************************************/
   1038 
   1039 static void
   1040 AcpiNsRemoveElement (
   1041     ACPI_OPERAND_OBJECT     *ObjDesc,
   1042     UINT32                  Index)
   1043 {
   1044     ACPI_OPERAND_OBJECT     **Source;
   1045     ACPI_OPERAND_OBJECT     **Dest;
   1046     UINT32                  Count;
   1047     UINT32                  NewCount;
   1048     UINT32                  i;
   1049 
   1050 
   1051     ACPI_FUNCTION_NAME (NsRemoveElement);
   1052 
   1053 
   1054     Count = ObjDesc->Package.Count;
   1055     NewCount = Count - 1;
   1056 
   1057     Source = ObjDesc->Package.Elements;
   1058     Dest = Source;
   1059 
   1060     /* Examine all elements of the package object, remove matched index */
   1061 
   1062     for (i = 0; i < Count; i++)
   1063     {
   1064         if (i == Index)
   1065         {
   1066             AcpiUtRemoveReference (*Source); /* Remove one ref for being in pkg */
   1067             AcpiUtRemoveReference (*Source);
   1068         }
   1069         else
   1070         {
   1071             *Dest = *Source;
   1072             Dest++;
   1073         }
   1074 
   1075         Source++;
   1076     }
   1077 
   1078     /* NULL terminate list and update the package count */
   1079 
   1080     *Dest = NULL;
   1081     ObjDesc->Package.Count = NewCount;
   1082 }
   1083