aslprepkg.c revision 256281
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 <contrib/dev/acpica/compiler/aslcompiler.h>
45#include "aslcompiler.y.h"
46#include <contrib/dev/acpica/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
98 *                                    the method
99 *
100 * RETURN:      None
101 *
102 * DESCRIPTION: Top-level validation for predefined name return package
103 *              objects.
104 *
105 ******************************************************************************/
106
107void
108ApCheckPackage (
109    ACPI_PARSE_OBJECT           *ParentOp,
110    const ACPI_PREDEFINED_INFO  *Predefined)
111{
112    ACPI_PARSE_OBJECT           *Op;
113    const ACPI_PREDEFINED_INFO  *Package;
114    ACPI_STATUS                 Status;
115    UINT32                      ExpectedCount;
116    UINT32                      Count;
117    UINT32                      i;
118
119
120    /* The package info for this name is in the next table entry */
121
122    Package = Predefined + 1;
123
124    /* First child is the package length */
125
126    Op = ParentOp->Asl.Child;
127    Count = (UINT32) Op->Asl.Value.Integer;
128
129    /*
130     * Many of the variable-length top-level packages are allowed to simply
131     * have zero elements. This allows the BIOS to tell the host that even
132     * though the predefined name/method exists, the feature is not supported.
133     * Other package types require one or more elements. In any case, there
134     * is no need to continue validation.
135     */
136    if (!Count)
137    {
138        switch (Package->RetInfo.Type)
139        {
140        case ACPI_PTYPE1_FIXED:
141        case ACPI_PTYPE1_OPTION:
142        case ACPI_PTYPE2_PKG_COUNT:
143        case ACPI_PTYPE2_REV_FIXED:
144
145            ApZeroLengthPackage (Predefined->Info.Name, ParentOp);
146            break;
147
148        case ACPI_PTYPE1_VAR:
149        case ACPI_PTYPE2:
150        case ACPI_PTYPE2_COUNT:
151        case ACPI_PTYPE2_FIXED:
152        case ACPI_PTYPE2_MIN:
153        case ACPI_PTYPE2_FIX_VAR:
154        default:
155
156            break;
157        }
158
159        return;
160    }
161
162    /* Get the first element of the package */
163
164    Op = Op->Asl.Next;
165
166    /* Decode the package type */
167
168    switch (Package->RetInfo.Type)
169    {
170    case ACPI_PTYPE1_FIXED:
171        /*
172         * The package count is fixed and there are no sub-packages
173         *
174         * If package is too small, exit.
175         * If package is larger than expected, issue warning but continue
176         */
177        ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
178        if (Count < ExpectedCount)
179        {
180            goto PackageTooSmall;
181        }
182        else if (Count > ExpectedCount)
183        {
184            ApPackageTooLarge (Predefined->Info.Name, ParentOp,
185                Count, ExpectedCount);
186        }
187
188        /* Validate all elements of the package */
189
190        ApCheckPackageElements (Predefined->Info.Name, Op,
191            Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
192            Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
193        break;
194
195    case ACPI_PTYPE1_VAR:
196        /*
197         * The package count is variable, there are no sub-packages,
198         * and all elements must be of the same type
199         */
200        for (i = 0; i < Count; i++)
201        {
202            ApCheckObjectType (Predefined->Info.Name, Op,
203                Package->RetInfo.ObjectType1, i);
204            Op = Op->Asl.Next;
205        }
206        break;
207
208    case ACPI_PTYPE1_OPTION:
209        /*
210         * The package count is variable, there are no sub-packages.
211         * There are a fixed number of required elements, and a variable
212         * number of optional elements.
213         *
214         * Check if package is at least as large as the minimum required
215         */
216        ExpectedCount = Package->RetInfo3.Count;
217        if (Count < ExpectedCount)
218        {
219            goto PackageTooSmall;
220        }
221
222        /* Variable number of sub-objects */
223
224        for (i = 0; i < Count; i++)
225        {
226            if (i < Package->RetInfo3.Count)
227            {
228                /* These are the required package elements (0, 1, or 2) */
229
230                ApCheckObjectType (Predefined->Info.Name, Op,
231                    Package->RetInfo3.ObjectType[i], i);
232            }
233            else
234            {
235                /* These are the optional package elements */
236
237                ApCheckObjectType (Predefined->Info.Name, Op,
238                    Package->RetInfo3.TailObjectType, i);
239            }
240            Op = Op->Asl.Next;
241        }
242        break;
243
244    case ACPI_PTYPE2_REV_FIXED:
245
246        /* First element is the (Integer) revision */
247
248        ApCheckObjectType (Predefined->Info.Name, Op,
249            ACPI_RTYPE_INTEGER, 0);
250
251        Op = Op->Asl.Next;
252        Count--;
253
254        /* Examine the sub-packages */
255
256        ApCheckPackageList (Predefined->Info.Name, Op,
257            Package, 1, Count);
258        break;
259
260    case ACPI_PTYPE2_PKG_COUNT:
261
262        /* First element is the (Integer) count of sub-packages to follow */
263
264        Status = ApCheckObjectType (Predefined->Info.Name, Op,
265            ACPI_RTYPE_INTEGER, 0);
266
267        /* We must have an integer count from above (otherwise, use Count) */
268
269        if (ACPI_SUCCESS (Status))
270        {
271            /*
272             * Count cannot be larger than the parent package length, but
273             * allow it to be smaller. The >= accounts for the Integer above.
274             */
275            ExpectedCount = (UINT32) Op->Asl.Value.Integer;
276            if (ExpectedCount >= Count)
277            {
278                goto PackageTooSmall;
279            }
280
281            Count = ExpectedCount;
282        }
283
284        Op = Op->Asl.Next;
285
286        /* Examine the sub-packages */
287
288        ApCheckPackageList (Predefined->Info.Name, Op,
289            Package, 1, Count);
290        break;
291
292    case ACPI_PTYPE2:
293    case ACPI_PTYPE2_FIXED:
294    case ACPI_PTYPE2_MIN:
295    case ACPI_PTYPE2_COUNT:
296    case ACPI_PTYPE2_FIX_VAR:
297        /*
298         * These types all return a single Package that consists of a
299         * variable number of sub-Packages.
300         */
301
302        /* Examine the sub-packages */
303
304        ApCheckPackageList (Predefined->Info.Name, Op,
305            Package, 0, Count);
306        break;
307
308    default:
309        return;
310    }
311
312    return;
313
314PackageTooSmall:
315    ApPackageTooSmall (Predefined->Info.Name, ParentOp,
316        Count, ExpectedCount);
317}
318
319
320/*******************************************************************************
321 *
322 * FUNCTION:    ApCheckPackageElements
323 *
324 * PARAMETERS:  PredefinedName      - Name of the predefined object
325 *              Op                  - Parser op for the package
326 *              Type1               - Object type for first group
327 *              Count1              - Count for first group
328 *              Type2               - Object type for second group
329 *              Count2              - Count for second group
330 *
331 * RETURN:      None
332 *
333 * DESCRIPTION: Validate all elements of a package. Works with packages that
334 *              are defined to contain up to two groups of different object
335 *              types.
336 *
337 ******************************************************************************/
338
339static void
340ApCheckPackageElements (
341    const char              *PredefinedName,
342    ACPI_PARSE_OBJECT       *Op,
343    UINT8                   Type1,
344    UINT32                  Count1,
345    UINT8                   Type2,
346    UINT32                  Count2)
347{
348    UINT32                  i;
349
350
351    /*
352     * Up to two groups of package elements are supported by the data
353     * structure. All elements in each group must be of the same type.
354     * The second group can have a count of zero.
355     *
356     * Aborts check upon a NULL package element, as this means (at compile
357     * time) that the remainder of the package elements are also NULL
358     * (This is the only way to create NULL package elements.)
359     */
360    for (i = 0; (i < Count1) && Op; i++)
361    {
362        ApCheckObjectType (PredefinedName, Op, Type1, i);
363        Op = Op->Asl.Next;
364    }
365
366    for (i = 0; (i < Count2) && Op; i++)
367    {
368        ApCheckObjectType (PredefinedName, Op, Type2, (i + Count1));
369        Op = Op->Asl.Next;
370    }
371}
372
373
374/*******************************************************************************
375 *
376 * FUNCTION:    ApCheckPackageList
377 *
378 * PARAMETERS:  PredefinedName      - Name of the predefined object
379 *              ParentOp            - Parser op of the parent package
380 *              Package             - Package info for this predefined name
381 *              StartIndex          - Index in parent package where list begins
382 *              ParentCount         - Element count of parent package
383 *
384 * RETURN:      None
385 *
386 * DESCRIPTION: Validate the individual package elements for a predefined name.
387 *              Handles the cases where the predefined name is defined as a
388 *              Package of Packages (subpackages). These are the types:
389 *
390 *              ACPI_PTYPE2
391 *              ACPI_PTYPE2_FIXED
392 *              ACPI_PTYPE2_MIN
393 *              ACPI_PTYPE2_COUNT
394 *              ACPI_PTYPE2_FIX_VAR
395 *
396 ******************************************************************************/
397
398static void
399ApCheckPackageList (
400    const char                  *PredefinedName,
401    ACPI_PARSE_OBJECT           *ParentOp,
402    const ACPI_PREDEFINED_INFO  *Package,
403    UINT32                      StartIndex,
404    UINT32                      ParentCount)
405{
406    ACPI_PARSE_OBJECT           *SubPackageOp = ParentOp;
407    ACPI_PARSE_OBJECT           *Op;
408    ACPI_STATUS                 Status;
409    UINT32                      Count;
410    UINT32                      ExpectedCount;
411    UINT32                      i;
412    UINT32                      j;
413
414
415    /*
416     * Validate each subpackage in the parent Package
417     *
418     * Note: We ignore NULL package elements on the assumption that
419     * they will be initialized by the BIOS or other ASL code.
420     */
421    for (i = 0; (i < ParentCount) && SubPackageOp; i++)
422    {
423        /* Each object in the list must be of type Package */
424
425        Status = ApCheckObjectType (PredefinedName, SubPackageOp,
426            ACPI_RTYPE_PACKAGE, i + StartIndex);
427        if (ACPI_FAILURE (Status))
428        {
429            goto NextSubpackage;
430        }
431
432        /* Examine the different types of expected subpackages */
433
434        Op = SubPackageOp->Asl.Child;
435
436        /* First child is the package length */
437
438        Count = (UINT32) Op->Asl.Value.Integer;
439        Op = Op->Asl.Next;
440
441        /* The subpackage must have at least one element */
442
443        if (!Count)
444        {
445            ApZeroLengthPackage (PredefinedName, SubPackageOp);
446            goto NextSubpackage;
447        }
448
449        /*
450         * Decode the package type.
451         * PTYPE2 indicates that a "package of packages" is expected for
452         * this name. The various flavors of PTYPE2 indicate the number
453         * and format of the subpackages.
454         */
455        switch (Package->RetInfo.Type)
456        {
457        case ACPI_PTYPE2:
458        case ACPI_PTYPE2_PKG_COUNT:
459        case ACPI_PTYPE2_REV_FIXED:
460
461            /* Each subpackage has a fixed number of elements */
462
463            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
464            if (Count < ExpectedCount)
465            {
466                ApPackageTooSmall (PredefinedName, SubPackageOp,
467                    Count, ExpectedCount);
468                break;
469            }
470
471            ApCheckPackageElements (PredefinedName, Op,
472                Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
473                Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
474            break;
475
476        case ACPI_PTYPE2_FIX_VAR:
477            /*
478             * Each subpackage has a fixed number of elements and an
479             * optional element
480             */
481            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
482            if (Count < ExpectedCount)
483            {
484                ApPackageTooSmall (PredefinedName, SubPackageOp,
485                    Count, ExpectedCount);
486                break;
487            }
488
489            ApCheckPackageElements (PredefinedName, Op,
490                Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
491                Package->RetInfo.ObjectType2,
492                Count - Package->RetInfo.Count1);
493            break;
494
495        case ACPI_PTYPE2_FIXED:
496
497            /* Each sub-package has a fixed length */
498
499            ExpectedCount = Package->RetInfo2.Count;
500            if (Count < ExpectedCount)
501            {
502                ApPackageTooSmall (PredefinedName, SubPackageOp,
503                    Count, ExpectedCount);
504                break;
505            }
506
507            /* Check each object/type combination */
508
509            for (j = 0; j < ExpectedCount; j++)
510            {
511                ApCheckObjectType (PredefinedName, Op,
512                    Package->RetInfo2.ObjectType[j], j);
513
514                Op = Op->Asl.Next;
515            }
516            break;
517
518        case ACPI_PTYPE2_MIN:
519
520            /* Each sub-package has a variable but minimum length */
521
522            ExpectedCount = Package->RetInfo.Count1;
523            if (Count < ExpectedCount)
524            {
525                ApPackageTooSmall (PredefinedName, SubPackageOp,
526                    Count, ExpectedCount);
527                break;
528            }
529
530            /* Check the type of each sub-package element */
531
532            ApCheckPackageElements (PredefinedName, Op,
533                Package->RetInfo.ObjectType1, Count, 0, 0);
534            break;
535
536        case ACPI_PTYPE2_COUNT:
537            /*
538             * First element is the (Integer) count of elements, including
539             * the count field (the ACPI name is NumElements)
540             */
541            Status = ApCheckObjectType (PredefinedName, Op,
542                ACPI_RTYPE_INTEGER, 0);
543
544            /* We must have an integer count from above (otherwise, use Count) */
545
546            if (ACPI_SUCCESS (Status))
547            {
548                /*
549                 * Make sure package is large enough for the Count and is
550                 * is as large as the minimum size
551                 */
552                ExpectedCount = (UINT32) Op->Asl.Value.Integer;
553
554                if (Count < ExpectedCount)
555                {
556                    ApPackageTooSmall (PredefinedName, SubPackageOp,
557                        Count, ExpectedCount);
558                    break;
559                }
560                else if (Count > ExpectedCount)
561                {
562                    ApPackageTooLarge (PredefinedName, SubPackageOp,
563                        Count, ExpectedCount);
564                }
565
566                /* Some names of this type have a minimum length */
567
568                if (Count < Package->RetInfo.Count1)
569                {
570                    ExpectedCount = Package->RetInfo.Count1;
571                    ApPackageTooSmall (PredefinedName, SubPackageOp,
572                        Count, ExpectedCount);
573                    break;
574                }
575
576                Count = ExpectedCount;
577            }
578
579            /* Check the type of each sub-package element */
580
581            Op = Op->Asl.Next;
582            ApCheckPackageElements (PredefinedName, Op,
583                Package->RetInfo.ObjectType1, (Count - 1), 0, 0);
584            break;
585
586        default:
587            break;
588        }
589
590NextSubpackage:
591        SubPackageOp = SubPackageOp->Asl.Next;
592    }
593}
594
595
596/*******************************************************************************
597 *
598 * FUNCTION:    ApPackageTooSmall
599 *
600 * PARAMETERS:  PredefinedName      - Name of the predefined object
601 *              Op                  - Current parser op
602 *              Count               - Actual package element count
603 *              ExpectedCount       - Expected package element count
604 *
605 * RETURN:      None
606 *
607 * DESCRIPTION: Issue error message for a package that is smaller than
608 *              required.
609 *
610 ******************************************************************************/
611
612static void
613ApPackageTooSmall (
614    const char                  *PredefinedName,
615    ACPI_PARSE_OBJECT           *Op,
616    UINT32                      Count,
617    UINT32                      ExpectedCount)
618{
619
620    sprintf (MsgBuffer, "%s: length %u, required minimum is %u",
621        PredefinedName, Count, ExpectedCount);
622
623    AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
624}
625
626
627/*******************************************************************************
628 *
629 * FUNCTION:    ApZeroLengthPackage
630 *
631 * PARAMETERS:  PredefinedName      - Name of the predefined object
632 *              Op                  - Current parser op
633 *
634 * RETURN:      None
635 *
636 * DESCRIPTION: Issue error message for a zero-length package (a package that
637 *              is required to have a non-zero length). Variable length
638 *              packages seem to be allowed to have zero length, however.
639 *              Even if not allowed, BIOS code does it.
640 *
641 ******************************************************************************/
642
643static void
644ApZeroLengthPackage (
645    const char                  *PredefinedName,
646    ACPI_PARSE_OBJECT           *Op)
647{
648
649    sprintf (MsgBuffer, "%s: length is zero", PredefinedName);
650
651    AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
652}
653
654
655/*******************************************************************************
656 *
657 * FUNCTION:    ApPackageTooLarge
658 *
659 * PARAMETERS:  PredefinedName      - Name of the predefined object
660 *              Op                  - Current parser op
661 *              Count               - Actual package element count
662 *              ExpectedCount       - Expected package element count
663 *
664 * RETURN:      None
665 *
666 * DESCRIPTION: Issue a remark for a package that is larger than expected.
667 *
668 ******************************************************************************/
669
670static void
671ApPackageTooLarge (
672    const char                  *PredefinedName,
673    ACPI_PARSE_OBJECT           *Op,
674    UINT32                      Count,
675    UINT32                      ExpectedCount)
676{
677
678    sprintf (MsgBuffer, "%s: length is %u, only %u required",
679        PredefinedName, Count, ExpectedCount);
680
681    AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
682}
683