1 /******************************************************************************
3 * Module Name: nsprepkg - Validation of package objects for predefined names
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2016, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
50 #define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsprepkg")
54 /* Local prototypes */
57 AcpiNsCheckPackageList (
58 ACPI_EVALUATE_INFO
*Info
,
59 const ACPI_PREDEFINED_INFO
*Package
,
60 ACPI_OPERAND_OBJECT
**Elements
,
64 AcpiNsCheckPackageElements (
65 ACPI_EVALUATE_INFO
*Info
,
66 ACPI_OPERAND_OBJECT
**Elements
,
75 ACPI_EVALUATE_INFO
*Info
,
76 ACPI_OPERAND_OBJECT
**Elements
,
80 /*******************************************************************************
82 * FUNCTION: AcpiNsCheckPackage
84 * PARAMETERS: Info - Method execution information block
85 * ReturnObjectPtr - Pointer to the object returned from the
86 * evaluation of a method or object
90 * DESCRIPTION: Check a returned package object for the correct count and
91 * correct type of all sub-objects.
93 ******************************************************************************/
97 ACPI_EVALUATE_INFO
*Info
,
98 ACPI_OPERAND_OBJECT
**ReturnObjectPtr
)
100 ACPI_OPERAND_OBJECT
*ReturnObject
= *ReturnObjectPtr
;
101 const ACPI_PREDEFINED_INFO
*Package
;
102 ACPI_OPERAND_OBJECT
**Elements
;
103 ACPI_STATUS Status
= AE_OK
;
104 UINT32 ExpectedCount
;
109 ACPI_FUNCTION_NAME (NsCheckPackage
);
112 /* The package info for this name is in the next table entry */
114 Package
= Info
->Predefined
+ 1;
116 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES
,
117 "%s Validating return Package of Type %X, Count %X\n",
118 Info
->FullPathname
, Package
->RetInfo
.Type
,
119 ReturnObject
->Package
.Count
));
122 * For variable-length Packages, we can safely remove all embedded
123 * and trailing NULL package elements
125 AcpiNsRemoveNullElements (Info
, Package
->RetInfo
.Type
, ReturnObject
);
127 /* Extract package count and elements array */
129 Elements
= ReturnObject
->Package
.Elements
;
130 Count
= ReturnObject
->Package
.Count
;
133 * Most packages must have at least one element. The only exception
134 * is the variable-length package (ACPI_PTYPE1_VAR).
138 if (Package
->RetInfo
.Type
== ACPI_PTYPE1_VAR
)
143 ACPI_WARN_PREDEFINED ((AE_INFO
, Info
->FullPathname
, Info
->NodeFlags
,
144 "Return Package has no elements (empty)"));
146 return (AE_AML_OPERAND_VALUE
);
150 * Decode the type of the expected package contents
152 * PTYPE1 packages contain no subpackages
153 * PTYPE2 packages contain subpackages
155 switch (Package
->RetInfo
.Type
)
157 case ACPI_PTYPE_CUSTOM
:
159 Status
= AcpiNsCustomPackage (Info
, Elements
, Count
);
162 case ACPI_PTYPE1_FIXED
:
164 * The package count is fixed and there are no subpackages
166 * If package is too small, exit.
167 * If package is larger than expected, issue warning but continue
169 ExpectedCount
= Package
->RetInfo
.Count1
+ Package
->RetInfo
.Count2
;
170 if (Count
< ExpectedCount
)
172 goto PackageTooSmall
;
174 else if (Count
> ExpectedCount
)
176 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR
,
177 "%s: Return Package is larger than needed - "
178 "found %u, expected %u\n",
179 Info
->FullPathname
, Count
, ExpectedCount
));
182 /* Validate all elements of the returned package */
184 Status
= AcpiNsCheckPackageElements (Info
, Elements
,
185 Package
->RetInfo
.ObjectType1
, Package
->RetInfo
.Count1
,
186 Package
->RetInfo
.ObjectType2
, Package
->RetInfo
.Count2
, 0);
189 case ACPI_PTYPE1_VAR
:
191 * The package count is variable, there are no subpackages, and all
192 * elements must be of the same type
194 for (i
= 0; i
< Count
; i
++)
196 Status
= AcpiNsCheckObjectType (Info
, Elements
,
197 Package
->RetInfo
.ObjectType1
, i
);
198 if (ACPI_FAILURE (Status
))
207 case ACPI_PTYPE1_OPTION
:
209 * The package count is variable, there are no subpackages. There are
210 * a fixed number of required elements, and a variable number of
213 * Check if package is at least as large as the minimum required
215 ExpectedCount
= Package
->RetInfo3
.Count
;
216 if (Count
< ExpectedCount
)
218 goto PackageTooSmall
;
221 /* Variable number of sub-objects */
223 for (i
= 0; i
< Count
; i
++)
225 if (i
< Package
->RetInfo3
.Count
)
227 /* These are the required package elements (0, 1, or 2) */
229 Status
= AcpiNsCheckObjectType (Info
, Elements
,
230 Package
->RetInfo3
.ObjectType
[i
], i
);
231 if (ACPI_FAILURE (Status
))
238 /* These are the optional package elements */
240 Status
= AcpiNsCheckObjectType (Info
, Elements
,
241 Package
->RetInfo3
.TailObjectType
, i
);
242 if (ACPI_FAILURE (Status
))
252 case ACPI_PTYPE2_REV_FIXED
:
254 /* First element is the (Integer) revision */
256 Status
= AcpiNsCheckObjectType (
257 Info
, Elements
, ACPI_RTYPE_INTEGER
, 0);
258 if (ACPI_FAILURE (Status
))
266 /* Examine the subpackages */
268 Status
= AcpiNsCheckPackageList (Info
, Package
, Elements
, Count
);
271 case ACPI_PTYPE2_PKG_COUNT
:
273 /* First element is the (Integer) count of subpackages to follow */
275 Status
= AcpiNsCheckObjectType (
276 Info
, Elements
, ACPI_RTYPE_INTEGER
, 0);
277 if (ACPI_FAILURE (Status
))
283 * Count cannot be larger than the parent package length, but allow it
284 * to be smaller. The >= accounts for the Integer above.
286 ExpectedCount
= (UINT32
) (*Elements
)->Integer
.Value
;
287 if (ExpectedCount
>= Count
)
289 goto PackageTooSmall
;
292 Count
= ExpectedCount
;
295 /* Examine the subpackages */
297 Status
= AcpiNsCheckPackageList (Info
, Package
, Elements
, Count
);
301 case ACPI_PTYPE2_FIXED
:
302 case ACPI_PTYPE2_MIN
:
303 case ACPI_PTYPE2_COUNT
:
304 case ACPI_PTYPE2_FIX_VAR
:
306 * These types all return a single Package that consists of a
307 * variable number of subpackages.
309 * First, ensure that the first element is a subpackage. If not,
310 * the BIOS may have incorrectly returned the object as a single
311 * package instead of a Package of Packages (a common error if
312 * there is only one entry). We may be able to repair this by
313 * wrapping the returned Package with a new outer Package.
315 if (*Elements
&& ((*Elements
)->Common
.Type
!= ACPI_TYPE_PACKAGE
))
317 /* Create the new outer package and populate it */
319 Status
= AcpiNsWrapWithPackage (
320 Info
, ReturnObject
, ReturnObjectPtr
);
321 if (ACPI_FAILURE (Status
))
326 /* Update locals to point to the new package (of 1 element) */
328 ReturnObject
= *ReturnObjectPtr
;
329 Elements
= ReturnObject
->Package
.Elements
;
333 /* Examine the subpackages */
335 Status
= AcpiNsCheckPackageList (Info
, Package
, Elements
, Count
);
338 case ACPI_PTYPE2_VAR_VAR
:
340 * Returns a variable list of packages, each with a variable list
345 case ACPI_PTYPE2_UUID_PAIR
:
347 /* The package must contain pairs of (UUID + type) */
351 ExpectedCount
= Count
+ 1;
352 goto PackageTooSmall
;
357 Status
= AcpiNsCheckObjectType(Info
, Elements
,
358 Package
->RetInfo
.ObjectType1
, 0);
359 if (ACPI_FAILURE(Status
))
364 /* Validate length of the UUID buffer */
366 if ((*Elements
)->Buffer
.Length
!= 16)
368 ACPI_WARN_PREDEFINED ((AE_INFO
, Info
->FullPathname
,
369 Info
->NodeFlags
, "Invalid length for UUID Buffer"));
370 return (AE_AML_OPERAND_VALUE
);
373 Status
= AcpiNsCheckObjectType(Info
, Elements
+ 1,
374 Package
->RetInfo
.ObjectType2
, 0);
375 if (ACPI_FAILURE(Status
))
387 /* Should not get here if predefined info table is correct */
389 ACPI_WARN_PREDEFINED ((AE_INFO
, Info
->FullPathname
, Info
->NodeFlags
,
390 "Invalid internal return type in table entry: %X",
391 Package
->RetInfo
.Type
));
393 return (AE_AML_INTERNAL
);
401 /* Error exit for the case with an incorrect package count */
403 ACPI_WARN_PREDEFINED ((AE_INFO
, Info
->FullPathname
, Info
->NodeFlags
,
404 "Return Package is too small - found %u elements, expected %u",
405 Count
, ExpectedCount
));
407 return (AE_AML_OPERAND_VALUE
);
411 /*******************************************************************************
413 * FUNCTION: AcpiNsCheckPackageList
415 * PARAMETERS: Info - Method execution information block
416 * Package - Pointer to package-specific info for method
417 * Elements - Element list of parent package. All elements
418 * of this list should be of type Package.
419 * Count - Count of subpackages
423 * DESCRIPTION: Examine a list of subpackages
425 ******************************************************************************/
428 AcpiNsCheckPackageList (
429 ACPI_EVALUATE_INFO
*Info
,
430 const ACPI_PREDEFINED_INFO
*Package
,
431 ACPI_OPERAND_OBJECT
**Elements
,
434 ACPI_OPERAND_OBJECT
*SubPackage
;
435 ACPI_OPERAND_OBJECT
**SubElements
;
437 UINT32 ExpectedCount
;
443 * Validate each subpackage in the parent Package
445 * NOTE: assumes list of subpackages contains no NULL elements.
446 * Any NULL elements should have been removed by earlier call
447 * to AcpiNsRemoveNullElements.
449 for (i
= 0; i
< Count
; i
++)
451 SubPackage
= *Elements
;
452 SubElements
= SubPackage
->Package
.Elements
;
453 Info
->ParentPackage
= SubPackage
;
455 /* Each sub-object must be of type Package */
457 Status
= AcpiNsCheckObjectType (Info
, &SubPackage
,
458 ACPI_RTYPE_PACKAGE
, i
);
459 if (ACPI_FAILURE (Status
))
464 /* Examine the different types of expected subpackages */
466 Info
->ParentPackage
= SubPackage
;
467 switch (Package
->RetInfo
.Type
)
470 case ACPI_PTYPE2_PKG_COUNT
:
471 case ACPI_PTYPE2_REV_FIXED
:
473 /* Each subpackage has a fixed number of elements */
475 ExpectedCount
= Package
->RetInfo
.Count1
+ Package
->RetInfo
.Count2
;
476 if (SubPackage
->Package
.Count
< ExpectedCount
)
478 goto PackageTooSmall
;
481 Status
= AcpiNsCheckPackageElements (Info
, SubElements
,
482 Package
->RetInfo
.ObjectType1
,
483 Package
->RetInfo
.Count1
,
484 Package
->RetInfo
.ObjectType2
,
485 Package
->RetInfo
.Count2
, 0);
486 if (ACPI_FAILURE (Status
))
492 case ACPI_PTYPE2_FIX_VAR
:
494 * Each subpackage has a fixed number of elements and an
497 ExpectedCount
= Package
->RetInfo
.Count1
+ Package
->RetInfo
.Count2
;
498 if (SubPackage
->Package
.Count
< ExpectedCount
)
500 goto PackageTooSmall
;
503 Status
= AcpiNsCheckPackageElements (Info
, SubElements
,
504 Package
->RetInfo
.ObjectType1
,
505 Package
->RetInfo
.Count1
,
506 Package
->RetInfo
.ObjectType2
,
507 SubPackage
->Package
.Count
- Package
->RetInfo
.Count1
, 0);
508 if (ACPI_FAILURE (Status
))
514 case ACPI_PTYPE2_VAR_VAR
:
516 * Each subpackage has a fixed or variable number of elements
520 case ACPI_PTYPE2_FIXED
:
522 /* Each subpackage has a fixed length */
524 ExpectedCount
= Package
->RetInfo2
.Count
;
525 if (SubPackage
->Package
.Count
< ExpectedCount
)
527 goto PackageTooSmall
;
530 /* Check the type of each subpackage element */
532 for (j
= 0; j
< ExpectedCount
; j
++)
534 Status
= AcpiNsCheckObjectType (Info
, &SubElements
[j
],
535 Package
->RetInfo2
.ObjectType
[j
], j
);
536 if (ACPI_FAILURE (Status
))
543 case ACPI_PTYPE2_MIN
:
545 /* Each subpackage has a variable but minimum length */
547 ExpectedCount
= Package
->RetInfo
.Count1
;
548 if (SubPackage
->Package
.Count
< ExpectedCount
)
550 goto PackageTooSmall
;
553 /* Check the type of each subpackage element */
555 Status
= AcpiNsCheckPackageElements (Info
, SubElements
,
556 Package
->RetInfo
.ObjectType1
,
557 SubPackage
->Package
.Count
, 0, 0, 0);
558 if (ACPI_FAILURE (Status
))
564 case ACPI_PTYPE2_COUNT
:
566 * First element is the (Integer) count of elements, including
567 * the count field (the ACPI name is NumElements)
569 Status
= AcpiNsCheckObjectType (Info
, SubElements
,
570 ACPI_RTYPE_INTEGER
, 0);
571 if (ACPI_FAILURE (Status
))
577 * Make sure package is large enough for the Count and is
578 * is as large as the minimum size
580 ExpectedCount
= (UINT32
) (*SubElements
)->Integer
.Value
;
581 if (SubPackage
->Package
.Count
< ExpectedCount
)
583 goto PackageTooSmall
;
586 if (SubPackage
->Package
.Count
< Package
->RetInfo
.Count1
)
588 ExpectedCount
= Package
->RetInfo
.Count1
;
589 goto PackageTooSmall
;
592 if (ExpectedCount
== 0)
595 * Either the NumEntries element was originally zero or it was
596 * a NULL element and repaired to an Integer of value zero.
597 * In either case, repair it by setting NumEntries to be the
598 * actual size of the subpackage.
600 ExpectedCount
= SubPackage
->Package
.Count
;
601 (*SubElements
)->Integer
.Value
= ExpectedCount
;
604 /* Check the type of each subpackage element */
606 Status
= AcpiNsCheckPackageElements (Info
, (SubElements
+ 1),
607 Package
->RetInfo
.ObjectType1
,
608 (ExpectedCount
- 1), 0, 0, 1);
609 if (ACPI_FAILURE (Status
))
615 default: /* Should not get here, type was validated by caller */
617 return (AE_AML_INTERNAL
);
628 /* The subpackage count was smaller than required */
630 ACPI_WARN_PREDEFINED ((AE_INFO
, Info
->FullPathname
, Info
->NodeFlags
,
631 "Return SubPackage[%u] is too small - found %u elements, expected %u",
632 i
, SubPackage
->Package
.Count
, ExpectedCount
));
634 return (AE_AML_OPERAND_VALUE
);
638 /*******************************************************************************
640 * FUNCTION: AcpiNsCustomPackage
642 * PARAMETERS: Info - Method execution information block
643 * Elements - Pointer to the package elements array
644 * Count - Element count for the package
648 * DESCRIPTION: Check a returned package object for the correct count and
649 * correct type of all sub-objects.
651 * NOTE: Currently used for the _BIX method only. When needed for two or more
652 * methods, probably a detect/dispatch mechanism will be required.
654 ******************************************************************************/
657 AcpiNsCustomPackage (
658 ACPI_EVALUATE_INFO
*Info
,
659 ACPI_OPERAND_OBJECT
**Elements
,
662 UINT32 ExpectedCount
;
664 ACPI_STATUS Status
= AE_OK
;
667 ACPI_FUNCTION_NAME (NsCustomPackage
);
670 /* Get version number, must be Integer */
672 if ((*Elements
)->Common
.Type
!= ACPI_TYPE_INTEGER
)
674 ACPI_WARN_PREDEFINED ((AE_INFO
, Info
->FullPathname
, Info
->NodeFlags
,
675 "Return Package has invalid object type for version number"));
676 return_ACPI_STATUS (AE_AML_OPERAND_TYPE
);
679 Version
= (UINT32
) (*Elements
)->Integer
.Value
;
680 ExpectedCount
= 21; /* Version 1 */
684 ExpectedCount
= 20; /* Version 0 */
687 if (Count
< ExpectedCount
)
689 ACPI_WARN_PREDEFINED ((AE_INFO
, Info
->FullPathname
, Info
->NodeFlags
,
690 "Return Package is too small - found %u elements, expected %u",
691 Count
, ExpectedCount
));
692 return_ACPI_STATUS (AE_AML_OPERAND_VALUE
);
694 else if (Count
> ExpectedCount
)
696 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR
,
697 "%s: Return Package is larger than needed - "
698 "found %u, expected %u\n",
699 Info
->FullPathname
, Count
, ExpectedCount
));
702 /* Validate all elements of the returned package */
704 Status
= AcpiNsCheckPackageElements (Info
, Elements
,
705 ACPI_RTYPE_INTEGER
, 16,
706 ACPI_RTYPE_STRING
, 4, 0);
707 if (ACPI_FAILURE (Status
))
709 return_ACPI_STATUS (Status
);
712 /* Version 1 has a single trailing integer */
716 Status
= AcpiNsCheckPackageElements (Info
, Elements
+ 20,
717 ACPI_RTYPE_INTEGER
, 1, 0, 0, 20);
720 return_ACPI_STATUS (Status
);
724 /*******************************************************************************
726 * FUNCTION: AcpiNsCheckPackageElements
728 * PARAMETERS: Info - Method execution information block
729 * Elements - Pointer to the package elements array
730 * Type1 - Object type for first group
731 * Count1 - Count for first group
732 * Type2 - Object type for second group
733 * Count2 - Count for second group
734 * StartIndex - Start of the first group of elements
738 * DESCRIPTION: Check that all elements of a package are of the correct object
739 * type. Supports up to two groups of different object types.
741 ******************************************************************************/
744 AcpiNsCheckPackageElements (
745 ACPI_EVALUATE_INFO
*Info
,
746 ACPI_OPERAND_OBJECT
**Elements
,
753 ACPI_OPERAND_OBJECT
**ThisElement
= Elements
;
759 * Up to two groups of package elements are supported by the data
760 * structure. All elements in each group must be of the same type.
761 * The second group can have a count of zero.
763 for (i
= 0; i
< Count1
; i
++)
765 Status
= AcpiNsCheckObjectType (Info
, ThisElement
,
766 Type1
, i
+ StartIndex
);
767 if (ACPI_FAILURE (Status
))
775 for (i
= 0; i
< Count2
; i
++)
777 Status
= AcpiNsCheckObjectType (Info
, ThisElement
,
778 Type2
, (i
+ Count1
+ StartIndex
));
779 if (ACPI_FAILURE (Status
))