xref: /openbmc/linux/drivers/acpi/acpica/nsprepkg.c (revision 612c2932)
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