1 /******************************************************************************
2  *
3  * Module Name: aslprepkg - support for ACPI predefined name package objects
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2014, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "acpredef.h"
47 
48 
49 #define _COMPONENT          ACPI_COMPILER
50         ACPI_MODULE_NAME    ("aslprepkg")
51 
52 
53 /* Local prototypes */
54 
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
98  *                                    the method
99  *
100  * RETURN:      None
101  *
102  * DESCRIPTION: Top-level validation for predefined name return package
103  *              objects.
104  *
105  ******************************************************************************/
106 
107 void
108 ApCheckPackage (
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:
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 subpackages.
300          */
301 
302         /* Examine the subpackages */
303 
304         ApCheckPackageList (Predefined->Info.Name, Op,
305             Package, 0, Count);
306         break;
307 
308     default:
309         return;
310     }
311 
312     return;
313 
314 PackageTooSmall:
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 
339 static void
340 ApCheckPackageElements (
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 
398 static void
399 ApCheckPackageList (
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             if (Count > ExpectedCount)
471             {
472                 ApPackageTooLarge (PredefinedName, SubPackageOp,
473                     Count, ExpectedCount);
474                 break;
475             }
476 
477             ApCheckPackageElements (PredefinedName, Op,
478                 Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
479                 Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
480             break;
481 
482         case ACPI_PTYPE2_FIX_VAR:
483             /*
484              * Each subpackage has a fixed number of elements and an
485              * optional element
486              */
487             ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
488             if (Count < ExpectedCount)
489             {
490                 ApPackageTooSmall (PredefinedName, SubPackageOp,
491                     Count, ExpectedCount);
492                 break;
493             }
494 
495             ApCheckPackageElements (PredefinedName, Op,
496                 Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
497                 Package->RetInfo.ObjectType2,
498                 Count - Package->RetInfo.Count1);
499             break;
500 
501         case ACPI_PTYPE2_FIXED:
502 
503             /* Each subpackage has a fixed length */
504 
505             ExpectedCount = Package->RetInfo2.Count;
506             if (Count < ExpectedCount)
507             {
508                 ApPackageTooSmall (PredefinedName, SubPackageOp,
509                     Count, ExpectedCount);
510                 break;
511             }
512             if (Count > ExpectedCount)
513             {
514                 ApPackageTooLarge (PredefinedName, SubPackageOp,
515                     Count, ExpectedCount);
516                 break;
517             }
518 
519             /* Check each object/type combination */
520 
521             for (j = 0; j < ExpectedCount; j++)
522             {
523                 ApCheckObjectType (PredefinedName, Op,
524                     Package->RetInfo2.ObjectType[j], j);
525 
526                 Op = Op->Asl.Next;
527             }
528             break;
529 
530         case ACPI_PTYPE2_MIN:
531 
532             /* Each subpackage has a variable but minimum length */
533 
534             ExpectedCount = Package->RetInfo.Count1;
535             if (Count < ExpectedCount)
536             {
537                 ApPackageTooSmall (PredefinedName, SubPackageOp,
538                     Count, ExpectedCount);
539                 break;
540             }
541 
542             /* Check the type of each subpackage element */
543 
544             ApCheckPackageElements (PredefinedName, Op,
545                 Package->RetInfo.ObjectType1, Count, 0, 0);
546             break;
547 
548         case ACPI_PTYPE2_COUNT:
549             /*
550              * First element is the (Integer) count of elements, including
551              * the count field (the ACPI name is NumElements)
552              */
553             Status = ApCheckObjectType (PredefinedName, Op,
554                 ACPI_RTYPE_INTEGER, 0);
555 
556             /* We must have an integer count from above (otherwise, use Count) */
557 
558             if (ACPI_SUCCESS (Status))
559             {
560                 /*
561                  * Make sure package is large enough for the Count and is
562                  * is as large as the minimum size
563                  */
564                 ExpectedCount = (UINT32) Op->Asl.Value.Integer;
565 
566                 if (Count < ExpectedCount)
567                 {
568                     ApPackageTooSmall (PredefinedName, SubPackageOp,
569                         Count, ExpectedCount);
570                     break;
571                 }
572                 else if (Count > ExpectedCount)
573                 {
574                     ApPackageTooLarge (PredefinedName, SubPackageOp,
575                         Count, ExpectedCount);
576                 }
577 
578                 /* Some names of this type have a minimum length */
579 
580                 if (Count < Package->RetInfo.Count1)
581                 {
582                     ExpectedCount = Package->RetInfo.Count1;
583                     ApPackageTooSmall (PredefinedName, SubPackageOp,
584                         Count, ExpectedCount);
585                     break;
586                 }
587 
588                 Count = ExpectedCount;
589             }
590 
591             /* Check the type of each subpackage element */
592 
593             Op = Op->Asl.Next;
594             ApCheckPackageElements (PredefinedName, Op,
595                 Package->RetInfo.ObjectType1, (Count - 1), 0, 0);
596             break;
597 
598         default:
599             break;
600         }
601 
602 NextSubpackage:
603         SubPackageOp = SubPackageOp->Asl.Next;
604     }
605 }
606 
607 
608 /*******************************************************************************
609  *
610  * FUNCTION:    ApPackageTooSmall
611  *
612  * PARAMETERS:  PredefinedName      - Name of the predefined object
613  *              Op                  - Current parser op
614  *              Count               - Actual package element count
615  *              ExpectedCount       - Expected package element count
616  *
617  * RETURN:      None
618  *
619  * DESCRIPTION: Issue error message for a package that is smaller than
620  *              required.
621  *
622  ******************************************************************************/
623 
624 static void
625 ApPackageTooSmall (
626     const char                  *PredefinedName,
627     ACPI_PARSE_OBJECT           *Op,
628     UINT32                      Count,
629     UINT32                      ExpectedCount)
630 {
631 
632     sprintf (MsgBuffer, "%s: length %u, required minimum is %u",
633         PredefinedName, Count, ExpectedCount);
634 
635     AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
636 }
637 
638 
639 /*******************************************************************************
640  *
641  * FUNCTION:    ApZeroLengthPackage
642  *
643  * PARAMETERS:  PredefinedName      - Name of the predefined object
644  *              Op                  - Current parser op
645  *
646  * RETURN:      None
647  *
648  * DESCRIPTION: Issue error message for a zero-length package (a package that
649  *              is required to have a non-zero length). Variable length
650  *              packages seem to be allowed to have zero length, however.
651  *              Even if not allowed, BIOS code does it.
652  *
653  ******************************************************************************/
654 
655 static void
656 ApZeroLengthPackage (
657     const char                  *PredefinedName,
658     ACPI_PARSE_OBJECT           *Op)
659 {
660 
661     sprintf (MsgBuffer, "%s: length is zero", PredefinedName);
662 
663     AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
664 }
665 
666 
667 /*******************************************************************************
668  *
669  * FUNCTION:    ApPackageTooLarge
670  *
671  * PARAMETERS:  PredefinedName      - Name of the predefined object
672  *              Op                  - Current parser op
673  *              Count               - Actual package element count
674  *              ExpectedCount       - Expected package element count
675  *
676  * RETURN:      None
677  *
678  * DESCRIPTION: Issue a remark for a package that is larger than expected.
679  *
680  ******************************************************************************/
681 
682 static void
683 ApPackageTooLarge (
684     const char                  *PredefinedName,
685     ACPI_PARSE_OBJECT           *Op,
686     UINT32                      Count,
687     UINT32                      ExpectedCount)
688 {
689 
690     sprintf (MsgBuffer, "%s: length is %u, only %u required",
691         PredefinedName, Count, ExpectedCount);
692 
693     AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
694 }
695