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