Home | History | Annotate | Line # | Download | only in namespace
nsrepair.c revision 1.1
      1 /******************************************************************************
      2  *
      3  * Module Name: nsrepair - Repair for objects returned by predefined methods
      4  *
      5  *****************************************************************************/
      6 
      7 /******************************************************************************
      8  *
      9  * 1. Copyright Notice
     10  *
     11  * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
     12  * All rights reserved.
     13  *
     14  * 2. License
     15  *
     16  * 2.1. This is your license from Intel Corp. under its intellectual property
     17  * rights.  You may have additional license terms from the party that provided
     18  * you this software, covering your right to use that party's intellectual
     19  * property rights.
     20  *
     21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     22  * copy of the source code appearing in this file ("Covered Code") an
     23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     24  * base code distributed originally by Intel ("Original Intel Code") to copy,
     25  * make derivatives, distribute, use and display any portion of the Covered
     26  * Code in any form, with the right to sublicense such rights; and
     27  *
     28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     29  * license (with the right to sublicense), under only those claims of Intel
     30  * patents that are infringed by the Original Intel Code, to make, use, sell,
     31  * offer to sell, and import the Covered Code and derivative works thereof
     32  * solely to the minimum extent necessary to exercise the above copyright
     33  * license, and in no event shall the patent license extend to any additions
     34  * to or modifications of the Original Intel Code.  No other license or right
     35  * is granted directly or by implication, estoppel or otherwise;
     36  *
     37  * The above copyright and patent license is granted only if the following
     38  * conditions are met:
     39  *
     40  * 3. Conditions
     41  *
     42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     43  * Redistribution of source code of any substantial portion of the Covered
     44  * Code or modification with rights to further distribute source must include
     45  * the above Copyright Notice, the above License, this list of Conditions,
     46  * and the following Disclaimer and Export Compliance provision.  In addition,
     47  * Licensee must cause all Covered Code to which Licensee contributes to
     48  * contain a file documenting the changes Licensee made to create that Covered
     49  * Code and the date of any change.  Licensee must include in that file the
     50  * documentation of any changes made by any predecessor Licensee.  Licensee
     51  * must include a prominent statement that the modification is derived,
     52  * directly or indirectly, from Original Intel Code.
     53  *
     54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     55  * Redistribution of source code of any substantial portion of the Covered
     56  * Code or modification without rights to further distribute source must
     57  * include the following Disclaimer and Export Compliance provision in the
     58  * documentation and/or other materials provided with distribution.  In
     59  * addition, Licensee may not authorize further sublicense of source of any
     60  * portion of the Covered Code, and must include terms to the effect that the
     61  * license from Licensee to its licensee is limited to the intellectual
     62  * property embodied in the software Licensee provides to its licensee, and
     63  * not to intellectual property embodied in modifications its licensee may
     64  * make.
     65  *
     66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     67  * substantial portion of the Covered Code or modification must reproduce the
     68  * above Copyright Notice, and the following Disclaimer and Export Compliance
     69  * provision in the documentation and/or other materials provided with the
     70  * distribution.
     71  *
     72  * 3.4. Intel retains all right, title, and interest in and to the Original
     73  * Intel Code.
     74  *
     75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     76  * Intel shall be used in advertising or otherwise to promote the sale, use or
     77  * other dealings in products derived from or relating to the Covered Code
     78  * without prior written authorization from Intel.
     79  *
     80  * 4. Disclaimer and Export Compliance
     81  *
     82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     83  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
     85  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
     86  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
     87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     88  * PARTICULAR PURPOSE.
     89  *
     90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
     96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     97  * LIMITED REMEDY.
     98  *
     99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    100  * software or system incorporating such software without first obtaining any
    101  * required license or other approval from the U. S. Department of Commerce or
    102  * any other agency or department of the United States Government.  In the
    103  * event Licensee exports any such software from the United States or
    104  * re-exports any such software from a foreign destination, Licensee shall
    105  * ensure that the distribution and export/re-export of the software is in
    106  * compliance with all laws, regulations, orders, or other restrictions of the
    107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    108  * any of its subsidiaries will export/re-export any technical data, process,
    109  * software, or service, directly or indirectly, to any country for which the
    110  * United States government or any agency thereof requires an export license,
    111  * other governmental approval, or letter of assurance, without first obtaining
    112  * such license, approval or letter.
    113  *
    114  *****************************************************************************/
    115 
    116 #define __NSREPAIR_C__
    117 
    118 #include "acpi.h"
    119 #include "accommon.h"
    120 #include "acnamesp.h"
    121 #include "acinterp.h"
    122 #include "acpredef.h"
    123 
    124 #define _COMPONENT          ACPI_NAMESPACE
    125         ACPI_MODULE_NAME    ("nsrepair")
    126 
    127 
    128 /*******************************************************************************
    129  *
    130  * This module attempts to repair or convert objects returned by the
    131  * predefined methods to an object type that is expected, as per the ACPI
    132  * specification. The need for this code is dictated by the many machines that
    133  * return incorrect types for the standard predefined methods. Performing these
    134  * conversions here, in one place, eliminates the need for individual ACPI
    135  * device drivers to do the same. Note: Most of these conversions are different
    136  * than the internal object conversion routines used for implicit object
    137  * conversion.
    138  *
    139  * The following conversions can be performed as necessary:
    140  *
    141  * Integer -> String
    142  * Integer -> Buffer
    143  * String  -> Integer
    144  * String  -> Buffer
    145  * Buffer  -> Integer
    146  * Buffer  -> String
    147  * Buffer  -> Package of Integers
    148  * Package -> Package of one Package
    149  *
    150  * Additional possible repairs:
    151  *
    152  * Optional/unnecessary NULL package elements removed
    153  * Required package elements that are NULL replaced by Integer/String/Buffer
    154  * Incorrect standalone package wrapped with required outer package
    155  *
    156  ******************************************************************************/
    157 
    158 
    159 /* Local prototypes */
    160 
    161 static ACPI_STATUS
    162 AcpiNsConvertToInteger (
    163     ACPI_OPERAND_OBJECT     *OriginalObject,
    164     ACPI_OPERAND_OBJECT     **ReturnObject);
    165 
    166 static ACPI_STATUS
    167 AcpiNsConvertToString (
    168     ACPI_OPERAND_OBJECT     *OriginalObject,
    169     ACPI_OPERAND_OBJECT     **ReturnObject);
    170 
    171 static ACPI_STATUS
    172 AcpiNsConvertToBuffer (
    173     ACPI_OPERAND_OBJECT     *OriginalObject,
    174     ACPI_OPERAND_OBJECT     **ReturnObject);
    175 
    176 static ACPI_STATUS
    177 AcpiNsConvertToPackage (
    178     ACPI_OPERAND_OBJECT     *OriginalObject,
    179     ACPI_OPERAND_OBJECT     **ReturnObject);
    180 
    181 
    182 /*******************************************************************************
    183  *
    184  * FUNCTION:    AcpiNsRepairObject
    185  *
    186  * PARAMETERS:  Data                - Pointer to validation data structure
    187  *              ExpectedBtypes      - Object types expected
    188  *              PackageIndex        - Index of object within parent package (if
    189  *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
    190  *                                    otherwise)
    191  *              ReturnObjectPtr     - Pointer to the object returned from the
    192  *                                    evaluation of a method or object
    193  *
    194  * RETURN:      Status. AE_OK if repair was successful.
    195  *
    196  * DESCRIPTION: Attempt to repair/convert a return object of a type that was
    197  *              not expected.
    198  *
    199  ******************************************************************************/
    200 
    201 ACPI_STATUS
    202 AcpiNsRepairObject (
    203     ACPI_PREDEFINED_DATA    *Data,
    204     UINT32                  ExpectedBtypes,
    205     UINT32                  PackageIndex,
    206     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    207 {
    208     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    209     ACPI_OPERAND_OBJECT     *NewObject;
    210     ACPI_STATUS             Status;
    211 
    212 
    213     ACPI_FUNCTION_NAME (NsRepairObject);
    214 
    215 
    216     /*
    217      * At this point, we know that the type of the returned object was not
    218      * one of the expected types for this predefined name. Attempt to
    219      * repair the object by converting it to one of the expected object
    220      * types for this predefined name.
    221      */
    222     if (ExpectedBtypes & ACPI_RTYPE_INTEGER)
    223     {
    224         Status = AcpiNsConvertToInteger (ReturnObject, &NewObject);
    225         if (ACPI_SUCCESS (Status))
    226         {
    227             goto ObjectRepaired;
    228         }
    229     }
    230     if (ExpectedBtypes & ACPI_RTYPE_STRING)
    231     {
    232         Status = AcpiNsConvertToString (ReturnObject, &NewObject);
    233         if (ACPI_SUCCESS (Status))
    234         {
    235             goto ObjectRepaired;
    236         }
    237     }
    238     if (ExpectedBtypes & ACPI_RTYPE_BUFFER)
    239     {
    240         Status = AcpiNsConvertToBuffer (ReturnObject, &NewObject);
    241         if (ACPI_SUCCESS (Status))
    242         {
    243             goto ObjectRepaired;
    244         }
    245     }
    246     if (ExpectedBtypes & ACPI_RTYPE_PACKAGE)
    247     {
    248         Status = AcpiNsConvertToPackage (ReturnObject, &NewObject);
    249         if (ACPI_SUCCESS (Status))
    250         {
    251             goto ObjectRepaired;
    252         }
    253     }
    254 
    255     /* We cannot repair this object */
    256 
    257     return (AE_AML_OPERAND_TYPE);
    258 
    259 
    260 ObjectRepaired:
    261 
    262     /* Object was successfully repaired */
    263 
    264     /*
    265      * If the original object is a package element, we need to:
    266      * 1. Set the reference count of the new object to match the
    267      *    reference count of the old object.
    268      * 2. Decrement the reference count of the original object.
    269      */
    270     if (PackageIndex != ACPI_NOT_PACKAGE_ELEMENT)
    271     {
    272         NewObject->Common.ReferenceCount =
    273             ReturnObject->Common.ReferenceCount;
    274 
    275         if (ReturnObject->Common.ReferenceCount > 1)
    276         {
    277             ReturnObject->Common.ReferenceCount--;
    278         }
    279 
    280         ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    281             "%s: Converted %s to expected %s at index %u\n",
    282             Data->Pathname, AcpiUtGetObjectTypeName (ReturnObject),
    283             AcpiUtGetObjectTypeName (NewObject), PackageIndex));
    284     }
    285     else
    286     {
    287         ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    288             "%s: Converted %s to expected %s\n",
    289             Data->Pathname, AcpiUtGetObjectTypeName (ReturnObject),
    290             AcpiUtGetObjectTypeName (NewObject)));
    291     }
    292 
    293     /* Delete old object, install the new return object */
    294 
    295     AcpiUtRemoveReference (ReturnObject);
    296     *ReturnObjectPtr = NewObject;
    297     Data->Flags |= ACPI_OBJECT_REPAIRED;
    298     return (AE_OK);
    299 }
    300 
    301 
    302 /*******************************************************************************
    303  *
    304  * FUNCTION:    AcpiNsConvertToInteger
    305  *
    306  * PARAMETERS:  OriginalObject      - Object to be converted
    307  *              ReturnObject        - Where the new converted object is returned
    308  *
    309  * RETURN:      Status. AE_OK if conversion was successful.
    310  *
    311  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
    312  *
    313  ******************************************************************************/
    314 
    315 static ACPI_STATUS
    316 AcpiNsConvertToInteger (
    317     ACPI_OPERAND_OBJECT     *OriginalObject,
    318     ACPI_OPERAND_OBJECT     **ReturnObject)
    319 {
    320     ACPI_OPERAND_OBJECT     *NewObject;
    321     ACPI_STATUS             Status;
    322     UINT64                  Value = 0;
    323     UINT32                  i;
    324 
    325 
    326     switch (OriginalObject->Common.Type)
    327     {
    328     case ACPI_TYPE_STRING:
    329 
    330         /* String-to-Integer conversion */
    331 
    332         Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer,
    333                     ACPI_ANY_BASE, &Value);
    334         if (ACPI_FAILURE (Status))
    335         {
    336             return (Status);
    337         }
    338         break;
    339 
    340     case ACPI_TYPE_BUFFER:
    341 
    342         /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
    343 
    344         if (OriginalObject->Buffer.Length > 8)
    345         {
    346             return (AE_AML_OPERAND_TYPE);
    347         }
    348 
    349         /* Extract each buffer byte to create the integer */
    350 
    351         for (i = 0; i < OriginalObject->Buffer.Length; i++)
    352         {
    353             Value |= ((UINT64) OriginalObject->Buffer.Pointer[i] << (i * 8));
    354         }
    355         break;
    356 
    357     default:
    358         return (AE_AML_OPERAND_TYPE);
    359     }
    360 
    361     NewObject = AcpiUtCreateIntegerObject (Value);
    362     if (!NewObject)
    363     {
    364         return (AE_NO_MEMORY);
    365     }
    366 
    367     *ReturnObject = NewObject;
    368     return (AE_OK);
    369 }
    370 
    371 
    372 /*******************************************************************************
    373  *
    374  * FUNCTION:    AcpiNsConvertToString
    375  *
    376  * PARAMETERS:  OriginalObject      - Object to be converted
    377  *              ReturnObject        - Where the new converted object is returned
    378  *
    379  * RETURN:      Status. AE_OK if conversion was successful.
    380  *
    381  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
    382  *
    383  ******************************************************************************/
    384 
    385 static ACPI_STATUS
    386 AcpiNsConvertToString (
    387     ACPI_OPERAND_OBJECT     *OriginalObject,
    388     ACPI_OPERAND_OBJECT     **ReturnObject)
    389 {
    390     ACPI_OPERAND_OBJECT     *NewObject;
    391     ACPI_SIZE               Length;
    392     ACPI_STATUS             Status;
    393 
    394 
    395     switch (OriginalObject->Common.Type)
    396     {
    397     case ACPI_TYPE_INTEGER:
    398         /*
    399          * Integer-to-String conversion. Commonly, convert
    400          * an integer of value 0 to a NULL string. The last element of
    401          * _BIF and _BIX packages occasionally need this fix.
    402          */
    403         if (OriginalObject->Integer.Value == 0)
    404         {
    405             /* Allocate a new NULL string object */
    406 
    407             NewObject = AcpiUtCreateStringObject (0);
    408             if (!NewObject)
    409             {
    410                 return (AE_NO_MEMORY);
    411             }
    412         }
    413         else
    414         {
    415             Status = AcpiExConvertToString (OriginalObject, &NewObject,
    416                         ACPI_IMPLICIT_CONVERT_HEX);
    417             if (ACPI_FAILURE (Status))
    418             {
    419                 return (Status);
    420             }
    421         }
    422         break;
    423 
    424     case ACPI_TYPE_BUFFER:
    425         /*
    426          * Buffer-to-String conversion. Use a ToString
    427          * conversion, no transform performed on the buffer data. The best
    428          * example of this is the _BIF method, where the string data from
    429          * the battery is often (incorrectly) returned as buffer object(s).
    430          */
    431         Length = 0;
    432         while ((Length < OriginalObject->Buffer.Length) &&
    433                 (OriginalObject->Buffer.Pointer[Length]))
    434         {
    435             Length++;
    436         }
    437 
    438         /* Allocate a new string object */
    439 
    440         NewObject = AcpiUtCreateStringObject (Length);
    441         if (!NewObject)
    442         {
    443             return (AE_NO_MEMORY);
    444         }
    445 
    446         /*
    447          * Copy the raw buffer data with no transform. String is already NULL
    448          * terminated at Length+1.
    449          */
    450         ACPI_MEMCPY (NewObject->String.Pointer,
    451             OriginalObject->Buffer.Pointer, Length);
    452         break;
    453 
    454     default:
    455         return (AE_AML_OPERAND_TYPE);
    456     }
    457 
    458     *ReturnObject = NewObject;
    459     return (AE_OK);
    460 }
    461 
    462 
    463 /*******************************************************************************
    464  *
    465  * FUNCTION:    AcpiNsConvertToBuffer
    466  *
    467  * PARAMETERS:  OriginalObject      - Object to be converted
    468  *              ReturnObject        - Where the new converted object is returned
    469  *
    470  * RETURN:      Status. AE_OK if conversion was successful.
    471  *
    472  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
    473  *
    474  ******************************************************************************/
    475 
    476 static ACPI_STATUS
    477 AcpiNsConvertToBuffer (
    478     ACPI_OPERAND_OBJECT     *OriginalObject,
    479     ACPI_OPERAND_OBJECT     **ReturnObject)
    480 {
    481     ACPI_OPERAND_OBJECT     *NewObject;
    482     ACPI_STATUS             Status;
    483     ACPI_OPERAND_OBJECT     **Elements;
    484     UINT32                  *DwordBuffer;
    485     UINT32                  Count;
    486     UINT32                  i;
    487 
    488 
    489     switch (OriginalObject->Common.Type)
    490     {
    491     case ACPI_TYPE_INTEGER:
    492         /*
    493          * Integer-to-Buffer conversion.
    494          * Convert the Integer to a packed-byte buffer. _MAT and other
    495          * objects need this sometimes, if a read has been performed on a
    496          * Field object that is less than or equal to the global integer
    497          * size (32 or 64 bits).
    498          */
    499         Status = AcpiExConvertToBuffer (OriginalObject, &NewObject);
    500         if (ACPI_FAILURE (Status))
    501         {
    502             return (Status);
    503         }
    504         break;
    505 
    506     case ACPI_TYPE_STRING:
    507 
    508         /* String-to-Buffer conversion. Simple data copy */
    509 
    510         NewObject = AcpiUtCreateBufferObject (OriginalObject->String.Length);
    511         if (!NewObject)
    512         {
    513             return (AE_NO_MEMORY);
    514         }
    515 
    516         ACPI_MEMCPY (NewObject->Buffer.Pointer,
    517             OriginalObject->String.Pointer, OriginalObject->String.Length);
    518         break;
    519 
    520     case ACPI_TYPE_PACKAGE:
    521         /*
    522          * This case is often seen for predefined names that must return a
    523          * Buffer object with multiple DWORD integers within. For example,
    524          * _FDE and _GTM. The Package can be converted to a Buffer.
    525          */
    526 
    527         /* All elements of the Package must be integers */
    528 
    529         Elements = OriginalObject->Package.Elements;
    530         Count = OriginalObject->Package.Count;
    531 
    532         for (i = 0; i < Count; i++)
    533         {
    534             if ((!*Elements) ||
    535                 ((*Elements)->Common.Type != ACPI_TYPE_INTEGER))
    536             {
    537                 return (AE_AML_OPERAND_TYPE);
    538             }
    539             Elements++;
    540         }
    541 
    542         /* Create the new buffer object to replace the Package */
    543 
    544         NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count));
    545         if (!NewObject)
    546         {
    547             return (AE_NO_MEMORY);
    548         }
    549 
    550         /* Copy the package elements (integers) to the buffer as DWORDs */
    551 
    552         Elements = OriginalObject->Package.Elements;
    553         DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer);
    554 
    555         for (i = 0; i < Count; i++)
    556         {
    557             *DwordBuffer = (UINT32) (*Elements)->Integer.Value;
    558             DwordBuffer++;
    559             Elements++;
    560         }
    561         break;
    562 
    563     default:
    564         return (AE_AML_OPERAND_TYPE);
    565     }
    566 
    567     *ReturnObject = NewObject;
    568     return (AE_OK);
    569 }
    570 
    571 
    572 /*******************************************************************************
    573  *
    574  * FUNCTION:    AcpiNsConvertToPackage
    575  *
    576  * PARAMETERS:  OriginalObject      - Object to be converted
    577  *              ReturnObject        - Where the new converted object is returned
    578  *
    579  * RETURN:      Status. AE_OK if conversion was successful.
    580  *
    581  * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of
    582  *              the buffer is converted to a single integer package element.
    583  *
    584  ******************************************************************************/
    585 
    586 static ACPI_STATUS
    587 AcpiNsConvertToPackage (
    588     ACPI_OPERAND_OBJECT     *OriginalObject,
    589     ACPI_OPERAND_OBJECT     **ReturnObject)
    590 {
    591     ACPI_OPERAND_OBJECT     *NewObject;
    592     ACPI_OPERAND_OBJECT     **Elements;
    593     UINT32                  Length;
    594     UINT8                   *Buffer;
    595 
    596 
    597     switch (OriginalObject->Common.Type)
    598     {
    599     case ACPI_TYPE_BUFFER:
    600 
    601         /* Buffer-to-Package conversion */
    602 
    603         Length = OriginalObject->Buffer.Length;
    604         NewObject = AcpiUtCreatePackageObject (Length);
    605         if (!NewObject)
    606         {
    607             return (AE_NO_MEMORY);
    608         }
    609 
    610         /* Convert each buffer byte to an integer package element */
    611 
    612         Elements = NewObject->Package.Elements;
    613         Buffer = OriginalObject->Buffer.Pointer;
    614 
    615         while (Length--)
    616         {
    617             *Elements = AcpiUtCreateIntegerObject ((UINT64) *Buffer);
    618             if (!*Elements)
    619             {
    620                 AcpiUtRemoveReference (NewObject);
    621                 return (AE_NO_MEMORY);
    622             }
    623             Elements++;
    624             Buffer++;
    625         }
    626         break;
    627 
    628     default:
    629         return (AE_AML_OPERAND_TYPE);
    630     }
    631 
    632     *ReturnObject = NewObject;
    633     return (AE_OK);
    634 }
    635 
    636 
    637 /*******************************************************************************
    638  *
    639  * FUNCTION:    AcpiNsRepairNullElement
    640  *
    641  * PARAMETERS:  Data                - Pointer to validation data structure
    642  *              ExpectedBtypes      - Object types expected
    643  *              PackageIndex        - Index of object within parent package (if
    644  *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
    645  *                                    otherwise)
    646  *              ReturnObjectPtr     - Pointer to the object returned from the
    647  *                                    evaluation of a method or object
    648  *
    649  * RETURN:      Status. AE_OK if repair was successful.
    650  *
    651  * DESCRIPTION: Attempt to repair a NULL element of a returned Package object.
    652  *
    653  ******************************************************************************/
    654 
    655 ACPI_STATUS
    656 AcpiNsRepairNullElement (
    657     ACPI_PREDEFINED_DATA    *Data,
    658     UINT32                  ExpectedBtypes,
    659     UINT32                  PackageIndex,
    660     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    661 {
    662     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    663     ACPI_OPERAND_OBJECT     *NewObject;
    664 
    665 
    666     ACPI_FUNCTION_NAME (NsRepairNullElement);
    667 
    668 
    669     /* No repair needed if return object is non-NULL */
    670 
    671     if (ReturnObject)
    672     {
    673         return (AE_OK);
    674     }
    675 
    676     /*
    677      * Attempt to repair a NULL element of a Package object. This applies to
    678      * predefined names that return a fixed-length package and each element
    679      * is required. It does not apply to variable-length packages where NULL
    680      * elements are allowed, especially at the end of the package.
    681      */
    682     if (ExpectedBtypes & ACPI_RTYPE_INTEGER)
    683     {
    684         /* Need an Integer - create a zero-value integer */
    685 
    686         NewObject = AcpiUtCreateIntegerObject (0);
    687     }
    688     else if (ExpectedBtypes & ACPI_RTYPE_STRING)
    689     {
    690         /* Need a String - create a NULL string */
    691 
    692         NewObject = AcpiUtCreateStringObject (0);
    693     }
    694     else if (ExpectedBtypes & ACPI_RTYPE_BUFFER)
    695     {
    696         /* Need a Buffer - create a zero-length buffer */
    697 
    698         NewObject = AcpiUtCreateBufferObject (0);
    699     }
    700     else
    701     {
    702         /* Error for all other expected types */
    703 
    704         return (AE_AML_OPERAND_TYPE);
    705     }
    706 
    707     if (!NewObject)
    708     {
    709         return (AE_NO_MEMORY);
    710     }
    711 
    712     /* Set the reference count according to the parent Package object */
    713 
    714     NewObject->Common.ReferenceCount = Data->ParentPackage->Common.ReferenceCount;
    715 
    716     ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    717         "%s: Converted NULL package element to expected %s at index %u\n",
    718          Data->Pathname, AcpiUtGetObjectTypeName (NewObject), PackageIndex));
    719 
    720     *ReturnObjectPtr = NewObject;
    721     Data->Flags |= ACPI_OBJECT_REPAIRED;
    722     return (AE_OK);
    723 }
    724 
    725 
    726 /******************************************************************************
    727  *
    728  * FUNCTION:    AcpiNsRemoveNullElements
    729  *
    730  * PARAMETERS:  Data                - Pointer to validation data structure
    731  *              PackageType         - An AcpiReturnPackageTypes value
    732  *              ObjDesc             - A Package object
    733  *
    734  * RETURN:      None.
    735  *
    736  * DESCRIPTION: Remove all NULL package elements from packages that contain
    737  *              a variable number of sub-packages. For these types of
    738  *              packages, NULL elements can be safely removed.
    739  *
    740  *****************************************************************************/
    741 
    742 void
    743 AcpiNsRemoveNullElements (
    744     ACPI_PREDEFINED_DATA    *Data,
    745     UINT8                   PackageType,
    746     ACPI_OPERAND_OBJECT     *ObjDesc)
    747 {
    748     ACPI_OPERAND_OBJECT     **Source;
    749     ACPI_OPERAND_OBJECT     **Dest;
    750     UINT32                  Count;
    751     UINT32                  NewCount;
    752     UINT32                  i;
    753 
    754 
    755     ACPI_FUNCTION_NAME (NsRemoveNullElements);
    756 
    757 
    758     /*
    759      * PTYPE1 packages contain no subpackages.
    760      * PTYPE2 packages contain a variable number of sub-packages. We can
    761      * safely remove all NULL elements from the PTYPE2 packages.
    762      */
    763     switch (PackageType)
    764     {
    765     case ACPI_PTYPE1_FIXED:
    766     case ACPI_PTYPE1_VAR:
    767     case ACPI_PTYPE1_OPTION:
    768         return;
    769 
    770     case ACPI_PTYPE2:
    771     case ACPI_PTYPE2_COUNT:
    772     case ACPI_PTYPE2_PKG_COUNT:
    773     case ACPI_PTYPE2_FIXED:
    774     case ACPI_PTYPE2_MIN:
    775     case ACPI_PTYPE2_REV_FIXED:
    776         break;
    777 
    778     default:
    779         return;
    780     }
    781 
    782     Count = ObjDesc->Package.Count;
    783     NewCount = Count;
    784 
    785     Source = ObjDesc->Package.Elements;
    786     Dest = Source;
    787 
    788     /* Examine all elements of the package object, remove nulls */
    789 
    790     for (i = 0; i < Count; i++)
    791     {
    792         if (!*Source)
    793         {
    794             NewCount--;
    795         }
    796         else
    797         {
    798             *Dest = *Source;
    799             Dest++;
    800         }
    801         Source++;
    802     }
    803 
    804     /* Update parent package if any null elements were removed */
    805 
    806     if (NewCount < Count)
    807     {
    808         ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    809             "%s: Found and removed %u NULL elements\n",
    810             Data->Pathname, (Count - NewCount)));
    811 
    812         /* NULL terminate list and update the package count */
    813 
    814         *Dest = NULL;
    815         ObjDesc->Package.Count = NewCount;
    816     }
    817 }
    818 
    819 
    820 /*******************************************************************************
    821  *
    822  * FUNCTION:    AcpiNsRepairPackageList
    823  *
    824  * PARAMETERS:  Data                - Pointer to validation data structure
    825  *              ObjDescPtr          - Pointer to the object to repair. The new
    826  *                                    package object is returned here,
    827  *                                    overwriting the old object.
    828  *
    829  * RETURN:      Status, new object in *ObjDescPtr
    830  *
    831  * DESCRIPTION: Repair a common problem with objects that are defined to return
    832  *              a variable-length Package of Packages. If the variable-length
    833  *              is one, some BIOS code mistakenly simply declares a single
    834  *              Package instead of a Package with one sub-Package. This
    835  *              function attempts to repair this error by wrapping a Package
    836  *              object around the original Package, creating the correct
    837  *              Package with one sub-Package.
    838  *
    839  *              Names that can be repaired in this manner include:
    840  *              _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS
    841  *
    842  ******************************************************************************/
    843 
    844 ACPI_STATUS
    845 AcpiNsRepairPackageList (
    846     ACPI_PREDEFINED_DATA    *Data,
    847     ACPI_OPERAND_OBJECT     **ObjDescPtr)
    848 {
    849     ACPI_OPERAND_OBJECT     *PkgObjDesc;
    850 
    851 
    852     ACPI_FUNCTION_NAME (NsRepairPackageList);
    853 
    854 
    855     /*
    856      * Create the new outer package and populate it. The new package will
    857      * have a single element, the lone subpackage.
    858      */
    859     PkgObjDesc = AcpiUtCreatePackageObject (1);
    860     if (!PkgObjDesc)
    861     {
    862         return (AE_NO_MEMORY);
    863     }
    864 
    865     PkgObjDesc->Package.Elements[0] = *ObjDescPtr;
    866 
    867     /* Return the new object in the object pointer */
    868 
    869     *ObjDescPtr = PkgObjDesc;
    870     Data->Flags |= ACPI_OBJECT_REPAIRED;
    871 
    872     ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    873         "%s: Repaired incorrectly formed Package\n", Data->Pathname));
    874 
    875     return (AE_OK);
    876 }
    877