195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
242f8fb75SBob Moore /******************************************************************************
342f8fb75SBob Moore *
442f8fb75SBob Moore * Module Name: nsprepkg - Validation of package objects for predefined names
542f8fb75SBob Moore *
6*612c2932SBob Moore * Copyright (C) 2000 - 2023, Intel Corp.
742f8fb75SBob Moore *
895857638SErik Schmauss *****************************************************************************/
942f8fb75SBob Moore
1042f8fb75SBob Moore #include <acpi/acpi.h>
1142f8fb75SBob Moore #include "accommon.h"
1242f8fb75SBob Moore #include "acnamesp.h"
1342f8fb75SBob Moore #include "acpredef.h"
1442f8fb75SBob Moore
1542f8fb75SBob Moore #define _COMPONENT ACPI_NAMESPACE
1642f8fb75SBob Moore ACPI_MODULE_NAME("nsprepkg")
1742f8fb75SBob Moore
1842f8fb75SBob Moore /* Local prototypes */
1942f8fb75SBob Moore static acpi_status
2029a241ccSBob Moore acpi_ns_check_package_list(struct acpi_evaluate_info *info,
2142f8fb75SBob Moore const union acpi_predefined_info *package,
2242f8fb75SBob Moore union acpi_operand_object **elements, u32 count);
2342f8fb75SBob Moore
2442f8fb75SBob Moore static acpi_status
2529a241ccSBob Moore acpi_ns_check_package_elements(struct acpi_evaluate_info *info,
2642f8fb75SBob Moore union acpi_operand_object **elements,
2742f8fb75SBob Moore u8 type1,
2842f8fb75SBob Moore u32 count1,
2942f8fb75SBob Moore u8 type2, u32 count2, u32 start_index);
3042f8fb75SBob Moore
317952d402SBob Moore static acpi_status
327952d402SBob Moore acpi_ns_custom_package(struct acpi_evaluate_info *info,
337952d402SBob Moore union acpi_operand_object **elements, u32 count);
347952d402SBob Moore
3542f8fb75SBob Moore /*******************************************************************************
3642f8fb75SBob Moore *
3742f8fb75SBob Moore * FUNCTION: acpi_ns_check_package
3842f8fb75SBob Moore *
3929a241ccSBob Moore * PARAMETERS: info - Method execution information block
4042f8fb75SBob Moore * return_object_ptr - Pointer to the object returned from the
4142f8fb75SBob Moore * evaluation of a method or object
4242f8fb75SBob Moore *
4342f8fb75SBob Moore * RETURN: Status
4442f8fb75SBob Moore *
4542f8fb75SBob Moore * DESCRIPTION: Check a returned package object for the correct count and
4642f8fb75SBob Moore * correct type of all sub-objects.
4742f8fb75SBob Moore *
4842f8fb75SBob Moore ******************************************************************************/
4942f8fb75SBob Moore
5042f8fb75SBob Moore acpi_status
acpi_ns_check_package(struct acpi_evaluate_info * info,union acpi_operand_object ** return_object_ptr)5129a241ccSBob Moore acpi_ns_check_package(struct acpi_evaluate_info *info,
5242f8fb75SBob Moore union acpi_operand_object **return_object_ptr)
5342f8fb75SBob Moore {
5442f8fb75SBob Moore union acpi_operand_object *return_object = *return_object_ptr;
5542f8fb75SBob Moore const union acpi_predefined_info *package;
5642f8fb75SBob Moore union acpi_operand_object **elements;
5742f8fb75SBob Moore acpi_status status = AE_OK;
5842f8fb75SBob Moore u32 expected_count;
5942f8fb75SBob Moore u32 count;
6042f8fb75SBob Moore u32 i;
6142f8fb75SBob Moore
620766efdfSErik Kaneda ACPI_FUNCTION_TRACE(ns_check_package);
6342f8fb75SBob Moore
6442f8fb75SBob Moore /* The package info for this name is in the next table entry */
6542f8fb75SBob Moore
6629a241ccSBob Moore package = info->predefined + 1;
6742f8fb75SBob Moore
6842f8fb75SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
6942f8fb75SBob Moore "%s Validating return Package of Type %X, Count %X\n",
7029a241ccSBob Moore info->full_pathname, package->ret_info.type,
7142f8fb75SBob Moore return_object->package.count));
7242f8fb75SBob Moore
7342f8fb75SBob Moore /*
7442f8fb75SBob Moore * For variable-length Packages, we can safely remove all embedded
7542f8fb75SBob Moore * and trailing NULL package elements
7642f8fb75SBob Moore */
7729a241ccSBob Moore acpi_ns_remove_null_elements(info, package->ret_info.type,
7842f8fb75SBob Moore return_object);
7942f8fb75SBob Moore
8042f8fb75SBob Moore /* Extract package count and elements array */
8142f8fb75SBob Moore
8242f8fb75SBob Moore elements = return_object->package.elements;
8342f8fb75SBob Moore count = return_object->package.count;
8442f8fb75SBob Moore
8502d4fb36SBob Moore /*
8602d4fb36SBob Moore * Most packages must have at least one element. The only exception
8702d4fb36SBob Moore * is the variable-length package (ACPI_PTYPE1_VAR).
8802d4fb36SBob Moore */
8942f8fb75SBob Moore if (!count) {
9002d4fb36SBob Moore if (package->ret_info.type == ACPI_PTYPE1_VAR) {
910766efdfSErik Kaneda return_ACPI_STATUS(AE_OK);
9202d4fb36SBob Moore }
9302d4fb36SBob Moore
9429a241ccSBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
9529a241ccSBob Moore info->node_flags,
9642f8fb75SBob Moore "Return Package has no elements (empty)"));
9742f8fb75SBob Moore
980766efdfSErik Kaneda return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
9942f8fb75SBob Moore }
10042f8fb75SBob Moore
10142f8fb75SBob Moore /*
10242f8fb75SBob Moore * Decode the type of the expected package contents
10342f8fb75SBob Moore *
10442f8fb75SBob Moore * PTYPE1 packages contain no subpackages
1050a16d12aSBob Moore * PTYPE2 packages contain subpackages
10642f8fb75SBob Moore */
10742f8fb75SBob Moore switch (package->ret_info.type) {
1087952d402SBob Moore case ACPI_PTYPE_CUSTOM:
1097952d402SBob Moore
1107952d402SBob Moore status = acpi_ns_custom_package(info, elements, count);
1117952d402SBob Moore break;
1127952d402SBob Moore
11342f8fb75SBob Moore case ACPI_PTYPE1_FIXED:
11442f8fb75SBob Moore /*
1150a16d12aSBob Moore * The package count is fixed and there are no subpackages
11642f8fb75SBob Moore *
11742f8fb75SBob Moore * If package is too small, exit.
11842f8fb75SBob Moore * If package is larger than expected, issue warning but continue
11942f8fb75SBob Moore */
12042f8fb75SBob Moore expected_count =
12142f8fb75SBob Moore package->ret_info.count1 + package->ret_info.count2;
12242f8fb75SBob Moore if (count < expected_count) {
12342f8fb75SBob Moore goto package_too_small;
12442f8fb75SBob Moore } else if (count > expected_count) {
12542f8fb75SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
12642f8fb75SBob Moore "%s: Return Package is larger than needed - "
12742f8fb75SBob Moore "found %u, expected %u\n",
12829a241ccSBob Moore info->full_pathname, count,
12942f8fb75SBob Moore expected_count));
13042f8fb75SBob Moore }
13142f8fb75SBob Moore
13242f8fb75SBob Moore /* Validate all elements of the returned package */
13342f8fb75SBob Moore
13429a241ccSBob Moore status = acpi_ns_check_package_elements(info, elements,
13542f8fb75SBob Moore package->ret_info.
13642f8fb75SBob Moore object_type1,
13742f8fb75SBob Moore package->ret_info.
13842f8fb75SBob Moore count1,
13942f8fb75SBob Moore package->ret_info.
14042f8fb75SBob Moore object_type2,
14142f8fb75SBob Moore package->ret_info.
14242f8fb75SBob Moore count2, 0);
14342f8fb75SBob Moore break;
14442f8fb75SBob Moore
14542f8fb75SBob Moore case ACPI_PTYPE1_VAR:
14642f8fb75SBob Moore /*
1470a16d12aSBob Moore * The package count is variable, there are no subpackages, and all
14842f8fb75SBob Moore * elements must be of the same type
14942f8fb75SBob Moore */
15042f8fb75SBob Moore for (i = 0; i < count; i++) {
15129a241ccSBob Moore status = acpi_ns_check_object_type(info, elements,
15242f8fb75SBob Moore package->ret_info.
15342f8fb75SBob Moore object_type1, i);
15442f8fb75SBob Moore if (ACPI_FAILURE(status)) {
1550766efdfSErik Kaneda return_ACPI_STATUS(status);
15642f8fb75SBob Moore }
1572156510fSBob Moore
15842f8fb75SBob Moore elements++;
15942f8fb75SBob Moore }
16042f8fb75SBob Moore break;
16142f8fb75SBob Moore
16242f8fb75SBob Moore case ACPI_PTYPE1_OPTION:
16342f8fb75SBob Moore /*
1640a16d12aSBob Moore * The package count is variable, there are no subpackages. There are
16542f8fb75SBob Moore * a fixed number of required elements, and a variable number of
16642f8fb75SBob Moore * optional elements.
16742f8fb75SBob Moore *
16842f8fb75SBob Moore * Check if package is at least as large as the minimum required
16942f8fb75SBob Moore */
17042f8fb75SBob Moore expected_count = package->ret_info3.count;
17142f8fb75SBob Moore if (count < expected_count) {
17242f8fb75SBob Moore goto package_too_small;
17342f8fb75SBob Moore }
17442f8fb75SBob Moore
17542f8fb75SBob Moore /* Variable number of sub-objects */
17642f8fb75SBob Moore
17742f8fb75SBob Moore for (i = 0; i < count; i++) {
17842f8fb75SBob Moore if (i < package->ret_info3.count) {
17942f8fb75SBob Moore
18042f8fb75SBob Moore /* These are the required package elements (0, 1, or 2) */
18142f8fb75SBob Moore
18242f8fb75SBob Moore status =
18329a241ccSBob Moore acpi_ns_check_object_type(info, elements,
18442f8fb75SBob Moore package->
18542f8fb75SBob Moore ret_info3.
18642f8fb75SBob Moore object_type[i],
18742f8fb75SBob Moore i);
18842f8fb75SBob Moore if (ACPI_FAILURE(status)) {
1890766efdfSErik Kaneda return_ACPI_STATUS(status);
19042f8fb75SBob Moore }
19142f8fb75SBob Moore } else {
19242f8fb75SBob Moore /* These are the optional package elements */
19342f8fb75SBob Moore
19442f8fb75SBob Moore status =
19529a241ccSBob Moore acpi_ns_check_object_type(info, elements,
19642f8fb75SBob Moore package->
19742f8fb75SBob Moore ret_info3.
19842f8fb75SBob Moore tail_object_type,
19942f8fb75SBob Moore i);
20042f8fb75SBob Moore if (ACPI_FAILURE(status)) {
2010766efdfSErik Kaneda return_ACPI_STATUS(status);
20242f8fb75SBob Moore }
20342f8fb75SBob Moore }
2042156510fSBob Moore
20542f8fb75SBob Moore elements++;
20642f8fb75SBob Moore }
20742f8fb75SBob Moore break;
20842f8fb75SBob Moore
20942f8fb75SBob Moore case ACPI_PTYPE2_REV_FIXED:
21042f8fb75SBob Moore
21142f8fb75SBob Moore /* First element is the (Integer) revision */
21242f8fb75SBob Moore
2131fad8738SBob Moore status =
2141fad8738SBob Moore acpi_ns_check_object_type(info, elements,
21542f8fb75SBob Moore ACPI_RTYPE_INTEGER, 0);
21642f8fb75SBob Moore if (ACPI_FAILURE(status)) {
2170766efdfSErik Kaneda return_ACPI_STATUS(status);
21842f8fb75SBob Moore }
21942f8fb75SBob Moore
22042f8fb75SBob Moore elements++;
22142f8fb75SBob Moore count--;
22242f8fb75SBob Moore
2230a16d12aSBob Moore /* Examine the subpackages */
22442f8fb75SBob Moore
22542f8fb75SBob Moore status =
22629a241ccSBob Moore acpi_ns_check_package_list(info, package, elements, count);
22742f8fb75SBob Moore break;
22842f8fb75SBob Moore
22942f8fb75SBob Moore case ACPI_PTYPE2_PKG_COUNT:
23042f8fb75SBob Moore
2310a16d12aSBob Moore /* First element is the (Integer) count of subpackages to follow */
23242f8fb75SBob Moore
2331fad8738SBob Moore status =
2341fad8738SBob Moore acpi_ns_check_object_type(info, elements,
23542f8fb75SBob Moore ACPI_RTYPE_INTEGER, 0);
23642f8fb75SBob Moore if (ACPI_FAILURE(status)) {
2370766efdfSErik Kaneda return_ACPI_STATUS(status);
23842f8fb75SBob Moore }
23942f8fb75SBob Moore
24042f8fb75SBob Moore /*
24142f8fb75SBob Moore * Count cannot be larger than the parent package length, but allow it
24242f8fb75SBob Moore * to be smaller. The >= accounts for the Integer above.
24342f8fb75SBob Moore */
24442f8fb75SBob Moore expected_count = (u32)(*elements)->integer.value;
24542f8fb75SBob Moore if (expected_count >= count) {
24642f8fb75SBob Moore goto package_too_small;
24742f8fb75SBob Moore }
24842f8fb75SBob Moore
24942f8fb75SBob Moore count = expected_count;
25042f8fb75SBob Moore elements++;
25142f8fb75SBob Moore
2520a16d12aSBob Moore /* Examine the subpackages */
25342f8fb75SBob Moore
25442f8fb75SBob Moore status =
25529a241ccSBob Moore acpi_ns_check_package_list(info, package, elements, count);
25642f8fb75SBob Moore break;
25742f8fb75SBob Moore
25842f8fb75SBob Moore case ACPI_PTYPE2:
25942f8fb75SBob Moore case ACPI_PTYPE2_FIXED:
26042f8fb75SBob Moore case ACPI_PTYPE2_MIN:
26142f8fb75SBob Moore case ACPI_PTYPE2_COUNT:
26242f8fb75SBob Moore case ACPI_PTYPE2_FIX_VAR:
26342f8fb75SBob Moore /*
26442f8fb75SBob Moore * These types all return a single Package that consists of a
2650a16d12aSBob Moore * variable number of subpackages.
26642f8fb75SBob Moore *
2670a16d12aSBob Moore * First, ensure that the first element is a subpackage. If not,
26842f8fb75SBob Moore * the BIOS may have incorrectly returned the object as a single
26942f8fb75SBob Moore * package instead of a Package of Packages (a common error if
27042f8fb75SBob Moore * there is only one entry). We may be able to repair this by
27142f8fb75SBob Moore * wrapping the returned Package with a new outer Package.
27242f8fb75SBob Moore */
27342f8fb75SBob Moore if (*elements
27442f8fb75SBob Moore && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) {
27542f8fb75SBob Moore
27642f8fb75SBob Moore /* Create the new outer package and populate it */
27742f8fb75SBob Moore
27842f8fb75SBob Moore status =
27929a241ccSBob Moore acpi_ns_wrap_with_package(info, return_object,
28042f8fb75SBob Moore return_object_ptr);
28142f8fb75SBob Moore if (ACPI_FAILURE(status)) {
2820766efdfSErik Kaneda return_ACPI_STATUS(status);
28342f8fb75SBob Moore }
28442f8fb75SBob Moore
28542f8fb75SBob Moore /* Update locals to point to the new package (of 1 element) */
28642f8fb75SBob Moore
28742f8fb75SBob Moore return_object = *return_object_ptr;
28842f8fb75SBob Moore elements = return_object->package.elements;
28942f8fb75SBob Moore count = 1;
29042f8fb75SBob Moore }
29142f8fb75SBob Moore
2920a16d12aSBob Moore /* Examine the subpackages */
29342f8fb75SBob Moore
29442f8fb75SBob Moore status =
29529a241ccSBob Moore acpi_ns_check_package_list(info, package, elements, count);
29642f8fb75SBob Moore break;
29742f8fb75SBob Moore
298e34a7813SBob Moore case ACPI_PTYPE2_VAR_VAR:
299e34a7813SBob Moore /*
300e34a7813SBob Moore * Returns a variable list of packages, each with a variable list
301e34a7813SBob Moore * of objects.
302e34a7813SBob Moore */
303e34a7813SBob Moore break;
304e34a7813SBob Moore
305b1272e1fSMika Westerberg case ACPI_PTYPE2_UUID_PAIR:
306b1272e1fSMika Westerberg
307b1272e1fSMika Westerberg /* The package must contain pairs of (UUID + type) */
308b1272e1fSMika Westerberg
309b1272e1fSMika Westerberg if (count & 1) {
310b1272e1fSMika Westerberg expected_count = count + 1;
311b1272e1fSMika Westerberg goto package_too_small;
312b1272e1fSMika Westerberg }
313b1272e1fSMika Westerberg
314b1272e1fSMika Westerberg while (count > 0) {
315b1272e1fSMika Westerberg status = acpi_ns_check_object_type(info, elements,
316b1272e1fSMika Westerberg package->ret_info.
317b1272e1fSMika Westerberg object_type1, 0);
318b1272e1fSMika Westerberg if (ACPI_FAILURE(status)) {
3190766efdfSErik Kaneda return_ACPI_STATUS(status);
320b1272e1fSMika Westerberg }
321b1272e1fSMika Westerberg
322b1272e1fSMika Westerberg /* Validate length of the UUID buffer */
323b1272e1fSMika Westerberg
324b1272e1fSMika Westerberg if ((*elements)->buffer.length != 16) {
325b1272e1fSMika Westerberg ACPI_WARN_PREDEFINED((AE_INFO,
326b1272e1fSMika Westerberg info->full_pathname,
327b1272e1fSMika Westerberg info->node_flags,
328b1272e1fSMika Westerberg "Invalid length for UUID Buffer"));
3290766efdfSErik Kaneda return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
330b1272e1fSMika Westerberg }
331b1272e1fSMika Westerberg
332b1272e1fSMika Westerberg status = acpi_ns_check_object_type(info, elements + 1,
333b1272e1fSMika Westerberg package->ret_info.
334b1272e1fSMika Westerberg object_type2, 0);
335b1272e1fSMika Westerberg if (ACPI_FAILURE(status)) {
3360766efdfSErik Kaneda return_ACPI_STATUS(status);
337b1272e1fSMika Westerberg }
338b1272e1fSMika Westerberg
339b1272e1fSMika Westerberg elements += 2;
340b1272e1fSMika Westerberg count -= 2;
341b1272e1fSMika Westerberg }
342b1272e1fSMika Westerberg break;
343b1272e1fSMika Westerberg
34442f8fb75SBob Moore default:
34542f8fb75SBob Moore
34642f8fb75SBob Moore /* Should not get here if predefined info table is correct */
34742f8fb75SBob Moore
34829a241ccSBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
34929a241ccSBob Moore info->node_flags,
35042f8fb75SBob Moore "Invalid internal return type in table entry: %X",
35142f8fb75SBob Moore package->ret_info.type));
35242f8fb75SBob Moore
3530766efdfSErik Kaneda return_ACPI_STATUS(AE_AML_INTERNAL);
35442f8fb75SBob Moore }
35542f8fb75SBob Moore
3560766efdfSErik Kaneda return_ACPI_STATUS(status);
35742f8fb75SBob Moore
35842f8fb75SBob Moore package_too_small:
35942f8fb75SBob Moore
36042f8fb75SBob Moore /* Error exit for the case with an incorrect package count */
36142f8fb75SBob Moore
36229a241ccSBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags,
36342f8fb75SBob Moore "Return Package is too small - found %u elements, expected %u",
36442f8fb75SBob Moore count, expected_count));
36542f8fb75SBob Moore
3660766efdfSErik Kaneda return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
36742f8fb75SBob Moore }
36842f8fb75SBob Moore
36942f8fb75SBob Moore /*******************************************************************************
37042f8fb75SBob Moore *
37142f8fb75SBob Moore * FUNCTION: acpi_ns_check_package_list
37242f8fb75SBob Moore *
37329a241ccSBob Moore * PARAMETERS: info - Method execution information block
37442f8fb75SBob Moore * package - Pointer to package-specific info for method
37542f8fb75SBob Moore * elements - Element list of parent package. All elements
37642f8fb75SBob Moore * of this list should be of type Package.
37742f8fb75SBob Moore * count - Count of subpackages
37842f8fb75SBob Moore *
37942f8fb75SBob Moore * RETURN: Status
38042f8fb75SBob Moore *
38142f8fb75SBob Moore * DESCRIPTION: Examine a list of subpackages
38242f8fb75SBob Moore *
38342f8fb75SBob Moore ******************************************************************************/
38442f8fb75SBob Moore
38542f8fb75SBob Moore static acpi_status
acpi_ns_check_package_list(struct acpi_evaluate_info * info,const union acpi_predefined_info * package,union acpi_operand_object ** elements,u32 count)38629a241ccSBob Moore acpi_ns_check_package_list(struct acpi_evaluate_info *info,
38742f8fb75SBob Moore const union acpi_predefined_info *package,
38842f8fb75SBob Moore union acpi_operand_object **elements, u32 count)
38942f8fb75SBob Moore {
39042f8fb75SBob Moore union acpi_operand_object *sub_package;
39142f8fb75SBob Moore union acpi_operand_object **sub_elements;
39242f8fb75SBob Moore acpi_status status;
39342f8fb75SBob Moore u32 expected_count;
39442f8fb75SBob Moore u32 i;
39542f8fb75SBob Moore u32 j;
39642f8fb75SBob Moore
39742f8fb75SBob Moore /*
3980a16d12aSBob Moore * Validate each subpackage in the parent Package
39942f8fb75SBob Moore *
4000a16d12aSBob Moore * NOTE: assumes list of subpackages contains no NULL elements.
40142f8fb75SBob Moore * Any NULL elements should have been removed by earlier call
40242f8fb75SBob Moore * to acpi_ns_remove_null_elements.
40342f8fb75SBob Moore */
40442f8fb75SBob Moore for (i = 0; i < count; i++) {
40542f8fb75SBob Moore sub_package = *elements;
40642f8fb75SBob Moore sub_elements = sub_package->package.elements;
40729a241ccSBob Moore info->parent_package = sub_package;
40842f8fb75SBob Moore
40942f8fb75SBob Moore /* Each sub-object must be of type Package */
41042f8fb75SBob Moore
41129a241ccSBob Moore status = acpi_ns_check_object_type(info, &sub_package,
41242f8fb75SBob Moore ACPI_RTYPE_PACKAGE, i);
41342f8fb75SBob Moore if (ACPI_FAILURE(status)) {
41442f8fb75SBob Moore return (status);
41542f8fb75SBob Moore }
41642f8fb75SBob Moore
4170a16d12aSBob Moore /* Examine the different types of expected subpackages */
41842f8fb75SBob Moore
41929a241ccSBob Moore info->parent_package = sub_package;
42042f8fb75SBob Moore switch (package->ret_info.type) {
42142f8fb75SBob Moore case ACPI_PTYPE2:
42242f8fb75SBob Moore case ACPI_PTYPE2_PKG_COUNT:
42342f8fb75SBob Moore case ACPI_PTYPE2_REV_FIXED:
42442f8fb75SBob Moore
42542f8fb75SBob Moore /* Each subpackage has a fixed number of elements */
42642f8fb75SBob Moore
42742f8fb75SBob Moore expected_count =
42842f8fb75SBob Moore package->ret_info.count1 + package->ret_info.count2;
42942f8fb75SBob Moore if (sub_package->package.count < expected_count) {
43042f8fb75SBob Moore goto package_too_small;
43142f8fb75SBob Moore }
43242f8fb75SBob Moore
43342f8fb75SBob Moore status =
43429a241ccSBob Moore acpi_ns_check_package_elements(info, sub_elements,
43542f8fb75SBob Moore package->ret_info.
43642f8fb75SBob Moore object_type1,
43742f8fb75SBob Moore package->ret_info.
43842f8fb75SBob Moore count1,
43942f8fb75SBob Moore package->ret_info.
44042f8fb75SBob Moore object_type2,
44142f8fb75SBob Moore package->ret_info.
44242f8fb75SBob Moore count2, 0);
44342f8fb75SBob Moore if (ACPI_FAILURE(status)) {
44442f8fb75SBob Moore return (status);
44542f8fb75SBob Moore }
44642f8fb75SBob Moore break;
44742f8fb75SBob Moore
44842f8fb75SBob Moore case ACPI_PTYPE2_FIX_VAR:
44942f8fb75SBob Moore /*
45042f8fb75SBob Moore * Each subpackage has a fixed number of elements and an
45142f8fb75SBob Moore * optional element
45242f8fb75SBob Moore */
45342f8fb75SBob Moore expected_count =
45442f8fb75SBob Moore package->ret_info.count1 + package->ret_info.count2;
45542f8fb75SBob Moore if (sub_package->package.count < expected_count) {
45642f8fb75SBob Moore goto package_too_small;
45742f8fb75SBob Moore }
45842f8fb75SBob Moore
45942f8fb75SBob Moore status =
46029a241ccSBob Moore acpi_ns_check_package_elements(info, sub_elements,
46142f8fb75SBob Moore package->ret_info.
46242f8fb75SBob Moore object_type1,
46342f8fb75SBob Moore package->ret_info.
46442f8fb75SBob Moore count1,
46542f8fb75SBob Moore package->ret_info.
46642f8fb75SBob Moore object_type2,
46742f8fb75SBob Moore sub_package->package.
46842f8fb75SBob Moore count -
46942f8fb75SBob Moore package->ret_info.
47042f8fb75SBob Moore count1, 0);
47142f8fb75SBob Moore if (ACPI_FAILURE(status)) {
47242f8fb75SBob Moore return (status);
47342f8fb75SBob Moore }
47442f8fb75SBob Moore break;
47542f8fb75SBob Moore
476e34a7813SBob Moore case ACPI_PTYPE2_VAR_VAR:
477e34a7813SBob Moore /*
478e34a7813SBob Moore * Each subpackage has a fixed or variable number of elements
479e34a7813SBob Moore */
480e34a7813SBob Moore break;
481e34a7813SBob Moore
48242f8fb75SBob Moore case ACPI_PTYPE2_FIXED:
48342f8fb75SBob Moore
4840a16d12aSBob Moore /* Each subpackage has a fixed length */
48542f8fb75SBob Moore
48642f8fb75SBob Moore expected_count = package->ret_info2.count;
48742f8fb75SBob Moore if (sub_package->package.count < expected_count) {
48842f8fb75SBob Moore goto package_too_small;
48942f8fb75SBob Moore }
49042f8fb75SBob Moore
4910a16d12aSBob Moore /* Check the type of each subpackage element */
49242f8fb75SBob Moore
49342f8fb75SBob Moore for (j = 0; j < expected_count; j++) {
49442f8fb75SBob Moore status =
49529a241ccSBob Moore acpi_ns_check_object_type(info,
49642f8fb75SBob Moore &sub_elements[j],
49742f8fb75SBob Moore package->
49842f8fb75SBob Moore ret_info2.
49942f8fb75SBob Moore object_type[j],
50042f8fb75SBob Moore j);
50142f8fb75SBob Moore if (ACPI_FAILURE(status)) {
50242f8fb75SBob Moore return (status);
50342f8fb75SBob Moore }
50442f8fb75SBob Moore }
50542f8fb75SBob Moore break;
50642f8fb75SBob Moore
50742f8fb75SBob Moore case ACPI_PTYPE2_MIN:
50842f8fb75SBob Moore
5090a16d12aSBob Moore /* Each subpackage has a variable but minimum length */
51042f8fb75SBob Moore
51142f8fb75SBob Moore expected_count = package->ret_info.count1;
51242f8fb75SBob Moore if (sub_package->package.count < expected_count) {
51342f8fb75SBob Moore goto package_too_small;
51442f8fb75SBob Moore }
51542f8fb75SBob Moore
5160a16d12aSBob Moore /* Check the type of each subpackage element */
51742f8fb75SBob Moore
51842f8fb75SBob Moore status =
51929a241ccSBob Moore acpi_ns_check_package_elements(info, sub_elements,
52042f8fb75SBob Moore package->ret_info.
52142f8fb75SBob Moore object_type1,
52242f8fb75SBob Moore sub_package->package.
52342f8fb75SBob Moore count, 0, 0, 0);
52442f8fb75SBob Moore if (ACPI_FAILURE(status)) {
52542f8fb75SBob Moore return (status);
52642f8fb75SBob Moore }
52742f8fb75SBob Moore break;
52842f8fb75SBob Moore
52942f8fb75SBob Moore case ACPI_PTYPE2_COUNT:
53042f8fb75SBob Moore /*
53142f8fb75SBob Moore * First element is the (Integer) count of elements, including
53242f8fb75SBob Moore * the count field (the ACPI name is num_elements)
53342f8fb75SBob Moore */
53429a241ccSBob Moore status = acpi_ns_check_object_type(info, sub_elements,
53542f8fb75SBob Moore ACPI_RTYPE_INTEGER,
53642f8fb75SBob Moore 0);
53742f8fb75SBob Moore if (ACPI_FAILURE(status)) {
53842f8fb75SBob Moore return (status);
53942f8fb75SBob Moore }
54042f8fb75SBob Moore
54142f8fb75SBob Moore /*
54242f8fb75SBob Moore * Make sure package is large enough for the Count and is
54342f8fb75SBob Moore * is as large as the minimum size
54442f8fb75SBob Moore */
54542f8fb75SBob Moore expected_count = (u32)(*sub_elements)->integer.value;
54642f8fb75SBob Moore if (sub_package->package.count < expected_count) {
54742f8fb75SBob Moore goto package_too_small;
54842f8fb75SBob Moore }
5492156510fSBob Moore
55042f8fb75SBob Moore if (sub_package->package.count <
55142f8fb75SBob Moore package->ret_info.count1) {
55242f8fb75SBob Moore expected_count = package->ret_info.count1;
55342f8fb75SBob Moore goto package_too_small;
55442f8fb75SBob Moore }
5552156510fSBob Moore
55642f8fb75SBob Moore if (expected_count == 0) {
55742f8fb75SBob Moore /*
55842f8fb75SBob Moore * Either the num_entries element was originally zero or it was
55942f8fb75SBob Moore * a NULL element and repaired to an Integer of value zero.
56042f8fb75SBob Moore * In either case, repair it by setting num_entries to be the
56142f8fb75SBob Moore * actual size of the subpackage.
56242f8fb75SBob Moore */
56342f8fb75SBob Moore expected_count = sub_package->package.count;
56442f8fb75SBob Moore (*sub_elements)->integer.value = expected_count;
56542f8fb75SBob Moore }
56642f8fb75SBob Moore
5670a16d12aSBob Moore /* Check the type of each subpackage element */
56842f8fb75SBob Moore
56942f8fb75SBob Moore status =
57029a241ccSBob Moore acpi_ns_check_package_elements(info,
57142f8fb75SBob Moore (sub_elements + 1),
57242f8fb75SBob Moore package->ret_info.
57342f8fb75SBob Moore object_type1,
57442f8fb75SBob Moore (expected_count - 1),
57542f8fb75SBob Moore 0, 0, 1);
57642f8fb75SBob Moore if (ACPI_FAILURE(status)) {
57742f8fb75SBob Moore return (status);
57842f8fb75SBob Moore }
57942f8fb75SBob Moore break;
58042f8fb75SBob Moore
58142f8fb75SBob Moore default: /* Should not get here, type was validated by caller */
58242f8fb75SBob Moore
583376a588cSBob Moore ACPI_ERROR((AE_INFO, "Invalid Package type: %X",
584376a588cSBob Moore package->ret_info.type));
58542f8fb75SBob Moore return (AE_AML_INTERNAL);
58642f8fb75SBob Moore }
58742f8fb75SBob Moore
58842f8fb75SBob Moore elements++;
58942f8fb75SBob Moore }
59042f8fb75SBob Moore
59142f8fb75SBob Moore return (AE_OK);
59242f8fb75SBob Moore
59342f8fb75SBob Moore package_too_small:
59442f8fb75SBob Moore
5950a16d12aSBob Moore /* The subpackage count was smaller than required */
59642f8fb75SBob Moore
59729a241ccSBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags,
5980a16d12aSBob Moore "Return SubPackage[%u] is too small - found %u elements, expected %u",
59942f8fb75SBob Moore i, sub_package->package.count, expected_count));
60042f8fb75SBob Moore
60142f8fb75SBob Moore return (AE_AML_OPERAND_VALUE);
60242f8fb75SBob Moore }
60342f8fb75SBob Moore
60442f8fb75SBob Moore /*******************************************************************************
60542f8fb75SBob Moore *
6067952d402SBob Moore * FUNCTION: acpi_ns_custom_package
6077952d402SBob Moore *
6087952d402SBob Moore * PARAMETERS: info - Method execution information block
6097952d402SBob Moore * elements - Pointer to the package elements array
6107952d402SBob Moore * count - Element count for the package
6117952d402SBob Moore *
6127952d402SBob Moore * RETURN: Status
6137952d402SBob Moore *
6147952d402SBob Moore * DESCRIPTION: Check a returned package object for the correct count and
6157952d402SBob Moore * correct type of all sub-objects.
6167952d402SBob Moore *
6177952d402SBob Moore * NOTE: Currently used for the _BIX method only. When needed for two or more
6187952d402SBob Moore * methods, probably a detect/dispatch mechanism will be required.
6197952d402SBob Moore *
6207952d402SBob Moore ******************************************************************************/
6217952d402SBob Moore
6227952d402SBob Moore static acpi_status
acpi_ns_custom_package(struct acpi_evaluate_info * info,union acpi_operand_object ** elements,u32 count)6237952d402SBob Moore acpi_ns_custom_package(struct acpi_evaluate_info *info,
6247952d402SBob Moore union acpi_operand_object **elements, u32 count)
6257952d402SBob Moore {
6267952d402SBob Moore u32 expected_count;
6277952d402SBob Moore u32 version;
6287952d402SBob Moore acpi_status status = AE_OK;
6297952d402SBob Moore
6307952d402SBob Moore ACPI_FUNCTION_NAME(ns_custom_package);
6317952d402SBob Moore
6327952d402SBob Moore /* Get version number, must be Integer */
6337952d402SBob Moore
6347952d402SBob Moore if ((*elements)->common.type != ACPI_TYPE_INTEGER) {
6357952d402SBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
6367952d402SBob Moore info->node_flags,
6377952d402SBob Moore "Return Package has invalid object type for version number"));
6387952d402SBob Moore return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
6397952d402SBob Moore }
6407952d402SBob Moore
6417952d402SBob Moore version = (u32)(*elements)->integer.value;
6427952d402SBob Moore expected_count = 21; /* Version 1 */
6437952d402SBob Moore
6447952d402SBob Moore if (version == 0) {
6457952d402SBob Moore expected_count = 20; /* Version 0 */
6467952d402SBob Moore }
6477952d402SBob Moore
6487952d402SBob Moore if (count < expected_count) {
6497952d402SBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
6507952d402SBob Moore info->node_flags,
6517952d402SBob Moore "Return Package is too small - found %u elements, expected %u",
6527952d402SBob Moore count, expected_count));
6537952d402SBob Moore return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
6547952d402SBob Moore } else if (count > expected_count) {
6557952d402SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
6567952d402SBob Moore "%s: Return Package is larger than needed - "
6577952d402SBob Moore "found %u, expected %u\n",
6587952d402SBob Moore info->full_pathname, count, expected_count));
6597952d402SBob Moore }
6607952d402SBob Moore
6617952d402SBob Moore /* Validate all elements of the returned package */
6627952d402SBob Moore
6637952d402SBob Moore status = acpi_ns_check_package_elements(info, elements,
6647952d402SBob Moore ACPI_RTYPE_INTEGER, 16,
6657952d402SBob Moore ACPI_RTYPE_STRING, 4, 0);
6667952d402SBob Moore if (ACPI_FAILURE(status)) {
6677952d402SBob Moore return_ACPI_STATUS(status);
6687952d402SBob Moore }
6697952d402SBob Moore
6707952d402SBob Moore /* Version 1 has a single trailing integer */
6717952d402SBob Moore
6727952d402SBob Moore if (version > 0) {
6737952d402SBob Moore status = acpi_ns_check_package_elements(info, elements + 20,
6747952d402SBob Moore ACPI_RTYPE_INTEGER, 1,
6757952d402SBob Moore 0, 0, 20);
6767952d402SBob Moore }
6777952d402SBob Moore
6787952d402SBob Moore return_ACPI_STATUS(status);
6797952d402SBob Moore }
6807952d402SBob Moore
6817952d402SBob Moore /*******************************************************************************
6827952d402SBob Moore *
68342f8fb75SBob Moore * FUNCTION: acpi_ns_check_package_elements
68442f8fb75SBob Moore *
68529a241ccSBob Moore * PARAMETERS: info - Method execution information block
68642f8fb75SBob Moore * elements - Pointer to the package elements array
68742f8fb75SBob Moore * type1 - Object type for first group
68842f8fb75SBob Moore * count1 - Count for first group
68942f8fb75SBob Moore * type2 - Object type for second group
69042f8fb75SBob Moore * count2 - Count for second group
69142f8fb75SBob Moore * start_index - Start of the first group of elements
69242f8fb75SBob Moore *
69342f8fb75SBob Moore * RETURN: Status
69442f8fb75SBob Moore *
69542f8fb75SBob Moore * DESCRIPTION: Check that all elements of a package are of the correct object
69642f8fb75SBob Moore * type. Supports up to two groups of different object types.
69742f8fb75SBob Moore *
69842f8fb75SBob Moore ******************************************************************************/
69942f8fb75SBob Moore
70042f8fb75SBob Moore static acpi_status
acpi_ns_check_package_elements(struct acpi_evaluate_info * info,union acpi_operand_object ** elements,u8 type1,u32 count1,u8 type2,u32 count2,u32 start_index)70129a241ccSBob Moore acpi_ns_check_package_elements(struct acpi_evaluate_info *info,
70242f8fb75SBob Moore union acpi_operand_object **elements,
70342f8fb75SBob Moore u8 type1,
70442f8fb75SBob Moore u32 count1,
70542f8fb75SBob Moore u8 type2, u32 count2, u32 start_index)
70642f8fb75SBob Moore {
70742f8fb75SBob Moore union acpi_operand_object **this_element = elements;
70842f8fb75SBob Moore acpi_status status;
70942f8fb75SBob Moore u32 i;
71042f8fb75SBob Moore
7110766efdfSErik Kaneda ACPI_FUNCTION_TRACE(ns_check_package_elements);
7120766efdfSErik Kaneda
71342f8fb75SBob Moore /*
71442f8fb75SBob Moore * Up to two groups of package elements are supported by the data
71542f8fb75SBob Moore * structure. All elements in each group must be of the same type.
71642f8fb75SBob Moore * The second group can have a count of zero.
71742f8fb75SBob Moore */
71842f8fb75SBob Moore for (i = 0; i < count1; i++) {
71929a241ccSBob Moore status = acpi_ns_check_object_type(info, this_element,
72042f8fb75SBob Moore type1, i + start_index);
72142f8fb75SBob Moore if (ACPI_FAILURE(status)) {
7220766efdfSErik Kaneda return_ACPI_STATUS(status);
72342f8fb75SBob Moore }
7242156510fSBob Moore
72542f8fb75SBob Moore this_element++;
72642f8fb75SBob Moore }
72742f8fb75SBob Moore
72842f8fb75SBob Moore for (i = 0; i < count2; i++) {
72929a241ccSBob Moore status = acpi_ns_check_object_type(info, this_element,
73042f8fb75SBob Moore type2,
73142f8fb75SBob Moore (i + count1 + start_index));
73242f8fb75SBob Moore if (ACPI_FAILURE(status)) {
7330766efdfSErik Kaneda return_ACPI_STATUS(status);
73442f8fb75SBob Moore }
7352156510fSBob Moore
73642f8fb75SBob Moore this_element++;
73742f8fb75SBob Moore }
73842f8fb75SBob Moore
7390766efdfSErik Kaneda return_ACPI_STATUS(AE_OK);
74042f8fb75SBob Moore }
741