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 * 6800ba7c5SBob Moore * Copyright (C) 2000 - 2020, 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 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 62*0766efdfSErik 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) { 91*0766efdfSErik 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 98*0766efdfSErik 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)) { 155*0766efdfSErik 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)) { 189*0766efdfSErik 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)) { 201*0766efdfSErik 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)) { 217*0766efdfSErik 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)) { 237*0766efdfSErik 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)) { 282*0766efdfSErik 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)) { 319*0766efdfSErik 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")); 329*0766efdfSErik 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)) { 336*0766efdfSErik 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 353*0766efdfSErik Kaneda return_ACPI_STATUS(AE_AML_INTERNAL); 35442f8fb75SBob Moore } 35542f8fb75SBob Moore 356*0766efdfSErik 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 366*0766efdfSErik 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 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 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 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 711*0766efdfSErik Kaneda ACPI_FUNCTION_TRACE(ns_check_package_elements); 712*0766efdfSErik 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)) { 722*0766efdfSErik 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)) { 733*0766efdfSErik Kaneda return_ACPI_STATUS(status); 73442f8fb75SBob Moore } 7352156510fSBob Moore 73642f8fb75SBob Moore this_element++; 73742f8fb75SBob Moore } 73842f8fb75SBob Moore 739*0766efdfSErik Kaneda return_ACPI_STATUS(AE_OK); 74042f8fb75SBob Moore } 741