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 }