xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/namespace/nsprepkg.c (revision d63ed5844d997a61afd7a6c4b7c9fad0dc01e9f3)
1 /******************************************************************************
2  *
3  * Module Name: nsprepkg - Validation of package objects for predefined names
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2016, 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 #include "acpi.h"
117 #include "accommon.h"
118 #include "acnamesp.h"
119 #include "acpredef.h"
120 
121 
122 #define _COMPONENT          ACPI_NAMESPACE
123         ACPI_MODULE_NAME    ("nsprepkg")
124 
125 
126 /* Local prototypes */
127 
128 static ACPI_STATUS
129 AcpiNsCheckPackageList (
130     ACPI_EVALUATE_INFO          *Info,
131     const ACPI_PREDEFINED_INFO  *Package,
132     ACPI_OPERAND_OBJECT         **Elements,
133     UINT32                      Count);
134 
135 static ACPI_STATUS
136 AcpiNsCheckPackageElements (
137     ACPI_EVALUATE_INFO          *Info,
138     ACPI_OPERAND_OBJECT         **Elements,
139     UINT8                       Type1,
140     UINT32                      Count1,
141     UINT8                       Type2,
142     UINT32                      Count2,
143     UINT32                      StartIndex);
144 
145 static ACPI_STATUS
146 AcpiNsCustomPackage (
147     ACPI_EVALUATE_INFO          *Info,
148     ACPI_OPERAND_OBJECT         **Elements,
149     UINT32                      Count);
150 
151 
152 /*******************************************************************************
153  *
154  * FUNCTION:    AcpiNsCheckPackage
155  *
156  * PARAMETERS:  Info                - Method execution information block
157  *              ReturnObjectPtr     - Pointer to the object returned from the
158  *                                    evaluation of a method or object
159  *
160  * RETURN:      Status
161  *
162  * DESCRIPTION: Check a returned package object for the correct count and
163  *              correct type of all sub-objects.
164  *
165  ******************************************************************************/
166 
167 ACPI_STATUS
168 AcpiNsCheckPackage (
169     ACPI_EVALUATE_INFO          *Info,
170     ACPI_OPERAND_OBJECT         **ReturnObjectPtr)
171 {
172     ACPI_OPERAND_OBJECT         *ReturnObject = *ReturnObjectPtr;
173     const ACPI_PREDEFINED_INFO  *Package;
174     ACPI_OPERAND_OBJECT         **Elements;
175     ACPI_STATUS                 Status = AE_OK;
176     UINT32                      ExpectedCount;
177     UINT32                      Count;
178     UINT32                      i;
179 
180 
181     ACPI_FUNCTION_NAME (NsCheckPackage);
182 
183 
184     /* The package info for this name is in the next table entry */
185 
186     Package = Info->Predefined + 1;
187 
188     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
189         "%s Validating return Package of Type %X, Count %X\n",
190         Info->FullPathname, Package->RetInfo.Type,
191         ReturnObject->Package.Count));
192 
193     /*
194      * For variable-length Packages, we can safely remove all embedded
195      * and trailing NULL package elements
196      */
197     AcpiNsRemoveNullElements (Info, Package->RetInfo.Type, ReturnObject);
198 
199     /* Extract package count and elements array */
200 
201     Elements = ReturnObject->Package.Elements;
202     Count = ReturnObject->Package.Count;
203 
204     /*
205      * Most packages must have at least one element. The only exception
206      * is the variable-length package (ACPI_PTYPE1_VAR).
207      */
208     if (!Count)
209     {
210         if (Package->RetInfo.Type == ACPI_PTYPE1_VAR)
211         {
212             return (AE_OK);
213         }
214 
215         ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
216             "Return Package has no elements (empty)"));
217 
218         return (AE_AML_OPERAND_VALUE);
219     }
220 
221     /*
222      * Decode the type of the expected package contents
223      *
224      * PTYPE1 packages contain no subpackages
225      * PTYPE2 packages contain subpackages
226      */
227     switch (Package->RetInfo.Type)
228     {
229     case ACPI_PTYPE_CUSTOM:
230 
231         Status = AcpiNsCustomPackage (Info, Elements, Count);
232         break;
233 
234     case ACPI_PTYPE1_FIXED:
235         /*
236          * The package count is fixed and there are no subpackages
237          *
238          * If package is too small, exit.
239          * If package is larger than expected, issue warning but continue
240          */
241         ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
242         if (Count < ExpectedCount)
243         {
244             goto PackageTooSmall;
245         }
246         else if (Count > ExpectedCount)
247         {
248             ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
249                 "%s: Return Package is larger than needed - "
250                 "found %u, expected %u\n",
251                 Info->FullPathname, Count, ExpectedCount));
252         }
253 
254         /* Validate all elements of the returned package */
255 
256         Status = AcpiNsCheckPackageElements (Info, Elements,
257             Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
258             Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0);
259         break;
260 
261     case ACPI_PTYPE1_VAR:
262         /*
263          * The package count is variable, there are no subpackages, and all
264          * elements must be of the same type
265          */
266         for (i = 0; i < Count; i++)
267         {
268             Status = AcpiNsCheckObjectType (Info, Elements,
269                 Package->RetInfo.ObjectType1, i);
270             if (ACPI_FAILURE (Status))
271             {
272                 return (Status);
273             }
274 
275             Elements++;
276         }
277         break;
278 
279     case ACPI_PTYPE1_OPTION:
280         /*
281          * The package count is variable, there are no subpackages. There are
282          * a fixed number of required elements, and a variable number of
283          * optional elements.
284          *
285          * Check if package is at least as large as the minimum required
286          */
287         ExpectedCount = Package->RetInfo3.Count;
288         if (Count < ExpectedCount)
289         {
290             goto PackageTooSmall;
291         }
292 
293         /* Variable number of sub-objects */
294 
295         for (i = 0; i < Count; i++)
296         {
297             if (i < Package->RetInfo3.Count)
298             {
299                 /* These are the required package elements (0, 1, or 2) */
300 
301                 Status = AcpiNsCheckObjectType (Info, Elements,
302                     Package->RetInfo3.ObjectType[i], i);
303                 if (ACPI_FAILURE (Status))
304                 {
305                     return (Status);
306                 }
307             }
308             else
309             {
310                 /* These are the optional package elements */
311 
312                 Status = AcpiNsCheckObjectType (Info, Elements,
313                     Package->RetInfo3.TailObjectType, i);
314                 if (ACPI_FAILURE (Status))
315                 {
316                     return (Status);
317                 }
318             }
319 
320             Elements++;
321         }
322         break;
323 
324     case ACPI_PTYPE2_REV_FIXED:
325 
326         /* First element is the (Integer) revision */
327 
328         Status = AcpiNsCheckObjectType (
329             Info, Elements, ACPI_RTYPE_INTEGER, 0);
330         if (ACPI_FAILURE (Status))
331         {
332             return (Status);
333         }
334 
335         Elements++;
336         Count--;
337 
338         /* Examine the subpackages */
339 
340         Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
341         break;
342 
343     case ACPI_PTYPE2_PKG_COUNT:
344 
345         /* First element is the (Integer) count of subpackages to follow */
346 
347         Status = AcpiNsCheckObjectType (
348             Info, Elements, ACPI_RTYPE_INTEGER, 0);
349         if (ACPI_FAILURE (Status))
350         {
351             return (Status);
352         }
353 
354         /*
355          * Count cannot be larger than the parent package length, but allow it
356          * to be smaller. The >= accounts for the Integer above.
357          */
358         ExpectedCount = (UINT32) (*Elements)->Integer.Value;
359         if (ExpectedCount >= Count)
360         {
361             goto PackageTooSmall;
362         }
363 
364         Count = ExpectedCount;
365         Elements++;
366 
367         /* Examine the subpackages */
368 
369         Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
370         break;
371 
372     case ACPI_PTYPE2:
373     case ACPI_PTYPE2_FIXED:
374     case ACPI_PTYPE2_MIN:
375     case ACPI_PTYPE2_COUNT:
376     case ACPI_PTYPE2_FIX_VAR:
377         /*
378          * These types all return a single Package that consists of a
379          * variable number of subpackages.
380          *
381          * First, ensure that the first element is a subpackage. If not,
382          * the BIOS may have incorrectly returned the object as a single
383          * package instead of a Package of Packages (a common error if
384          * there is only one entry). We may be able to repair this by
385          * wrapping the returned Package with a new outer Package.
386          */
387         if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE))
388         {
389             /* Create the new outer package and populate it */
390 
391             Status = AcpiNsWrapWithPackage (
392                 Info, ReturnObject, ReturnObjectPtr);
393             if (ACPI_FAILURE (Status))
394             {
395                 return (Status);
396             }
397 
398             /* Update locals to point to the new package (of 1 element) */
399 
400             ReturnObject = *ReturnObjectPtr;
401             Elements = ReturnObject->Package.Elements;
402             Count = 1;
403         }
404 
405         /* Examine the subpackages */
406 
407         Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
408         break;
409 
410     case ACPI_PTYPE2_VAR_VAR:
411         /*
412          * Returns a variable list of packages, each with a variable list
413          * of objects.
414          */
415         break;
416 
417     case ACPI_PTYPE2_UUID_PAIR:
418 
419         /* The package must contain pairs of (UUID + type) */
420 
421         if (Count & 1)
422         {
423             ExpectedCount = Count + 1;
424             goto PackageTooSmall;
425         }
426 
427         while (Count > 0)
428         {
429             Status = AcpiNsCheckObjectType(Info, Elements,
430                 Package->RetInfo.ObjectType1, 0);
431             if (ACPI_FAILURE(Status))
432             {
433                 return (Status);
434             }
435 
436             /* Validate length of the UUID buffer */
437 
438             if ((*Elements)->Buffer.Length != 16)
439             {
440                 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname,
441                     Info->NodeFlags, "Invalid length for UUID Buffer"));
442                 return (AE_AML_OPERAND_VALUE);
443             }
444 
445             Status = AcpiNsCheckObjectType(Info, Elements + 1,
446                 Package->RetInfo.ObjectType2, 0);
447             if (ACPI_FAILURE(Status))
448             {
449                 return (Status);
450             }
451 
452             Elements += 2;
453             Count -= 2;
454         }
455         break;
456 
457     default:
458 
459         /* Should not get here if predefined info table is correct */
460 
461         ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
462             "Invalid internal return type in table entry: %X",
463             Package->RetInfo.Type));
464 
465         return (AE_AML_INTERNAL);
466     }
467 
468     return (Status);
469 
470 
471 PackageTooSmall:
472 
473     /* Error exit for the case with an incorrect package count */
474 
475     ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
476         "Return Package is too small - found %u elements, expected %u",
477         Count, ExpectedCount));
478 
479     return (AE_AML_OPERAND_VALUE);
480 }
481 
482 
483 /*******************************************************************************
484  *
485  * FUNCTION:    AcpiNsCheckPackageList
486  *
487  * PARAMETERS:  Info            - Method execution information block
488  *              Package         - Pointer to package-specific info for method
489  *              Elements        - Element list of parent package. All elements
490  *                                of this list should be of type Package.
491  *              Count           - Count of subpackages
492  *
493  * RETURN:      Status
494  *
495  * DESCRIPTION: Examine a list of subpackages
496  *
497  ******************************************************************************/
498 
499 static ACPI_STATUS
500 AcpiNsCheckPackageList (
501     ACPI_EVALUATE_INFO          *Info,
502     const ACPI_PREDEFINED_INFO  *Package,
503     ACPI_OPERAND_OBJECT         **Elements,
504     UINT32                      Count)
505 {
506     ACPI_OPERAND_OBJECT         *SubPackage;
507     ACPI_OPERAND_OBJECT         **SubElements;
508     ACPI_STATUS                 Status;
509     UINT32                      ExpectedCount;
510     UINT32                      i;
511     UINT32                      j;
512 
513 
514     /*
515      * Validate each subpackage in the parent Package
516      *
517      * NOTE: assumes list of subpackages contains no NULL elements.
518      * Any NULL elements should have been removed by earlier call
519      * to AcpiNsRemoveNullElements.
520      */
521     for (i = 0; i < Count; i++)
522     {
523         SubPackage = *Elements;
524         SubElements = SubPackage->Package.Elements;
525         Info->ParentPackage = SubPackage;
526 
527         /* Each sub-object must be of type Package */
528 
529         Status = AcpiNsCheckObjectType (Info, &SubPackage,
530             ACPI_RTYPE_PACKAGE, i);
531         if (ACPI_FAILURE (Status))
532         {
533             return (Status);
534         }
535 
536         /* Examine the different types of expected subpackages */
537 
538         Info->ParentPackage = SubPackage;
539         switch (Package->RetInfo.Type)
540         {
541         case ACPI_PTYPE2:
542         case ACPI_PTYPE2_PKG_COUNT:
543         case ACPI_PTYPE2_REV_FIXED:
544 
545             /* Each subpackage has a fixed number of elements */
546 
547             ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
548             if (SubPackage->Package.Count < ExpectedCount)
549             {
550                 goto PackageTooSmall;
551             }
552 
553             Status = AcpiNsCheckPackageElements (Info, SubElements,
554                 Package->RetInfo.ObjectType1,
555                 Package->RetInfo.Count1,
556                 Package->RetInfo.ObjectType2,
557                 Package->RetInfo.Count2, 0);
558             if (ACPI_FAILURE (Status))
559             {
560                 return (Status);
561             }
562             break;
563 
564         case ACPI_PTYPE2_FIX_VAR:
565             /*
566              * Each subpackage has a fixed number of elements and an
567              * optional element
568              */
569             ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
570             if (SubPackage->Package.Count < ExpectedCount)
571             {
572                 goto PackageTooSmall;
573             }
574 
575             Status = AcpiNsCheckPackageElements (Info, SubElements,
576                 Package->RetInfo.ObjectType1,
577                 Package->RetInfo.Count1,
578                 Package->RetInfo.ObjectType2,
579                 SubPackage->Package.Count - Package->RetInfo.Count1, 0);
580             if (ACPI_FAILURE (Status))
581             {
582                 return (Status);
583             }
584             break;
585 
586         case ACPI_PTYPE2_VAR_VAR:
587             /*
588              * Each subpackage has a fixed or variable number of elements
589              */
590             break;
591 
592         case ACPI_PTYPE2_FIXED:
593 
594             /* Each subpackage has a fixed length */
595 
596             ExpectedCount = Package->RetInfo2.Count;
597             if (SubPackage->Package.Count < ExpectedCount)
598             {
599                 goto PackageTooSmall;
600             }
601 
602             /* Check the type of each subpackage element */
603 
604             for (j = 0; j < ExpectedCount; j++)
605             {
606                 Status = AcpiNsCheckObjectType (Info, &SubElements[j],
607                     Package->RetInfo2.ObjectType[j], j);
608                 if (ACPI_FAILURE (Status))
609                 {
610                     return (Status);
611                 }
612             }
613             break;
614 
615         case ACPI_PTYPE2_MIN:
616 
617             /* Each subpackage has a variable but minimum length */
618 
619             ExpectedCount = Package->RetInfo.Count1;
620             if (SubPackage->Package.Count < ExpectedCount)
621             {
622                 goto PackageTooSmall;
623             }
624 
625             /* Check the type of each subpackage element */
626 
627             Status = AcpiNsCheckPackageElements (Info, SubElements,
628                 Package->RetInfo.ObjectType1,
629                 SubPackage->Package.Count, 0, 0, 0);
630             if (ACPI_FAILURE (Status))
631             {
632                 return (Status);
633             }
634             break;
635 
636         case ACPI_PTYPE2_COUNT:
637             /*
638              * First element is the (Integer) count of elements, including
639              * the count field (the ACPI name is NumElements)
640              */
641             Status = AcpiNsCheckObjectType (Info, SubElements,
642                 ACPI_RTYPE_INTEGER, 0);
643             if (ACPI_FAILURE (Status))
644             {
645                 return (Status);
646             }
647 
648             /*
649              * Make sure package is large enough for the Count and is
650              * is as large as the minimum size
651              */
652             ExpectedCount = (UINT32) (*SubElements)->Integer.Value;
653             if (SubPackage->Package.Count < ExpectedCount)
654             {
655                 goto PackageTooSmall;
656             }
657 
658             if (SubPackage->Package.Count < Package->RetInfo.Count1)
659             {
660                 ExpectedCount = Package->RetInfo.Count1;
661                 goto PackageTooSmall;
662             }
663 
664             if (ExpectedCount == 0)
665             {
666                 /*
667                  * Either the NumEntries element was originally zero or it was
668                  * a NULL element and repaired to an Integer of value zero.
669                  * In either case, repair it by setting NumEntries to be the
670                  * actual size of the subpackage.
671                  */
672                 ExpectedCount = SubPackage->Package.Count;
673                 (*SubElements)->Integer.Value = ExpectedCount;
674             }
675 
676             /* Check the type of each subpackage element */
677 
678             Status = AcpiNsCheckPackageElements (Info, (SubElements + 1),
679                 Package->RetInfo.ObjectType1,
680                 (ExpectedCount - 1), 0, 0, 1);
681             if (ACPI_FAILURE (Status))
682             {
683                 return (Status);
684             }
685             break;
686 
687         default: /* Should not get here, type was validated by caller */
688 
689             return (AE_AML_INTERNAL);
690         }
691 
692         Elements++;
693     }
694 
695     return (AE_OK);
696 
697 
698 PackageTooSmall:
699 
700     /* The subpackage count was smaller than required */
701 
702     ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
703         "Return SubPackage[%u] is too small - found %u elements, expected %u",
704         i, SubPackage->Package.Count, ExpectedCount));
705 
706     return (AE_AML_OPERAND_VALUE);
707 }
708 
709 
710 /*******************************************************************************
711  *
712  * FUNCTION:    AcpiNsCustomPackage
713  *
714  * PARAMETERS:  Info                - Method execution information block
715  *              Elements            - Pointer to the package elements array
716  *              Count               - Element count for the package
717  *
718  * RETURN:      Status
719  *
720  * DESCRIPTION: Check a returned package object for the correct count and
721  *              correct type of all sub-objects.
722  *
723  * NOTE: Currently used for the _BIX method only. When needed for two or more
724  * methods, probably a detect/dispatch mechanism will be required.
725  *
726  ******************************************************************************/
727 
728 static ACPI_STATUS
729 AcpiNsCustomPackage (
730     ACPI_EVALUATE_INFO          *Info,
731     ACPI_OPERAND_OBJECT         **Elements,
732     UINT32                      Count)
733 {
734     UINT32                      ExpectedCount;
735     UINT32                      Version;
736     ACPI_STATUS                 Status = AE_OK;
737 
738 
739     ACPI_FUNCTION_NAME (NsCustomPackage);
740 
741 
742     /* Get version number, must be Integer */
743 
744     if ((*Elements)->Common.Type != ACPI_TYPE_INTEGER)
745     {
746         ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
747             "Return Package has invalid object type for version number"));
748         return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
749     }
750 
751     Version = (UINT32) (*Elements)->Integer.Value;
752     ExpectedCount = 21;         /* Version 1 */
753 
754     if (Version == 0)
755     {
756         ExpectedCount = 20;     /* Version 0 */
757     }
758 
759     if (Count < ExpectedCount)
760     {
761         ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
762             "Return Package is too small - found %u elements, expected %u",
763             Count, ExpectedCount));
764         return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
765     }
766     else if (Count > ExpectedCount)
767     {
768         ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
769             "%s: Return Package is larger than needed - "
770             "found %u, expected %u\n",
771             Info->FullPathname, Count, ExpectedCount));
772     }
773 
774     /* Validate all elements of the returned package */
775 
776     Status = AcpiNsCheckPackageElements (Info, Elements,
777         ACPI_RTYPE_INTEGER, 16,
778         ACPI_RTYPE_STRING, 4, 0);
779     if (ACPI_FAILURE (Status))
780     {
781         return_ACPI_STATUS (Status);
782     }
783 
784     /* Version 1 has a single trailing integer */
785 
786     if (Version > 0)
787     {
788         Status = AcpiNsCheckPackageElements (Info, Elements + 20,
789             ACPI_RTYPE_INTEGER, 1, 0, 0, 20);
790     }
791 
792     return_ACPI_STATUS (Status);
793 }
794 
795 
796 /*******************************************************************************
797  *
798  * FUNCTION:    AcpiNsCheckPackageElements
799  *
800  * PARAMETERS:  Info            - Method execution information block
801  *              Elements        - Pointer to the package elements array
802  *              Type1           - Object type for first group
803  *              Count1          - Count for first group
804  *              Type2           - Object type for second group
805  *              Count2          - Count for second group
806  *              StartIndex      - Start of the first group of elements
807  *
808  * RETURN:      Status
809  *
810  * DESCRIPTION: Check that all elements of a package are of the correct object
811  *              type. Supports up to two groups of different object types.
812  *
813  ******************************************************************************/
814 
815 static ACPI_STATUS
816 AcpiNsCheckPackageElements (
817     ACPI_EVALUATE_INFO          *Info,
818     ACPI_OPERAND_OBJECT         **Elements,
819     UINT8                       Type1,
820     UINT32                      Count1,
821     UINT8                       Type2,
822     UINT32                      Count2,
823     UINT32                      StartIndex)
824 {
825     ACPI_OPERAND_OBJECT         **ThisElement = Elements;
826     ACPI_STATUS                 Status;
827     UINT32                      i;
828 
829 
830     /*
831      * Up to two groups of package elements are supported by the data
832      * structure. All elements in each group must be of the same type.
833      * The second group can have a count of zero.
834      */
835     for (i = 0; i < Count1; i++)
836     {
837         Status = AcpiNsCheckObjectType (Info, ThisElement,
838             Type1, i + StartIndex);
839         if (ACPI_FAILURE (Status))
840         {
841             return (Status);
842         }
843 
844         ThisElement++;
845     }
846 
847     for (i = 0; i < Count2; i++)
848     {
849         Status = AcpiNsCheckObjectType (Info, ThisElement,
850             Type2, (i + Count1 + StartIndex));
851         if (ACPI_FAILURE (Status))
852         {
853             return (Status);
854         }
855 
856         ThisElement++;
857     }
858 
859     return (AE_OK);
860 }
861