1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
4 * Module Name: nsprepkg - Validation of package objects for predefined names
6 * Copyright (C) 2000 - 2020, Intel Corp.
8 *****************************************************************************/
10 #include <acpi/acpi.h>
15 #define _COMPONENT ACPI_NAMESPACE
16 ACPI_MODULE_NAME("nsprepkg")
18 /* Local prototypes */
20 acpi_ns_check_package_list(struct acpi_evaluate_info
*info
,
21 const union acpi_predefined_info
*package
,
22 union acpi_operand_object
**elements
, u32 count
);
25 acpi_ns_check_package_elements(struct acpi_evaluate_info
*info
,
26 union acpi_operand_object
**elements
,
29 u8 type2
, u32 count2
, u32 start_index
);
32 acpi_ns_custom_package(struct acpi_evaluate_info
*info
,
33 union acpi_operand_object
**elements
, u32 count
);
35 /*******************************************************************************
37 * FUNCTION: acpi_ns_check_package
39 * PARAMETERS: info - Method execution information block
40 * return_object_ptr - Pointer to the object returned from the
41 * evaluation of a method or object
45 * DESCRIPTION: Check a returned package object for the correct count and
46 * correct type of all sub-objects.
48 ******************************************************************************/
51 acpi_ns_check_package(struct acpi_evaluate_info
*info
,
52 union acpi_operand_object
**return_object_ptr
)
54 union acpi_operand_object
*return_object
= *return_object_ptr
;
55 const union acpi_predefined_info
*package
;
56 union acpi_operand_object
**elements
;
57 acpi_status status
= AE_OK
;
62 ACPI_FUNCTION_TRACE(ns_check_package
);
64 /* The package info for this name is in the next table entry */
66 package
= info
->predefined
+ 1;
68 ACPI_DEBUG_PRINT((ACPI_DB_NAMES
,
69 "%s Validating return Package of Type %X, Count %X\n",
70 info
->full_pathname
, package
->ret_info
.type
,
71 return_object
->package
.count
));
74 * For variable-length Packages, we can safely remove all embedded
75 * and trailing NULL package elements
77 acpi_ns_remove_null_elements(info
, package
->ret_info
.type
,
80 /* Extract package count and elements array */
82 elements
= return_object
->package
.elements
;
83 count
= return_object
->package
.count
;
86 * Most packages must have at least one element. The only exception
87 * is the variable-length package (ACPI_PTYPE1_VAR).
90 if (package
->ret_info
.type
== ACPI_PTYPE1_VAR
) {
91 return_ACPI_STATUS(AE_OK
);
94 ACPI_WARN_PREDEFINED((AE_INFO
, info
->full_pathname
,
96 "Return Package has no elements (empty)"));
98 return_ACPI_STATUS(AE_AML_OPERAND_VALUE
);
102 * Decode the type of the expected package contents
104 * PTYPE1 packages contain no subpackages
105 * PTYPE2 packages contain subpackages
107 switch (package
->ret_info
.type
) {
108 case ACPI_PTYPE_CUSTOM
:
110 status
= acpi_ns_custom_package(info
, elements
, count
);
113 case ACPI_PTYPE1_FIXED
:
115 * The package count is fixed and there are no subpackages
117 * If package is too small, exit.
118 * If package is larger than expected, issue warning but continue
121 package
->ret_info
.count1
+ package
->ret_info
.count2
;
122 if (count
< expected_count
) {
123 goto package_too_small
;
124 } else if (count
> expected_count
) {
125 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR
,
126 "%s: Return Package is larger than needed - "
127 "found %u, expected %u\n",
128 info
->full_pathname
, count
,
132 /* Validate all elements of the returned package */
134 status
= acpi_ns_check_package_elements(info
, elements
,
145 case ACPI_PTYPE1_VAR
:
147 * The package count is variable, there are no subpackages, and all
148 * elements must be of the same type
150 for (i
= 0; i
< count
; i
++) {
151 status
= acpi_ns_check_object_type(info
, elements
,
154 if (ACPI_FAILURE(status
)) {
155 return_ACPI_STATUS(status
);
162 case ACPI_PTYPE1_OPTION
:
164 * The package count is variable, there are no subpackages. There are
165 * a fixed number of required elements, and a variable number of
168 * Check if package is at least as large as the minimum required
170 expected_count
= package
->ret_info3
.count
;
171 if (count
< expected_count
) {
172 goto package_too_small
;
175 /* Variable number of sub-objects */
177 for (i
= 0; i
< count
; i
++) {
178 if (i
< package
->ret_info3
.count
) {
180 /* These are the required package elements (0, 1, or 2) */
183 acpi_ns_check_object_type(info
, elements
,
188 if (ACPI_FAILURE(status
)) {
189 return_ACPI_STATUS(status
);
192 /* These are the optional package elements */
195 acpi_ns_check_object_type(info
, elements
,
200 if (ACPI_FAILURE(status
)) {
201 return_ACPI_STATUS(status
);
209 case ACPI_PTYPE2_REV_FIXED
:
211 /* First element is the (Integer) revision */
214 acpi_ns_check_object_type(info
, elements
,
215 ACPI_RTYPE_INTEGER
, 0);
216 if (ACPI_FAILURE(status
)) {
217 return_ACPI_STATUS(status
);
223 /* Examine the subpackages */
226 acpi_ns_check_package_list(info
, package
, elements
, count
);
229 case ACPI_PTYPE2_PKG_COUNT
:
231 /* First element is the (Integer) count of subpackages to follow */
234 acpi_ns_check_object_type(info
, elements
,
235 ACPI_RTYPE_INTEGER
, 0);
236 if (ACPI_FAILURE(status
)) {
237 return_ACPI_STATUS(status
);
241 * Count cannot be larger than the parent package length, but allow it
242 * to be smaller. The >= accounts for the Integer above.
244 expected_count
= (u32
)(*elements
)->integer
.value
;
245 if (expected_count
>= count
) {
246 goto package_too_small
;
249 count
= expected_count
;
252 /* Examine the subpackages */
255 acpi_ns_check_package_list(info
, package
, elements
, count
);
259 case ACPI_PTYPE2_FIXED
:
260 case ACPI_PTYPE2_MIN
:
261 case ACPI_PTYPE2_COUNT
:
262 case ACPI_PTYPE2_FIX_VAR
:
264 * These types all return a single Package that consists of a
265 * variable number of subpackages.
267 * First, ensure that the first element is a subpackage. If not,
268 * the BIOS may have incorrectly returned the object as a single
269 * package instead of a Package of Packages (a common error if
270 * there is only one entry). We may be able to repair this by
271 * wrapping the returned Package with a new outer Package.
274 && ((*elements
)->common
.type
!= ACPI_TYPE_PACKAGE
)) {
276 /* Create the new outer package and populate it */
279 acpi_ns_wrap_with_package(info
, return_object
,
281 if (ACPI_FAILURE(status
)) {
282 return_ACPI_STATUS(status
);
285 /* Update locals to point to the new package (of 1 element) */
287 return_object
= *return_object_ptr
;
288 elements
= return_object
->package
.elements
;
292 /* Examine the subpackages */
295 acpi_ns_check_package_list(info
, package
, elements
, count
);
298 case ACPI_PTYPE2_VAR_VAR
:
300 * Returns a variable list of packages, each with a variable list
305 case ACPI_PTYPE2_UUID_PAIR
:
307 /* The package must contain pairs of (UUID + type) */
310 expected_count
= count
+ 1;
311 goto package_too_small
;
315 status
= acpi_ns_check_object_type(info
, elements
,
318 if (ACPI_FAILURE(status
)) {
319 return_ACPI_STATUS(status
);
322 /* Validate length of the UUID buffer */
324 if ((*elements
)->buffer
.length
!= 16) {
325 ACPI_WARN_PREDEFINED((AE_INFO
,
328 "Invalid length for UUID Buffer"));
329 return_ACPI_STATUS(AE_AML_OPERAND_VALUE
);
332 status
= acpi_ns_check_object_type(info
, elements
+ 1,
335 if (ACPI_FAILURE(status
)) {
336 return_ACPI_STATUS(status
);
346 /* Should not get here if predefined info table is correct */
348 ACPI_WARN_PREDEFINED((AE_INFO
, info
->full_pathname
,
350 "Invalid internal return type in table entry: %X",
351 package
->ret_info
.type
));
353 return_ACPI_STATUS(AE_AML_INTERNAL
);
356 return_ACPI_STATUS(status
);
360 /* Error exit for the case with an incorrect package count */
362 ACPI_WARN_PREDEFINED((AE_INFO
, info
->full_pathname
, info
->node_flags
,
363 "Return Package is too small - found %u elements, expected %u",
364 count
, expected_count
));
366 return_ACPI_STATUS(AE_AML_OPERAND_VALUE
);
369 /*******************************************************************************
371 * FUNCTION: acpi_ns_check_package_list
373 * PARAMETERS: info - Method execution information block
374 * package - Pointer to package-specific info for method
375 * elements - Element list of parent package. All elements
376 * of this list should be of type Package.
377 * count - Count of subpackages
381 * DESCRIPTION: Examine a list of subpackages
383 ******************************************************************************/
386 acpi_ns_check_package_list(struct acpi_evaluate_info
*info
,
387 const union acpi_predefined_info
*package
,
388 union acpi_operand_object
**elements
, u32 count
)
390 union acpi_operand_object
*sub_package
;
391 union acpi_operand_object
**sub_elements
;
398 * Validate each subpackage in the parent Package
400 * NOTE: assumes list of subpackages contains no NULL elements.
401 * Any NULL elements should have been removed by earlier call
402 * to acpi_ns_remove_null_elements.
404 for (i
= 0; i
< count
; i
++) {
405 sub_package
= *elements
;
406 sub_elements
= sub_package
->package
.elements
;
407 info
->parent_package
= sub_package
;
409 /* Each sub-object must be of type Package */
411 status
= acpi_ns_check_object_type(info
, &sub_package
,
412 ACPI_RTYPE_PACKAGE
, i
);
413 if (ACPI_FAILURE(status
)) {
417 /* Examine the different types of expected subpackages */
419 info
->parent_package
= sub_package
;
420 switch (package
->ret_info
.type
) {
422 case ACPI_PTYPE2_PKG_COUNT
:
423 case ACPI_PTYPE2_REV_FIXED
:
425 /* Each subpackage has a fixed number of elements */
428 package
->ret_info
.count1
+ package
->ret_info
.count2
;
429 if (sub_package
->package
.count
< expected_count
) {
430 goto package_too_small
;
434 acpi_ns_check_package_elements(info
, sub_elements
,
443 if (ACPI_FAILURE(status
)) {
448 case ACPI_PTYPE2_FIX_VAR
:
450 * Each subpackage has a fixed number of elements and an
454 package
->ret_info
.count1
+ package
->ret_info
.count2
;
455 if (sub_package
->package
.count
< expected_count
) {
456 goto package_too_small
;
460 acpi_ns_check_package_elements(info
, sub_elements
,
467 sub_package
->package
.
471 if (ACPI_FAILURE(status
)) {
476 case ACPI_PTYPE2_VAR_VAR
:
478 * Each subpackage has a fixed or variable number of elements
482 case ACPI_PTYPE2_FIXED
:
484 /* Each subpackage has a fixed length */
486 expected_count
= package
->ret_info2
.count
;
487 if (sub_package
->package
.count
< expected_count
) {
488 goto package_too_small
;
491 /* Check the type of each subpackage element */
493 for (j
= 0; j
< expected_count
; j
++) {
495 acpi_ns_check_object_type(info
,
501 if (ACPI_FAILURE(status
)) {
507 case ACPI_PTYPE2_MIN
:
509 /* Each subpackage has a variable but minimum length */
511 expected_count
= package
->ret_info
.count1
;
512 if (sub_package
->package
.count
< expected_count
) {
513 goto package_too_small
;
516 /* Check the type of each subpackage element */
519 acpi_ns_check_package_elements(info
, sub_elements
,
522 sub_package
->package
.
524 if (ACPI_FAILURE(status
)) {
529 case ACPI_PTYPE2_COUNT
:
531 * First element is the (Integer) count of elements, including
532 * the count field (the ACPI name is num_elements)
534 status
= acpi_ns_check_object_type(info
, sub_elements
,
537 if (ACPI_FAILURE(status
)) {
542 * Make sure package is large enough for the Count and is
543 * is as large as the minimum size
545 expected_count
= (u32
)(*sub_elements
)->integer
.value
;
546 if (sub_package
->package
.count
< expected_count
) {
547 goto package_too_small
;
550 if (sub_package
->package
.count
<
551 package
->ret_info
.count1
) {
552 expected_count
= package
->ret_info
.count1
;
553 goto package_too_small
;
556 if (expected_count
== 0) {
558 * Either the num_entries element was originally zero or it was
559 * a NULL element and repaired to an Integer of value zero.
560 * In either case, repair it by setting num_entries to be the
561 * actual size of the subpackage.
563 expected_count
= sub_package
->package
.count
;
564 (*sub_elements
)->integer
.value
= expected_count
;
567 /* Check the type of each subpackage element */
570 acpi_ns_check_package_elements(info
,
574 (expected_count
- 1),
576 if (ACPI_FAILURE(status
)) {
581 default: /* Should not get here, type was validated by caller */
583 ACPI_ERROR((AE_INFO
, "Invalid Package type: %X",
584 package
->ret_info
.type
));
585 return (AE_AML_INTERNAL
);
595 /* The subpackage count was smaller than required */
597 ACPI_WARN_PREDEFINED((AE_INFO
, info
->full_pathname
, info
->node_flags
,
598 "Return SubPackage[%u] is too small - found %u elements, expected %u",
599 i
, sub_package
->package
.count
, expected_count
));
601 return (AE_AML_OPERAND_VALUE
);
604 /*******************************************************************************
606 * FUNCTION: acpi_ns_custom_package
608 * PARAMETERS: info - Method execution information block
609 * elements - Pointer to the package elements array
610 * count - Element count for the package
614 * DESCRIPTION: Check a returned package object for the correct count and
615 * correct type of all sub-objects.
617 * NOTE: Currently used for the _BIX method only. When needed for two or more
618 * methods, probably a detect/dispatch mechanism will be required.
620 ******************************************************************************/
623 acpi_ns_custom_package(struct acpi_evaluate_info
*info
,
624 union acpi_operand_object
**elements
, u32 count
)
628 acpi_status status
= AE_OK
;
630 ACPI_FUNCTION_NAME(ns_custom_package
);
632 /* Get version number, must be Integer */
634 if ((*elements
)->common
.type
!= ACPI_TYPE_INTEGER
) {
635 ACPI_WARN_PREDEFINED((AE_INFO
, info
->full_pathname
,
637 "Return Package has invalid object type for version number"));
638 return_ACPI_STATUS(AE_AML_OPERAND_TYPE
);
641 version
= (u32
)(*elements
)->integer
.value
;
642 expected_count
= 21; /* Version 1 */
645 expected_count
= 20; /* Version 0 */
648 if (count
< expected_count
) {
649 ACPI_WARN_PREDEFINED((AE_INFO
, info
->full_pathname
,
651 "Return Package is too small - found %u elements, expected %u",
652 count
, expected_count
));
653 return_ACPI_STATUS(AE_AML_OPERAND_VALUE
);
654 } else if (count
> expected_count
) {
655 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR
,
656 "%s: Return Package is larger than needed - "
657 "found %u, expected %u\n",
658 info
->full_pathname
, count
, expected_count
));
661 /* Validate all elements of the returned package */
663 status
= acpi_ns_check_package_elements(info
, elements
,
664 ACPI_RTYPE_INTEGER
, 16,
665 ACPI_RTYPE_STRING
, 4, 0);
666 if (ACPI_FAILURE(status
)) {
667 return_ACPI_STATUS(status
);
670 /* Version 1 has a single trailing integer */
673 status
= acpi_ns_check_package_elements(info
, elements
+ 20,
674 ACPI_RTYPE_INTEGER
, 1,
678 return_ACPI_STATUS(status
);
681 /*******************************************************************************
683 * FUNCTION: acpi_ns_check_package_elements
685 * PARAMETERS: info - Method execution information block
686 * elements - Pointer to the package elements array
687 * type1 - Object type for first group
688 * count1 - Count for first group
689 * type2 - Object type for second group
690 * count2 - Count for second group
691 * start_index - Start of the first group of elements
695 * DESCRIPTION: Check that all elements of a package are of the correct object
696 * type. Supports up to two groups of different object types.
698 ******************************************************************************/
701 acpi_ns_check_package_elements(struct acpi_evaluate_info
*info
,
702 union acpi_operand_object
**elements
,
705 u8 type2
, u32 count2
, u32 start_index
)
707 union acpi_operand_object
**this_element
= elements
;
711 ACPI_FUNCTION_TRACE(ns_check_package_elements
);
714 * Up to two groups of package elements are supported by the data
715 * structure. All elements in each group must be of the same type.
716 * The second group can have a count of zero.
718 for (i
= 0; i
< count1
; i
++) {
719 status
= acpi_ns_check_object_type(info
, this_element
,
720 type1
, i
+ start_index
);
721 if (ACPI_FAILURE(status
)) {
722 return_ACPI_STATUS(status
);
728 for (i
= 0; i
< count2
; i
++) {
729 status
= acpi_ns_check_object_type(info
, this_element
,
731 (i
+ count1
+ start_index
));
732 if (ACPI_FAILURE(status
)) {
733 return_ACPI_STATUS(status
);
739 return_ACPI_STATUS(AE_OK
);