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