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_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 
349 PackageTooSmall:
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 
374 static void
375 ApCheckPackageElements (
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 
433 static void
434 ApCheckPackageList (
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 
637 NextSubpackage:
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 
659 static void
660 ApPackageTooSmall (
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 
690 static void
691 ApZeroLengthPackage (
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 
717 static void
718 ApPackageTooLarge (
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