aslprepkg.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: aslprepkg - support for ACPI predefined name package objects
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, 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 subpackages
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 subpackages,
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 subpackages.
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 subpackages */
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 subpackages 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 subpackages */
287
288        ApCheckPackageList (Predefined->Info.Name, Op,
289            Package, 1, Count);
290        break;
291
292    case ACPI_PTYPE2_UUID_PAIR:
293
294        /* The package contains a variable list of UUID Buffer/Package pairs */
295
296        /* The length of the package must be even */
297
298        if (Count & 1)
299        {
300            sprintf (MsgBuffer, "%4.4s: Package length, %d, must be even.",
301                Predefined->Info.Name, Count);
302
303            AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH,
304                ParentOp->Asl.Child, MsgBuffer);
305        }
306
307        /* Validate the alternating types */
308
309        for (i = 0; i < Count; ++i)
310        {
311            if (i & 1)
312            {
313                ApCheckObjectType (Predefined->Info.Name, Op,
314                    Package->RetInfo.ObjectType2, i);
315            }
316            else
317            {
318                ApCheckObjectType (Predefined->Info.Name, Op,
319                    Package->RetInfo.ObjectType1, i);
320            }
321
322            Op = Op->Asl.Next;
323        }
324
325        break;
326
327    case ACPI_PTYPE2:
328    case ACPI_PTYPE2_FIXED:
329    case ACPI_PTYPE2_MIN:
330    case ACPI_PTYPE2_COUNT:
331    case ACPI_PTYPE2_FIX_VAR:
332        /*
333         * These types all return a single Package that consists of a
334         * variable number of subpackages.
335         */
336
337        /* Examine the subpackages */
338
339        ApCheckPackageList (Predefined->Info.Name, Op,
340            Package, 0, Count);
341        break;
342
343    default:
344        return;
345    }
346
347    return;
348
349PackageTooSmall:
350    ApPackageTooSmall (Predefined->Info.Name, ParentOp,
351        Count, ExpectedCount);
352}
353
354
355/*******************************************************************************
356 *
357 * FUNCTION:    ApCheckPackageElements
358 *
359 * PARAMETERS:  PredefinedName      - Name of the predefined object
360 *              Op                  - Parser op for the package
361 *              Type1               - Object type for first group
362 *              Count1              - Count for first group
363 *              Type2               - Object type for second group
364 *              Count2              - Count for second group
365 *
366 * RETURN:      None
367 *
368 * DESCRIPTION: Validate all elements of a package. Works with packages that
369 *              are defined to contain up to two groups of different object
370 *              types.
371 *
372 ******************************************************************************/
373
374static void
375ApCheckPackageElements (
376    const char              *PredefinedName,
377    ACPI_PARSE_OBJECT       *Op,
378    UINT8                   Type1,
379    UINT32                  Count1,
380    UINT8                   Type2,
381    UINT32                  Count2)
382{
383    UINT32                  i;
384
385
386    /*
387     * Up to two groups of package elements are supported by the data
388     * structure. All elements in each group must be of the same type.
389     * The second group can have a count of zero.
390     *
391     * Aborts check upon a NULL package element, as this means (at compile
392     * time) that the remainder of the package elements are also NULL
393     * (This is the only way to create NULL package elements.)
394     */
395    for (i = 0; (i < Count1) && Op; i++)
396    {
397        ApCheckObjectType (PredefinedName, Op, Type1, i);
398        Op = Op->Asl.Next;
399    }
400
401    for (i = 0; (i < Count2) && Op; i++)
402    {
403        ApCheckObjectType (PredefinedName, Op, Type2, (i + Count1));
404        Op = Op->Asl.Next;
405    }
406}
407
408
409/*******************************************************************************
410 *
411 * FUNCTION:    ApCheckPackageList
412 *
413 * PARAMETERS:  PredefinedName      - Name of the predefined object
414 *              ParentOp            - Parser op of the parent package
415 *              Package             - Package info for this predefined name
416 *              StartIndex          - Index in parent package where list begins
417 *              ParentCount         - Element count of parent package
418 *
419 * RETURN:      None
420 *
421 * DESCRIPTION: Validate the individual package elements for a predefined name.
422 *              Handles the cases where the predefined name is defined as a
423 *              Package of Packages (subpackages). These are the types:
424 *
425 *              ACPI_PTYPE2
426 *              ACPI_PTYPE2_FIXED
427 *              ACPI_PTYPE2_MIN
428 *              ACPI_PTYPE2_COUNT
429 *              ACPI_PTYPE2_FIX_VAR
430 *
431 ******************************************************************************/
432
433static void
434ApCheckPackageList (
435    const char                  *PredefinedName,
436    ACPI_PARSE_OBJECT           *ParentOp,
437    const ACPI_PREDEFINED_INFO  *Package,
438    UINT32                      StartIndex,
439    UINT32                      ParentCount)
440{
441    ACPI_PARSE_OBJECT           *SubPackageOp = ParentOp;
442    ACPI_PARSE_OBJECT           *Op;
443    ACPI_STATUS                 Status;
444    UINT32                      Count;
445    UINT32                      ExpectedCount;
446    UINT32                      i;
447    UINT32                      j;
448
449
450    /*
451     * Validate each subpackage in the parent Package
452     *
453     * Note: We ignore NULL package elements on the assumption that
454     * they will be initialized by the BIOS or other ASL code.
455     */
456    for (i = 0; (i < ParentCount) && SubPackageOp; i++)
457    {
458        /* Each object in the list must be of type Package */
459
460        Status = ApCheckObjectType (PredefinedName, SubPackageOp,
461            ACPI_RTYPE_PACKAGE, i + StartIndex);
462        if (ACPI_FAILURE (Status))
463        {
464            goto NextSubpackage;
465        }
466
467        /* Examine the different types of expected subpackages */
468
469        Op = SubPackageOp->Asl.Child;
470
471        /* First child is the package length */
472
473        Count = (UINT32) Op->Asl.Value.Integer;
474        Op = Op->Asl.Next;
475
476        /* The subpackage must have at least one element */
477
478        if (!Count)
479        {
480            ApZeroLengthPackage (PredefinedName, SubPackageOp);
481            goto NextSubpackage;
482        }
483
484        /*
485         * Decode the package type.
486         * PTYPE2 indicates that a "package of packages" is expected for
487         * this name. The various flavors of PTYPE2 indicate the number
488         * and format of the subpackages.
489         */
490        switch (Package->RetInfo.Type)
491        {
492        case ACPI_PTYPE2:
493        case ACPI_PTYPE2_PKG_COUNT:
494        case ACPI_PTYPE2_REV_FIXED:
495
496            /* Each subpackage has a fixed number of elements */
497
498            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
499            if (Count < ExpectedCount)
500            {
501                ApPackageTooSmall (PredefinedName, SubPackageOp,
502                    Count, ExpectedCount);
503                break;
504            }
505            if (Count > ExpectedCount)
506            {
507                ApPackageTooLarge (PredefinedName, SubPackageOp,
508                    Count, ExpectedCount);
509                break;
510            }
511
512            ApCheckPackageElements (PredefinedName, Op,
513                Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
514                Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
515            break;
516
517        case ACPI_PTYPE2_FIX_VAR:
518            /*
519             * Each subpackage has a fixed number of elements and an
520             * optional element
521             */
522            ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
523            if (Count < ExpectedCount)
524            {
525                ApPackageTooSmall (PredefinedName, SubPackageOp,
526                    Count, ExpectedCount);
527                break;
528            }
529
530            ApCheckPackageElements (PredefinedName, Op,
531                Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
532                Package->RetInfo.ObjectType2,
533                Count - Package->RetInfo.Count1);
534            break;
535
536        case ACPI_PTYPE2_FIXED:
537
538            /* Each subpackage has a fixed length */
539
540            ExpectedCount = Package->RetInfo2.Count;
541            if (Count < ExpectedCount)
542            {
543                ApPackageTooSmall (PredefinedName, SubPackageOp,
544                    Count, ExpectedCount);
545                break;
546            }
547            if (Count > ExpectedCount)
548            {
549                ApPackageTooLarge (PredefinedName, SubPackageOp,
550                    Count, ExpectedCount);
551                break;
552            }
553
554            /* Check each object/type combination */
555
556            for (j = 0; j < ExpectedCount; j++)
557            {
558                ApCheckObjectType (PredefinedName, Op,
559                    Package->RetInfo2.ObjectType[j], j);
560
561                Op = Op->Asl.Next;
562            }
563            break;
564
565        case ACPI_PTYPE2_MIN:
566
567            /* Each subpackage has a variable but minimum length */
568
569            ExpectedCount = Package->RetInfo.Count1;
570            if (Count < ExpectedCount)
571            {
572                ApPackageTooSmall (PredefinedName, SubPackageOp,
573                    Count, ExpectedCount);
574                break;
575            }
576
577            /* Check the type of each subpackage element */
578
579            ApCheckPackageElements (PredefinedName, Op,
580                Package->RetInfo.ObjectType1, Count, 0, 0);
581            break;
582
583        case ACPI_PTYPE2_COUNT:
584            /*
585             * First element is the (Integer) count of elements, including
586             * the count field (the ACPI name is NumElements)
587             */
588            Status = ApCheckObjectType (PredefinedName, Op,
589                ACPI_RTYPE_INTEGER, 0);
590
591            /* We must have an integer count from above (otherwise, use Count) */
592
593            if (ACPI_SUCCESS (Status))
594            {
595                /*
596                 * Make sure package is large enough for the Count and is
597                 * is as large as the minimum size
598                 */
599                ExpectedCount = (UINT32) Op->Asl.Value.Integer;
600
601                if (Count < ExpectedCount)
602                {
603                    ApPackageTooSmall (PredefinedName, SubPackageOp,
604                        Count, ExpectedCount);
605                    break;
606                }
607                else if (Count > ExpectedCount)
608                {
609                    ApPackageTooLarge (PredefinedName, SubPackageOp,
610                        Count, ExpectedCount);
611                }
612
613                /* Some names of this type have a minimum length */
614
615                if (Count < Package->RetInfo.Count1)
616                {
617                    ExpectedCount = Package->RetInfo.Count1;
618                    ApPackageTooSmall (PredefinedName, SubPackageOp,
619                        Count, ExpectedCount);
620                    break;
621                }
622
623                Count = ExpectedCount;
624            }
625
626            /* Check the type of each subpackage element */
627
628            Op = Op->Asl.Next;
629            ApCheckPackageElements (PredefinedName, Op,
630                Package->RetInfo.ObjectType1, (Count - 1), 0, 0);
631            break;
632
633        default:
634            break;
635        }
636
637NextSubpackage:
638        SubPackageOp = SubPackageOp->Asl.Next;
639    }
640}
641
642
643/*******************************************************************************
644 *
645 * FUNCTION:    ApPackageTooSmall
646 *
647 * PARAMETERS:  PredefinedName      - Name of the predefined object
648 *              Op                  - Current parser op
649 *              Count               - Actual package element count
650 *              ExpectedCount       - Expected package element count
651 *
652 * RETURN:      None
653 *
654 * DESCRIPTION: Issue error message for a package that is smaller than
655 *              required.
656 *
657 ******************************************************************************/
658
659static void
660ApPackageTooSmall (
661    const char                  *PredefinedName,
662    ACPI_PARSE_OBJECT           *Op,
663    UINT32                      Count,
664    UINT32                      ExpectedCount)
665{
666
667    sprintf (MsgBuffer, "%s: length %u, required minimum is %u",
668        PredefinedName, Count, ExpectedCount);
669
670    AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
671}
672
673
674/*******************************************************************************
675 *
676 * FUNCTION:    ApZeroLengthPackage
677 *
678 * PARAMETERS:  PredefinedName      - Name of the predefined object
679 *              Op                  - Current parser op
680 *
681 * RETURN:      None
682 *
683 * DESCRIPTION: Issue error message for a zero-length package (a package that
684 *              is required to have a non-zero length). Variable length
685 *              packages seem to be allowed to have zero length, however.
686 *              Even if not allowed, BIOS code does it.
687 *
688 ******************************************************************************/
689
690static void
691ApZeroLengthPackage (
692    const char                  *PredefinedName,
693    ACPI_PARSE_OBJECT           *Op)
694{
695
696    sprintf (MsgBuffer, "%s: length is zero", PredefinedName);
697
698    AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
699}
700
701
702/*******************************************************************************
703 *
704 * FUNCTION:    ApPackageTooLarge
705 *
706 * PARAMETERS:  PredefinedName      - Name of the predefined object
707 *              Op                  - Current parser op
708 *              Count               - Actual package element count
709 *              ExpectedCount       - Expected package element count
710 *
711 * RETURN:      None
712 *
713 * DESCRIPTION: Issue a remark for a package that is larger than expected.
714 *
715 ******************************************************************************/
716
717static void
718ApPackageTooLarge (
719    const char                  *PredefinedName,
720    ACPI_PARSE_OBJECT           *Op,
721    UINT32                      Count,
722    UINT32                      ExpectedCount)
723{
724
725    sprintf (MsgBuffer, "%s: length is %u, only %u required",
726        PredefinedName, Count, ExpectedCount);
727
728    AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
729}
730