1246847Sjkim/******************************************************************************
2246847Sjkim *
3246847Sjkim * Module Name: aslprepkg - support for ACPI predefined name package objects
4246847Sjkim *
5246847Sjkim *****************************************************************************/
6246847Sjkim
7246847Sjkim/*
8298714Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9246847Sjkim * All rights reserved.
10246847Sjkim *
11246847Sjkim * Redistribution and use in source and binary forms, with or without
12246847Sjkim * modification, are permitted provided that the following conditions
13246847Sjkim * are met:
14246847Sjkim * 1. Redistributions of source code must retain the above copyright
15246847Sjkim *    notice, this list of conditions, and the following disclaimer,
16246847Sjkim *    without modification.
17246847Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18246847Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19246847Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20246847Sjkim *    including a substantially similar Disclaimer requirement for further
21246847Sjkim *    binary redistribution.
22246847Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23246847Sjkim *    of any contributors may be used to endorse or promote products derived
24246847Sjkim *    from this software without specific prior written permission.
25246847Sjkim *
26246847Sjkim * Alternatively, this software may be distributed under the terms of the
27246847Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28246847Sjkim * Software Foundation.
29246847Sjkim *
30246847Sjkim * NO WARRANTY
31246847Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32246847Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33246847Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34246847Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35246847Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36246847Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37246847Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38246847Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39246847Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40246847Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41246847Sjkim * POSSIBILITY OF SUCH DAMAGES.
42246847Sjkim */
43246847Sjkim
44246849Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
45246847Sjkim#include "aslcompiler.y.h"
46246849Sjkim#include <contrib/dev/acpica/include/acpredef.h>
47246847Sjkim
48246847Sjkim
49246847Sjkim#define _COMPONENT          ACPI_COMPILER
50246847Sjkim        ACPI_MODULE_NAME    ("aslprepkg")
51246847Sjkim
52246847Sjkim
53246847Sjkim/* Local prototypes */
54246847Sjkim
55298714Sjkimstatic ACPI_PARSE_OBJECT *
56246847SjkimApCheckPackageElements (
57249663Sjkim    const char                  *PredefinedName,
58249663Sjkim    ACPI_PARSE_OBJECT           *Op,
59249663Sjkim    UINT8                       Type1,
60249663Sjkim    UINT32                      Count1,
61249663Sjkim    UINT8                       Type2,
62249663Sjkim    UINT32                      Count2);
63246847Sjkim
64246847Sjkimstatic void
65246847SjkimApCheckPackageList (
66246847Sjkim    const char                  *PredefinedName,
67246847Sjkim    ACPI_PARSE_OBJECT           *ParentOp,
68246847Sjkim    const ACPI_PREDEFINED_INFO  *Package,
69246847Sjkim    UINT32                      StartIndex,
70246847Sjkim    UINT32                      Count);
71246847Sjkim
72246847Sjkimstatic void
73246847SjkimApPackageTooSmall (
74246847Sjkim    const char                  *PredefinedName,
75246847Sjkim    ACPI_PARSE_OBJECT           *Op,
76246847Sjkim    UINT32                      Count,
77246847Sjkim    UINT32                      ExpectedCount);
78246847Sjkim
79246847Sjkimstatic void
80246847SjkimApZeroLengthPackage (
81246847Sjkim    const char                  *PredefinedName,
82246847Sjkim    ACPI_PARSE_OBJECT           *Op);
83246847Sjkim
84246847Sjkimstatic void
85246847SjkimApPackageTooLarge (
86246847Sjkim    const char                  *PredefinedName,
87246847Sjkim    ACPI_PARSE_OBJECT           *Op,
88246847Sjkim    UINT32                      Count,
89246847Sjkim    UINT32                      ExpectedCount);
90246847Sjkim
91298714Sjkimstatic void
92298714SjkimApCustomPackage (
93298714Sjkim    ACPI_PARSE_OBJECT           *ParentOp,
94298714Sjkim    const ACPI_PREDEFINED_INFO  *Predefined);
95246847Sjkim
96298714Sjkim
97246847Sjkim/*******************************************************************************
98246847Sjkim *
99246847Sjkim * FUNCTION:    ApCheckPackage
100246847Sjkim *
101249663Sjkim * PARAMETERS:  ParentOp            - Parser op for the package
102249663Sjkim *              Predefined          - Pointer to package-specific info for
103249663Sjkim *                                    the method
104246847Sjkim *
105246847Sjkim * RETURN:      None
106246847Sjkim *
107246847Sjkim * DESCRIPTION: Top-level validation for predefined name return package
108246847Sjkim *              objects.
109246847Sjkim *
110246847Sjkim ******************************************************************************/
111246847Sjkim
112246847Sjkimvoid
113246847SjkimApCheckPackage (
114246847Sjkim    ACPI_PARSE_OBJECT           *ParentOp,
115246847Sjkim    const ACPI_PREDEFINED_INFO  *Predefined)
116246847Sjkim{
117246847Sjkim    ACPI_PARSE_OBJECT           *Op;
118246847Sjkim    const ACPI_PREDEFINED_INFO  *Package;
119246847Sjkim    ACPI_STATUS                 Status;
120246847Sjkim    UINT32                      ExpectedCount;
121246847Sjkim    UINT32                      Count;
122246847Sjkim    UINT32                      i;
123246847Sjkim
124246847Sjkim
125246847Sjkim    /* The package info for this name is in the next table entry */
126246847Sjkim
127246847Sjkim    Package = Predefined + 1;
128246847Sjkim
129246847Sjkim    /* First child is the package length */
130246847Sjkim
131246847Sjkim    Op = ParentOp->Asl.Child;
132246847Sjkim    Count = (UINT32) Op->Asl.Value.Integer;
133246847Sjkim
134246847Sjkim    /*
135249112Sjkim     * Many of the variable-length top-level packages are allowed to simply
136249112Sjkim     * have zero elements. This allows the BIOS to tell the host that even
137249112Sjkim     * though the predefined name/method exists, the feature is not supported.
138249112Sjkim     * Other package types require one or more elements. In any case, there
139249112Sjkim     * is no need to continue validation.
140246847Sjkim     */
141246847Sjkim    if (!Count)
142246847Sjkim    {
143249112Sjkim        switch (Package->RetInfo.Type)
144246847Sjkim        {
145249112Sjkim        case ACPI_PTYPE1_FIXED:
146249112Sjkim        case ACPI_PTYPE1_OPTION:
147249112Sjkim        case ACPI_PTYPE2_PKG_COUNT:
148249112Sjkim        case ACPI_PTYPE2_REV_FIXED:
149249112Sjkim
150246847Sjkim            ApZeroLengthPackage (Predefined->Info.Name, ParentOp);
151249112Sjkim            break;
152249112Sjkim
153249112Sjkim        case ACPI_PTYPE1_VAR:
154249112Sjkim        case ACPI_PTYPE2:
155249112Sjkim        case ACPI_PTYPE2_COUNT:
156249112Sjkim        case ACPI_PTYPE2_FIXED:
157249112Sjkim        case ACPI_PTYPE2_MIN:
158249112Sjkim        case ACPI_PTYPE2_FIX_VAR:
159283092Sjkim        case ACPI_PTYPE2_VAR_VAR:
160249112Sjkim        default:
161249112Sjkim
162249112Sjkim            break;
163246847Sjkim        }
164249112Sjkim
165246847Sjkim        return;
166246847Sjkim    }
167246847Sjkim
168246847Sjkim    /* Get the first element of the package */
169246847Sjkim
170246847Sjkim    Op = Op->Asl.Next;
171246847Sjkim
172246847Sjkim    /* Decode the package type */
173246847Sjkim
174246847Sjkim    switch (Package->RetInfo.Type)
175246847Sjkim    {
176298714Sjkim    case ACPI_PTYPE_CUSTOM:
177298714Sjkim
178298714Sjkim        ApCustomPackage (ParentOp, Predefined);
179298714Sjkim        break;
180298714Sjkim
181246847Sjkim    case ACPI_PTYPE1_FIXED:
182246847Sjkim        /*
183272444Sjkim         * The package count is fixed and there are no subpackages
184246847Sjkim         *
185246847Sjkim         * If package is too small, exit.
186246847Sjkim         * If package is larger than expected, issue warning but continue
187246847Sjkim         */
188246847Sjkim        ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
189246847Sjkim        if (Count < ExpectedCount)
190246847Sjkim        {
191246847Sjkim            goto PackageTooSmall;
192246847Sjkim        }
193246847Sjkim        else if (Count > ExpectedCount)
194246847Sjkim        {
195246847Sjkim            ApPackageTooLarge (Predefined->Info.Name, ParentOp,
196246847Sjkim                Count, ExpectedCount);
197246847Sjkim        }
198246847Sjkim
199246847Sjkim        /* Validate all elements of the package */
200246847Sjkim
201246847Sjkim        ApCheckPackageElements (Predefined->Info.Name, Op,
202246847Sjkim            Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
203246847Sjkim            Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
204246847Sjkim        break;
205246847Sjkim
206246847Sjkim    case ACPI_PTYPE1_VAR:
207246847Sjkim        /*
208272444Sjkim         * The package count is variable, there are no subpackages,
209249663Sjkim         * and all elements must be of the same type
210246847Sjkim         */
211246847Sjkim        for (i = 0; i < Count; i++)
212246847Sjkim        {
213246847Sjkim            ApCheckObjectType (Predefined->Info.Name, Op,
214246847Sjkim                Package->RetInfo.ObjectType1, i);
215246847Sjkim            Op = Op->Asl.Next;
216246847Sjkim        }
217246847Sjkim        break;
218246847Sjkim
219246847Sjkim    case ACPI_PTYPE1_OPTION:
220246847Sjkim        /*
221272444Sjkim         * The package count is variable, there are no subpackages.
222249663Sjkim         * There are a fixed number of required elements, and a variable
223249663Sjkim         * number of optional elements.
224246847Sjkim         *
225246847Sjkim         * Check if package is at least as large as the minimum required
226246847Sjkim         */
227246847Sjkim        ExpectedCount = Package->RetInfo3.Count;
228246847Sjkim        if (Count < ExpectedCount)
229246847Sjkim        {
230246847Sjkim            goto PackageTooSmall;
231246847Sjkim        }
232246847Sjkim
233246847Sjkim        /* Variable number of sub-objects */
234246847Sjkim
235246847Sjkim        for (i = 0; i < Count; i++)
236246847Sjkim        {
237246847Sjkim            if (i < Package->RetInfo3.Count)
238246847Sjkim            {
239246847Sjkim                /* These are the required package elements (0, 1, or 2) */
240246847Sjkim
241246847Sjkim                ApCheckObjectType (Predefined->Info.Name, Op,
242246847Sjkim                    Package->RetInfo3.ObjectType[i], i);
243246847Sjkim            }
244246847Sjkim            else
245246847Sjkim            {
246246847Sjkim                /* These are the optional package elements */
247246847Sjkim
248246847Sjkim                ApCheckObjectType (Predefined->Info.Name, Op,
249246847Sjkim                    Package->RetInfo3.TailObjectType, i);
250246847Sjkim            }
251298714Sjkim
252246847Sjkim            Op = Op->Asl.Next;
253246847Sjkim        }
254246847Sjkim        break;
255246847Sjkim
256246847Sjkim    case ACPI_PTYPE2_REV_FIXED:
257246847Sjkim
258246847Sjkim        /* First element is the (Integer) revision */
259246847Sjkim
260246847Sjkim        ApCheckObjectType (Predefined->Info.Name, Op,
261246847Sjkim            ACPI_RTYPE_INTEGER, 0);
262246847Sjkim
263246847Sjkim        Op = Op->Asl.Next;
264246847Sjkim        Count--;
265246847Sjkim
266272444Sjkim        /* Examine the subpackages */
267246847Sjkim
268246847Sjkim        ApCheckPackageList (Predefined->Info.Name, Op,
269246847Sjkim            Package, 1, Count);
270246847Sjkim        break;
271246847Sjkim
272246847Sjkim    case ACPI_PTYPE2_PKG_COUNT:
273246847Sjkim
274272444Sjkim        /* First element is the (Integer) count of subpackages to follow */
275246847Sjkim
276246847Sjkim        Status = ApCheckObjectType (Predefined->Info.Name, Op,
277246847Sjkim            ACPI_RTYPE_INTEGER, 0);
278246847Sjkim
279246847Sjkim        /* We must have an integer count from above (otherwise, use Count) */
280246847Sjkim
281246847Sjkim        if (ACPI_SUCCESS (Status))
282246847Sjkim        {
283246847Sjkim            /*
284249663Sjkim             * Count cannot be larger than the parent package length, but
285249663Sjkim             * allow it to be smaller. The >= accounts for the Integer above.
286246847Sjkim             */
287246847Sjkim            ExpectedCount = (UINT32) Op->Asl.Value.Integer;
288246847Sjkim            if (ExpectedCount >= Count)
289246847Sjkim            {
290246847Sjkim                goto PackageTooSmall;
291246847Sjkim            }
292246847Sjkim
293246847Sjkim            Count = ExpectedCount;
294246847Sjkim        }
295246847Sjkim
296246847Sjkim        Op = Op->Asl.Next;
297246847Sjkim
298272444Sjkim        /* Examine the subpackages */
299246847Sjkim
300246847Sjkim        ApCheckPackageList (Predefined->Info.Name, Op,
301246847Sjkim            Package, 1, Count);
302246847Sjkim        break;
303246847Sjkim
304272444Sjkim    case ACPI_PTYPE2_UUID_PAIR:
305272444Sjkim
306272444Sjkim        /* The package contains a variable list of UUID Buffer/Package pairs */
307272444Sjkim
308272444Sjkim        /* The length of the package must be even */
309272444Sjkim
310272444Sjkim        if (Count & 1)
311272444Sjkim        {
312272444Sjkim            sprintf (MsgBuffer, "%4.4s: Package length, %d, must be even.",
313272444Sjkim                Predefined->Info.Name, Count);
314272444Sjkim
315272444Sjkim            AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH,
316272444Sjkim                ParentOp->Asl.Child, MsgBuffer);
317272444Sjkim        }
318272444Sjkim
319272444Sjkim        /* Validate the alternating types */
320272444Sjkim
321272444Sjkim        for (i = 0; i < Count; ++i)
322272444Sjkim        {
323272444Sjkim            if (i & 1)
324272444Sjkim            {
325272444Sjkim                ApCheckObjectType (Predefined->Info.Name, Op,
326272444Sjkim                    Package->RetInfo.ObjectType2, i);
327272444Sjkim            }
328272444Sjkim            else
329272444Sjkim            {
330272444Sjkim                ApCheckObjectType (Predefined->Info.Name, Op,
331272444Sjkim                    Package->RetInfo.ObjectType1, i);
332272444Sjkim            }
333272444Sjkim
334272444Sjkim            Op = Op->Asl.Next;
335272444Sjkim        }
336272444Sjkim
337272444Sjkim        break;
338272444Sjkim
339283092Sjkim    case ACPI_PTYPE2_VAR_VAR:
340283092Sjkim
341283092Sjkim        /* Check for minimum size (ints at beginning + 1 subpackage) */
342283092Sjkim
343283092Sjkim        ExpectedCount = Package->RetInfo4.Count1 + 1;
344283092Sjkim        if (Count < ExpectedCount)
345283092Sjkim        {
346283092Sjkim            goto PackageTooSmall;
347283092Sjkim        }
348283092Sjkim
349283092Sjkim        /* Check the non-package elements at beginning of main package */
350283092Sjkim
351283092Sjkim        for (i = 0; i < Package->RetInfo4.Count1; ++i)
352283092Sjkim        {
353283092Sjkim            Status = ApCheckObjectType (Predefined->Info.Name, Op,
354283092Sjkim                Package->RetInfo4.ObjectType1, i);
355283092Sjkim            Op = Op->Asl.Next;
356283092Sjkim        }
357283092Sjkim
358283092Sjkim        /* Examine the variable-length list of subpackages */
359283092Sjkim
360283092Sjkim        ApCheckPackageList (Predefined->Info.Name, Op,
361283092Sjkim            Package, Package->RetInfo4.Count1, Count);
362283092Sjkim
363283092Sjkim        break;
364283092Sjkim
365246847Sjkim    case ACPI_PTYPE2:
366246847Sjkim    case ACPI_PTYPE2_FIXED:
367246847Sjkim    case ACPI_PTYPE2_MIN:
368246847Sjkim    case ACPI_PTYPE2_COUNT:
369246847Sjkim    case ACPI_PTYPE2_FIX_VAR:
370246847Sjkim        /*
371246847Sjkim         * These types all return a single Package that consists of a
372272444Sjkim         * variable number of subpackages.
373246847Sjkim         */
374246847Sjkim
375272444Sjkim        /* Examine the subpackages */
376246847Sjkim
377246847Sjkim        ApCheckPackageList (Predefined->Info.Name, Op,
378246847Sjkim            Package, 0, Count);
379246847Sjkim        break;
380246847Sjkim
381246847Sjkim    default:
382246847Sjkim        return;
383246847Sjkim    }
384246847Sjkim
385246847Sjkim    return;
386246847Sjkim
387246847SjkimPackageTooSmall:
388246847Sjkim    ApPackageTooSmall (Predefined->Info.Name, ParentOp,
389246847Sjkim        Count, ExpectedCount);
390246847Sjkim}
391246847Sjkim
392246847Sjkim
393246847Sjkim/*******************************************************************************
394246847Sjkim *
395298714Sjkim * FUNCTION:    ApCustomPackage
396298714Sjkim *
397298714Sjkim * PARAMETERS:  ParentOp            - Parse op for the package
398298714Sjkim *              Predefined          - Pointer to package-specific info for
399298714Sjkim *                                    the method
400298714Sjkim *
401298714Sjkim * RETURN:      None
402298714Sjkim *
403298714Sjkim * DESCRIPTION: Validate packages that don't fit into the standard model and
404298714Sjkim *              require custom code.
405298714Sjkim *
406298714Sjkim * NOTE: Currently used for the _BIX method only. When needed for two or more
407298714Sjkim * methods, probably a detect/dispatch mechanism will be required.
408298714Sjkim *
409298714Sjkim ******************************************************************************/
410298714Sjkim
411298714Sjkimstatic void
412298714SjkimApCustomPackage (
413298714Sjkim    ACPI_PARSE_OBJECT           *ParentOp,
414298714Sjkim    const ACPI_PREDEFINED_INFO  *Predefined)
415298714Sjkim{
416298714Sjkim    ACPI_PARSE_OBJECT           *Op;
417298714Sjkim    UINT32                      Count;
418298714Sjkim    UINT32                      ExpectedCount;
419298714Sjkim    UINT32                      Version;
420298714Sjkim
421298714Sjkim
422298714Sjkim    /* First child is the package length */
423298714Sjkim
424298714Sjkim    Op = ParentOp->Asl.Child;
425298714Sjkim    Count = (UINT32) Op->Asl.Value.Integer;
426298714Sjkim
427298714Sjkim    /* Get the version number, must be Integer */
428298714Sjkim
429298714Sjkim    Op = Op->Asl.Next;
430298714Sjkim    Version = (UINT32) Op->Asl.Value.Integer;
431298714Sjkim    if (Op->Asl.ParseOpcode != PARSEOP_INTEGER)
432298714Sjkim    {
433298714Sjkim        AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Op, MsgBuffer);
434298714Sjkim        return;
435298714Sjkim    }
436298714Sjkim
437298714Sjkim    /* Validate count (# of elements) */
438298714Sjkim
439298714Sjkim    ExpectedCount = 21;         /* Version 1 */
440298714Sjkim    if (Version == 0)
441298714Sjkim    {
442298714Sjkim        ExpectedCount = 20;     /* Version 0 */
443298714Sjkim    }
444298714Sjkim
445298714Sjkim    if (Count < ExpectedCount)
446298714Sjkim    {
447298714Sjkim        ApPackageTooSmall (Predefined->Info.Name, ParentOp,
448298714Sjkim            Count, ExpectedCount);
449298714Sjkim        return;
450298714Sjkim    }
451298714Sjkim    else if (Count > ExpectedCount)
452298714Sjkim    {
453298714Sjkim        ApPackageTooLarge (Predefined->Info.Name, ParentOp,
454298714Sjkim            Count, ExpectedCount);
455298714Sjkim    }
456298714Sjkim
457298714Sjkim    /* Validate all elements of the package */
458298714Sjkim
459298714Sjkim    Op = ApCheckPackageElements (Predefined->Info.Name, Op,
460298714Sjkim        ACPI_RTYPE_INTEGER, 16,
461298714Sjkim        ACPI_RTYPE_STRING, 4);
462298714Sjkim
463298714Sjkim    /* Version 1 has a single trailing integer */
464298714Sjkim
465298714Sjkim    if (Version > 0)
466298714Sjkim    {
467298714Sjkim        ApCheckPackageElements (Predefined->Info.Name, Op,
468298714Sjkim            ACPI_RTYPE_INTEGER, 1, 0, 0);
469298714Sjkim    }
470298714Sjkim}
471298714Sjkim
472298714Sjkim
473298714Sjkim/*******************************************************************************
474298714Sjkim *
475246847Sjkim * FUNCTION:    ApCheckPackageElements
476246847Sjkim *
477249663Sjkim * PARAMETERS:  PredefinedName      - Name of the predefined object
478249663Sjkim *              Op                  - Parser op for the package
479249663Sjkim *              Type1               - Object type for first group
480249663Sjkim *              Count1              - Count for first group
481249663Sjkim *              Type2               - Object type for second group
482249663Sjkim *              Count2              - Count for second group
483246847Sjkim *
484298714Sjkim * RETURN:      Next Op peer in the parse tree, after all specified elements
485298714Sjkim *              have been validated. Used for multiple validations (calls
486298714Sjkim *              to this function).
487246847Sjkim *
488246847Sjkim * DESCRIPTION: Validate all elements of a package. Works with packages that
489246847Sjkim *              are defined to contain up to two groups of different object
490246847Sjkim *              types.
491246847Sjkim *
492246847Sjkim ******************************************************************************/
493246847Sjkim
494298714Sjkimstatic ACPI_PARSE_OBJECT *
495246847SjkimApCheckPackageElements (
496246847Sjkim    const char              *PredefinedName,
497246847Sjkim    ACPI_PARSE_OBJECT       *Op,
498246847Sjkim    UINT8                   Type1,
499246847Sjkim    UINT32                  Count1,
500246847Sjkim    UINT8                   Type2,
501246847Sjkim    UINT32                  Count2)
502246847Sjkim{
503246847Sjkim    UINT32                  i;
504246847Sjkim
505246847Sjkim
506246847Sjkim    /*
507246847Sjkim     * Up to two groups of package elements are supported by the data
508246847Sjkim     * structure. All elements in each group must be of the same type.
509246847Sjkim     * The second group can have a count of zero.
510246847Sjkim     *
511246847Sjkim     * Aborts check upon a NULL package element, as this means (at compile
512246847Sjkim     * time) that the remainder of the package elements are also NULL
513246847Sjkim     * (This is the only way to create NULL package elements.)
514246847Sjkim     */
515246847Sjkim    for (i = 0; (i < Count1) && Op; i++)
516246847Sjkim    {
517246847Sjkim        ApCheckObjectType (PredefinedName, Op, Type1, i);
518246847Sjkim        Op = Op->Asl.Next;
519246847Sjkim    }
520246847Sjkim
521246847Sjkim    for (i = 0; (i < Count2) && Op; i++)
522246847Sjkim    {
523246847Sjkim        ApCheckObjectType (PredefinedName, Op, Type2, (i + Count1));
524246847Sjkim        Op = Op->Asl.Next;
525246847Sjkim    }
526298714Sjkim
527298714Sjkim    return (Op);
528246847Sjkim}
529246847Sjkim
530246847Sjkim
531246847Sjkim/*******************************************************************************
532246847Sjkim *
533246847Sjkim * FUNCTION:    ApCheckPackageList
534246847Sjkim *
535246847Sjkim * PARAMETERS:  PredefinedName      - Name of the predefined object
536246847Sjkim *              ParentOp            - Parser op of the parent package
537246847Sjkim *              Package             - Package info for this predefined name
538246847Sjkim *              StartIndex          - Index in parent package where list begins
539246847Sjkim *              ParentCount         - Element count of parent package
540246847Sjkim *
541246847Sjkim * RETURN:      None
542246847Sjkim *
543246847Sjkim * DESCRIPTION: Validate the individual package elements for a predefined name.
544246847Sjkim *              Handles the cases where the predefined name is defined as a
545246847Sjkim *              Package of Packages (subpackages). These are the types:
546246847Sjkim *
547246847Sjkim *              ACPI_PTYPE2
548246847Sjkim *              ACPI_PTYPE2_FIXED
549246847Sjkim *              ACPI_PTYPE2_MIN
550246847Sjkim *              ACPI_PTYPE2_COUNT
551246847Sjkim *              ACPI_PTYPE2_FIX_VAR
552283092Sjkim *              ACPI_PTYPE2_VAR_VAR
553246847Sjkim *
554246847Sjkim ******************************************************************************/
555246847Sjkim
556246847Sjkimstatic void
557246847SjkimApCheckPackageList (
558246847Sjkim    const char                  *PredefinedName,
559246847Sjkim    ACPI_PARSE_OBJECT           *ParentOp,
560246847Sjkim    const ACPI_PREDEFINED_INFO  *Package,
561246847Sjkim    UINT32                      StartIndex,
562246847Sjkim    UINT32                      ParentCount)
563246847Sjkim{
564246847Sjkim    ACPI_PARSE_OBJECT           *SubPackageOp = ParentOp;
565246847Sjkim    ACPI_PARSE_OBJECT           *Op;
566246847Sjkim    ACPI_STATUS                 Status;
567246847Sjkim    UINT32                      Count;
568246847Sjkim    UINT32                      ExpectedCount;
569246847Sjkim    UINT32                      i;
570246847Sjkim    UINT32                      j;
571246847Sjkim
572246847Sjkim
573246847Sjkim    /*
574246847Sjkim     * Validate each subpackage in the parent Package
575246847Sjkim     *
576246847Sjkim     * Note: We ignore NULL package elements on the assumption that
577246847Sjkim     * they will be initialized by the BIOS or other ASL code.
578246847Sjkim     */
579246847Sjkim    for (i = 0; (i < ParentCount) && SubPackageOp; i++)
580246847Sjkim    {
581246847Sjkim        /* Each object in the list must be of type Package */
582246847Sjkim
583246847Sjkim        Status = ApCheckObjectType (PredefinedName, SubPackageOp,
584246847Sjkim            ACPI_RTYPE_PACKAGE, i + StartIndex);
585246847Sjkim        if (ACPI_FAILURE (Status))
586246847Sjkim        {
587246847Sjkim            goto NextSubpackage;
588246847Sjkim        }
589246847Sjkim
590246847Sjkim        /* Examine the different types of expected subpackages */
591246847Sjkim
592246847Sjkim        Op = SubPackageOp->Asl.Child;
593246847Sjkim
594246847Sjkim        /* First child is the package length */
595246847Sjkim
596246847Sjkim        Count = (UINT32) Op->Asl.Value.Integer;
597246847Sjkim        Op = Op->Asl.Next;
598246847Sjkim
599283092Sjkim        /*
600283092Sjkim         * Most subpackage must have at least one element, with
601283092Sjkim         * only rare exceptions. (_RDI)
602283092Sjkim         */
603283092Sjkim        if (!Count &&
604283092Sjkim            (Package->RetInfo.Type != ACPI_PTYPE2_VAR_VAR))
605246847Sjkim        {
606246847Sjkim            ApZeroLengthPackage (PredefinedName, SubPackageOp);
607246847Sjkim            goto NextSubpackage;
608246847Sjkim        }
609246847Sjkim
610246847Sjkim        /*
611246847Sjkim         * Decode the package type.
612246847Sjkim         * PTYPE2 indicates that a "package of packages" is expected for
613246847Sjkim         * this name. The various flavors of PTYPE2 indicate the number
614246847Sjkim         * and format of the subpackages.
615246847Sjkim         */
616246847Sjkim        switch (Package->RetInfo.Type)
617246847Sjkim        {
618246847Sjkim        case ACPI_PTYPE2:
619246847Sjkim        case ACPI_PTYPE2_PKG_COUNT:
620246847Sjkim        case ACPI_PTYPE2_REV_FIXED:
621246847Sjkim
622246847Sjkim            /* Each subpackage has a fixed number of elements */
623246847Sjkim
624246847Sjkim            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
625246847Sjkim            if (Count < ExpectedCount)
626246847Sjkim            {
627246847Sjkim                ApPackageTooSmall (PredefinedName, SubPackageOp,
628246847Sjkim                    Count, ExpectedCount);
629246847Sjkim                break;
630246847Sjkim            }
631272444Sjkim            if (Count > ExpectedCount)
632272444Sjkim            {
633272444Sjkim                ApPackageTooLarge (PredefinedName, SubPackageOp,
634272444Sjkim                    Count, ExpectedCount);
635272444Sjkim                break;
636272444Sjkim            }
637246847Sjkim
638246847Sjkim            ApCheckPackageElements (PredefinedName, Op,
639246847Sjkim                Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
640246847Sjkim                Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
641246847Sjkim            break;
642246847Sjkim
643246847Sjkim        case ACPI_PTYPE2_FIX_VAR:
644246847Sjkim            /*
645246847Sjkim             * Each subpackage has a fixed number of elements and an
646246847Sjkim             * optional element
647246847Sjkim             */
648246847Sjkim            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
649246847Sjkim            if (Count < ExpectedCount)
650246847Sjkim            {
651246847Sjkim                ApPackageTooSmall (PredefinedName, SubPackageOp,
652246847Sjkim                    Count, ExpectedCount);
653246847Sjkim                break;
654246847Sjkim            }
655246847Sjkim
656246847Sjkim            ApCheckPackageElements (PredefinedName, Op,
657246847Sjkim                Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
658246847Sjkim                Package->RetInfo.ObjectType2,
659246847Sjkim                Count - Package->RetInfo.Count1);
660246847Sjkim            break;
661246847Sjkim
662283092Sjkim        case ACPI_PTYPE2_VAR_VAR:
663283092Sjkim            /*
664283092Sjkim             * Must have at least the minimum number elements.
665283092Sjkim             * A zero PkgCount means the number of elements is variable.
666283092Sjkim             */
667283092Sjkim            ExpectedCount = Package->RetInfo4.PkgCount;
668283092Sjkim            if (ExpectedCount && (Count < ExpectedCount))
669283092Sjkim            {
670283092Sjkim                ApPackageTooSmall (PredefinedName, SubPackageOp,
671283092Sjkim                    Count, 1);
672283092Sjkim                break;
673283092Sjkim            }
674283092Sjkim
675283092Sjkim            ApCheckPackageElements (PredefinedName, Op,
676283092Sjkim                Package->RetInfo4.SubObjectTypes,
677283092Sjkim                Package->RetInfo4.PkgCount,
678283092Sjkim                0, 0);
679283092Sjkim            break;
680283092Sjkim
681246847Sjkim        case ACPI_PTYPE2_FIXED:
682246847Sjkim
683272444Sjkim            /* Each subpackage has a fixed length */
684246847Sjkim
685246847Sjkim            ExpectedCount = Package->RetInfo2.Count;
686246847Sjkim            if (Count < ExpectedCount)
687246847Sjkim            {
688246847Sjkim                ApPackageTooSmall (PredefinedName, SubPackageOp,
689246847Sjkim                    Count, ExpectedCount);
690246847Sjkim                break;
691246847Sjkim            }
692272444Sjkim            if (Count > ExpectedCount)
693272444Sjkim            {
694272444Sjkim                ApPackageTooLarge (PredefinedName, SubPackageOp,
695272444Sjkim                    Count, ExpectedCount);
696272444Sjkim                break;
697272444Sjkim            }
698246847Sjkim
699246847Sjkim            /* Check each object/type combination */
700246847Sjkim
701246847Sjkim            for (j = 0; j < ExpectedCount; j++)
702246847Sjkim            {
703246847Sjkim                ApCheckObjectType (PredefinedName, Op,
704246847Sjkim                    Package->RetInfo2.ObjectType[j], j);
705246847Sjkim
706246847Sjkim                Op = Op->Asl.Next;
707246847Sjkim            }
708246847Sjkim            break;
709246847Sjkim
710246847Sjkim        case ACPI_PTYPE2_MIN:
711246847Sjkim
712272444Sjkim            /* Each subpackage has a variable but minimum length */
713246847Sjkim
714246847Sjkim            ExpectedCount = Package->RetInfo.Count1;
715246847Sjkim            if (Count < ExpectedCount)
716246847Sjkim            {
717246847Sjkim                ApPackageTooSmall (PredefinedName, SubPackageOp,
718246847Sjkim                    Count, ExpectedCount);
719246847Sjkim                break;
720246847Sjkim            }
721246847Sjkim
722272444Sjkim            /* Check the type of each subpackage element */
723246847Sjkim
724246847Sjkim            ApCheckPackageElements (PredefinedName, Op,
725246847Sjkim                Package->RetInfo.ObjectType1, Count, 0, 0);
726246847Sjkim            break;
727246847Sjkim
728246847Sjkim        case ACPI_PTYPE2_COUNT:
729246847Sjkim            /*
730246847Sjkim             * First element is the (Integer) count of elements, including
731246847Sjkim             * the count field (the ACPI name is NumElements)
732246847Sjkim             */
733246847Sjkim            Status = ApCheckObjectType (PredefinedName, Op,
734246847Sjkim                ACPI_RTYPE_INTEGER, 0);
735246847Sjkim
736246847Sjkim            /* We must have an integer count from above (otherwise, use Count) */
737246847Sjkim
738246847Sjkim            if (ACPI_SUCCESS (Status))
739246847Sjkim            {
740246847Sjkim                /*
741246847Sjkim                 * Make sure package is large enough for the Count and is
742246847Sjkim                 * is as large as the minimum size
743246847Sjkim                 */
744246847Sjkim                ExpectedCount = (UINT32) Op->Asl.Value.Integer;
745246847Sjkim
746246847Sjkim                if (Count < ExpectedCount)
747246847Sjkim                {
748246847Sjkim                    ApPackageTooSmall (PredefinedName, SubPackageOp,
749246847Sjkim                        Count, ExpectedCount);
750246847Sjkim                    break;
751246847Sjkim                }
752246847Sjkim                else if (Count > ExpectedCount)
753246847Sjkim                {
754246847Sjkim                    ApPackageTooLarge (PredefinedName, SubPackageOp,
755246847Sjkim                        Count, ExpectedCount);
756246847Sjkim                }
757246847Sjkim
758246847Sjkim                /* Some names of this type have a minimum length */
759246847Sjkim
760246847Sjkim                if (Count < Package->RetInfo.Count1)
761246847Sjkim                {
762246847Sjkim                    ExpectedCount = Package->RetInfo.Count1;
763246847Sjkim                    ApPackageTooSmall (PredefinedName, SubPackageOp,
764246847Sjkim                        Count, ExpectedCount);
765246847Sjkim                    break;
766246847Sjkim                }
767246847Sjkim
768246847Sjkim                Count = ExpectedCount;
769246847Sjkim            }
770246847Sjkim
771272444Sjkim            /* Check the type of each subpackage element */
772246847Sjkim
773246847Sjkim            Op = Op->Asl.Next;
774246847Sjkim            ApCheckPackageElements (PredefinedName, Op,
775246847Sjkim                Package->RetInfo.ObjectType1, (Count - 1), 0, 0);
776246847Sjkim            break;
777246847Sjkim
778246847Sjkim        default:
779246847Sjkim            break;
780246847Sjkim        }
781246847Sjkim
782246847SjkimNextSubpackage:
783246847Sjkim        SubPackageOp = SubPackageOp->Asl.Next;
784246847Sjkim    }
785246847Sjkim}
786246847Sjkim
787246847Sjkim
788246847Sjkim/*******************************************************************************
789246847Sjkim *
790246847Sjkim * FUNCTION:    ApPackageTooSmall
791246847Sjkim *
792246847Sjkim * PARAMETERS:  PredefinedName      - Name of the predefined object
793246847Sjkim *              Op                  - Current parser op
794246847Sjkim *              Count               - Actual package element count
795246847Sjkim *              ExpectedCount       - Expected package element count
796246847Sjkim *
797246847Sjkim * RETURN:      None
798246847Sjkim *
799246847Sjkim * DESCRIPTION: Issue error message for a package that is smaller than
800246847Sjkim *              required.
801246847Sjkim *
802246847Sjkim ******************************************************************************/
803246847Sjkim
804246847Sjkimstatic void
805246847SjkimApPackageTooSmall (
806246847Sjkim    const char                  *PredefinedName,
807246847Sjkim    ACPI_PARSE_OBJECT           *Op,
808246847Sjkim    UINT32                      Count,
809246847Sjkim    UINT32                      ExpectedCount)
810246847Sjkim{
811246847Sjkim
812246847Sjkim    sprintf (MsgBuffer, "%s: length %u, required minimum is %u",
813246847Sjkim        PredefinedName, Count, ExpectedCount);
814246847Sjkim
815246847Sjkim    AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
816246847Sjkim}
817246847Sjkim
818246847Sjkim
819246847Sjkim/*******************************************************************************
820246847Sjkim *
821246847Sjkim * FUNCTION:    ApZeroLengthPackage
822246847Sjkim *
823246847Sjkim * PARAMETERS:  PredefinedName      - Name of the predefined object
824246847Sjkim *              Op                  - Current parser op
825246847Sjkim *
826246847Sjkim * RETURN:      None
827246847Sjkim *
828246847Sjkim * DESCRIPTION: Issue error message for a zero-length package (a package that
829246847Sjkim *              is required to have a non-zero length). Variable length
830246847Sjkim *              packages seem to be allowed to have zero length, however.
831246847Sjkim *              Even if not allowed, BIOS code does it.
832246847Sjkim *
833246847Sjkim ******************************************************************************/
834246847Sjkim
835246847Sjkimstatic void
836246847SjkimApZeroLengthPackage (
837246847Sjkim    const char                  *PredefinedName,
838246847Sjkim    ACPI_PARSE_OBJECT           *Op)
839246847Sjkim{
840246847Sjkim
841246847Sjkim    sprintf (MsgBuffer, "%s: length is zero", PredefinedName);
842246847Sjkim
843246847Sjkim    AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
844246847Sjkim}
845246847Sjkim
846246847Sjkim
847246847Sjkim/*******************************************************************************
848246847Sjkim *
849246847Sjkim * FUNCTION:    ApPackageTooLarge
850246847Sjkim *
851246847Sjkim * PARAMETERS:  PredefinedName      - Name of the predefined object
852246847Sjkim *              Op                  - Current parser op
853246847Sjkim *              Count               - Actual package element count
854246847Sjkim *              ExpectedCount       - Expected package element count
855246847Sjkim *
856246847Sjkim * RETURN:      None
857246847Sjkim *
858246847Sjkim * DESCRIPTION: Issue a remark for a package that is larger than expected.
859246847Sjkim *
860246847Sjkim ******************************************************************************/
861246847Sjkim
862246847Sjkimstatic void
863246847SjkimApPackageTooLarge (
864246847Sjkim    const char                  *PredefinedName,
865246847Sjkim    ACPI_PARSE_OBJECT           *Op,
866246847Sjkim    UINT32                      Count,
867246847Sjkim    UINT32                      ExpectedCount)
868246847Sjkim{
869246847Sjkim
870246847Sjkim    sprintf (MsgBuffer, "%s: length is %u, only %u required",
871246847Sjkim        PredefinedName, Count, ExpectedCount);
872246847Sjkim
873246847Sjkim    AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
874246847Sjkim}
875