brintos

brintos / linux-shallow public Read only

0
0
Text · 19.5 KiB · dd37fc1 Raw
741 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: nsprepkg - Validation of package objects for predefined names5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acnamesp.h"13#include "acpredef.h"14 15#define _COMPONENT          ACPI_NAMESPACE16ACPI_MODULE_NAME("nsprepkg")17 18/* Local prototypes */19static acpi_status20acpi_ns_check_package_list(struct acpi_evaluate_info *info,21			   const union acpi_predefined_info *package,22			   union acpi_operand_object **elements, u32 count);23 24static acpi_status25acpi_ns_check_package_elements(struct acpi_evaluate_info *info,26			       union acpi_operand_object **elements,27			       u8 type1,28			       u32 count1,29			       u8 type2, u32 count2, u32 start_index);30 31static acpi_status32acpi_ns_custom_package(struct acpi_evaluate_info *info,33		       union acpi_operand_object **elements, u32 count);34 35/*******************************************************************************36 *37 * FUNCTION:    acpi_ns_check_package38 *39 * PARAMETERS:  info                - Method execution information block40 *              return_object_ptr   - Pointer to the object returned from the41 *                                    evaluation of a method or object42 *43 * RETURN:      Status44 *45 * DESCRIPTION: Check a returned package object for the correct count and46 *              correct type of all sub-objects.47 *48 ******************************************************************************/49 50acpi_status51acpi_ns_check_package(struct acpi_evaluate_info *info,52		      union acpi_operand_object **return_object_ptr)53{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;58	u32 expected_count;59	u32 count;60	u32 i;61 62	ACPI_FUNCTION_TRACE(ns_check_package);63 64	/* The package info for this name is in the next table entry */65 66	package = info->predefined + 1;67 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));72 73	/*74	 * For variable-length Packages, we can safely remove all embedded75	 * and trailing NULL package elements76	 */77	acpi_ns_remove_null_elements(info, package->ret_info.type,78				     return_object);79 80	/* Extract package count and elements array */81 82	elements = return_object->package.elements;83	count = return_object->package.count;84 85	/*86	 * Most packages must have at least one element. The only exception87	 * is the variable-length package (ACPI_PTYPE1_VAR).88	 */89	if (!count) {90		if (package->ret_info.type == ACPI_PTYPE1_VAR) {91			return_ACPI_STATUS(AE_OK);92		}93 94		ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,95				      info->node_flags,96				      "Return Package has no elements (empty)"));97 98		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);99	}100 101	/*102	 * Decode the type of the expected package contents103	 *104	 * PTYPE1 packages contain no subpackages105	 * PTYPE2 packages contain subpackages106	 */107	switch (package->ret_info.type) {108	case ACPI_PTYPE_CUSTOM:109 110		status = acpi_ns_custom_package(info, elements, count);111		break;112 113	case ACPI_PTYPE1_FIXED:114		/*115		 * The package count is fixed and there are no subpackages116		 *117		 * If package is too small, exit.118		 * If package is larger than expected, issue warning but continue119		 */120		expected_count =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,129					  expected_count));130		}131 132		/* Validate all elements of the returned package */133 134		status = acpi_ns_check_package_elements(info, elements,135							package->ret_info.136							object_type1,137							package->ret_info.138							count1,139							package->ret_info.140							object_type2,141							package->ret_info.142							count2, 0);143		break;144 145	case ACPI_PTYPE1_VAR:146		/*147		 * The package count is variable, there are no subpackages, and all148		 * elements must be of the same type149		 */150		for (i = 0; i < count; i++) {151			status = acpi_ns_check_object_type(info, elements,152							   package->ret_info.153							   object_type1, i);154			if (ACPI_FAILURE(status)) {155				return_ACPI_STATUS(status);156			}157 158			elements++;159		}160		break;161 162	case ACPI_PTYPE1_OPTION:163		/*164		 * The package count is variable, there are no subpackages. There are165		 * a fixed number of required elements, and a variable number of166		 * optional elements.167		 *168		 * Check if package is at least as large as the minimum required169		 */170		expected_count = package->ret_info3.count;171		if (count < expected_count) {172			goto package_too_small;173		}174 175		/* Variable number of sub-objects */176 177		for (i = 0; i < count; i++) {178			if (i < package->ret_info3.count) {179 180				/* These are the required package elements (0, 1, or 2) */181 182				status =183				    acpi_ns_check_object_type(info, elements,184							      package->185							      ret_info3.186							      object_type[i],187							      i);188				if (ACPI_FAILURE(status)) {189					return_ACPI_STATUS(status);190				}191			} else {192				/* These are the optional package elements */193 194				status =195				    acpi_ns_check_object_type(info, elements,196							      package->197							      ret_info3.198							      tail_object_type,199							      i);200				if (ACPI_FAILURE(status)) {201					return_ACPI_STATUS(status);202				}203			}204 205			elements++;206		}207		break;208 209	case ACPI_PTYPE2_REV_FIXED:210 211		/* First element is the (Integer) revision */212 213		status =214		    acpi_ns_check_object_type(info, elements,215					      ACPI_RTYPE_INTEGER, 0);216		if (ACPI_FAILURE(status)) {217			return_ACPI_STATUS(status);218		}219 220		elements++;221		count--;222 223		/* Examine the subpackages */224 225		status =226		    acpi_ns_check_package_list(info, package, elements, count);227		break;228 229	case ACPI_PTYPE2_PKG_COUNT:230 231		/* First element is the (Integer) count of subpackages to follow */232 233		status =234		    acpi_ns_check_object_type(info, elements,235					      ACPI_RTYPE_INTEGER, 0);236		if (ACPI_FAILURE(status)) {237			return_ACPI_STATUS(status);238		}239 240		/*241		 * Count cannot be larger than the parent package length, but allow it242		 * to be smaller. The >= accounts for the Integer above.243		 */244		expected_count = (u32)(*elements)->integer.value;245		if (expected_count >= count) {246			goto package_too_small;247		}248 249		count = expected_count;250		elements++;251 252		/* Examine the subpackages */253 254		status =255		    acpi_ns_check_package_list(info, package, elements, count);256		break;257 258	case ACPI_PTYPE2:259	case ACPI_PTYPE2_FIXED:260	case ACPI_PTYPE2_MIN:261	case ACPI_PTYPE2_COUNT:262	case ACPI_PTYPE2_FIX_VAR:263		/*264		 * These types all return a single Package that consists of a265		 * variable number of subpackages.266		 *267		 * First, ensure that the first element is a subpackage. If not,268		 * the BIOS may have incorrectly returned the object as a single269		 * package instead of a Package of Packages (a common error if270		 * there is only one entry). We may be able to repair this by271		 * wrapping the returned Package with a new outer Package.272		 */273		if (*elements274		    && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) {275 276			/* Create the new outer package and populate it */277 278			status =279			    acpi_ns_wrap_with_package(info, return_object,280						      return_object_ptr);281			if (ACPI_FAILURE(status)) {282				return_ACPI_STATUS(status);283			}284 285			/* Update locals to point to the new package (of 1 element) */286 287			return_object = *return_object_ptr;288			elements = return_object->package.elements;289			count = 1;290		}291 292		/* Examine the subpackages */293 294		status =295		    acpi_ns_check_package_list(info, package, elements, count);296		break;297 298	case ACPI_PTYPE2_VAR_VAR:299		/*300		 * Returns a variable list of packages, each with a variable list301		 * of objects.302		 */303		break;304 305	case ACPI_PTYPE2_UUID_PAIR:306 307		/* The package must contain pairs of (UUID + type) */308 309		if (count & 1) {310			expected_count = count + 1;311			goto package_too_small;312		}313 314		while (count > 0) {315			status = acpi_ns_check_object_type(info, elements,316							   package->ret_info.317							   object_type1, 0);318			if (ACPI_FAILURE(status)) {319				return_ACPI_STATUS(status);320			}321 322			/* Validate length of the UUID buffer */323 324			if ((*elements)->buffer.length != 16) {325				ACPI_WARN_PREDEFINED((AE_INFO,326						      info->full_pathname,327						      info->node_flags,328						      "Invalid length for UUID Buffer"));329				return_ACPI_STATUS(AE_AML_OPERAND_VALUE);330			}331 332			status = acpi_ns_check_object_type(info, elements + 1,333							   package->ret_info.334							   object_type2, 0);335			if (ACPI_FAILURE(status)) {336				return_ACPI_STATUS(status);337			}338 339			elements += 2;340			count -= 2;341		}342		break;343 344	default:345 346		/* Should not get here if predefined info table is correct */347 348		ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,349				      info->node_flags,350				      "Invalid internal return type in table entry: %X",351				      package->ret_info.type));352 353		return_ACPI_STATUS(AE_AML_INTERNAL);354	}355 356	return_ACPI_STATUS(status);357 358package_too_small:359 360	/* Error exit for the case with an incorrect package count */361 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));365 366	return_ACPI_STATUS(AE_AML_OPERAND_VALUE);367}368 369/*******************************************************************************370 *371 * FUNCTION:    acpi_ns_check_package_list372 *373 * PARAMETERS:  info            - Method execution information block374 *              package         - Pointer to package-specific info for method375 *              elements        - Element list of parent package. All elements376 *                                of this list should be of type Package.377 *              count           - Count of subpackages378 *379 * RETURN:      Status380 *381 * DESCRIPTION: Examine a list of subpackages382 *383 ******************************************************************************/384 385static acpi_status386acpi_ns_check_package_list(struct acpi_evaluate_info *info,387			   const union acpi_predefined_info *package,388			   union acpi_operand_object **elements, u32 count)389{390	union acpi_operand_object *sub_package;391	union acpi_operand_object **sub_elements;392	acpi_status status;393	u32 expected_count;394	u32 i;395	u32 j;396 397	/*398	 * Validate each subpackage in the parent Package399	 *400	 * NOTE: assumes list of subpackages contains no NULL elements.401	 * Any NULL elements should have been removed by earlier call402	 * to acpi_ns_remove_null_elements.403	 */404	for (i = 0; i < count; i++) {405		sub_package = *elements;406		sub_elements = sub_package->package.elements;407		info->parent_package = sub_package;408 409		/* Each sub-object must be of type Package */410 411		status = acpi_ns_check_object_type(info, &sub_package,412						   ACPI_RTYPE_PACKAGE, i);413		if (ACPI_FAILURE(status)) {414			return (status);415		}416 417		/* Examine the different types of expected subpackages */418 419		info->parent_package = sub_package;420		switch (package->ret_info.type) {421		case ACPI_PTYPE2:422		case ACPI_PTYPE2_PKG_COUNT:423		case ACPI_PTYPE2_REV_FIXED:424 425			/* Each subpackage has a fixed number of elements */426 427			expected_count =428			    package->ret_info.count1 + package->ret_info.count2;429			if (sub_package->package.count < expected_count) {430				goto package_too_small;431			}432 433			status =434			    acpi_ns_check_package_elements(info, sub_elements,435							   package->ret_info.436							   object_type1,437							   package->ret_info.438							   count1,439							   package->ret_info.440							   object_type2,441							   package->ret_info.442							   count2, 0);443			if (ACPI_FAILURE(status)) {444				return (status);445			}446			break;447 448		case ACPI_PTYPE2_FIX_VAR:449			/*450			 * Each subpackage has a fixed number of elements and an451			 * optional element452			 */453			expected_count =454			    package->ret_info.count1 + package->ret_info.count2;455			if (sub_package->package.count < expected_count) {456				goto package_too_small;457			}458 459			status =460			    acpi_ns_check_package_elements(info, sub_elements,461							   package->ret_info.462							   object_type1,463							   package->ret_info.464							   count1,465							   package->ret_info.466							   object_type2,467							   sub_package->package.468							   count -469							   package->ret_info.470							   count1, 0);471			if (ACPI_FAILURE(status)) {472				return (status);473			}474			break;475 476		case ACPI_PTYPE2_VAR_VAR:477			/*478			 * Each subpackage has a fixed or variable number of elements479			 */480			break;481 482		case ACPI_PTYPE2_FIXED:483 484			/* Each subpackage has a fixed length */485 486			expected_count = package->ret_info2.count;487			if (sub_package->package.count < expected_count) {488				goto package_too_small;489			}490 491			/* Check the type of each subpackage element */492 493			for (j = 0; j < expected_count; j++) {494				status =495				    acpi_ns_check_object_type(info,496							      &sub_elements[j],497							      package->498							      ret_info2.499							      object_type[j],500							      j);501				if (ACPI_FAILURE(status)) {502					return (status);503				}504			}505			break;506 507		case ACPI_PTYPE2_MIN:508 509			/* Each subpackage has a variable but minimum length */510 511			expected_count = package->ret_info.count1;512			if (sub_package->package.count < expected_count) {513				goto package_too_small;514			}515 516			/* Check the type of each subpackage element */517 518			status =519			    acpi_ns_check_package_elements(info, sub_elements,520							   package->ret_info.521							   object_type1,522							   sub_package->package.523							   count, 0, 0, 0);524			if (ACPI_FAILURE(status)) {525				return (status);526			}527			break;528 529		case ACPI_PTYPE2_COUNT:530			/*531			 * First element is the (Integer) count of elements, including532			 * the count field (the ACPI name is num_elements)533			 */534			status = acpi_ns_check_object_type(info, sub_elements,535							   ACPI_RTYPE_INTEGER,536							   0);537			if (ACPI_FAILURE(status)) {538				return (status);539			}540 541			/*542			 * Make sure package is large enough for the Count and is543			 * is as large as the minimum size544			 */545			expected_count = (u32)(*sub_elements)->integer.value;546			if (sub_package->package.count < expected_count) {547				goto package_too_small;548			}549 550			if (sub_package->package.count <551			    package->ret_info.count1) {552				expected_count = package->ret_info.count1;553				goto package_too_small;554			}555 556			if (expected_count == 0) {557				/*558				 * Either the num_entries element was originally zero or it was559				 * a NULL element and repaired to an Integer of value zero.560				 * In either case, repair it by setting num_entries to be the561				 * actual size of the subpackage.562				 */563				expected_count = sub_package->package.count;564				(*sub_elements)->integer.value = expected_count;565			}566 567			/* Check the type of each subpackage element */568 569			status =570			    acpi_ns_check_package_elements(info,571							   (sub_elements + 1),572							   package->ret_info.573							   object_type1,574							   (expected_count - 1),575							   0, 0, 1);576			if (ACPI_FAILURE(status)) {577				return (status);578			}579			break;580 581		default:	/* Should not get here, type was validated by caller */582 583			ACPI_ERROR((AE_INFO, "Invalid Package type: %X",584				    package->ret_info.type));585			return (AE_AML_INTERNAL);586		}587 588		elements++;589	}590 591	return (AE_OK);592 593package_too_small:594 595	/* The subpackage count was smaller than required */596 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));600 601	return (AE_AML_OPERAND_VALUE);602}603 604/*******************************************************************************605 *606 * FUNCTION:    acpi_ns_custom_package607 *608 * PARAMETERS:  info                - Method execution information block609 *              elements            - Pointer to the package elements array610 *              count               - Element count for the package611 *612 * RETURN:      Status613 *614 * DESCRIPTION: Check a returned package object for the correct count and615 *              correct type of all sub-objects.616 *617 * NOTE: Currently used for the _BIX method only. When needed for two or more618 * methods, probably a detect/dispatch mechanism will be required.619 *620 ******************************************************************************/621 622static acpi_status623acpi_ns_custom_package(struct acpi_evaluate_info *info,624		       union acpi_operand_object **elements, u32 count)625{626	u32 expected_count;627	u32 version;628	acpi_status status = AE_OK;629 630	ACPI_FUNCTION_NAME(ns_custom_package);631 632	/* Get version number, must be Integer */633 634	if ((*elements)->common.type != ACPI_TYPE_INTEGER) {635		ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,636				      info->node_flags,637				      "Return Package has invalid object type for version number"));638		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);639	}640 641	version = (u32)(*elements)->integer.value;642	expected_count = 21;	/* Version 1 */643 644	if (version == 0) {645		expected_count = 20;	/* Version 0 */646	}647 648	if (count < expected_count) {649		ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,650				      info->node_flags,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));659	}660 661	/* Validate all elements of the returned package */662 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);668	}669 670	/* Version 1 has a single trailing integer */671 672	if (version > 0) {673		status = acpi_ns_check_package_elements(info, elements + 20,674							ACPI_RTYPE_INTEGER, 1,675							0, 0, 20);676	}677 678	return_ACPI_STATUS(status);679}680 681/*******************************************************************************682 *683 * FUNCTION:    acpi_ns_check_package_elements684 *685 * PARAMETERS:  info            - Method execution information block686 *              elements        - Pointer to the package elements array687 *              type1           - Object type for first group688 *              count1          - Count for first group689 *              type2           - Object type for second group690 *              count2          - Count for second group691 *              start_index     - Start of the first group of elements692 *693 * RETURN:      Status694 *695 * DESCRIPTION: Check that all elements of a package are of the correct object696 *              type. Supports up to two groups of different object types.697 *698 ******************************************************************************/699 700static acpi_status701acpi_ns_check_package_elements(struct acpi_evaluate_info *info,702			       union acpi_operand_object **elements,703			       u8 type1,704			       u32 count1,705			       u8 type2, u32 count2, u32 start_index)706{707	union acpi_operand_object **this_element = elements;708	acpi_status status;709	u32 i;710 711	ACPI_FUNCTION_TRACE(ns_check_package_elements);712 713	/*714	 * Up to two groups of package elements are supported by the data715	 * structure. All elements in each group must be of the same type.716	 * The second group can have a count of zero.717	 */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);723		}724 725		this_element++;726	}727 728	for (i = 0; i < count2; i++) {729		status = acpi_ns_check_object_type(info, this_element,730						   type2,731						   (i + count1 + start_index));732		if (ACPI_FAILURE(status)) {733			return_ACPI_STATUS(status);734		}735 736		this_element++;737	}738 739	return_ACPI_STATUS(AE_OK);740}741