1214518Srpaulo/******************************************************************************
2190214Srpaulo *
3190214Srpaulo * Module Name: nsprepkg - Validation of package objects for predefined names
4190214Srpaulo *
5190214Srpaulo *****************************************************************************/
6190214Srpaulo
7190214Srpaulo/*
8190214Srpaulo * Copyright (C) 2000 - 2016, Intel Corp.
9190214Srpaulo * All rights reserved.
10190214Srpaulo *
11190214Srpaulo * Redistribution and use in source and binary forms, with or without
12190214Srpaulo * modification, are permitted provided that the following conditions
13190214Srpaulo * are met:
14190214Srpaulo * 1. Redistributions of source code must retain the above copyright
15190214Srpaulo *    notice, this list of conditions, and the following disclaimer,
16190214Srpaulo *    without modification.
17190214Srpaulo * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18190214Srpaulo *    substantially similar to the "NO WARRANTY" disclaimer below
19190214Srpaulo *    ("Disclaimer") and any redistribution must be conditioned upon
20190214Srpaulo *    including a substantially similar Disclaimer requirement for further
21190214Srpaulo *    binary redistribution.
22190214Srpaulo * 3. Neither the names of the above-listed copyright holders nor the names
23190214Srpaulo *    of any contributors may be used to endorse or promote products derived
24190214Srpaulo *    from this software without specific prior written permission.
25190214Srpaulo *
26190214Srpaulo * Alternatively, this software may be distributed under the terms of the
27190214Srpaulo * GNU General Public License ("GPL") version 2 as published by the Free
28190214Srpaulo * Software Foundation.
29190214Srpaulo *
30190214Srpaulo * NO WARRANTY
31190214Srpaulo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32190214Srpaulo * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33190214Srpaulo * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34190214Srpaulo * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35190214Srpaulo * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36190214Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37190214Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38190214Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39190214Srpaulo * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40190214Srpaulo * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41190214Srpaulo * POSSIBILITY OF SUCH DAMAGES.
42190214Srpaulo */
43190214Srpaulo
44190214Srpaulo#include <contrib/dev/acpica/include/acpi.h>
45190214Srpaulo#include <contrib/dev/acpica/include/accommon.h>
46190214Srpaulo#include <contrib/dev/acpica/include/acnamesp.h>
47190214Srpaulo#include <contrib/dev/acpica/include/acpredef.h>
48
49
50#define _COMPONENT          ACPI_NAMESPACE
51        ACPI_MODULE_NAME    ("nsprepkg")
52
53
54/* Local prototypes */
55
56static ACPI_STATUS
57AcpiNsCheckPackageList (
58    ACPI_EVALUATE_INFO          *Info,
59    const ACPI_PREDEFINED_INFO  *Package,
60    ACPI_OPERAND_OBJECT         **Elements,
61    UINT32                      Count);
62
63static ACPI_STATUS
64AcpiNsCheckPackageElements (
65    ACPI_EVALUATE_INFO          *Info,
66    ACPI_OPERAND_OBJECT         **Elements,
67    UINT8                       Type1,
68    UINT32                      Count1,
69    UINT8                       Type2,
70    UINT32                      Count2,
71    UINT32                      StartIndex);
72
73static ACPI_STATUS
74AcpiNsCustomPackage (
75    ACPI_EVALUATE_INFO          *Info,
76    ACPI_OPERAND_OBJECT         **Elements,
77    UINT32                      Count);
78
79
80/*******************************************************************************
81 *
82 * FUNCTION:    AcpiNsCheckPackage
83 *
84 * PARAMETERS:  Info                - Method execution information block
85 *              ReturnObjectPtr     - Pointer to the object returned from the
86 *                                    evaluation of a method or object
87 *
88 * RETURN:      Status
89 *
90 * DESCRIPTION: Check a returned package object for the correct count and
91 *              correct type of all sub-objects.
92 *
93 ******************************************************************************/
94
95ACPI_STATUS
96AcpiNsCheckPackage (
97    ACPI_EVALUATE_INFO          *Info,
98    ACPI_OPERAND_OBJECT         **ReturnObjectPtr)
99{
100    ACPI_OPERAND_OBJECT         *ReturnObject = *ReturnObjectPtr;
101    const ACPI_PREDEFINED_INFO  *Package;
102    ACPI_OPERAND_OBJECT         **Elements;
103    ACPI_STATUS                 Status = AE_OK;
104    UINT32                      ExpectedCount;
105    UINT32                      Count;
106    UINT32                      i;
107
108
109    ACPI_FUNCTION_NAME (NsCheckPackage);
110
111
112    /* The package info for this name is in the next table entry */
113
114    Package = Info->Predefined + 1;
115
116    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
117        "%s Validating return Package of Type %X, Count %X\n",
118        Info->FullPathname, Package->RetInfo.Type,
119        ReturnObject->Package.Count));
120
121    /*
122     * For variable-length Packages, we can safely remove all embedded
123     * and trailing NULL package elements
124     */
125    AcpiNsRemoveNullElements (Info, Package->RetInfo.Type, ReturnObject);
126
127    /* Extract package count and elements array */
128
129    Elements = ReturnObject->Package.Elements;
130    Count = ReturnObject->Package.Count;
131
132    /*
133     * Most packages must have at least one element. The only exception
134     * is the variable-length package (ACPI_PTYPE1_VAR).
135     */
136    if (!Count)
137    {
138        if (Package->RetInfo.Type == ACPI_PTYPE1_VAR)
139        {
140            return (AE_OK);
141        }
142
143        ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
144            "Return Package has no elements (empty)"));
145
146        return (AE_AML_OPERAND_VALUE);
147    }
148
149    /*
150     * Decode the type of the expected package contents
151     *
152     * PTYPE1 packages contain no subpackages
153     * PTYPE2 packages contain subpackages
154     */
155    switch (Package->RetInfo.Type)
156    {
157    case ACPI_PTYPE_CUSTOM:
158
159        Status = AcpiNsCustomPackage (Info, Elements, Count);
160        break;
161
162    case ACPI_PTYPE1_FIXED:
163        /*
164         * The package count is fixed and there are no subpackages
165         *
166         * If package is too small, exit.
167         * If package is larger than expected, issue warning but continue
168         */
169        ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
170        if (Count < ExpectedCount)
171        {
172            goto PackageTooSmall;
173        }
174        else if (Count > ExpectedCount)
175        {
176            ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
177                "%s: Return Package is larger than needed - "
178                "found %u, expected %u\n",
179                Info->FullPathname, Count, ExpectedCount));
180        }
181
182        /* Validate all elements of the returned package */
183
184        Status = AcpiNsCheckPackageElements (Info, Elements,
185            Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
186            Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0);
187        break;
188
189    case ACPI_PTYPE1_VAR:
190        /*
191         * The package count is variable, there are no subpackages, and all
192         * elements must be of the same type
193         */
194        for (i = 0; i < Count; i++)
195        {
196            Status = AcpiNsCheckObjectType (Info, Elements,
197                Package->RetInfo.ObjectType1, i);
198            if (ACPI_FAILURE (Status))
199            {
200                return (Status);
201            }
202
203            Elements++;
204        }
205        break;
206
207    case ACPI_PTYPE1_OPTION:
208        /*
209         * The package count is variable, there are no subpackages. There are
210         * a fixed number of required elements, and a variable number of
211         * optional elements.
212         *
213         * Check if package is at least as large as the minimum required
214         */
215        ExpectedCount = Package->RetInfo3.Count;
216        if (Count < ExpectedCount)
217        {
218            goto PackageTooSmall;
219        }
220
221        /* Variable number of sub-objects */
222
223        for (i = 0; i < Count; i++)
224        {
225            if (i < Package->RetInfo3.Count)
226            {
227                /* These are the required package elements (0, 1, or 2) */
228
229                Status = AcpiNsCheckObjectType (Info, Elements,
230                    Package->RetInfo3.ObjectType[i], i);
231                if (ACPI_FAILURE (Status))
232                {
233                    return (Status);
234                }
235            }
236            else
237            {
238                /* These are the optional package elements */
239
240                Status = AcpiNsCheckObjectType (Info, Elements,
241                    Package->RetInfo3.TailObjectType, i);
242                if (ACPI_FAILURE (Status))
243                {
244                    return (Status);
245                }
246            }
247
248            Elements++;
249        }
250        break;
251
252    case ACPI_PTYPE2_REV_FIXED:
253
254        /* First element is the (Integer) revision */
255
256        Status = AcpiNsCheckObjectType (
257            Info, Elements, ACPI_RTYPE_INTEGER, 0);
258        if (ACPI_FAILURE (Status))
259        {
260            return (Status);
261        }
262
263        Elements++;
264        Count--;
265
266        /* Examine the subpackages */
267
268        Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
269        break;
270
271    case ACPI_PTYPE2_PKG_COUNT:
272
273        /* First element is the (Integer) count of subpackages to follow */
274
275        Status = AcpiNsCheckObjectType (
276            Info, Elements, ACPI_RTYPE_INTEGER, 0);
277        if (ACPI_FAILURE (Status))
278        {
279            return (Status);
280        }
281
282        /*
283         * Count cannot be larger than the parent package length, but allow it
284         * to be smaller. The >= accounts for the Integer above.
285         */
286        ExpectedCount = (UINT32) (*Elements)->Integer.Value;
287        if (ExpectedCount >= Count)
288        {
289            goto PackageTooSmall;
290        }
291
292        Count = ExpectedCount;
293        Elements++;
294
295        /* Examine the subpackages */
296
297        Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
298        break;
299
300    case ACPI_PTYPE2:
301    case ACPI_PTYPE2_FIXED:
302    case ACPI_PTYPE2_MIN:
303    case ACPI_PTYPE2_COUNT:
304    case ACPI_PTYPE2_FIX_VAR:
305        /*
306         * These types all return a single Package that consists of a
307         * variable number of subpackages.
308         *
309         * First, ensure that the first element is a subpackage. If not,
310         * the BIOS may have incorrectly returned the object as a single
311         * package instead of a Package of Packages (a common error if
312         * there is only one entry). We may be able to repair this by
313         * wrapping the returned Package with a new outer Package.
314         */
315        if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE))
316        {
317            /* Create the new outer package and populate it */
318
319            Status = AcpiNsWrapWithPackage (
320                Info, ReturnObject, ReturnObjectPtr);
321            if (ACPI_FAILURE (Status))
322            {
323                return (Status);
324            }
325
326            /* Update locals to point to the new package (of 1 element) */
327
328            ReturnObject = *ReturnObjectPtr;
329            Elements = ReturnObject->Package.Elements;
330            Count = 1;
331        }
332
333        /* Examine the subpackages */
334
335        Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
336        break;
337
338    case ACPI_PTYPE2_VAR_VAR:
339        /*
340         * Returns a variable list of packages, each with a variable list
341         * of objects.
342         */
343        break;
344
345    case ACPI_PTYPE2_UUID_PAIR:
346
347        /* The package must contain pairs of (UUID + type) */
348
349        if (Count & 1)
350        {
351            ExpectedCount = Count + 1;
352            goto PackageTooSmall;
353        }
354
355        while (Count > 0)
356        {
357            Status = AcpiNsCheckObjectType(Info, Elements,
358                Package->RetInfo.ObjectType1, 0);
359            if (ACPI_FAILURE(Status))
360            {
361                return (Status);
362            }
363
364            /* Validate length of the UUID buffer */
365
366            if ((*Elements)->Buffer.Length != 16)
367            {
368                ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname,
369                    Info->NodeFlags, "Invalid length for UUID Buffer"));
370                return (AE_AML_OPERAND_VALUE);
371            }
372
373            Status = AcpiNsCheckObjectType(Info, Elements + 1,
374                Package->RetInfo.ObjectType2, 0);
375            if (ACPI_FAILURE(Status))
376            {
377                return (Status);
378            }
379
380            Elements += 2;
381            Count -= 2;
382        }
383        break;
384
385    default:
386
387        /* Should not get here if predefined info table is correct */
388
389        ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
390            "Invalid internal return type in table entry: %X",
391            Package->RetInfo.Type));
392
393        return (AE_AML_INTERNAL);
394    }
395
396    return (Status);
397
398
399PackageTooSmall:
400
401    /* Error exit for the case with an incorrect package count */
402
403    ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
404        "Return Package is too small - found %u elements, expected %u",
405        Count, ExpectedCount));
406
407    return (AE_AML_OPERAND_VALUE);
408}
409
410
411/*******************************************************************************
412 *
413 * FUNCTION:    AcpiNsCheckPackageList
414 *
415 * PARAMETERS:  Info            - Method execution information block
416 *              Package         - Pointer to package-specific info for method
417 *              Elements        - Element list of parent package. All elements
418 *                                of this list should be of type Package.
419 *              Count           - Count of subpackages
420 *
421 * RETURN:      Status
422 *
423 * DESCRIPTION: Examine a list of subpackages
424 *
425 ******************************************************************************/
426
427static ACPI_STATUS
428AcpiNsCheckPackageList (
429    ACPI_EVALUATE_INFO          *Info,
430    const ACPI_PREDEFINED_INFO  *Package,
431    ACPI_OPERAND_OBJECT         **Elements,
432    UINT32                      Count)
433{
434    ACPI_OPERAND_OBJECT         *SubPackage;
435    ACPI_OPERAND_OBJECT         **SubElements;
436    ACPI_STATUS                 Status;
437    UINT32                      ExpectedCount;
438    UINT32                      i;
439    UINT32                      j;
440
441
442    /*
443     * Validate each subpackage in the parent Package
444     *
445     * NOTE: assumes list of subpackages contains no NULL elements.
446     * Any NULL elements should have been removed by earlier call
447     * to AcpiNsRemoveNullElements.
448     */
449    for (i = 0; i < Count; i++)
450    {
451        SubPackage = *Elements;
452        SubElements = SubPackage->Package.Elements;
453        Info->ParentPackage = SubPackage;
454
455        /* Each sub-object must be of type Package */
456
457        Status = AcpiNsCheckObjectType (Info, &SubPackage,
458            ACPI_RTYPE_PACKAGE, i);
459        if (ACPI_FAILURE (Status))
460        {
461            return (Status);
462        }
463
464        /* Examine the different types of expected subpackages */
465
466        Info->ParentPackage = SubPackage;
467        switch (Package->RetInfo.Type)
468        {
469        case ACPI_PTYPE2:
470        case ACPI_PTYPE2_PKG_COUNT:
471        case ACPI_PTYPE2_REV_FIXED:
472
473            /* Each subpackage has a fixed number of elements */
474
475            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
476            if (SubPackage->Package.Count < ExpectedCount)
477            {
478                goto PackageTooSmall;
479            }
480
481            Status = AcpiNsCheckPackageElements (Info, SubElements,
482                Package->RetInfo.ObjectType1,
483                Package->RetInfo.Count1,
484                Package->RetInfo.ObjectType2,
485                Package->RetInfo.Count2, 0);
486            if (ACPI_FAILURE (Status))
487            {
488                return (Status);
489            }
490            break;
491
492        case ACPI_PTYPE2_FIX_VAR:
493            /*
494             * Each subpackage has a fixed number of elements and an
495             * optional element
496             */
497            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
498            if (SubPackage->Package.Count < ExpectedCount)
499            {
500                goto PackageTooSmall;
501            }
502
503            Status = AcpiNsCheckPackageElements (Info, SubElements,
504                Package->RetInfo.ObjectType1,
505                Package->RetInfo.Count1,
506                Package->RetInfo.ObjectType2,
507                SubPackage->Package.Count - Package->RetInfo.Count1, 0);
508            if (ACPI_FAILURE (Status))
509            {
510                return (Status);
511            }
512            break;
513
514        case ACPI_PTYPE2_VAR_VAR:
515            /*
516             * Each subpackage has a fixed or variable number of elements
517             */
518            break;
519
520        case ACPI_PTYPE2_FIXED:
521
522            /* Each subpackage has a fixed length */
523
524            ExpectedCount = Package->RetInfo2.Count;
525            if (SubPackage->Package.Count < ExpectedCount)
526            {
527                goto PackageTooSmall;
528            }
529
530            /* Check the type of each subpackage element */
531
532            for (j = 0; j < ExpectedCount; j++)
533            {
534                Status = AcpiNsCheckObjectType (Info, &SubElements[j],
535                    Package->RetInfo2.ObjectType[j], j);
536                if (ACPI_FAILURE (Status))
537                {
538                    return (Status);
539                }
540            }
541            break;
542
543        case ACPI_PTYPE2_MIN:
544
545            /* Each subpackage has a variable but minimum length */
546
547            ExpectedCount = Package->RetInfo.Count1;
548            if (SubPackage->Package.Count < ExpectedCount)
549            {
550                goto PackageTooSmall;
551            }
552
553            /* Check the type of each subpackage element */
554
555            Status = AcpiNsCheckPackageElements (Info, SubElements,
556                Package->RetInfo.ObjectType1,
557                SubPackage->Package.Count, 0, 0, 0);
558            if (ACPI_FAILURE (Status))
559            {
560                return (Status);
561            }
562            break;
563
564        case ACPI_PTYPE2_COUNT:
565            /*
566             * First element is the (Integer) count of elements, including
567             * the count field (the ACPI name is NumElements)
568             */
569            Status = AcpiNsCheckObjectType (Info, SubElements,
570                ACPI_RTYPE_INTEGER, 0);
571            if (ACPI_FAILURE (Status))
572            {
573                return (Status);
574            }
575
576            /*
577             * Make sure package is large enough for the Count and is
578             * is as large as the minimum size
579             */
580            ExpectedCount = (UINT32) (*SubElements)->Integer.Value;
581            if (SubPackage->Package.Count < ExpectedCount)
582            {
583                goto PackageTooSmall;
584            }
585
586            if (SubPackage->Package.Count < Package->RetInfo.Count1)
587            {
588                ExpectedCount = Package->RetInfo.Count1;
589                goto PackageTooSmall;
590            }
591
592            if (ExpectedCount == 0)
593            {
594                /*
595                 * Either the NumEntries element was originally zero or it was
596                 * a NULL element and repaired to an Integer of value zero.
597                 * In either case, repair it by setting NumEntries to be the
598                 * actual size of the subpackage.
599                 */
600                ExpectedCount = SubPackage->Package.Count;
601                (*SubElements)->Integer.Value = ExpectedCount;
602            }
603
604            /* Check the type of each subpackage element */
605
606            Status = AcpiNsCheckPackageElements (Info, (SubElements + 1),
607                Package->RetInfo.ObjectType1,
608                (ExpectedCount - 1), 0, 0, 1);
609            if (ACPI_FAILURE (Status))
610            {
611                return (Status);
612            }
613            break;
614
615        default: /* Should not get here, type was validated by caller */
616
617            return (AE_AML_INTERNAL);
618        }
619
620        Elements++;
621    }
622
623    return (AE_OK);
624
625
626PackageTooSmall:
627
628    /* The subpackage count was smaller than required */
629
630    ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
631        "Return SubPackage[%u] is too small - found %u elements, expected %u",
632        i, SubPackage->Package.Count, ExpectedCount));
633
634    return (AE_AML_OPERAND_VALUE);
635}
636
637
638/*******************************************************************************
639 *
640 * FUNCTION:    AcpiNsCustomPackage
641 *
642 * PARAMETERS:  Info                - Method execution information block
643 *              Elements            - Pointer to the package elements array
644 *              Count               - Element count for the package
645 *
646 * RETURN:      Status
647 *
648 * DESCRIPTION: Check a returned package object for the correct count and
649 *              correct type of all sub-objects.
650 *
651 * NOTE: Currently used for the _BIX method only. When needed for two or more
652 * methods, probably a detect/dispatch mechanism will be required.
653 *
654 ******************************************************************************/
655
656static ACPI_STATUS
657AcpiNsCustomPackage (
658    ACPI_EVALUATE_INFO          *Info,
659    ACPI_OPERAND_OBJECT         **Elements,
660    UINT32                      Count)
661{
662    UINT32                      ExpectedCount;
663    UINT32                      Version;
664    ACPI_STATUS                 Status = AE_OK;
665
666
667    ACPI_FUNCTION_NAME (NsCustomPackage);
668
669
670    /* Get version number, must be Integer */
671
672    if ((*Elements)->Common.Type != ACPI_TYPE_INTEGER)
673    {
674        ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
675            "Return Package has invalid object type for version number"));
676        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
677    }
678
679    Version = (UINT32) (*Elements)->Integer.Value;
680    ExpectedCount = 21;         /* Version 1 */
681
682    if (Version == 0)
683    {
684        ExpectedCount = 20;     /* Version 0 */
685    }
686
687    if (Count < ExpectedCount)
688    {
689        ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
690            "Return Package is too small - found %u elements, expected %u",
691            Count, ExpectedCount));
692        return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
693    }
694    else if (Count > ExpectedCount)
695    {
696        ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
697            "%s: Return Package is larger than needed - "
698            "found %u, expected %u\n",
699            Info->FullPathname, Count, ExpectedCount));
700    }
701
702    /* Validate all elements of the returned package */
703
704    Status = AcpiNsCheckPackageElements (Info, Elements,
705        ACPI_RTYPE_INTEGER, 16,
706        ACPI_RTYPE_STRING, 4, 0);
707    if (ACPI_FAILURE (Status))
708    {
709        return_ACPI_STATUS (Status);
710    }
711
712    /* Version 1 has a single trailing integer */
713
714    if (Version > 0)
715    {
716        Status = AcpiNsCheckPackageElements (Info, Elements + 20,
717            ACPI_RTYPE_INTEGER, 1, 0, 0, 20);
718    }
719
720    return_ACPI_STATUS (Status);
721}
722
723
724/*******************************************************************************
725 *
726 * FUNCTION:    AcpiNsCheckPackageElements
727 *
728 * PARAMETERS:  Info            - Method execution information block
729 *              Elements        - Pointer to the package elements array
730 *              Type1           - Object type for first group
731 *              Count1          - Count for first group
732 *              Type2           - Object type for second group
733 *              Count2          - Count for second group
734 *              StartIndex      - Start of the first group of elements
735 *
736 * RETURN:      Status
737 *
738 * DESCRIPTION: Check that all elements of a package are of the correct object
739 *              type. Supports up to two groups of different object types.
740 *
741 ******************************************************************************/
742
743static ACPI_STATUS
744AcpiNsCheckPackageElements (
745    ACPI_EVALUATE_INFO          *Info,
746    ACPI_OPERAND_OBJECT         **Elements,
747    UINT8                       Type1,
748    UINT32                      Count1,
749    UINT8                       Type2,
750    UINT32                      Count2,
751    UINT32                      StartIndex)
752{
753    ACPI_OPERAND_OBJECT         **ThisElement = Elements;
754    ACPI_STATUS                 Status;
755    UINT32                      i;
756
757
758    /*
759     * Up to two groups of package elements are supported by the data
760     * structure. All elements in each group must be of the same type.
761     * The second group can have a count of zero.
762     */
763    for (i = 0; i < Count1; i++)
764    {
765        Status = AcpiNsCheckObjectType (Info, ThisElement,
766            Type1, i + StartIndex);
767        if (ACPI_FAILURE (Status))
768        {
769            return (Status);
770        }
771
772        ThisElement++;
773    }
774
775    for (i = 0; i < Count2; i++)
776    {
777        Status = AcpiNsCheckObjectType (Info, ThisElement,
778            Type2, (i + Count1 + StartIndex));
779        if (ACPI_FAILURE (Status))
780        {
781            return (Status);
782        }
783
784        ThisElement++;
785    }
786
787    return (AE_OK);
788}
789