aslprepkg.c revision 246847
1/******************************************************************************
2 *
3 * Module Name: aslprepkg - support for ACPI predefined name package objects
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include "aslcompiler.h"
45#include "aslcompiler.y.h"
46#include "acpredef.h"
47
48
49#define _COMPONENT          ACPI_COMPILER
50        ACPI_MODULE_NAME    ("aslprepkg")
51
52
53/* Local prototypes */
54
55static void
56ApCheckPackageElements (
57    const char              *PredefinedName,
58    ACPI_PARSE_OBJECT       *Op,
59    UINT8                   Type1,
60    UINT32                  Count1,
61    UINT8                   Type2,
62    UINT32                  Count2);
63
64static void
65ApCheckPackageList (
66    const char                  *PredefinedName,
67    ACPI_PARSE_OBJECT           *ParentOp,
68    const ACPI_PREDEFINED_INFO  *Package,
69    UINT32                      StartIndex,
70    UINT32                      Count);
71
72static void
73ApPackageTooSmall (
74    const char                  *PredefinedName,
75    ACPI_PARSE_OBJECT           *Op,
76    UINT32                      Count,
77    UINT32                      ExpectedCount);
78
79static void
80ApZeroLengthPackage (
81    const char                  *PredefinedName,
82    ACPI_PARSE_OBJECT           *Op);
83
84static void
85ApPackageTooLarge (
86    const char                  *PredefinedName,
87    ACPI_PARSE_OBJECT           *Op,
88    UINT32                      Count,
89    UINT32                      ExpectedCount);
90
91
92/*******************************************************************************
93 *
94 * FUNCTION:    ApCheckPackage
95 *
96 * PARAMETERS:  ParentOp        - Parser op for the package
97 *              Predefined      - Pointer to package-specific info for method
98 *
99 * RETURN:      None
100 *
101 * DESCRIPTION: Top-level validation for predefined name return package
102 *              objects.
103 *
104 ******************************************************************************/
105
106void
107ApCheckPackage (
108    ACPI_PARSE_OBJECT           *ParentOp,
109    const ACPI_PREDEFINED_INFO  *Predefined)
110{
111    ACPI_PARSE_OBJECT           *Op;
112    const ACPI_PREDEFINED_INFO  *Package;
113    ACPI_STATUS                 Status;
114    UINT32                      ExpectedCount;
115    UINT32                      Count;
116    UINT32                      i;
117
118
119    /* The package info for this name is in the next table entry */
120
121    Package = Predefined + 1;
122
123    /* First child is the package length */
124
125    Op = ParentOp->Asl.Child;
126    Count = (UINT32) Op->Asl.Value.Integer;
127
128    /*
129     * Most packages must have at least one element. The only exception
130     * is the variable-length package (ACPI_PTYPE1_VAR).
131     */
132    if (!Count)
133    {
134        if (Package->RetInfo.Type != ACPI_PTYPE1_VAR)
135        {
136            ApZeroLengthPackage (Predefined->Info.Name, ParentOp);
137        }
138        return;
139    }
140
141    /* Get the first element of the package */
142
143    Op = Op->Asl.Next;
144
145    /* Decode the package type */
146
147    switch (Package->RetInfo.Type)
148    {
149    case ACPI_PTYPE1_FIXED:
150        /*
151         * The package count is fixed and there are no sub-packages
152         *
153         * If package is too small, exit.
154         * If package is larger than expected, issue warning but continue
155         */
156        ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
157        if (Count < ExpectedCount)
158        {
159            goto PackageTooSmall;
160        }
161        else if (Count > ExpectedCount)
162        {
163            ApPackageTooLarge (Predefined->Info.Name, ParentOp,
164                Count, ExpectedCount);
165        }
166
167        /* Validate all elements of the package */
168
169        ApCheckPackageElements (Predefined->Info.Name, Op,
170            Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
171            Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
172        break;
173
174    case ACPI_PTYPE1_VAR:
175        /*
176         * The package count is variable, there are no sub-packages, and all
177         * elements must be of the same type
178         */
179        for (i = 0; i < Count; i++)
180        {
181            ApCheckObjectType (Predefined->Info.Name, Op,
182                Package->RetInfo.ObjectType1, i);
183            Op = Op->Asl.Next;
184        }
185        break;
186
187    case ACPI_PTYPE1_OPTION:
188        /*
189         * The package count is variable, there are no sub-packages. There are
190         * a fixed number of required elements, and a variable number of
191         * optional elements.
192         *
193         * Check if package is at least as large as the minimum required
194         */
195        ExpectedCount = Package->RetInfo3.Count;
196        if (Count < ExpectedCount)
197        {
198            goto PackageTooSmall;
199        }
200
201        /* Variable number of sub-objects */
202
203        for (i = 0; i < Count; i++)
204        {
205            if (i < Package->RetInfo3.Count)
206            {
207                /* These are the required package elements (0, 1, or 2) */
208
209                ApCheckObjectType (Predefined->Info.Name, Op,
210                    Package->RetInfo3.ObjectType[i], i);
211            }
212            else
213            {
214                /* These are the optional package elements */
215
216                ApCheckObjectType (Predefined->Info.Name, Op,
217                    Package->RetInfo3.TailObjectType, i);
218            }
219            Op = Op->Asl.Next;
220        }
221        break;
222
223    case ACPI_PTYPE2_REV_FIXED:
224
225        /* First element is the (Integer) revision */
226
227        ApCheckObjectType (Predefined->Info.Name, Op,
228            ACPI_RTYPE_INTEGER, 0);
229
230        Op = Op->Asl.Next;
231        Count--;
232
233        /* Examine the sub-packages */
234
235        ApCheckPackageList (Predefined->Info.Name, Op,
236            Package, 1, Count);
237        break;
238
239    case ACPI_PTYPE2_PKG_COUNT:
240
241        /* First element is the (Integer) count of sub-packages to follow */
242
243        Status = ApCheckObjectType (Predefined->Info.Name, Op,
244            ACPI_RTYPE_INTEGER, 0);
245
246        /* We must have an integer count from above (otherwise, use Count) */
247
248        if (ACPI_SUCCESS (Status))
249        {
250            /*
251             * Count cannot be larger than the parent package length, but allow it
252             * to be smaller. The >= accounts for the Integer above.
253             */
254            ExpectedCount = (UINT32) Op->Asl.Value.Integer;
255            if (ExpectedCount >= Count)
256            {
257                goto PackageTooSmall;
258            }
259
260            Count = ExpectedCount;
261        }
262
263        Op = Op->Asl.Next;
264
265        /* Examine the sub-packages */
266
267        ApCheckPackageList (Predefined->Info.Name, Op,
268            Package, 1, Count);
269        break;
270
271    case ACPI_PTYPE2:
272    case ACPI_PTYPE2_FIXED:
273    case ACPI_PTYPE2_MIN:
274    case ACPI_PTYPE2_COUNT:
275    case ACPI_PTYPE2_FIX_VAR:
276        /*
277         * These types all return a single Package that consists of a
278         * variable number of sub-Packages.
279         */
280
281        /* Examine the sub-packages */
282
283        ApCheckPackageList (Predefined->Info.Name, Op,
284            Package, 0, Count);
285        break;
286
287    default:
288        return;
289    }
290
291    return;
292
293PackageTooSmall:
294    ApPackageTooSmall (Predefined->Info.Name, ParentOp,
295        Count, ExpectedCount);
296}
297
298
299/*******************************************************************************
300 *
301 * FUNCTION:    ApCheckPackageElements
302 *
303 * PARAMETERS:  PredefinedName  - Pointer to validation data structure
304 *              Op              - Parser op for the package
305 *              Type1           - Object type for first group
306 *              Count1          - Count for first group
307 *              Type2           - Object type for second group
308 *              Count2          - Count for second group
309 *
310 * RETURN:      None
311 *
312 * DESCRIPTION: Validate all elements of a package. Works with packages that
313 *              are defined to contain up to two groups of different object
314 *              types.
315 *
316 ******************************************************************************/
317
318static void
319ApCheckPackageElements (
320    const char              *PredefinedName,
321    ACPI_PARSE_OBJECT       *Op,
322    UINT8                   Type1,
323    UINT32                  Count1,
324    UINT8                   Type2,
325    UINT32                  Count2)
326{
327    UINT32                  i;
328
329
330    /*
331     * Up to two groups of package elements are supported by the data
332     * structure. All elements in each group must be of the same type.
333     * The second group can have a count of zero.
334     *
335     * Aborts check upon a NULL package element, as this means (at compile
336     * time) that the remainder of the package elements are also NULL
337     * (This is the only way to create NULL package elements.)
338     */
339    for (i = 0; (i < Count1) && Op; i++)
340    {
341        ApCheckObjectType (PredefinedName, Op, Type1, i);
342        Op = Op->Asl.Next;
343    }
344
345    for (i = 0; (i < Count2) && Op; i++)
346    {
347        ApCheckObjectType (PredefinedName, Op, Type2, (i + Count1));
348        Op = Op->Asl.Next;
349    }
350}
351
352
353/*******************************************************************************
354 *
355 * FUNCTION:    ApCheckPackageList
356 *
357 * PARAMETERS:  PredefinedName      - Name of the predefined object
358 *              ParentOp            - Parser op of the parent package
359 *              Package             - Package info for this predefined name
360 *              StartIndex          - Index in parent package where list begins
361 *              ParentCount         - Element count of parent package
362 *
363 * RETURN:      None
364 *
365 * DESCRIPTION: Validate the individual package elements for a predefined name.
366 *              Handles the cases where the predefined name is defined as a
367 *              Package of Packages (subpackages). These are the types:
368 *
369 *              ACPI_PTYPE2
370 *              ACPI_PTYPE2_FIXED
371 *              ACPI_PTYPE2_MIN
372 *              ACPI_PTYPE2_COUNT
373 *              ACPI_PTYPE2_FIX_VAR
374 *
375 ******************************************************************************/
376
377static void
378ApCheckPackageList (
379    const char                  *PredefinedName,
380    ACPI_PARSE_OBJECT           *ParentOp,
381    const ACPI_PREDEFINED_INFO  *Package,
382    UINT32                      StartIndex,
383    UINT32                      ParentCount)
384{
385    ACPI_PARSE_OBJECT           *SubPackageOp = ParentOp;
386    ACPI_PARSE_OBJECT           *Op;
387    ACPI_STATUS                 Status;
388    UINT32                      Count;
389    UINT32                      ExpectedCount;
390    UINT32                      i;
391    UINT32                      j;
392
393
394    /*
395     * Validate each subpackage in the parent Package
396     *
397     * Note: We ignore NULL package elements on the assumption that
398     * they will be initialized by the BIOS or other ASL code.
399     */
400    for (i = 0; (i < ParentCount) && SubPackageOp; i++)
401    {
402        /* Each object in the list must be of type Package */
403
404        Status = ApCheckObjectType (PredefinedName, SubPackageOp,
405            ACPI_RTYPE_PACKAGE, i + StartIndex);
406        if (ACPI_FAILURE (Status))
407        {
408            goto NextSubpackage;
409        }
410
411        /* Examine the different types of expected subpackages */
412
413        Op = SubPackageOp->Asl.Child;
414
415        /* First child is the package length */
416
417        Count = (UINT32) Op->Asl.Value.Integer;
418        Op = Op->Asl.Next;
419
420        /* The subpackage must have at least one element */
421
422        if (!Count)
423        {
424            ApZeroLengthPackage (PredefinedName, SubPackageOp);
425            goto NextSubpackage;
426        }
427
428        /*
429         * Decode the package type.
430         * PTYPE2 indicates that a "package of packages" is expected for
431         * this name. The various flavors of PTYPE2 indicate the number
432         * and format of the subpackages.
433         */
434        switch (Package->RetInfo.Type)
435        {
436        case ACPI_PTYPE2:
437        case ACPI_PTYPE2_PKG_COUNT:
438        case ACPI_PTYPE2_REV_FIXED:
439
440            /* Each subpackage has a fixed number of elements */
441
442            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
443            if (Count < ExpectedCount)
444            {
445                ApPackageTooSmall (PredefinedName, SubPackageOp,
446                    Count, ExpectedCount);
447                break;
448            }
449
450            ApCheckPackageElements (PredefinedName, Op,
451                Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
452                Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
453            break;
454
455        case ACPI_PTYPE2_FIX_VAR:
456            /*
457             * Each subpackage has a fixed number of elements and an
458             * optional element
459             */
460            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
461            if (Count < ExpectedCount)
462            {
463                ApPackageTooSmall (PredefinedName, SubPackageOp,
464                    Count, ExpectedCount);
465                break;
466            }
467
468            ApCheckPackageElements (PredefinedName, Op,
469                Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
470                Package->RetInfo.ObjectType2,
471                Count - Package->RetInfo.Count1);
472            break;
473
474        case ACPI_PTYPE2_FIXED:
475
476            /* Each sub-package has a fixed length */
477
478            ExpectedCount = Package->RetInfo2.Count;
479            if (Count < ExpectedCount)
480            {
481                ApPackageTooSmall (PredefinedName, SubPackageOp,
482                    Count, ExpectedCount);
483                break;
484            }
485
486            /* Check each object/type combination */
487
488            for (j = 0; j < ExpectedCount; j++)
489            {
490                ApCheckObjectType (PredefinedName, Op,
491                    Package->RetInfo2.ObjectType[j], j);
492
493                Op = Op->Asl.Next;
494            }
495            break;
496
497        case ACPI_PTYPE2_MIN:
498
499            /* Each sub-package has a variable but minimum length */
500
501            ExpectedCount = Package->RetInfo.Count1;
502            if (Count < ExpectedCount)
503            {
504                ApPackageTooSmall (PredefinedName, SubPackageOp,
505                    Count, ExpectedCount);
506                break;
507            }
508
509            /* Check the type of each sub-package element */
510
511            ApCheckPackageElements (PredefinedName, Op,
512                Package->RetInfo.ObjectType1, Count, 0, 0);
513            break;
514
515        case ACPI_PTYPE2_COUNT:
516            /*
517             * First element is the (Integer) count of elements, including
518             * the count field (the ACPI name is NumElements)
519             */
520            Status = ApCheckObjectType (PredefinedName, Op,
521                ACPI_RTYPE_INTEGER, 0);
522
523            /* We must have an integer count from above (otherwise, use Count) */
524
525            if (ACPI_SUCCESS (Status))
526            {
527                /*
528                 * Make sure package is large enough for the Count and is
529                 * is as large as the minimum size
530                 */
531                ExpectedCount = (UINT32) Op->Asl.Value.Integer;
532
533                if (Count < ExpectedCount)
534                {
535                    ApPackageTooSmall (PredefinedName, SubPackageOp,
536                        Count, ExpectedCount);
537                    break;
538                }
539                else if (Count > ExpectedCount)
540                {
541                    ApPackageTooLarge (PredefinedName, SubPackageOp,
542                        Count, ExpectedCount);
543                }
544
545                /* Some names of this type have a minimum length */
546
547                if (Count < Package->RetInfo.Count1)
548                {
549                    ExpectedCount = Package->RetInfo.Count1;
550                    ApPackageTooSmall (PredefinedName, SubPackageOp,
551                        Count, ExpectedCount);
552                    break;
553                }
554
555                Count = ExpectedCount;
556            }
557
558            /* Check the type of each sub-package element */
559
560            Op = Op->Asl.Next;
561            ApCheckPackageElements (PredefinedName, Op,
562                Package->RetInfo.ObjectType1, (Count - 1), 0, 0);
563            break;
564
565        default:
566            break;
567        }
568
569NextSubpackage:
570        SubPackageOp = SubPackageOp->Asl.Next;
571    }
572}
573
574
575/*******************************************************************************
576 *
577 * FUNCTION:    ApPackageTooSmall
578 *
579 * PARAMETERS:  PredefinedName      - Name of the predefined object
580 *              Op                  - Current parser op
581 *              Count               - Actual package element count
582 *              ExpectedCount       - Expected package element count
583 *
584 * RETURN:      None
585 *
586 * DESCRIPTION: Issue error message for a package that is smaller than
587 *              required.
588 *
589 ******************************************************************************/
590
591static void
592ApPackageTooSmall (
593    const char                  *PredefinedName,
594    ACPI_PARSE_OBJECT           *Op,
595    UINT32                      Count,
596    UINT32                      ExpectedCount)
597{
598
599    sprintf (MsgBuffer, "%s: length %u, required minimum is %u",
600        PredefinedName, Count, ExpectedCount);
601
602    AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
603}
604
605
606/*******************************************************************************
607 *
608 * FUNCTION:    ApZeroLengthPackage
609 *
610 * PARAMETERS:  PredefinedName      - Name of the predefined object
611 *              Op                  - Current parser op
612 *
613 * RETURN:      None
614 *
615 * DESCRIPTION: Issue error message for a zero-length package (a package that
616 *              is required to have a non-zero length). Variable length
617 *              packages seem to be allowed to have zero length, however.
618 *              Even if not allowed, BIOS code does it.
619 *
620 ******************************************************************************/
621
622static void
623ApZeroLengthPackage (
624    const char                  *PredefinedName,
625    ACPI_PARSE_OBJECT           *Op)
626{
627
628    sprintf (MsgBuffer, "%s: length is zero", PredefinedName);
629
630    AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
631}
632
633
634/*******************************************************************************
635 *
636 * FUNCTION:    ApPackageTooLarge
637 *
638 * PARAMETERS:  PredefinedName      - Name of the predefined object
639 *              Op                  - Current parser op
640 *              Count               - Actual package element count
641 *              ExpectedCount       - Expected package element count
642 *
643 * RETURN:      None
644 *
645 * DESCRIPTION: Issue a remark for a package that is larger than expected.
646 *
647 ******************************************************************************/
648
649static void
650ApPackageTooLarge (
651    const char                  *PredefinedName,
652    ACPI_PARSE_OBJECT           *Op,
653    UINT32                      Count,
654    UINT32                      ExpectedCount)
655{
656
657    sprintf (MsgBuffer, "%s: length is %u, only %u required",
658        PredefinedName, Count, ExpectedCount);
659
660    AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
661}
662