xref: /freebsd-src/sys/contrib/dev/acpica/compiler/aslprepkg.c (revision f5678b698afb3a97f99804f87ebb179de5f87df0)
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      * 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 
293 PackageTooSmall:
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 
318 static void
319 ApCheckPackageElements (
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 
377 static void
378 ApCheckPackageList (
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 
569 NextSubpackage:
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 
591 static void
592 ApPackageTooSmall (
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 
622 static void
623 ApZeroLengthPackage (
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 
649 static void
650 ApPackageTooLarge (
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