Home | History | Annotate | Line # | Download | only in namespace
nsrepair.c revision 1.1.1.3
      1 /******************************************************************************
      2  *
      3  * Module Name: nsrepair - Repair for objects returned by predefined methods
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2011, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #define __NSREPAIR_C__
     45 
     46 #include "acpi.h"
     47 #include "accommon.h"
     48 #include "acnamesp.h"
     49 #include "acinterp.h"
     50 #include "acpredef.h"
     51 
     52 #define _COMPONENT          ACPI_NAMESPACE
     53         ACPI_MODULE_NAME    ("nsrepair")
     54 
     55 
     56 /*******************************************************************************
     57  *
     58  * This module attempts to repair or convert objects returned by the
     59  * predefined methods to an object type that is expected, as per the ACPI
     60  * specification. The need for this code is dictated by the many machines that
     61  * return incorrect types for the standard predefined methods. Performing these
     62  * conversions here, in one place, eliminates the need for individual ACPI
     63  * device drivers to do the same. Note: Most of these conversions are different
     64  * than the internal object conversion routines used for implicit object
     65  * conversion.
     66  *
     67  * The following conversions can be performed as necessary:
     68  *
     69  * Integer -> String
     70  * Integer -> Buffer
     71  * String  -> Integer
     72  * String  -> Buffer
     73  * Buffer  -> Integer
     74  * Buffer  -> String
     75  * Buffer  -> Package of Integers
     76  * Package -> Package of one Package
     77  *
     78  * Additional possible repairs:
     79  *
     80  * Required package elements that are NULL replaced by Integer/String/Buffer
     81  * Incorrect standalone package wrapped with required outer package
     82  *
     83  ******************************************************************************/
     84 
     85 
     86 /* Local prototypes */
     87 
     88 static ACPI_STATUS
     89 AcpiNsConvertToInteger (
     90     ACPI_OPERAND_OBJECT     *OriginalObject,
     91     ACPI_OPERAND_OBJECT     **ReturnObject);
     92 
     93 static ACPI_STATUS
     94 AcpiNsConvertToString (
     95     ACPI_OPERAND_OBJECT     *OriginalObject,
     96     ACPI_OPERAND_OBJECT     **ReturnObject);
     97 
     98 static ACPI_STATUS
     99 AcpiNsConvertToBuffer (
    100     ACPI_OPERAND_OBJECT     *OriginalObject,
    101     ACPI_OPERAND_OBJECT     **ReturnObject);
    102 
    103 static ACPI_STATUS
    104 AcpiNsConvertToPackage (
    105     ACPI_OPERAND_OBJECT     *OriginalObject,
    106     ACPI_OPERAND_OBJECT     **ReturnObject);
    107 
    108 
    109 /*******************************************************************************
    110  *
    111  * FUNCTION:    AcpiNsRepairObject
    112  *
    113  * PARAMETERS:  Data                - Pointer to validation data structure
    114  *              ExpectedBtypes      - Object types expected
    115  *              PackageIndex        - Index of object within parent package (if
    116  *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
    117  *                                    otherwise)
    118  *              ReturnObjectPtr     - Pointer to the object returned from the
    119  *                                    evaluation of a method or object
    120  *
    121  * RETURN:      Status. AE_OK if repair was successful.
    122  *
    123  * DESCRIPTION: Attempt to repair/convert a return object of a type that was
    124  *              not expected.
    125  *
    126  ******************************************************************************/
    127 
    128 ACPI_STATUS
    129 AcpiNsRepairObject (
    130     ACPI_PREDEFINED_DATA    *Data,
    131     UINT32                  ExpectedBtypes,
    132     UINT32                  PackageIndex,
    133     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    134 {
    135     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    136     ACPI_OPERAND_OBJECT     *NewObject;
    137     ACPI_STATUS             Status;
    138 
    139 
    140     ACPI_FUNCTION_NAME (NsRepairObject);
    141 
    142 
    143     /*
    144      * At this point, we know that the type of the returned object was not
    145      * one of the expected types for this predefined name. Attempt to
    146      * repair the object by converting it to one of the expected object
    147      * types for this predefined name.
    148      */
    149     if (ExpectedBtypes & ACPI_RTYPE_INTEGER)
    150     {
    151         Status = AcpiNsConvertToInteger (ReturnObject, &NewObject);
    152         if (ACPI_SUCCESS (Status))
    153         {
    154             goto ObjectRepaired;
    155         }
    156     }
    157     if (ExpectedBtypes & ACPI_RTYPE_STRING)
    158     {
    159         Status = AcpiNsConvertToString (ReturnObject, &NewObject);
    160         if (ACPI_SUCCESS (Status))
    161         {
    162             goto ObjectRepaired;
    163         }
    164     }
    165     if (ExpectedBtypes & ACPI_RTYPE_BUFFER)
    166     {
    167         Status = AcpiNsConvertToBuffer (ReturnObject, &NewObject);
    168         if (ACPI_SUCCESS (Status))
    169         {
    170             goto ObjectRepaired;
    171         }
    172     }
    173     if (ExpectedBtypes & ACPI_RTYPE_PACKAGE)
    174     {
    175         Status = AcpiNsConvertToPackage (ReturnObject, &NewObject);
    176         if (ACPI_SUCCESS (Status))
    177         {
    178             goto ObjectRepaired;
    179         }
    180     }
    181 
    182     /* We cannot repair this object */
    183 
    184     return (AE_AML_OPERAND_TYPE);
    185 
    186 
    187 ObjectRepaired:
    188 
    189     /* Object was successfully repaired */
    190 
    191     /*
    192      * If the original object is a package element, we need to:
    193      * 1. Set the reference count of the new object to match the
    194      *    reference count of the old object.
    195      * 2. Decrement the reference count of the original object.
    196      */
    197     if (PackageIndex != ACPI_NOT_PACKAGE_ELEMENT)
    198     {
    199         NewObject->Common.ReferenceCount =
    200             ReturnObject->Common.ReferenceCount;
    201 
    202         if (ReturnObject->Common.ReferenceCount > 1)
    203         {
    204             ReturnObject->Common.ReferenceCount--;
    205         }
    206 
    207         ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    208             "%s: Converted %s to expected %s at index %u\n",
    209             Data->Pathname, AcpiUtGetObjectTypeName (ReturnObject),
    210             AcpiUtGetObjectTypeName (NewObject), PackageIndex));
    211     }
    212     else
    213     {
    214         ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    215             "%s: Converted %s to expected %s\n",
    216             Data->Pathname, AcpiUtGetObjectTypeName (ReturnObject),
    217             AcpiUtGetObjectTypeName (NewObject)));
    218     }
    219 
    220     /* Delete old object, install the new return object */
    221 
    222     AcpiUtRemoveReference (ReturnObject);
    223     *ReturnObjectPtr = NewObject;
    224     Data->Flags |= ACPI_OBJECT_REPAIRED;
    225     return (AE_OK);
    226 }
    227 
    228 
    229 /*******************************************************************************
    230  *
    231  * FUNCTION:    AcpiNsConvertToInteger
    232  *
    233  * PARAMETERS:  OriginalObject      - Object to be converted
    234  *              ReturnObject        - Where the new converted object is returned
    235  *
    236  * RETURN:      Status. AE_OK if conversion was successful.
    237  *
    238  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
    239  *
    240  ******************************************************************************/
    241 
    242 static ACPI_STATUS
    243 AcpiNsConvertToInteger (
    244     ACPI_OPERAND_OBJECT     *OriginalObject,
    245     ACPI_OPERAND_OBJECT     **ReturnObject)
    246 {
    247     ACPI_OPERAND_OBJECT     *NewObject;
    248     ACPI_STATUS             Status;
    249     UINT64                  Value = 0;
    250     UINT32                  i;
    251 
    252 
    253     switch (OriginalObject->Common.Type)
    254     {
    255     case ACPI_TYPE_STRING:
    256 
    257         /* String-to-Integer conversion */
    258 
    259         Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer,
    260                     ACPI_ANY_BASE, &Value);
    261         if (ACPI_FAILURE (Status))
    262         {
    263             return (Status);
    264         }
    265         break;
    266 
    267     case ACPI_TYPE_BUFFER:
    268 
    269         /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
    270 
    271         if (OriginalObject->Buffer.Length > 8)
    272         {
    273             return (AE_AML_OPERAND_TYPE);
    274         }
    275 
    276         /* Extract each buffer byte to create the integer */
    277 
    278         for (i = 0; i < OriginalObject->Buffer.Length; i++)
    279         {
    280             Value |= ((UINT64) OriginalObject->Buffer.Pointer[i] << (i * 8));
    281         }
    282         break;
    283 
    284     default:
    285         return (AE_AML_OPERAND_TYPE);
    286     }
    287 
    288     NewObject = AcpiUtCreateIntegerObject (Value);
    289     if (!NewObject)
    290     {
    291         return (AE_NO_MEMORY);
    292     }
    293 
    294     *ReturnObject = NewObject;
    295     return (AE_OK);
    296 }
    297 
    298 
    299 /*******************************************************************************
    300  *
    301  * FUNCTION:    AcpiNsConvertToString
    302  *
    303  * PARAMETERS:  OriginalObject      - Object to be converted
    304  *              ReturnObject        - Where the new converted object is returned
    305  *
    306  * RETURN:      Status. AE_OK if conversion was successful.
    307  *
    308  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
    309  *
    310  ******************************************************************************/
    311 
    312 static ACPI_STATUS
    313 AcpiNsConvertToString (
    314     ACPI_OPERAND_OBJECT     *OriginalObject,
    315     ACPI_OPERAND_OBJECT     **ReturnObject)
    316 {
    317     ACPI_OPERAND_OBJECT     *NewObject;
    318     ACPI_SIZE               Length;
    319     ACPI_STATUS             Status;
    320 
    321 
    322     switch (OriginalObject->Common.Type)
    323     {
    324     case ACPI_TYPE_INTEGER:
    325         /*
    326          * Integer-to-String conversion. Commonly, convert
    327          * an integer of value 0 to a NULL string. The last element of
    328          * _BIF and _BIX packages occasionally need this fix.
    329          */
    330         if (OriginalObject->Integer.Value == 0)
    331         {
    332             /* Allocate a new NULL string object */
    333 
    334             NewObject = AcpiUtCreateStringObject (0);
    335             if (!NewObject)
    336             {
    337                 return (AE_NO_MEMORY);
    338             }
    339         }
    340         else
    341         {
    342             Status = AcpiExConvertToString (OriginalObject, &NewObject,
    343                         ACPI_IMPLICIT_CONVERT_HEX);
    344             if (ACPI_FAILURE (Status))
    345             {
    346                 return (Status);
    347             }
    348         }
    349         break;
    350 
    351     case ACPI_TYPE_BUFFER:
    352         /*
    353          * Buffer-to-String conversion. Use a ToString
    354          * conversion, no transform performed on the buffer data. The best
    355          * example of this is the _BIF method, where the string data from
    356          * the battery is often (incorrectly) returned as buffer object(s).
    357          */
    358         Length = 0;
    359         while ((Length < OriginalObject->Buffer.Length) &&
    360                 (OriginalObject->Buffer.Pointer[Length]))
    361         {
    362             Length++;
    363         }
    364 
    365         /* Allocate a new string object */
    366 
    367         NewObject = AcpiUtCreateStringObject (Length);
    368         if (!NewObject)
    369         {
    370             return (AE_NO_MEMORY);
    371         }
    372 
    373         /*
    374          * Copy the raw buffer data with no transform. String is already NULL
    375          * terminated at Length+1.
    376          */
    377         ACPI_MEMCPY (NewObject->String.Pointer,
    378             OriginalObject->Buffer.Pointer, Length);
    379         break;
    380 
    381     default:
    382         return (AE_AML_OPERAND_TYPE);
    383     }
    384 
    385     *ReturnObject = NewObject;
    386     return (AE_OK);
    387 }
    388 
    389 
    390 /*******************************************************************************
    391  *
    392  * FUNCTION:    AcpiNsConvertToBuffer
    393  *
    394  * PARAMETERS:  OriginalObject      - Object to be converted
    395  *              ReturnObject        - Where the new converted object is returned
    396  *
    397  * RETURN:      Status. AE_OK if conversion was successful.
    398  *
    399  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
    400  *
    401  ******************************************************************************/
    402 
    403 static ACPI_STATUS
    404 AcpiNsConvertToBuffer (
    405     ACPI_OPERAND_OBJECT     *OriginalObject,
    406     ACPI_OPERAND_OBJECT     **ReturnObject)
    407 {
    408     ACPI_OPERAND_OBJECT     *NewObject;
    409     ACPI_STATUS             Status;
    410     ACPI_OPERAND_OBJECT     **Elements;
    411     UINT32                  *DwordBuffer;
    412     UINT32                  Count;
    413     UINT32                  i;
    414 
    415 
    416     switch (OriginalObject->Common.Type)
    417     {
    418     case ACPI_TYPE_INTEGER:
    419         /*
    420          * Integer-to-Buffer conversion.
    421          * Convert the Integer to a packed-byte buffer. _MAT and other
    422          * objects need this sometimes, if a read has been performed on a
    423          * Field object that is less than or equal to the global integer
    424          * size (32 or 64 bits).
    425          */
    426         Status = AcpiExConvertToBuffer (OriginalObject, &NewObject);
    427         if (ACPI_FAILURE (Status))
    428         {
    429             return (Status);
    430         }
    431         break;
    432 
    433     case ACPI_TYPE_STRING:
    434 
    435         /* String-to-Buffer conversion. Simple data copy */
    436 
    437         NewObject = AcpiUtCreateBufferObject (OriginalObject->String.Length);
    438         if (!NewObject)
    439         {
    440             return (AE_NO_MEMORY);
    441         }
    442 
    443         ACPI_MEMCPY (NewObject->Buffer.Pointer,
    444             OriginalObject->String.Pointer, OriginalObject->String.Length);
    445         break;
    446 
    447     case ACPI_TYPE_PACKAGE:
    448         /*
    449          * This case is often seen for predefined names that must return a
    450          * Buffer object with multiple DWORD integers within. For example,
    451          * _FDE and _GTM. The Package can be converted to a Buffer.
    452          */
    453 
    454         /* All elements of the Package must be integers */
    455 
    456         Elements = OriginalObject->Package.Elements;
    457         Count = OriginalObject->Package.Count;
    458 
    459         for (i = 0; i < Count; i++)
    460         {
    461             if ((!*Elements) ||
    462                 ((*Elements)->Common.Type != ACPI_TYPE_INTEGER))
    463             {
    464                 return (AE_AML_OPERAND_TYPE);
    465             }
    466             Elements++;
    467         }
    468 
    469         /* Create the new buffer object to replace the Package */
    470 
    471         NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count));
    472         if (!NewObject)
    473         {
    474             return (AE_NO_MEMORY);
    475         }
    476 
    477         /* Copy the package elements (integers) to the buffer as DWORDs */
    478 
    479         Elements = OriginalObject->Package.Elements;
    480         DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer);
    481 
    482         for (i = 0; i < Count; i++)
    483         {
    484             *DwordBuffer = (UINT32) (*Elements)->Integer.Value;
    485             DwordBuffer++;
    486             Elements++;
    487         }
    488         break;
    489 
    490     default:
    491         return (AE_AML_OPERAND_TYPE);
    492     }
    493 
    494     *ReturnObject = NewObject;
    495     return (AE_OK);
    496 }
    497 
    498 
    499 /*******************************************************************************
    500  *
    501  * FUNCTION:    AcpiNsConvertToPackage
    502  *
    503  * PARAMETERS:  OriginalObject      - Object to be converted
    504  *              ReturnObject        - Where the new converted object is returned
    505  *
    506  * RETURN:      Status. AE_OK if conversion was successful.
    507  *
    508  * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of
    509  *              the buffer is converted to a single integer package element.
    510  *
    511  ******************************************************************************/
    512 
    513 static ACPI_STATUS
    514 AcpiNsConvertToPackage (
    515     ACPI_OPERAND_OBJECT     *OriginalObject,
    516     ACPI_OPERAND_OBJECT     **ReturnObject)
    517 {
    518     ACPI_OPERAND_OBJECT     *NewObject;
    519     ACPI_OPERAND_OBJECT     **Elements;
    520     UINT32                  Length;
    521     UINT8                   *Buffer;
    522 
    523 
    524     switch (OriginalObject->Common.Type)
    525     {
    526     case ACPI_TYPE_BUFFER:
    527 
    528         /* Buffer-to-Package conversion */
    529 
    530         Length = OriginalObject->Buffer.Length;
    531         NewObject = AcpiUtCreatePackageObject (Length);
    532         if (!NewObject)
    533         {
    534             return (AE_NO_MEMORY);
    535         }
    536 
    537         /* Convert each buffer byte to an integer package element */
    538 
    539         Elements = NewObject->Package.Elements;
    540         Buffer = OriginalObject->Buffer.Pointer;
    541 
    542         while (Length--)
    543         {
    544             *Elements = AcpiUtCreateIntegerObject ((UINT64) *Buffer);
    545             if (!*Elements)
    546             {
    547                 AcpiUtRemoveReference (NewObject);
    548                 return (AE_NO_MEMORY);
    549             }
    550             Elements++;
    551             Buffer++;
    552         }
    553         break;
    554 
    555     default:
    556         return (AE_AML_OPERAND_TYPE);
    557     }
    558 
    559     *ReturnObject = NewObject;
    560     return (AE_OK);
    561 }
    562 
    563 
    564 /*******************************************************************************
    565  *
    566  * FUNCTION:    AcpiNsRepairNullElement
    567  *
    568  * PARAMETERS:  Data                - Pointer to validation data structure
    569  *              ExpectedBtypes      - Object types expected
    570  *              PackageIndex        - Index of object within parent package (if
    571  *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
    572  *                                    otherwise)
    573  *              ReturnObjectPtr     - Pointer to the object returned from the
    574  *                                    evaluation of a method or object
    575  *
    576  * RETURN:      Status. AE_OK if repair was successful.
    577  *
    578  * DESCRIPTION: Attempt to repair a NULL element of a returned Package object.
    579  *
    580  ******************************************************************************/
    581 
    582 ACPI_STATUS
    583 AcpiNsRepairNullElement (
    584     ACPI_PREDEFINED_DATA    *Data,
    585     UINT32                  ExpectedBtypes,
    586     UINT32                  PackageIndex,
    587     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
    588 {
    589     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    590     ACPI_OPERAND_OBJECT     *NewObject;
    591 
    592 
    593     ACPI_FUNCTION_NAME (NsRepairNullElement);
    594 
    595 
    596     /* No repair needed if return object is non-NULL */
    597 
    598     if (ReturnObject)
    599     {
    600         return (AE_OK);
    601     }
    602 
    603     /*
    604      * Attempt to repair a NULL element of a Package object. This applies to
    605      * predefined names that return a fixed-length package and each element
    606      * is required. It does not apply to variable-length packages where NULL
    607      * elements are allowed, especially at the end of the package.
    608      */
    609     if (ExpectedBtypes & ACPI_RTYPE_INTEGER)
    610     {
    611         /* Need an Integer - create a zero-value integer */
    612 
    613         NewObject = AcpiUtCreateIntegerObject ((UINT64) 0);
    614     }
    615     else if (ExpectedBtypes & ACPI_RTYPE_STRING)
    616     {
    617         /* Need a String - create a NULL string */
    618 
    619         NewObject = AcpiUtCreateStringObject (0);
    620     }
    621     else if (ExpectedBtypes & ACPI_RTYPE_BUFFER)
    622     {
    623         /* Need a Buffer - create a zero-length buffer */
    624 
    625         NewObject = AcpiUtCreateBufferObject (0);
    626     }
    627     else
    628     {
    629         /* Error for all other expected types */
    630 
    631         return (AE_AML_OPERAND_TYPE);
    632     }
    633 
    634     if (!NewObject)
    635     {
    636         return (AE_NO_MEMORY);
    637     }
    638 
    639     /* Set the reference count according to the parent Package object */
    640 
    641     NewObject->Common.ReferenceCount = Data->ParentPackage->Common.ReferenceCount;
    642 
    643     ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    644         "%s: Converted NULL package element to expected %s at index %u\n",
    645          Data->Pathname, AcpiUtGetObjectTypeName (NewObject), PackageIndex));
    646 
    647     *ReturnObjectPtr = NewObject;
    648     Data->Flags |= ACPI_OBJECT_REPAIRED;
    649     return (AE_OK);
    650 }
    651 
    652 
    653 /******************************************************************************
    654  *
    655  * FUNCTION:    AcpiNsRemoveNullElements
    656  *
    657  * PARAMETERS:  Data                - Pointer to validation data structure
    658  *              PackageType         - An AcpiReturnPackageTypes value
    659  *              ObjDesc             - A Package object
    660  *
    661  * RETURN:      None.
    662  *
    663  * DESCRIPTION: Remove all NULL package elements from packages that contain
    664  *              a variable number of sub-packages. For these types of
    665  *              packages, NULL elements can be safely removed.
    666  *
    667  *****************************************************************************/
    668 
    669 void
    670 AcpiNsRemoveNullElements (
    671     ACPI_PREDEFINED_DATA    *Data,
    672     UINT8                   PackageType,
    673     ACPI_OPERAND_OBJECT     *ObjDesc)
    674 {
    675     ACPI_OPERAND_OBJECT     **Source;
    676     ACPI_OPERAND_OBJECT     **Dest;
    677     UINT32                  Count;
    678     UINT32                  NewCount;
    679     UINT32                  i;
    680 
    681 
    682     ACPI_FUNCTION_NAME (NsRemoveNullElements);
    683 
    684 
    685     /*
    686      * We can safely remove all NULL elements from these package types:
    687      * PTYPE1_VAR packages contain a variable number of simple data types.
    688      * PTYPE2 packages contain a variable number of sub-packages.
    689      */
    690     switch (PackageType)
    691     {
    692     case ACPI_PTYPE1_VAR:
    693     case ACPI_PTYPE2:
    694     case ACPI_PTYPE2_COUNT:
    695     case ACPI_PTYPE2_PKG_COUNT:
    696     case ACPI_PTYPE2_FIXED:
    697     case ACPI_PTYPE2_MIN:
    698     case ACPI_PTYPE2_REV_FIXED:
    699         break;
    700 
    701     default:
    702     case ACPI_PTYPE1_FIXED:
    703     case ACPI_PTYPE1_OPTION:
    704         return;
    705     }
    706 
    707     Count = ObjDesc->Package.Count;
    708     NewCount = Count;
    709 
    710     Source = ObjDesc->Package.Elements;
    711     Dest = Source;
    712 
    713     /* Examine all elements of the package object, remove nulls */
    714 
    715     for (i = 0; i < Count; i++)
    716     {
    717         if (!*Source)
    718         {
    719             NewCount--;
    720         }
    721         else
    722         {
    723             *Dest = *Source;
    724             Dest++;
    725         }
    726         Source++;
    727     }
    728 
    729     /* Update parent package if any null elements were removed */
    730 
    731     if (NewCount < Count)
    732     {
    733         ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    734             "%s: Found and removed %u NULL elements\n",
    735             Data->Pathname, (Count - NewCount)));
    736 
    737         /* NULL terminate list and update the package count */
    738 
    739         *Dest = NULL;
    740         ObjDesc->Package.Count = NewCount;
    741     }
    742 }
    743 
    744 
    745 /*******************************************************************************
    746  *
    747  * FUNCTION:    AcpiNsRepairPackageList
    748  *
    749  * PARAMETERS:  Data                - Pointer to validation data structure
    750  *              ObjDescPtr          - Pointer to the object to repair. The new
    751  *                                    package object is returned here,
    752  *                                    overwriting the old object.
    753  *
    754  * RETURN:      Status, new object in *ObjDescPtr
    755  *
    756  * DESCRIPTION: Repair a common problem with objects that are defined to return
    757  *              a variable-length Package of Packages. If the variable-length
    758  *              is one, some BIOS code mistakenly simply declares a single
    759  *              Package instead of a Package with one sub-Package. This
    760  *              function attempts to repair this error by wrapping a Package
    761  *              object around the original Package, creating the correct
    762  *              Package with one sub-Package.
    763  *
    764  *              Names that can be repaired in this manner include:
    765  *              _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS
    766  *
    767  ******************************************************************************/
    768 
    769 ACPI_STATUS
    770 AcpiNsRepairPackageList (
    771     ACPI_PREDEFINED_DATA    *Data,
    772     ACPI_OPERAND_OBJECT     **ObjDescPtr)
    773 {
    774     ACPI_OPERAND_OBJECT     *PkgObjDesc;
    775 
    776 
    777     ACPI_FUNCTION_NAME (NsRepairPackageList);
    778 
    779 
    780     /*
    781      * Create the new outer package and populate it. The new package will
    782      * have a single element, the lone subpackage.
    783      */
    784     PkgObjDesc = AcpiUtCreatePackageObject (1);
    785     if (!PkgObjDesc)
    786     {
    787         return (AE_NO_MEMORY);
    788     }
    789 
    790     PkgObjDesc->Package.Elements[0] = *ObjDescPtr;
    791 
    792     /* Return the new object in the object pointer */
    793 
    794     *ObjDescPtr = PkgObjDesc;
    795     Data->Flags |= ACPI_OBJECT_REPAIRED;
    796 
    797     ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
    798         "%s: Repaired incorrectly formed Package\n", Data->Pathname));
    799 
    800     return (AE_OK);
    801 }
    802