nsrepair.c revision 228110
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 * 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
88static ACPI_STATUS
89AcpiNsConvertToInteger (
90    ACPI_OPERAND_OBJECT     *OriginalObject,
91    ACPI_OPERAND_OBJECT     **ReturnObject);
92
93static ACPI_STATUS
94AcpiNsConvertToString (
95    ACPI_OPERAND_OBJECT     *OriginalObject,
96    ACPI_OPERAND_OBJECT     **ReturnObject);
97
98static ACPI_STATUS
99AcpiNsConvertToBuffer (
100    ACPI_OPERAND_OBJECT     *OriginalObject,
101    ACPI_OPERAND_OBJECT     **ReturnObject);
102
103static ACPI_STATUS
104AcpiNsConvertToPackage (
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
128ACPI_STATUS
129AcpiNsRepairObject (
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
187ObjectRepaired:
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
242static ACPI_STATUS
243AcpiNsConvertToInteger (
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
312static ACPI_STATUS
313AcpiNsConvertToString (
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
403static ACPI_STATUS
404AcpiNsConvertToBuffer (
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
513static ACPI_STATUS
514AcpiNsConvertToPackage (
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
582ACPI_STATUS
583AcpiNsRepairNullElement (
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
669void
670AcpiNsRemoveNullElements (
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    case ACPI_PTYPE2_FIX_VAR:
700        break;
701
702    default:
703    case ACPI_PTYPE1_FIXED:
704    case ACPI_PTYPE1_OPTION:
705        return;
706    }
707
708    Count = ObjDesc->Package.Count;
709    NewCount = Count;
710
711    Source = ObjDesc->Package.Elements;
712    Dest = Source;
713
714    /* Examine all elements of the package object, remove nulls */
715
716    for (i = 0; i < Count; i++)
717    {
718        if (!*Source)
719        {
720            NewCount--;
721        }
722        else
723        {
724            *Dest = *Source;
725            Dest++;
726        }
727        Source++;
728    }
729
730    /* Update parent package if any null elements were removed */
731
732    if (NewCount < Count)
733    {
734        ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
735            "%s: Found and removed %u NULL elements\n",
736            Data->Pathname, (Count - NewCount)));
737
738        /* NULL terminate list and update the package count */
739
740        *Dest = NULL;
741        ObjDesc->Package.Count = NewCount;
742    }
743}
744
745
746/*******************************************************************************
747 *
748 * FUNCTION:    AcpiNsRepairPackageList
749 *
750 * PARAMETERS:  Data                - Pointer to validation data structure
751 *              ObjDescPtr          - Pointer to the object to repair. The new
752 *                                    package object is returned here,
753 *                                    overwriting the old object.
754 *
755 * RETURN:      Status, new object in *ObjDescPtr
756 *
757 * DESCRIPTION: Repair a common problem with objects that are defined to return
758 *              a variable-length Package of Packages. If the variable-length
759 *              is one, some BIOS code mistakenly simply declares a single
760 *              Package instead of a Package with one sub-Package. This
761 *              function attempts to repair this error by wrapping a Package
762 *              object around the original Package, creating the correct
763 *              Package with one sub-Package.
764 *
765 *              Names that can be repaired in this manner include:
766 *              _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS
767 *
768 ******************************************************************************/
769
770ACPI_STATUS
771AcpiNsRepairPackageList (
772    ACPI_PREDEFINED_DATA    *Data,
773    ACPI_OPERAND_OBJECT     **ObjDescPtr)
774{
775    ACPI_OPERAND_OBJECT     *PkgObjDesc;
776
777
778    ACPI_FUNCTION_NAME (NsRepairPackageList);
779
780
781    /*
782     * Create the new outer package and populate it. The new package will
783     * have a single element, the lone subpackage.
784     */
785    PkgObjDesc = AcpiUtCreatePackageObject (1);
786    if (!PkgObjDesc)
787    {
788        return (AE_NO_MEMORY);
789    }
790
791    PkgObjDesc->Package.Elements[0] = *ObjDescPtr;
792
793    /* Return the new object in the object pointer */
794
795    *ObjDescPtr = PkgObjDesc;
796    Data->Flags |= ACPI_OBJECT_REPAIRED;
797
798    ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
799        "%s: Repaired incorrectly formed Package\n", Data->Pathname));
800
801    return (AE_OK);
802}
803