aslprepkg.c revision 1.1.1.5 1 /******************************************************************************
2 *
3 * Module Name: aslprepkg - support for ACPI predefined name package objects
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2016, 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 case ACPI_PTYPE2_VAR_VAR:
155 default:
156
157 break;
158 }
159
160 return;
161 }
162
163 /* Get the first element of the package */
164
165 Op = Op->Asl.Next;
166
167 /* Decode the package type */
168
169 switch (Package->RetInfo.Type)
170 {
171 case ACPI_PTYPE1_FIXED:
172 /*
173 * The package count is fixed and there are no subpackages
174 *
175 * If package is too small, exit.
176 * If package is larger than expected, issue warning but continue
177 */
178 ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
179 if (Count < ExpectedCount)
180 {
181 goto PackageTooSmall;
182 }
183 else if (Count > ExpectedCount)
184 {
185 ApPackageTooLarge (Predefined->Info.Name, ParentOp,
186 Count, ExpectedCount);
187 }
188
189 /* Validate all elements of the package */
190
191 ApCheckPackageElements (Predefined->Info.Name, Op,
192 Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
193 Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
194 break;
195
196 case ACPI_PTYPE1_VAR:
197 /*
198 * The package count is variable, there are no subpackages,
199 * and all elements must be of the same type
200 */
201 for (i = 0; i < Count; i++)
202 {
203 ApCheckObjectType (Predefined->Info.Name, Op,
204 Package->RetInfo.ObjectType1, i);
205 Op = Op->Asl.Next;
206 }
207 break;
208
209 case ACPI_PTYPE1_OPTION:
210 /*
211 * The package count is variable, there are no subpackages.
212 * There are a fixed number of required elements, and a variable
213 * number of optional elements.
214 *
215 * Check if package is at least as large as the minimum required
216 */
217 ExpectedCount = Package->RetInfo3.Count;
218 if (Count < ExpectedCount)
219 {
220 goto PackageTooSmall;
221 }
222
223 /* Variable number of sub-objects */
224
225 for (i = 0; i < Count; i++)
226 {
227 if (i < Package->RetInfo3.Count)
228 {
229 /* These are the required package elements (0, 1, or 2) */
230
231 ApCheckObjectType (Predefined->Info.Name, Op,
232 Package->RetInfo3.ObjectType[i], i);
233 }
234 else
235 {
236 /* These are the optional package elements */
237
238 ApCheckObjectType (Predefined->Info.Name, Op,
239 Package->RetInfo3.TailObjectType, i);
240 }
241
242 Op = Op->Asl.Next;
243 }
244 break;
245
246 case ACPI_PTYPE2_REV_FIXED:
247
248 /* First element is the (Integer) revision */
249
250 ApCheckObjectType (Predefined->Info.Name, Op,
251 ACPI_RTYPE_INTEGER, 0);
252
253 Op = Op->Asl.Next;
254 Count--;
255
256 /* Examine the subpackages */
257
258 ApCheckPackageList (Predefined->Info.Name, Op,
259 Package, 1, Count);
260 break;
261
262 case ACPI_PTYPE2_PKG_COUNT:
263
264 /* First element is the (Integer) count of subpackages to follow */
265
266 Status = ApCheckObjectType (Predefined->Info.Name, Op,
267 ACPI_RTYPE_INTEGER, 0);
268
269 /* We must have an integer count from above (otherwise, use Count) */
270
271 if (ACPI_SUCCESS (Status))
272 {
273 /*
274 * Count cannot be larger than the parent package length, but
275 * allow it to be smaller. The >= accounts for the Integer above.
276 */
277 ExpectedCount = (UINT32) Op->Asl.Value.Integer;
278 if (ExpectedCount >= Count)
279 {
280 goto PackageTooSmall;
281 }
282
283 Count = ExpectedCount;
284 }
285
286 Op = Op->Asl.Next;
287
288 /* Examine the subpackages */
289
290 ApCheckPackageList (Predefined->Info.Name, Op,
291 Package, 1, Count);
292 break;
293
294 case ACPI_PTYPE2_UUID_PAIR:
295
296 /* The package contains a variable list of UUID Buffer/Package pairs */
297
298 /* The length of the package must be even */
299
300 if (Count & 1)
301 {
302 sprintf (MsgBuffer, "%4.4s: Package length, %d, must be even.",
303 Predefined->Info.Name, Count);
304
305 AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH,
306 ParentOp->Asl.Child, MsgBuffer);
307 }
308
309 /* Validate the alternating types */
310
311 for (i = 0; i < Count; ++i)
312 {
313 if (i & 1)
314 {
315 ApCheckObjectType (Predefined->Info.Name, Op,
316 Package->RetInfo.ObjectType2, i);
317 }
318 else
319 {
320 ApCheckObjectType (Predefined->Info.Name, Op,
321 Package->RetInfo.ObjectType1, i);
322 }
323
324 Op = Op->Asl.Next;
325 }
326
327 break;
328
329 case ACPI_PTYPE2_VAR_VAR:
330
331 /* Check for minimum size (ints at beginning + 1 subpackage) */
332
333 ExpectedCount = Package->RetInfo4.Count1 + 1;
334 if (Count < ExpectedCount)
335 {
336 goto PackageTooSmall;
337 }
338
339 /* Check the non-package elements at beginning of main package */
340
341 for (i = 0; i < Package->RetInfo4.Count1; ++i)
342 {
343 Status = ApCheckObjectType (Predefined->Info.Name, Op,
344 Package->RetInfo4.ObjectType1, i);
345 Op = Op->Asl.Next;
346 }
347
348 /* Examine the variable-length list of subpackages */
349
350 ApCheckPackageList (Predefined->Info.Name, Op,
351 Package, Package->RetInfo4.Count1, Count);
352
353 break;
354
355 case ACPI_PTYPE2:
356 case ACPI_PTYPE2_FIXED:
357 case ACPI_PTYPE2_MIN:
358 case ACPI_PTYPE2_COUNT:
359 case ACPI_PTYPE2_FIX_VAR:
360 /*
361 * These types all return a single Package that consists of a
362 * variable number of subpackages.
363 */
364
365 /* Examine the subpackages */
366
367 ApCheckPackageList (Predefined->Info.Name, Op,
368 Package, 0, Count);
369 break;
370
371 default:
372 return;
373 }
374
375 return;
376
377 PackageTooSmall:
378 ApPackageTooSmall (Predefined->Info.Name, ParentOp,
379 Count, ExpectedCount);
380 }
381
382
383 /*******************************************************************************
384 *
385 * FUNCTION: ApCheckPackageElements
386 *
387 * PARAMETERS: PredefinedName - Name of the predefined object
388 * Op - Parser op for the package
389 * Type1 - Object type for first group
390 * Count1 - Count for first group
391 * Type2 - Object type for second group
392 * Count2 - Count for second group
393 *
394 * RETURN: None
395 *
396 * DESCRIPTION: Validate all elements of a package. Works with packages that
397 * are defined to contain up to two groups of different object
398 * types.
399 *
400 ******************************************************************************/
401
402 static void
403 ApCheckPackageElements (
404 const char *PredefinedName,
405 ACPI_PARSE_OBJECT *Op,
406 UINT8 Type1,
407 UINT32 Count1,
408 UINT8 Type2,
409 UINT32 Count2)
410 {
411 UINT32 i;
412
413
414 /*
415 * Up to two groups of package elements are supported by the data
416 * structure. All elements in each group must be of the same type.
417 * The second group can have a count of zero.
418 *
419 * Aborts check upon a NULL package element, as this means (at compile
420 * time) that the remainder of the package elements are also NULL
421 * (This is the only way to create NULL package elements.)
422 */
423 for (i = 0; (i < Count1) && Op; i++)
424 {
425 ApCheckObjectType (PredefinedName, Op, Type1, i);
426 Op = Op->Asl.Next;
427 }
428
429 for (i = 0; (i < Count2) && Op; i++)
430 {
431 ApCheckObjectType (PredefinedName, Op, Type2, (i + Count1));
432 Op = Op->Asl.Next;
433 }
434 }
435
436
437 /*******************************************************************************
438 *
439 * FUNCTION: ApCheckPackageList
440 *
441 * PARAMETERS: PredefinedName - Name of the predefined object
442 * ParentOp - Parser op of the parent package
443 * Package - Package info for this predefined name
444 * StartIndex - Index in parent package where list begins
445 * ParentCount - Element count of parent package
446 *
447 * RETURN: None
448 *
449 * DESCRIPTION: Validate the individual package elements for a predefined name.
450 * Handles the cases where the predefined name is defined as a
451 * Package of Packages (subpackages). These are the types:
452 *
453 * ACPI_PTYPE2
454 * ACPI_PTYPE2_FIXED
455 * ACPI_PTYPE2_MIN
456 * ACPI_PTYPE2_COUNT
457 * ACPI_PTYPE2_FIX_VAR
458 * ACPI_PTYPE2_VAR_VAR
459 *
460 ******************************************************************************/
461
462 static void
463 ApCheckPackageList (
464 const char *PredefinedName,
465 ACPI_PARSE_OBJECT *ParentOp,
466 const ACPI_PREDEFINED_INFO *Package,
467 UINT32 StartIndex,
468 UINT32 ParentCount)
469 {
470 ACPI_PARSE_OBJECT *SubPackageOp = ParentOp;
471 ACPI_PARSE_OBJECT *Op;
472 ACPI_STATUS Status;
473 UINT32 Count;
474 UINT32 ExpectedCount;
475 UINT32 i;
476 UINT32 j;
477
478
479 /*
480 * Validate each subpackage in the parent Package
481 *
482 * Note: We ignore NULL package elements on the assumption that
483 * they will be initialized by the BIOS or other ASL code.
484 */
485 for (i = 0; (i < ParentCount) && SubPackageOp; i++)
486 {
487 /* Each object in the list must be of type Package */
488
489 Status = ApCheckObjectType (PredefinedName, SubPackageOp,
490 ACPI_RTYPE_PACKAGE, i + StartIndex);
491 if (ACPI_FAILURE (Status))
492 {
493 goto NextSubpackage;
494 }
495
496 /* Examine the different types of expected subpackages */
497
498 Op = SubPackageOp->Asl.Child;
499
500 /* First child is the package length */
501
502 Count = (UINT32) Op->Asl.Value.Integer;
503 Op = Op->Asl.Next;
504
505 /*
506 * Most subpackage must have at least one element, with
507 * only rare exceptions. (_RDI)
508 */
509 if (!Count &&
510 (Package->RetInfo.Type != ACPI_PTYPE2_VAR_VAR))
511 {
512 ApZeroLengthPackage (PredefinedName, SubPackageOp);
513 goto NextSubpackage;
514 }
515
516 /*
517 * Decode the package type.
518 * PTYPE2 indicates that a "package of packages" is expected for
519 * this name. The various flavors of PTYPE2 indicate the number
520 * and format of the subpackages.
521 */
522 switch (Package->RetInfo.Type)
523 {
524 case ACPI_PTYPE2:
525 case ACPI_PTYPE2_PKG_COUNT:
526 case ACPI_PTYPE2_REV_FIXED:
527
528 /* Each subpackage has a fixed number of elements */
529
530 ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
531 if (Count < ExpectedCount)
532 {
533 ApPackageTooSmall (PredefinedName, SubPackageOp,
534 Count, ExpectedCount);
535 break;
536 }
537 if (Count > ExpectedCount)
538 {
539 ApPackageTooLarge (PredefinedName, SubPackageOp,
540 Count, ExpectedCount);
541 break;
542 }
543
544 ApCheckPackageElements (PredefinedName, Op,
545 Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
546 Package->RetInfo.ObjectType2, Package->RetInfo.Count2);
547 break;
548
549 case ACPI_PTYPE2_FIX_VAR:
550 /*
551 * Each subpackage has a fixed number of elements and an
552 * optional element
553 */
554 ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
555 if (Count < ExpectedCount)
556 {
557 ApPackageTooSmall (PredefinedName, SubPackageOp,
558 Count, ExpectedCount);
559 break;
560 }
561
562 ApCheckPackageElements (PredefinedName, Op,
563 Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
564 Package->RetInfo.ObjectType2,
565 Count - Package->RetInfo.Count1);
566 break;
567
568 case ACPI_PTYPE2_VAR_VAR:
569 /*
570 * Must have at least the minimum number elements.
571 * A zero PkgCount means the number of elements is variable.
572 */
573 ExpectedCount = Package->RetInfo4.PkgCount;
574 if (ExpectedCount && (Count < ExpectedCount))
575 {
576 ApPackageTooSmall (PredefinedName, SubPackageOp,
577 Count, 1);
578 break;
579 }
580
581 ApCheckPackageElements (PredefinedName, Op,
582 Package->RetInfo4.SubObjectTypes,
583 Package->RetInfo4.PkgCount,
584 0, 0);
585 break;
586
587 case ACPI_PTYPE2_FIXED:
588
589 /* Each subpackage has a fixed length */
590
591 ExpectedCount = Package->RetInfo2.Count;
592 if (Count < ExpectedCount)
593 {
594 ApPackageTooSmall (PredefinedName, SubPackageOp,
595 Count, ExpectedCount);
596 break;
597 }
598 if (Count > ExpectedCount)
599 {
600 ApPackageTooLarge (PredefinedName, SubPackageOp,
601 Count, ExpectedCount);
602 break;
603 }
604
605 /* Check each object/type combination */
606
607 for (j = 0; j < ExpectedCount; j++)
608 {
609 ApCheckObjectType (PredefinedName, Op,
610 Package->RetInfo2.ObjectType[j], j);
611
612 Op = Op->Asl.Next;
613 }
614 break;
615
616 case ACPI_PTYPE2_MIN:
617
618 /* Each subpackage has a variable but minimum length */
619
620 ExpectedCount = Package->RetInfo.Count1;
621 if (Count < ExpectedCount)
622 {
623 ApPackageTooSmall (PredefinedName, SubPackageOp,
624 Count, ExpectedCount);
625 break;
626 }
627
628 /* Check the type of each subpackage element */
629
630 ApCheckPackageElements (PredefinedName, Op,
631 Package->RetInfo.ObjectType1, Count, 0, 0);
632 break;
633
634 case ACPI_PTYPE2_COUNT:
635 /*
636 * First element is the (Integer) count of elements, including
637 * the count field (the ACPI name is NumElements)
638 */
639 Status = ApCheckObjectType (PredefinedName, Op,
640 ACPI_RTYPE_INTEGER, 0);
641
642 /* We must have an integer count from above (otherwise, use Count) */
643
644 if (ACPI_SUCCESS (Status))
645 {
646 /*
647 * Make sure package is large enough for the Count and is
648 * is as large as the minimum size
649 */
650 ExpectedCount = (UINT32) Op->Asl.Value.Integer;
651
652 if (Count < ExpectedCount)
653 {
654 ApPackageTooSmall (PredefinedName, SubPackageOp,
655 Count, ExpectedCount);
656 break;
657 }
658 else if (Count > ExpectedCount)
659 {
660 ApPackageTooLarge (PredefinedName, SubPackageOp,
661 Count, ExpectedCount);
662 }
663
664 /* Some names of this type have a minimum length */
665
666 if (Count < Package->RetInfo.Count1)
667 {
668 ExpectedCount = Package->RetInfo.Count1;
669 ApPackageTooSmall (PredefinedName, SubPackageOp,
670 Count, ExpectedCount);
671 break;
672 }
673
674 Count = ExpectedCount;
675 }
676
677 /* Check the type of each subpackage element */
678
679 Op = Op->Asl.Next;
680 ApCheckPackageElements (PredefinedName, Op,
681 Package->RetInfo.ObjectType1, (Count - 1), 0, 0);
682 break;
683
684 default:
685 break;
686 }
687
688 NextSubpackage:
689 SubPackageOp = SubPackageOp->Asl.Next;
690 }
691 }
692
693
694 /*******************************************************************************
695 *
696 * FUNCTION: ApPackageTooSmall
697 *
698 * PARAMETERS: PredefinedName - Name of the predefined object
699 * Op - Current parser op
700 * Count - Actual package element count
701 * ExpectedCount - Expected package element count
702 *
703 * RETURN: None
704 *
705 * DESCRIPTION: Issue error message for a package that is smaller than
706 * required.
707 *
708 ******************************************************************************/
709
710 static void
711 ApPackageTooSmall (
712 const char *PredefinedName,
713 ACPI_PARSE_OBJECT *Op,
714 UINT32 Count,
715 UINT32 ExpectedCount)
716 {
717
718 sprintf (MsgBuffer, "%s: length %u, required minimum is %u",
719 PredefinedName, Count, ExpectedCount);
720
721 AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
722 }
723
724
725 /*******************************************************************************
726 *
727 * FUNCTION: ApZeroLengthPackage
728 *
729 * PARAMETERS: PredefinedName - Name of the predefined object
730 * Op - Current parser op
731 *
732 * RETURN: None
733 *
734 * DESCRIPTION: Issue error message for a zero-length package (a package that
735 * is required to have a non-zero length). Variable length
736 * packages seem to be allowed to have zero length, however.
737 * Even if not allowed, BIOS code does it.
738 *
739 ******************************************************************************/
740
741 static void
742 ApZeroLengthPackage (
743 const char *PredefinedName,
744 ACPI_PARSE_OBJECT *Op)
745 {
746
747 sprintf (MsgBuffer, "%s: length is zero", PredefinedName);
748
749 AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
750 }
751
752
753 /*******************************************************************************
754 *
755 * FUNCTION: ApPackageTooLarge
756 *
757 * PARAMETERS: PredefinedName - Name of the predefined object
758 * Op - Current parser op
759 * Count - Actual package element count
760 * ExpectedCount - Expected package element count
761 *
762 * RETURN: None
763 *
764 * DESCRIPTION: Issue a remark for a package that is larger than expected.
765 *
766 ******************************************************************************/
767
768 static void
769 ApPackageTooLarge (
770 const char *PredefinedName,
771 ACPI_PARSE_OBJECT *Op,
772 UINT32 Count,
773 UINT32 ExpectedCount)
774 {
775
776 sprintf (MsgBuffer, "%s: length is %u, only %u required",
777 PredefinedName, Count, ExpectedCount);
778
779 AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer);
780 }
781