aslprepkg.c revision 306536
1321369Sdim/******************************************************************************
2303231Sdim *
3353358Sdim * Module Name: aslprepkg - support for ACPI predefined name package objects
4353358Sdim *
5353358Sdim *****************************************************************************/
6303231Sdim
7303231Sdim/*
8303231Sdim * Copyright (C) 2000 - 2016, Intel Corp.
9303231Sdim * All rights reserved.
10303231Sdim *
11303231Sdim * Redistribution and use in source and binary forms, with or without
12303231Sdim * modification, are permitted provided that the following conditions
13303231Sdim * are met:
14321369Sdim * 1. Redistributions of source code must retain the above copyright
15321369Sdim *    notice, this list of conditions, and the following disclaimer,
16303231Sdim *    without modification.
17303231Sdim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18303231Sdim *    substantially similar to the "NO WARRANTY" disclaimer below
19341825Sdim *    ("Disclaimer") and any redistribution must be conditioned upon
20303231Sdim *    including a substantially similar Disclaimer requirement for further
21321369Sdim *    binary redistribution.
22321369Sdim * 3. Neither the names of the above-listed copyright holders nor the names
23314564Sdim *    of any contributors may be used to endorse or promote products derived
24303231Sdim *    from this software without specific prior written permission.
25321369Sdim *
26303231Sdim * Alternatively, this software may be distributed under the terms of the
27321369Sdim * GNU General Public License ("GPL") version 2 as published by the Free
28303231Sdim * Software Foundation.
29303231Sdim *
30321369Sdim * NO WARRANTY
31303231Sdim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32321369Sdim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33321369Sdim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34321369Sdim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35321369Sdim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36321369Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37303231Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38303231Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39321369Sdim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40321369Sdim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41303231Sdim * POSSIBILITY OF SUCH DAMAGES.
42303231Sdim */
43321369Sdim
44321369Sdim#include <contrib/dev/acpica/compiler/aslcompiler.h>
45321369Sdim#include "aslcompiler.y.h"
46303231Sdim#include <contrib/dev/acpica/include/acpredef.h>
47303231Sdim
48321369Sdim
49321369Sdim#define _COMPONENT          ACPI_COMPILER
50321369Sdim        ACPI_MODULE_NAME    ("aslprepkg")
51303231Sdim
52303231Sdim
53303231Sdim/* Local prototypes */
54303231Sdim
55303231Sdimstatic ACPI_PARSE_OBJECT *
56303231SdimApCheckPackageElements (
57303231Sdim    const char                  *PredefinedName,
58303231Sdim    ACPI_PARSE_OBJECT           *Op,
59303231Sdim    UINT8                       Type1,
60303231Sdim    UINT32                      Count1,
61303231Sdim    UINT8                       Type2,
62303231Sdim    UINT32                      Count2);
63303231Sdim
64303231Sdimstatic void
65303231SdimApCheckPackageList (
66303231Sdim    const char                  *PredefinedName,
67303231Sdim    ACPI_PARSE_OBJECT           *ParentOp,
68303231Sdim    const ACPI_PREDEFINED_INFO  *Package,
69303231Sdim    UINT32                      StartIndex,
70303231Sdim    UINT32                      Count);
71303231Sdim
72303231Sdimstatic void
73303231SdimApPackageTooSmall (
74303231Sdim    const char                  *PredefinedName,
75303231Sdim    ACPI_PARSE_OBJECT           *Op,
76303231Sdim    UINT32                      Count,
77303231Sdim    UINT32                      ExpectedCount);
78303231Sdim
79303231Sdimstatic void
80303231SdimApZeroLengthPackage (
81303231Sdim    const char                  *PredefinedName,
82303231Sdim    ACPI_PARSE_OBJECT           *Op);
83303231Sdim
84303231Sdimstatic void
85303231SdimApPackageTooLarge (
86303231Sdim    const char                  *PredefinedName,
87303231Sdim    ACPI_PARSE_OBJECT           *Op,
88327952Sdim    UINT32                      Count,
89303231Sdim    UINT32                      ExpectedCount);
90303231Sdim
91303231Sdimstatic void
92303231SdimApCustomPackage (
93303231Sdim    ACPI_PARSE_OBJECT           *ParentOp,
94303231Sdim    const ACPI_PREDEFINED_INFO  *Predefined);
95303231Sdim
96303231Sdim
97303231Sdim/*******************************************************************************
98321369Sdim *
99321369Sdim * FUNCTION:    ApCheckPackage
100303231Sdim *
101303231Sdim * PARAMETERS:  ParentOp            - Parser op for the package
102303231Sdim *              Predefined          - Pointer to package-specific info for
103303231Sdim *                                    the method
104321369Sdim *
105303231Sdim * RETURN:      None
106303231Sdim *
107303231Sdim * DESCRIPTION: Top-level validation for predefined name return package
108303231Sdim *              objects.
109303231Sdim *
110303231Sdim ******************************************************************************/
111303231Sdim
112303231Sdimvoid
113303231SdimApCheckPackage (
114303231Sdim    ACPI_PARSE_OBJECT           *ParentOp,
115303231Sdim    const ACPI_PREDEFINED_INFO  *Predefined)
116303231Sdim{
117303231Sdim    ACPI_PARSE_OBJECT           *Op;
118303231Sdim    const ACPI_PREDEFINED_INFO  *Package;
119303231Sdim    ACPI_STATUS                 Status;
120303231Sdim    UINT32                      ExpectedCount;
121303231Sdim    UINT32                      Count;
122303231Sdim    UINT32                      i;
123303231Sdim
124303231Sdim
125303231Sdim    /* The package info for this name is in the next table entry */
126303231Sdim
127303231Sdim    Package = Predefined + 1;
128327952Sdim
129303231Sdim    /* First child is the package length */
130303231Sdim
131327952Sdim    Op = ParentOp->Asl.Child;
132303231Sdim    Count = (UINT32) Op->Asl.Value.Integer;
133303231Sdim
134303231Sdim    /*
135303231Sdim     * Many of the variable-length top-level packages are allowed to simply
136327952Sdim     * have zero elements. This allows the BIOS to tell the host that even
137327952Sdim     * though the predefined name/method exists, the feature is not supported.
138303231Sdim     * Other package types require one or more elements. In any case, there
139303231Sdim     * is no need to continue validation.
140303231Sdim     */
141303231Sdim    if (!Count)
142303231Sdim    {
143327952Sdim        switch (Package->RetInfo.Type)
144327952Sdim        {
145303231Sdim        case ACPI_PTYPE1_FIXED:
146303231Sdim        case ACPI_PTYPE1_OPTION:
147303231Sdim        case ACPI_PTYPE2_PKG_COUNT:
148303231Sdim        case ACPI_PTYPE2_REV_FIXED:
149303231Sdim
150303231Sdim            ApZeroLengthPackage (Predefined->Info.Name, ParentOp);
151303231Sdim            break;
152303231Sdim
153303231Sdim        case ACPI_PTYPE1_VAR:
154327952Sdim        case ACPI_PTYPE2:
155327952Sdim        case ACPI_PTYPE2_COUNT:
156303231Sdim        case ACPI_PTYPE2_FIXED:
157327952Sdim        case ACPI_PTYPE2_MIN:
158303231Sdim        case ACPI_PTYPE2_FIX_VAR:
159321369Sdim        case ACPI_PTYPE2_VAR_VAR:
160327952Sdim        default:
161321369Sdim
162303231Sdim            break;
163327952Sdim        }
164303231Sdim
165303231Sdim        return;
166303231Sdim    }
167303231Sdim
168303231Sdim    /* Get the first element of the package */
169303231Sdim
170321369Sdim    Op = Op->Asl.Next;
171321369Sdim
172321369Sdim    /* Decode the package type */
173321369Sdim
174321369Sdim    switch (Package->RetInfo.Type)
175321369Sdim    {
176321369Sdim    case ACPI_PTYPE_CUSTOM:
177321369Sdim
178321369Sdim        ApCustomPackage (ParentOp, Predefined);
179327952Sdim        break;
180303231Sdim
181303231Sdim    case ACPI_PTYPE1_FIXED:
182303231Sdim        /*
183303231Sdim         * The package count is fixed and there are no subpackages
184321369Sdim         *
185303231Sdim         * If package is too small, exit.
186327952Sdim         * If package is larger than expected, issue warning but continue
187303231Sdim         */
188303231Sdim        ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
189303231Sdim        if (Count < ExpectedCount)
190303231Sdim        {
191303231Sdim            goto PackageTooSmall;
192303231Sdim        }
193327952Sdim        else if (Count > ExpectedCount)
194303231Sdim        {
195303231Sdim            ApPackageTooLarge (Predefined->Info.Name, ParentOp,
196327952Sdim                Count, ExpectedCount);
197327952Sdim        }
198303231Sdim
199303231Sdim        /* Validate all elements of the package */
200303231Sdim
201327952Sdim        ApCheckPackageElements (Predefined->Info.Name, Op,
202327952Sdim            Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
203327952Sdim            Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
204303231Sdim        break;
205303231Sdim
206327952Sdim    case ACPI_PTYPE1_VAR:
207303231Sdim        /*
208303231Sdim         * The package count is variable, there are no subpackages,
209341825Sdim         * and all elements must be of the same type
210327952Sdim         */
211327952Sdim        for (i = 0; i < Count; i++)
212303231Sdim        {
213303231Sdim            ApCheckObjectType (Predefined->Info.Name, Op,
214327952Sdim                Package->RetInfo.ObjectType1, i);
215327952Sdim            Op = Op->Asl.Next;
216327952Sdim        }
217327952Sdim        break;
218327952Sdim
219327952Sdim    case ACPI_PTYPE1_OPTION:
220327952Sdim        /*
221303231Sdim         * The package count is variable, there are no subpackages.
222303231Sdim         * There are a fixed number of required elements, and a variable
223303231Sdim         * number of optional elements.
224303231Sdim         *
225303231Sdim         * Check if package is at least as large as the minimum required
226303231Sdim         */
227303231Sdim        ExpectedCount = Package->RetInfo3.Count;
228303231Sdim        if (Count < ExpectedCount)
229303231Sdim        {
230303231Sdim            goto PackageTooSmall;
231303231Sdim        }
232303231Sdim
233303231Sdim        /* Variable number of sub-objects */
234303231Sdim
235303231Sdim        for (i = 0; i < Count; i++)
236303231Sdim        {
237303231Sdim            if (i < Package->RetInfo3.Count)
238303231Sdim            {
239303231Sdim                /* These are the required package elements (0, 1, or 2) */
240303231Sdim
241303231Sdim                ApCheckObjectType (Predefined->Info.Name, Op,
242303231Sdim                    Package->RetInfo3.ObjectType[i], i);
243303231Sdim            }
244303231Sdim            else
245303231Sdim            {
246303231Sdim                /* These are the optional package elements */
247303231Sdim
248303231Sdim                ApCheckObjectType (Predefined->Info.Name, Op,
249303231Sdim                    Package->RetInfo3.TailObjectType, i);
250303231Sdim            }
251303231Sdim
252303231Sdim            Op = Op->Asl.Next;
253303231Sdim        }
254303231Sdim        break;
255303231Sdim
256303231Sdim    case ACPI_PTYPE2_REV_FIXED:
257327952Sdim
258327952Sdim        /* First element is the (Integer) revision */
259327952Sdim
260327952Sdim        ApCheckObjectType (Predefined->Info.Name, Op,
261327952Sdim            ACPI_RTYPE_INTEGER, 0);
262303231Sdim
263303231Sdim        Op = Op->Asl.Next;
264327952Sdim        Count--;
265327952Sdim
266303231Sdim        /* Examine the subpackages */
267327952Sdim
268327952Sdim        ApCheckPackageList (Predefined->Info.Name, Op,
269303231Sdim            Package, 1, Count);
270303231Sdim        break;
271327952Sdim
272303231Sdim    case ACPI_PTYPE2_PKG_COUNT:
273303231Sdim
274303231Sdim        /* First element is the (Integer) count of subpackages to follow */
275303231Sdim
276303231Sdim        Status = ApCheckObjectType (Predefined->Info.Name, Op,
277303231Sdim            ACPI_RTYPE_INTEGER, 0);
278303231Sdim
279327952Sdim        /* We must have an integer count from above (otherwise, use Count) */
280327952Sdim
281303231Sdim        if (ACPI_SUCCESS (Status))
282303231Sdim        {
283303231Sdim            /*
284303231Sdim             * Count cannot be larger than the parent package length, but
285303231Sdim             * allow it to be smaller. The >= accounts for the Integer above.
286303231Sdim             */
287303231Sdim            ExpectedCount = (UINT32) Op->Asl.Value.Integer;
288303231Sdim            if (ExpectedCount >= Count)
289303231Sdim            {
290303231Sdim                goto PackageTooSmall;
291303231Sdim            }
292321369Sdim
293303231Sdim            Count = ExpectedCount;
294303231Sdim        }
295327952Sdim
296327952Sdim        Op = Op->Asl.Next;
297303231Sdim
298303231Sdim        /* Examine the subpackages */
299303231Sdim
300327952Sdim        ApCheckPackageList (Predefined->Info.Name, Op,
301303231Sdim            Package, 1, Count);
302327952Sdim        break;
303303231Sdim
304360784Sdim    case ACPI_PTYPE2_UUID_PAIR:
305360784Sdim
306360784Sdim        /* The package contains a variable list of UUID Buffer/Package pairs */
307360784Sdim
308360784Sdim        /* The length of the package must be even */
309360784Sdim
310303231Sdim        if (Count & 1)
311327952Sdim        {
312303231Sdim            sprintf (MsgBuffer, "%4.4s: Package length, %d, must be even.",
313327952Sdim                Predefined->Info.Name, Count);
314360784Sdim
315303231Sdim            AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH,
316303231Sdim                ParentOp->Asl.Child, MsgBuffer);
317303231Sdim        }
318303231Sdim
319314564Sdim        /* Validate the alternating types */
320314564Sdim
321314564Sdim        for (i = 0; i < Count; ++i)
322303231Sdim        {
323303231Sdim            if (i & 1)
324303231Sdim            {
325303231Sdim                ApCheckObjectType (Predefined->Info.Name, Op,
326303231Sdim                    Package->RetInfo.ObjectType2, i);
327303231Sdim            }
328303231Sdim            else
329327952Sdim            {
330303231Sdim                ApCheckObjectType (Predefined->Info.Name, Op,
331303231Sdim                    Package->RetInfo.ObjectType1, i);
332303231Sdim            }
333303231Sdim
334303231Sdim            Op = Op->Asl.Next;
335303231Sdim        }
336303231Sdim
337327952Sdim        break;
338303231Sdim
339303231Sdim    case ACPI_PTYPE2_VAR_VAR:
340303231Sdim
341303231Sdim        /* Check for minimum size (ints at beginning + 1 subpackage) */
342303231Sdim
343303231Sdim        ExpectedCount = Package->RetInfo4.Count1 + 1;
344303231Sdim        if (Count < ExpectedCount)
345303231Sdim        {
346303231Sdim            goto PackageTooSmall;
347303231Sdim        }
348303231Sdim
349303231Sdim        /* Check the non-package elements at beginning of main package */
350303231Sdim
351303231Sdim        for (i = 0; i < Package->RetInfo4.Count1; ++i)
352303231Sdim        {
353303231Sdim            Status = ApCheckObjectType (Predefined->Info.Name, Op,
354303231Sdim                Package->RetInfo4.ObjectType1, i);
355303231Sdim            Op = Op->Asl.Next;
356303231Sdim        }
357303231Sdim
358303231Sdim        /* Examine the variable-length list of subpackages */
359303231Sdim
360303231Sdim        ApCheckPackageList (Predefined->Info.Name, Op,
361303231Sdim            Package, Package->RetInfo4.Count1, Count);
362303231Sdim
363327952Sdim        break;
364303231Sdim
365303231Sdim    case ACPI_PTYPE2:
366303231Sdim    case ACPI_PTYPE2_FIXED:
367303231Sdim    case ACPI_PTYPE2_MIN:
368303231Sdim    case ACPI_PTYPE2_COUNT:
369327952Sdim    case ACPI_PTYPE2_FIX_VAR:
370303231Sdim        /*
371327952Sdim         * These types all return a single Package that consists of a
372303231Sdim         * variable number of subpackages.
373327952Sdim         */
374303231Sdim
375303231Sdim        /* Examine the subpackages */
376303231Sdim
377303231Sdim        ApCheckPackageList (Predefined->Info.Name, Op,
378303231Sdim            Package, 0, Count);
379303231Sdim        break;
380303231Sdim
381327952Sdim    default:
382303231Sdim        return;
383303231Sdim    }
384303231Sdim
385303231Sdim    return;
386327952Sdim
387303231SdimPackageTooSmall:
388327952Sdim    ApPackageTooSmall (Predefined->Info.Name, ParentOp,
389303231Sdim        Count, ExpectedCount);
390327952Sdim}
391303231Sdim
392327952Sdim
393303231Sdim/*******************************************************************************
394327952Sdim *
395303231Sdim * FUNCTION:    ApCustomPackage
396327952Sdim *
397327952Sdim * PARAMETERS:  ParentOp            - Parse op for the package
398303231Sdim *              Predefined          - Pointer to package-specific info for
399303231Sdim *                                    the method
400303231Sdim *
401327952Sdim * RETURN:      None
402303231Sdim *
403303231Sdim * DESCRIPTION: Validate packages that don't fit into the standard model and
404327952Sdim *              require custom code.
405303231Sdim *
406327952Sdim * NOTE: Currently used for the _BIX method only. When needed for two or more
407303231Sdim * methods, probably a detect/dispatch mechanism will be required.
408303231Sdim *
409327952Sdim ******************************************************************************/
410327952Sdim
411327952Sdimstatic void
412327952SdimApCustomPackage (
413303231Sdim    ACPI_PARSE_OBJECT           *ParentOp,
414303231Sdim    const ACPI_PREDEFINED_INFO  *Predefined)
415303231Sdim{
416327952Sdim    ACPI_PARSE_OBJECT           *Op;
417327952Sdim    UINT32                      Count;
418303231Sdim    UINT32                      ExpectedCount;
419327952Sdim    UINT32                      Version;
420327952Sdim
421327952Sdim
422327952Sdim    /* First child is the package length */
423327952Sdim
424327952Sdim    Op = ParentOp->Asl.Child;
425327952Sdim    Count = (UINT32) Op->Asl.Value.Integer;
426327952Sdim
427327952Sdim    /* Get the version number, must be Integer */
428327952Sdim
429327952Sdim    Op = Op->Asl.Next;
430327952Sdim    Version = (UINT32) Op->Asl.Value.Integer;
431327952Sdim    if (Op->Asl.ParseOpcode != PARSEOP_INTEGER)
432327952Sdim    {
433327952Sdim        AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Op, MsgBuffer);
434327952Sdim        return;
435327952Sdim    }
436327952Sdim
437327952Sdim    /* Validate count (# of elements) */
438327952Sdim
439327952Sdim    ExpectedCount = 21;         /* Version 1 */
440327952Sdim    if (Version == 0)
441327952Sdim    {
442327952Sdim        ExpectedCount = 20;     /* Version 0 */
443327952Sdim    }
444327952Sdim
445327952Sdim    if (Count < ExpectedCount)
446327952Sdim    {
447327952Sdim        ApPackageTooSmall (Predefined->Info.Name, ParentOp,
448327952Sdim            Count, ExpectedCount);
449327952Sdim        return;
450327952Sdim    }
451327952Sdim    else if (Count > ExpectedCount)
452327952Sdim    {
453327952Sdim        ApPackageTooLarge (Predefined->Info.Name, ParentOp,
454327952Sdim            Count, ExpectedCount);
455327952Sdim    }
456327952Sdim
457327952Sdim    /* Validate all elements of the package */
458327952Sdim
459327952Sdim    Op = ApCheckPackageElements (Predefined->Info.Name, Op,
460327952Sdim        ACPI_RTYPE_INTEGER, 16,
461327952Sdim        ACPI_RTYPE_STRING, 4);
462327952Sdim
463327952Sdim    /* Version 1 has a single trailing integer */
464327952Sdim
465327952Sdim    if (Version > 0)
466327952Sdim    {
467327952Sdim        ApCheckPackageElements (Predefined->Info.Name, Op,
468327952Sdim            ACPI_RTYPE_INTEGER, 1, 0, 0);
469327952Sdim    }
470327952Sdim}
471327952Sdim
472327952Sdim
473327952Sdim/*******************************************************************************
474327952Sdim *
475303231Sdim * FUNCTION:    ApCheckPackageElements
476303231Sdim *
477303231Sdim * PARAMETERS:  PredefinedName      - Name of the predefined object
478303231Sdim *              Op                  - Parser op for the package
479321369Sdim *              Type1               - Object type for first group
480321369Sdim *              Count1              - Count for first group
481303231Sdim *              Type2               - Object type for second group
482303231Sdim *              Count2              - Count for second group
483303231Sdim *
484303231Sdim * RETURN:      Next Op peer in the parse tree, after all specified elements
485303231Sdim *              have been validated. Used for multiple validations (calls
486321369Sdim *              to this function).
487303231Sdim *
488303231Sdim * DESCRIPTION: Validate all elements of a package. Works with packages that
489303231Sdim *              are defined to contain up to two groups of different object
490327952Sdim *              types.
491303231Sdim *
492303231Sdim ******************************************************************************/
493327952Sdim
494327952Sdimstatic ACPI_PARSE_OBJECT *
495314564SdimApCheckPackageElements (
496314564Sdim    const char              *PredefinedName,
497314564Sdim    ACPI_PARSE_OBJECT       *Op,
498321369Sdim    UINT8                   Type1,
499314564Sdim    UINT32                  Count1,
500314564Sdim    UINT8                   Type2,
501314564Sdim    UINT32                  Count2)
502321369Sdim{
503314564Sdim    UINT32                  i;
504303231Sdim
505327952Sdim
506314564Sdim    /*
507303231Sdim     * Up to two groups of package elements are supported by the data
508303231Sdim     * structure. All elements in each group must be of the same type.
509327952Sdim     * The second group can have a count of zero.
510303231Sdim     *
511303231Sdim     * Aborts check upon a NULL package element, as this means (at compile
512303231Sdim     * time) that the remainder of the package elements are also NULL
513303231Sdim     * (This is the only way to create NULL package elements.)
514341825Sdim     */
515303231Sdim    for (i = 0; (i < Count1) && Op; i++)
516360784Sdim    {
517327952Sdim        ApCheckObjectType (PredefinedName, Op, Type1, i);
518303231Sdim        Op = Op->Asl.Next;
519321369Sdim    }
520303231Sdim
521327952Sdim    for (i = 0; (i < Count2) && Op; i++)
522314564Sdim    {
523314564Sdim        ApCheckObjectType (PredefinedName, Op, Type2, (i + Count1));
524314564Sdim        Op = Op->Asl.Next;
525360784Sdim    }
526360784Sdim
527360784Sdim    return (Op);
528360784Sdim}
529360784Sdim
530360784Sdim
531360784Sdim/*******************************************************************************
532303231Sdim *
533321369Sdim * FUNCTION:    ApCheckPackageList
534321369Sdim *
535321369Sdim * PARAMETERS:  PredefinedName      - Name of the predefined object
536327952Sdim *              ParentOp            - Parser op of the parent package
537303231Sdim *              Package             - Package info for this predefined name
538314564Sdim *              StartIndex          - Index in parent package where list begins
539314564Sdim *              ParentCount         - Element count of parent package
540314564Sdim *
541327952Sdim * RETURN:      None
542327952Sdim *
543360784Sdim * DESCRIPTION: Validate the individual package elements for a predefined name.
544303231Sdim *              Handles the cases where the predefined name is defined as a
545314564Sdim *              Package of Packages (subpackages). These are the types:
546327952Sdim *
547303231Sdim *              ACPI_PTYPE2
548327952Sdim *              ACPI_PTYPE2_FIXED
549303231Sdim *              ACPI_PTYPE2_MIN
550303231Sdim *              ACPI_PTYPE2_COUNT
551303231Sdim *              ACPI_PTYPE2_FIX_VAR
552344779Sdim *              ACPI_PTYPE2_VAR_VAR
553303231Sdim *
554327952Sdim ******************************************************************************/
555327952Sdim
556327952Sdimstatic void
557327952SdimApCheckPackageList (
558327952Sdim    const char                  *PredefinedName,
559327952Sdim    ACPI_PARSE_OBJECT           *ParentOp,
560327952Sdim    const ACPI_PREDEFINED_INFO  *Package,
561327952Sdim    UINT32                      StartIndex,
562327952Sdim    UINT32                      ParentCount)
563314564Sdim{
564303231Sdim    ACPI_PARSE_OBJECT           *SubPackageOp = ParentOp;
565303231Sdim    ACPI_PARSE_OBJECT           *Op;
566327952Sdim    ACPI_STATUS                 Status;
567303231Sdim    UINT32                      Count;
568303231Sdim    UINT32                      ExpectedCount;
569303231Sdim    UINT32                      i;
570303231Sdim    UINT32                      j;
571303231Sdim
572303231Sdim
573327952Sdim    /*
574327952Sdim     * Validate each subpackage in the parent Package
575327952Sdim     *
576327952Sdim     * Note: We ignore NULL package elements on the assumption that
577327952Sdim     * they will be initialized by the BIOS or other ASL code.
578327952Sdim     */
579327952Sdim    for (i = 0; (i < ParentCount) && SubPackageOp; i++)
580303231Sdim    {
581303231Sdim        /* Each object in the list must be of type Package */
582303231Sdim
583303231Sdim        Status = ApCheckObjectType (PredefinedName, SubPackageOp,
584303231Sdim            ACPI_RTYPE_PACKAGE, i + StartIndex);
585327952Sdim        if (ACPI_FAILURE (Status))
586303231Sdim        {
587303231Sdim            goto NextSubpackage;
588303231Sdim        }
589303231Sdim
590303231Sdim        /* Examine the different types of expected subpackages */
591303231Sdim
592327952Sdim        Op = SubPackageOp->Asl.Child;
593303231Sdim
594327952Sdim        /* First child is the package length */
595327952Sdim
596327952Sdim        Count = (UINT32) Op->Asl.Value.Integer;
597327952Sdim        Op = Op->Asl.Next;
598327952Sdim
599303231Sdim        /*
600327952Sdim         * Most subpackage must have at least one element, with
601327952Sdim         * only rare exceptions. (_RDI)
602327952Sdim         */
603327952Sdim        if (!Count &&
604327952Sdim            (Package->RetInfo.Type != ACPI_PTYPE2_VAR_VAR))
605327952Sdim        {
606327952Sdim            ApZeroLengthPackage (PredefinedName, SubPackageOp);
607327952Sdim            goto NextSubpackage;
608303231Sdim        }
609327952Sdim
610327952Sdim        /*
611327952Sdim         * Decode the package type.
612327952Sdim         * PTYPE2 indicates that a "package of packages" is expected for
613327952Sdim         * this name. The various flavors of PTYPE2 indicate the number
614327952Sdim         * and format of the subpackages.
615327952Sdim         */
616327952Sdim        switch (Package->RetInfo.Type)
617327952Sdim        {
618327952Sdim        case ACPI_PTYPE2:
619327952Sdim        case ACPI_PTYPE2_PKG_COUNT:
620327952Sdim        case ACPI_PTYPE2_REV_FIXED:
621327952Sdim
622327952Sdim            /* Each subpackage has a fixed number of elements */
623327952Sdim
624327952Sdim            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
625327952Sdim            if (Count < ExpectedCount)
626327952Sdim            {
627327952Sdim                ApPackageTooSmall (PredefinedName, SubPackageOp,
628327952Sdim                    Count, ExpectedCount);
629303231Sdim                break;
630303231Sdim            }
631327952Sdim            if (Count > ExpectedCount)
632327952Sdim            {
633327952Sdim                ApPackageTooLarge (PredefinedName, SubPackageOp,
634327952Sdim                    Count, ExpectedCount);
635327952Sdim                break;
636327952Sdim            }
637327952Sdim
638327952Sdim            ApCheckPackageElements (PredefinedName, Op,
639327952Sdim                Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
640327952Sdim                Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
641327952Sdim            break;
642327952Sdim
643327952Sdim        case ACPI_PTYPE2_FIX_VAR:
644327952Sdim            /*
645327952Sdim             * Each subpackage has a fixed number of elements and an
646327952Sdim             * optional element
647327952Sdim             */
648327952Sdim            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
649327952Sdim            if (Count < ExpectedCount)
650327952Sdim            {
651327952Sdim                ApPackageTooSmall (PredefinedName, SubPackageOp,
652327952Sdim                    Count, ExpectedCount);
653327952Sdim                break;
654327952Sdim            }
655327952Sdim
656327952Sdim            ApCheckPackageElements (PredefinedName, Op,
657327952Sdim                Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
658327952Sdim                Package->RetInfo.ObjectType2,
659327952Sdim                Count - Package->RetInfo.Count1);
660327952Sdim            break;
661327952Sdim
662327952Sdim        case ACPI_PTYPE2_VAR_VAR:
663327952Sdim            /*
664327952Sdim             * Must have at least the minimum number elements.
665327952Sdim             * A zero PkgCount means the number of elements is variable.
666327952Sdim             */
667327952Sdim            ExpectedCount = Package->RetInfo4.PkgCount;
668327952Sdim            if (ExpectedCount && (Count < ExpectedCount))
669327952Sdim            {
670327952Sdim                ApPackageTooSmall (PredefinedName, SubPackageOp,
671327952Sdim                    Count, 1);
672327952Sdim                break;
673327952Sdim            }
674327952Sdim
675327952Sdim            ApCheckPackageElements (PredefinedName, Op,
676327952Sdim                Package->RetInfo4.SubObjectTypes,
677327952Sdim                Package->RetInfo4.PkgCount,
678327952Sdim                0, 0);
679327952Sdim            break;
680327952Sdim
681303231Sdim        case ACPI_PTYPE2_FIXED:
682303231Sdim
683303231Sdim            /* Each subpackage has a fixed length */
684303231Sdim
685303231Sdim            ExpectedCount = Package->RetInfo2.Count;
686303231Sdim            if (Count < ExpectedCount)
687303231Sdim            {
688303231Sdim                ApPackageTooSmall (PredefinedName, SubPackageOp,
689303231Sdim                    Count, ExpectedCount);
690303231Sdim                break;
691303231Sdim            }
692303231Sdim            if (Count > ExpectedCount)
693303231Sdim            {
694303231Sdim                ApPackageTooLarge (PredefinedName, SubPackageOp,
695303231Sdim                    Count, ExpectedCount);
696303231Sdim                break;
697303231Sdim            }
698303231Sdim
699303231Sdim            /* Check each object/type combination */
700321369Sdim
701303231Sdim            for (j = 0; j < ExpectedCount; j++)
702303231Sdim            {
703303231Sdim                ApCheckObjectType (PredefinedName, Op,
704303231Sdim                    Package->RetInfo2.ObjectType[j], j);
705321369Sdim
706303231Sdim                Op = Op->Asl.Next;
707303231Sdim            }
708303231Sdim            break;
709303231Sdim
710321369Sdim        case ACPI_PTYPE2_MIN:
711303231Sdim
712303231Sdim            /* Each subpackage has a variable but minimum length */
713303231Sdim
714303231Sdim            ExpectedCount = Package->RetInfo.Count1;
715303231Sdim            if (Count < ExpectedCount)
716303231Sdim            {
717303231Sdim                ApPackageTooSmall (PredefinedName, SubPackageOp,
718303231Sdim                    Count, ExpectedCount);
719303231Sdim                break;
720303231Sdim            }
721303231Sdim
722303231Sdim            /* Check the type of each subpackage element */
723303231Sdim
724303231Sdim            ApCheckPackageElements (PredefinedName, Op,
725303231Sdim                Package->RetInfo.ObjectType1, Count, 0, 0);
726303231Sdim            break;
727303231Sdim
728303231Sdim        case ACPI_PTYPE2_COUNT:
729303231Sdim            /*
730303231Sdim             * First element is the (Integer) count of elements, including
731321369Sdim             * the count field (the ACPI name is NumElements)
732303231Sdim             */
733303231Sdim            Status = ApCheckObjectType (PredefinedName, Op,
734303231Sdim                ACPI_RTYPE_INTEGER, 0);
735303231Sdim
736321369Sdim            /* We must have an integer count from above (otherwise, use Count) */
737303231Sdim
738303231Sdim            if (ACPI_SUCCESS (Status))
739303231Sdim            {
740303231Sdim                /*
741321369Sdim                 * Make sure package is large enough for the Count and is
742303231Sdim                 * is as large as the minimum size
743303231Sdim                 */
744303231Sdim                ExpectedCount = (UINT32) Op->Asl.Value.Integer;
745303231Sdim
746303231Sdim                if (Count < ExpectedCount)
747303231Sdim                {
748303231Sdim                    ApPackageTooSmall (PredefinedName, SubPackageOp,
749303231Sdim                        Count, ExpectedCount);
750303231Sdim                    break;
751303231Sdim                }
752303231Sdim                else if (Count > ExpectedCount)
753303231Sdim                {
754303231Sdim                    ApPackageTooLarge (PredefinedName, SubPackageOp,
755303231Sdim                        Count, ExpectedCount);
756303231Sdim                }
757303231Sdim
758303231Sdim                /* Some names of this type have a minimum length */
759321369Sdim
760303231Sdim                if (Count < Package->RetInfo.Count1)
761303231Sdim                {
762303231Sdim                    ExpectedCount = Package->RetInfo.Count1;
763321369Sdim                    ApPackageTooSmall (PredefinedName, SubPackageOp,
764303231Sdim                        Count, ExpectedCount);
765303231Sdim                    break;
766303231Sdim                }
767321369Sdim
768303231Sdim                Count = ExpectedCount;
769303231Sdim            }
770303231Sdim
771303231Sdim            /* Check the type of each subpackage element */
772303231Sdim
773303231Sdim            Op = Op->Asl.Next;
774303231Sdim            ApCheckPackageElements (PredefinedName, Op,
775303231Sdim                Package->RetInfo.ObjectType1, (Count - 1), 0, 0);
776303231Sdim            break;
777303231Sdim
778303231Sdim        default:
779303231Sdim            break;
780303231Sdim        }
781327952Sdim
782327952SdimNextSubpackage:
783327952Sdim        SubPackageOp = SubPackageOp->Asl.Next;
784327952Sdim    }
785303231Sdim}
786303231Sdim
787303231Sdim
788303231Sdim/*******************************************************************************
789321369Sdim *
790321369Sdim * FUNCTION:    ApPackageTooSmall
791303231Sdim *
792303231Sdim * PARAMETERS:  PredefinedName      - Name of the predefined object
793303231Sdim *              Op                  - Current parser op
794321369Sdim *              Count               - Actual package element count
795321369Sdim *              ExpectedCount       - Expected package element count
796303231Sdim *
797303231Sdim * RETURN:      None
798303231Sdim *
799303231Sdim * DESCRIPTION: Issue error message for a package that is smaller than
800327952Sdim *              required.
801303231Sdim *
802303231Sdim ******************************************************************************/
803303231Sdim
804321369Sdimstatic void
805303231SdimApPackageTooSmall (
806303231Sdim    const char                  *PredefinedName,
807303231Sdim    ACPI_PARSE_OBJECT           *Op,
808303231Sdim    UINT32                      Count,
809303231Sdim    UINT32                      ExpectedCount)
810303231Sdim{
811303231Sdim
812321369Sdim    sprintf (MsgBuffer, "%s: length %u, required minimum is %u",
813303231Sdim        PredefinedName, Count, ExpectedCount);
814303231Sdim
815303231Sdim    AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
816303231Sdim}
817303231Sdim
818303231Sdim
819303231Sdim/*******************************************************************************
820303231Sdim *
821303231Sdim * FUNCTION:    ApZeroLengthPackage
822303231Sdim *
823303231Sdim * PARAMETERS:  PredefinedName      - Name of the predefined object
824303231Sdim *              Op                  - Current parser op
825303231Sdim *
826303231Sdim * RETURN:      None
827303231Sdim *
828303231Sdim * DESCRIPTION: Issue error message for a zero-length package (a package that
829303231Sdim *              is required to have a non-zero length). Variable length
830303231Sdim *              packages seem to be allowed to have zero length, however.
831303231Sdim *              Even if not allowed, BIOS code does it.
832321369Sdim *
833 ******************************************************************************/
834
835static void
836ApZeroLengthPackage (
837    const char                  *PredefinedName,
838    ACPI_PARSE_OBJECT           *Op)
839{
840
841    sprintf (MsgBuffer, "%s: length is zero", PredefinedName);
842
843    AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
844}
845
846
847/*******************************************************************************
848 *
849 * FUNCTION:    ApPackageTooLarge
850 *
851 * PARAMETERS:  PredefinedName      - Name of the predefined object
852 *              Op                  - Current parser op
853 *              Count               - Actual package element count
854 *              ExpectedCount       - Expected package element count
855 *
856 * RETURN:      None
857 *
858 * DESCRIPTION: Issue a remark for a package that is larger than expected.
859 *
860 ******************************************************************************/
861
862static void
863ApPackageTooLarge (
864    const char                  *PredefinedName,
865    ACPI_PARSE_OBJECT           *Op,
866    UINT32                      Count,
867    UINT32                      ExpectedCount)
868{
869
870    sprintf (MsgBuffer, "%s: length is %u, only %u required",
871        PredefinedName, Count, ExpectedCount);
872
873    AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
874}
875