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