142f8fb75SBob Moore /****************************************************************************** 242f8fb75SBob Moore * 342f8fb75SBob Moore * Module Name: nsprepkg - Validation of package objects for predefined names 442f8fb75SBob Moore * 542f8fb75SBob Moore *****************************************************************************/ 642f8fb75SBob Moore 742f8fb75SBob Moore /* 882a80941SDavid E. Box * Copyright (C) 2000 - 2015, Intel Corp. 942f8fb75SBob Moore * All rights reserved. 1042f8fb75SBob Moore * 1142f8fb75SBob Moore * Redistribution and use in source and binary forms, with or without 1242f8fb75SBob Moore * modification, are permitted provided that the following conditions 1342f8fb75SBob Moore * are met: 1442f8fb75SBob Moore * 1. Redistributions of source code must retain the above copyright 1542f8fb75SBob Moore * notice, this list of conditions, and the following disclaimer, 1642f8fb75SBob Moore * without modification. 1742f8fb75SBob Moore * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1842f8fb75SBob Moore * substantially similar to the "NO WARRANTY" disclaimer below 1942f8fb75SBob Moore * ("Disclaimer") and any redistribution must be conditioned upon 2042f8fb75SBob Moore * including a substantially similar Disclaimer requirement for further 2142f8fb75SBob Moore * binary redistribution. 2242f8fb75SBob Moore * 3. Neither the names of the above-listed copyright holders nor the names 2342f8fb75SBob Moore * of any contributors may be used to endorse or promote products derived 2442f8fb75SBob Moore * from this software without specific prior written permission. 2542f8fb75SBob Moore * 2642f8fb75SBob Moore * Alternatively, this software may be distributed under the terms of the 2742f8fb75SBob Moore * GNU General Public License ("GPL") version 2 as published by the Free 2842f8fb75SBob Moore * Software Foundation. 2942f8fb75SBob Moore * 3042f8fb75SBob Moore * NO WARRANTY 3142f8fb75SBob Moore * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3242f8fb75SBob Moore * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3342f8fb75SBob Moore * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3442f8fb75SBob Moore * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3542f8fb75SBob Moore * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3642f8fb75SBob Moore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3742f8fb75SBob Moore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3842f8fb75SBob Moore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3942f8fb75SBob Moore * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4042f8fb75SBob Moore * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4142f8fb75SBob Moore * POSSIBILITY OF SUCH DAMAGES. 4242f8fb75SBob Moore */ 4342f8fb75SBob Moore 4442f8fb75SBob Moore #include <acpi/acpi.h> 4542f8fb75SBob Moore #include "accommon.h" 4642f8fb75SBob Moore #include "acnamesp.h" 4742f8fb75SBob Moore #include "acpredef.h" 4842f8fb75SBob Moore 4942f8fb75SBob Moore #define _COMPONENT ACPI_NAMESPACE 5042f8fb75SBob Moore ACPI_MODULE_NAME("nsprepkg") 5142f8fb75SBob Moore 5242f8fb75SBob Moore /* Local prototypes */ 5342f8fb75SBob Moore static acpi_status 5429a241ccSBob Moore acpi_ns_check_package_list(struct acpi_evaluate_info *info, 5542f8fb75SBob Moore const union acpi_predefined_info *package, 5642f8fb75SBob Moore union acpi_operand_object **elements, u32 count); 5742f8fb75SBob Moore 5842f8fb75SBob Moore static acpi_status 5929a241ccSBob Moore acpi_ns_check_package_elements(struct acpi_evaluate_info *info, 6042f8fb75SBob Moore union acpi_operand_object **elements, 6142f8fb75SBob Moore u8 type1, 6242f8fb75SBob Moore u32 count1, 6342f8fb75SBob Moore u8 type2, u32 count2, u32 start_index); 6442f8fb75SBob Moore 6542f8fb75SBob Moore /******************************************************************************* 6642f8fb75SBob Moore * 6742f8fb75SBob Moore * FUNCTION: acpi_ns_check_package 6842f8fb75SBob Moore * 6929a241ccSBob Moore * PARAMETERS: info - Method execution information block 7042f8fb75SBob Moore * return_object_ptr - Pointer to the object returned from the 7142f8fb75SBob Moore * evaluation of a method or object 7242f8fb75SBob Moore * 7342f8fb75SBob Moore * RETURN: Status 7442f8fb75SBob Moore * 7542f8fb75SBob Moore * DESCRIPTION: Check a returned package object for the correct count and 7642f8fb75SBob Moore * correct type of all sub-objects. 7742f8fb75SBob Moore * 7842f8fb75SBob Moore ******************************************************************************/ 7942f8fb75SBob Moore 8042f8fb75SBob Moore acpi_status 8129a241ccSBob Moore acpi_ns_check_package(struct acpi_evaluate_info *info, 8242f8fb75SBob Moore union acpi_operand_object **return_object_ptr) 8342f8fb75SBob Moore { 8442f8fb75SBob Moore union acpi_operand_object *return_object = *return_object_ptr; 8542f8fb75SBob Moore const union acpi_predefined_info *package; 8642f8fb75SBob Moore union acpi_operand_object **elements; 8742f8fb75SBob Moore acpi_status status = AE_OK; 8842f8fb75SBob Moore u32 expected_count; 8942f8fb75SBob Moore u32 count; 9042f8fb75SBob Moore u32 i; 9142f8fb75SBob Moore 9242f8fb75SBob Moore ACPI_FUNCTION_NAME(ns_check_package); 9342f8fb75SBob Moore 9442f8fb75SBob Moore /* The package info for this name is in the next table entry */ 9542f8fb75SBob Moore 9629a241ccSBob Moore package = info->predefined + 1; 9742f8fb75SBob Moore 9842f8fb75SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 9942f8fb75SBob Moore "%s Validating return Package of Type %X, Count %X\n", 10029a241ccSBob Moore info->full_pathname, package->ret_info.type, 10142f8fb75SBob Moore return_object->package.count)); 10242f8fb75SBob Moore 10342f8fb75SBob Moore /* 10442f8fb75SBob Moore * For variable-length Packages, we can safely remove all embedded 10542f8fb75SBob Moore * and trailing NULL package elements 10642f8fb75SBob Moore */ 10729a241ccSBob Moore acpi_ns_remove_null_elements(info, package->ret_info.type, 10842f8fb75SBob Moore return_object); 10942f8fb75SBob Moore 11042f8fb75SBob Moore /* Extract package count and elements array */ 11142f8fb75SBob Moore 11242f8fb75SBob Moore elements = return_object->package.elements; 11342f8fb75SBob Moore count = return_object->package.count; 11442f8fb75SBob Moore 11502d4fb36SBob Moore /* 11602d4fb36SBob Moore * Most packages must have at least one element. The only exception 11702d4fb36SBob Moore * is the variable-length package (ACPI_PTYPE1_VAR). 11802d4fb36SBob Moore */ 11942f8fb75SBob Moore if (!count) { 12002d4fb36SBob Moore if (package->ret_info.type == ACPI_PTYPE1_VAR) { 12102d4fb36SBob Moore return (AE_OK); 12202d4fb36SBob Moore } 12302d4fb36SBob Moore 12429a241ccSBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 12529a241ccSBob Moore info->node_flags, 12642f8fb75SBob Moore "Return Package has no elements (empty)")); 12742f8fb75SBob Moore 12842f8fb75SBob Moore return (AE_AML_OPERAND_VALUE); 12942f8fb75SBob Moore } 13042f8fb75SBob Moore 13142f8fb75SBob Moore /* 13242f8fb75SBob Moore * Decode the type of the expected package contents 13342f8fb75SBob Moore * 13442f8fb75SBob Moore * PTYPE1 packages contain no subpackages 1350a16d12aSBob Moore * PTYPE2 packages contain subpackages 13642f8fb75SBob Moore */ 13742f8fb75SBob Moore switch (package->ret_info.type) { 13842f8fb75SBob Moore case ACPI_PTYPE1_FIXED: 13942f8fb75SBob Moore /* 1400a16d12aSBob Moore * The package count is fixed and there are no subpackages 14142f8fb75SBob Moore * 14242f8fb75SBob Moore * If package is too small, exit. 14342f8fb75SBob Moore * If package is larger than expected, issue warning but continue 14442f8fb75SBob Moore */ 14542f8fb75SBob Moore expected_count = 14642f8fb75SBob Moore package->ret_info.count1 + package->ret_info.count2; 14742f8fb75SBob Moore if (count < expected_count) { 14842f8fb75SBob Moore goto package_too_small; 14942f8fb75SBob Moore } else if (count > expected_count) { 15042f8fb75SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 15142f8fb75SBob Moore "%s: Return Package is larger than needed - " 15242f8fb75SBob Moore "found %u, expected %u\n", 15329a241ccSBob Moore info->full_pathname, count, 15442f8fb75SBob Moore expected_count)); 15542f8fb75SBob Moore } 15642f8fb75SBob Moore 15742f8fb75SBob Moore /* Validate all elements of the returned package */ 15842f8fb75SBob Moore 15929a241ccSBob Moore status = acpi_ns_check_package_elements(info, elements, 16042f8fb75SBob Moore package->ret_info. 16142f8fb75SBob Moore object_type1, 16242f8fb75SBob Moore package->ret_info. 16342f8fb75SBob Moore count1, 16442f8fb75SBob Moore package->ret_info. 16542f8fb75SBob Moore object_type2, 16642f8fb75SBob Moore package->ret_info. 16742f8fb75SBob Moore count2, 0); 16842f8fb75SBob Moore break; 16942f8fb75SBob Moore 17042f8fb75SBob Moore case ACPI_PTYPE1_VAR: 17142f8fb75SBob Moore /* 1720a16d12aSBob Moore * The package count is variable, there are no subpackages, and all 17342f8fb75SBob Moore * elements must be of the same type 17442f8fb75SBob Moore */ 17542f8fb75SBob Moore for (i = 0; i < count; i++) { 17629a241ccSBob Moore status = acpi_ns_check_object_type(info, elements, 17742f8fb75SBob Moore package->ret_info. 17842f8fb75SBob Moore object_type1, i); 17942f8fb75SBob Moore if (ACPI_FAILURE(status)) { 18042f8fb75SBob Moore return (status); 18142f8fb75SBob Moore } 18242f8fb75SBob Moore elements++; 18342f8fb75SBob Moore } 18442f8fb75SBob Moore break; 18542f8fb75SBob Moore 18642f8fb75SBob Moore case ACPI_PTYPE1_OPTION: 18742f8fb75SBob Moore /* 1880a16d12aSBob Moore * The package count is variable, there are no subpackages. There are 18942f8fb75SBob Moore * a fixed number of required elements, and a variable number of 19042f8fb75SBob Moore * optional elements. 19142f8fb75SBob Moore * 19242f8fb75SBob Moore * Check if package is at least as large as the minimum required 19342f8fb75SBob Moore */ 19442f8fb75SBob Moore expected_count = package->ret_info3.count; 19542f8fb75SBob Moore if (count < expected_count) { 19642f8fb75SBob Moore goto package_too_small; 19742f8fb75SBob Moore } 19842f8fb75SBob Moore 19942f8fb75SBob Moore /* Variable number of sub-objects */ 20042f8fb75SBob Moore 20142f8fb75SBob Moore for (i = 0; i < count; i++) { 20242f8fb75SBob Moore if (i < package->ret_info3.count) { 20342f8fb75SBob Moore 20442f8fb75SBob Moore /* These are the required package elements (0, 1, or 2) */ 20542f8fb75SBob Moore 20642f8fb75SBob Moore status = 20729a241ccSBob Moore acpi_ns_check_object_type(info, elements, 20842f8fb75SBob Moore package-> 20942f8fb75SBob Moore ret_info3. 21042f8fb75SBob Moore object_type[i], 21142f8fb75SBob Moore i); 21242f8fb75SBob Moore if (ACPI_FAILURE(status)) { 21342f8fb75SBob Moore return (status); 21442f8fb75SBob Moore } 21542f8fb75SBob Moore } else { 21642f8fb75SBob Moore /* These are the optional package elements */ 21742f8fb75SBob Moore 21842f8fb75SBob Moore status = 21929a241ccSBob Moore acpi_ns_check_object_type(info, elements, 22042f8fb75SBob Moore package-> 22142f8fb75SBob Moore ret_info3. 22242f8fb75SBob Moore tail_object_type, 22342f8fb75SBob Moore i); 22442f8fb75SBob Moore if (ACPI_FAILURE(status)) { 22542f8fb75SBob Moore return (status); 22642f8fb75SBob Moore } 22742f8fb75SBob Moore } 22842f8fb75SBob Moore elements++; 22942f8fb75SBob Moore } 23042f8fb75SBob Moore break; 23142f8fb75SBob Moore 23242f8fb75SBob Moore case ACPI_PTYPE2_REV_FIXED: 23342f8fb75SBob Moore 23442f8fb75SBob Moore /* First element is the (Integer) revision */ 23542f8fb75SBob Moore 236*1fad8738SBob Moore status = 237*1fad8738SBob Moore acpi_ns_check_object_type(info, elements, 23842f8fb75SBob Moore ACPI_RTYPE_INTEGER, 0); 23942f8fb75SBob Moore if (ACPI_FAILURE(status)) { 24042f8fb75SBob Moore return (status); 24142f8fb75SBob Moore } 24242f8fb75SBob Moore 24342f8fb75SBob Moore elements++; 24442f8fb75SBob Moore count--; 24542f8fb75SBob Moore 2460a16d12aSBob Moore /* Examine the subpackages */ 24742f8fb75SBob Moore 24842f8fb75SBob Moore status = 24929a241ccSBob Moore acpi_ns_check_package_list(info, package, elements, count); 25042f8fb75SBob Moore break; 25142f8fb75SBob Moore 25242f8fb75SBob Moore case ACPI_PTYPE2_PKG_COUNT: 25342f8fb75SBob Moore 2540a16d12aSBob Moore /* First element is the (Integer) count of subpackages to follow */ 25542f8fb75SBob Moore 256*1fad8738SBob Moore status = 257*1fad8738SBob Moore acpi_ns_check_object_type(info, elements, 25842f8fb75SBob Moore ACPI_RTYPE_INTEGER, 0); 25942f8fb75SBob Moore if (ACPI_FAILURE(status)) { 26042f8fb75SBob Moore return (status); 26142f8fb75SBob Moore } 26242f8fb75SBob Moore 26342f8fb75SBob Moore /* 26442f8fb75SBob Moore * Count cannot be larger than the parent package length, but allow it 26542f8fb75SBob Moore * to be smaller. The >= accounts for the Integer above. 26642f8fb75SBob Moore */ 26742f8fb75SBob Moore expected_count = (u32)(*elements)->integer.value; 26842f8fb75SBob Moore if (expected_count >= count) { 26942f8fb75SBob Moore goto package_too_small; 27042f8fb75SBob Moore } 27142f8fb75SBob Moore 27242f8fb75SBob Moore count = expected_count; 27342f8fb75SBob Moore elements++; 27442f8fb75SBob Moore 2750a16d12aSBob Moore /* Examine the subpackages */ 27642f8fb75SBob Moore 27742f8fb75SBob Moore status = 27829a241ccSBob Moore acpi_ns_check_package_list(info, package, elements, count); 27942f8fb75SBob Moore break; 28042f8fb75SBob Moore 28142f8fb75SBob Moore case ACPI_PTYPE2: 28242f8fb75SBob Moore case ACPI_PTYPE2_FIXED: 28342f8fb75SBob Moore case ACPI_PTYPE2_MIN: 28442f8fb75SBob Moore case ACPI_PTYPE2_COUNT: 28542f8fb75SBob Moore case ACPI_PTYPE2_FIX_VAR: 28642f8fb75SBob Moore /* 28742f8fb75SBob Moore * These types all return a single Package that consists of a 2880a16d12aSBob Moore * variable number of subpackages. 28942f8fb75SBob Moore * 2900a16d12aSBob Moore * First, ensure that the first element is a subpackage. If not, 29142f8fb75SBob Moore * the BIOS may have incorrectly returned the object as a single 29242f8fb75SBob Moore * package instead of a Package of Packages (a common error if 29342f8fb75SBob Moore * there is only one entry). We may be able to repair this by 29442f8fb75SBob Moore * wrapping the returned Package with a new outer Package. 29542f8fb75SBob Moore */ 29642f8fb75SBob Moore if (*elements 29742f8fb75SBob Moore && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) { 29842f8fb75SBob Moore 29942f8fb75SBob Moore /* Create the new outer package and populate it */ 30042f8fb75SBob Moore 30142f8fb75SBob Moore status = 30229a241ccSBob Moore acpi_ns_wrap_with_package(info, return_object, 30342f8fb75SBob Moore return_object_ptr); 30442f8fb75SBob Moore if (ACPI_FAILURE(status)) { 30542f8fb75SBob Moore return (status); 30642f8fb75SBob Moore } 30742f8fb75SBob Moore 30842f8fb75SBob Moore /* Update locals to point to the new package (of 1 element) */ 30942f8fb75SBob Moore 31042f8fb75SBob Moore return_object = *return_object_ptr; 31142f8fb75SBob Moore elements = return_object->package.elements; 31242f8fb75SBob Moore count = 1; 31342f8fb75SBob Moore } 31442f8fb75SBob Moore 3150a16d12aSBob Moore /* Examine the subpackages */ 31642f8fb75SBob Moore 31742f8fb75SBob Moore status = 31829a241ccSBob Moore acpi_ns_check_package_list(info, package, elements, count); 31942f8fb75SBob Moore break; 32042f8fb75SBob Moore 321e34a7813SBob Moore case ACPI_PTYPE2_VAR_VAR: 322e34a7813SBob Moore /* 323e34a7813SBob Moore * Returns a variable list of packages, each with a variable list 324e34a7813SBob Moore * of objects. 325e34a7813SBob Moore */ 326e34a7813SBob Moore break; 327e34a7813SBob Moore 328b1272e1fSMika Westerberg case ACPI_PTYPE2_UUID_PAIR: 329b1272e1fSMika Westerberg 330b1272e1fSMika Westerberg /* The package must contain pairs of (UUID + type) */ 331b1272e1fSMika Westerberg 332b1272e1fSMika Westerberg if (count & 1) { 333b1272e1fSMika Westerberg expected_count = count + 1; 334b1272e1fSMika Westerberg goto package_too_small; 335b1272e1fSMika Westerberg } 336b1272e1fSMika Westerberg 337b1272e1fSMika Westerberg while (count > 0) { 338b1272e1fSMika Westerberg status = acpi_ns_check_object_type(info, elements, 339b1272e1fSMika Westerberg package->ret_info. 340b1272e1fSMika Westerberg object_type1, 0); 341b1272e1fSMika Westerberg if (ACPI_FAILURE(status)) { 342b1272e1fSMika Westerberg return (status); 343b1272e1fSMika Westerberg } 344b1272e1fSMika Westerberg 345b1272e1fSMika Westerberg /* Validate length of the UUID buffer */ 346b1272e1fSMika Westerberg 347b1272e1fSMika Westerberg if ((*elements)->buffer.length != 16) { 348b1272e1fSMika Westerberg ACPI_WARN_PREDEFINED((AE_INFO, 349b1272e1fSMika Westerberg info->full_pathname, 350b1272e1fSMika Westerberg info->node_flags, 351b1272e1fSMika Westerberg "Invalid length for UUID Buffer")); 352b1272e1fSMika Westerberg return (AE_AML_OPERAND_VALUE); 353b1272e1fSMika Westerberg } 354b1272e1fSMika Westerberg 355b1272e1fSMika Westerberg status = acpi_ns_check_object_type(info, elements + 1, 356b1272e1fSMika Westerberg package->ret_info. 357b1272e1fSMika Westerberg object_type2, 0); 358b1272e1fSMika Westerberg if (ACPI_FAILURE(status)) { 359b1272e1fSMika Westerberg return (status); 360b1272e1fSMika Westerberg } 361b1272e1fSMika Westerberg 362b1272e1fSMika Westerberg elements += 2; 363b1272e1fSMika Westerberg count -= 2; 364b1272e1fSMika Westerberg } 365b1272e1fSMika Westerberg break; 366b1272e1fSMika Westerberg 36742f8fb75SBob Moore default: 36842f8fb75SBob Moore 36942f8fb75SBob Moore /* Should not get here if predefined info table is correct */ 37042f8fb75SBob Moore 37129a241ccSBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 37229a241ccSBob Moore info->node_flags, 37342f8fb75SBob Moore "Invalid internal return type in table entry: %X", 37442f8fb75SBob Moore package->ret_info.type)); 37542f8fb75SBob Moore 37642f8fb75SBob Moore return (AE_AML_INTERNAL); 37742f8fb75SBob Moore } 37842f8fb75SBob Moore 37942f8fb75SBob Moore return (status); 38042f8fb75SBob Moore 38142f8fb75SBob Moore package_too_small: 38242f8fb75SBob Moore 38342f8fb75SBob Moore /* Error exit for the case with an incorrect package count */ 38442f8fb75SBob Moore 38529a241ccSBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, 38642f8fb75SBob Moore "Return Package is too small - found %u elements, expected %u", 38742f8fb75SBob Moore count, expected_count)); 38842f8fb75SBob Moore 38942f8fb75SBob Moore return (AE_AML_OPERAND_VALUE); 39042f8fb75SBob Moore } 39142f8fb75SBob Moore 39242f8fb75SBob Moore /******************************************************************************* 39342f8fb75SBob Moore * 39442f8fb75SBob Moore * FUNCTION: acpi_ns_check_package_list 39542f8fb75SBob Moore * 39629a241ccSBob Moore * PARAMETERS: info - Method execution information block 39742f8fb75SBob Moore * package - Pointer to package-specific info for method 39842f8fb75SBob Moore * elements - Element list of parent package. All elements 39942f8fb75SBob Moore * of this list should be of type Package. 40042f8fb75SBob Moore * count - Count of subpackages 40142f8fb75SBob Moore * 40242f8fb75SBob Moore * RETURN: Status 40342f8fb75SBob Moore * 40442f8fb75SBob Moore * DESCRIPTION: Examine a list of subpackages 40542f8fb75SBob Moore * 40642f8fb75SBob Moore ******************************************************************************/ 40742f8fb75SBob Moore 40842f8fb75SBob Moore static acpi_status 40929a241ccSBob Moore acpi_ns_check_package_list(struct acpi_evaluate_info *info, 41042f8fb75SBob Moore const union acpi_predefined_info *package, 41142f8fb75SBob Moore union acpi_operand_object **elements, u32 count) 41242f8fb75SBob Moore { 41342f8fb75SBob Moore union acpi_operand_object *sub_package; 41442f8fb75SBob Moore union acpi_operand_object **sub_elements; 41542f8fb75SBob Moore acpi_status status; 41642f8fb75SBob Moore u32 expected_count; 41742f8fb75SBob Moore u32 i; 41842f8fb75SBob Moore u32 j; 41942f8fb75SBob Moore 42042f8fb75SBob Moore /* 4210a16d12aSBob Moore * Validate each subpackage in the parent Package 42242f8fb75SBob Moore * 4230a16d12aSBob Moore * NOTE: assumes list of subpackages contains no NULL elements. 42442f8fb75SBob Moore * Any NULL elements should have been removed by earlier call 42542f8fb75SBob Moore * to acpi_ns_remove_null_elements. 42642f8fb75SBob Moore */ 42742f8fb75SBob Moore for (i = 0; i < count; i++) { 42842f8fb75SBob Moore sub_package = *elements; 42942f8fb75SBob Moore sub_elements = sub_package->package.elements; 43029a241ccSBob Moore info->parent_package = sub_package; 43142f8fb75SBob Moore 43242f8fb75SBob Moore /* Each sub-object must be of type Package */ 43342f8fb75SBob Moore 43429a241ccSBob Moore status = acpi_ns_check_object_type(info, &sub_package, 43542f8fb75SBob Moore ACPI_RTYPE_PACKAGE, i); 43642f8fb75SBob Moore if (ACPI_FAILURE(status)) { 43742f8fb75SBob Moore return (status); 43842f8fb75SBob Moore } 43942f8fb75SBob Moore 4400a16d12aSBob Moore /* Examine the different types of expected subpackages */ 44142f8fb75SBob Moore 44229a241ccSBob Moore info->parent_package = sub_package; 44342f8fb75SBob Moore switch (package->ret_info.type) { 44442f8fb75SBob Moore case ACPI_PTYPE2: 44542f8fb75SBob Moore case ACPI_PTYPE2_PKG_COUNT: 44642f8fb75SBob Moore case ACPI_PTYPE2_REV_FIXED: 44742f8fb75SBob Moore 44842f8fb75SBob Moore /* Each subpackage has a fixed number of elements */ 44942f8fb75SBob Moore 45042f8fb75SBob Moore expected_count = 45142f8fb75SBob Moore package->ret_info.count1 + package->ret_info.count2; 45242f8fb75SBob Moore if (sub_package->package.count < expected_count) { 45342f8fb75SBob Moore goto package_too_small; 45442f8fb75SBob Moore } 45542f8fb75SBob Moore 45642f8fb75SBob Moore status = 45729a241ccSBob Moore acpi_ns_check_package_elements(info, sub_elements, 45842f8fb75SBob Moore package->ret_info. 45942f8fb75SBob Moore object_type1, 46042f8fb75SBob Moore package->ret_info. 46142f8fb75SBob Moore count1, 46242f8fb75SBob Moore package->ret_info. 46342f8fb75SBob Moore object_type2, 46442f8fb75SBob Moore package->ret_info. 46542f8fb75SBob Moore count2, 0); 46642f8fb75SBob Moore if (ACPI_FAILURE(status)) { 46742f8fb75SBob Moore return (status); 46842f8fb75SBob Moore } 46942f8fb75SBob Moore break; 47042f8fb75SBob Moore 47142f8fb75SBob Moore case ACPI_PTYPE2_FIX_VAR: 47242f8fb75SBob Moore /* 47342f8fb75SBob Moore * Each subpackage has a fixed number of elements and an 47442f8fb75SBob Moore * optional element 47542f8fb75SBob Moore */ 47642f8fb75SBob Moore expected_count = 47742f8fb75SBob Moore package->ret_info.count1 + package->ret_info.count2; 47842f8fb75SBob Moore if (sub_package->package.count < expected_count) { 47942f8fb75SBob Moore goto package_too_small; 48042f8fb75SBob Moore } 48142f8fb75SBob Moore 48242f8fb75SBob Moore status = 48329a241ccSBob Moore acpi_ns_check_package_elements(info, sub_elements, 48442f8fb75SBob Moore package->ret_info. 48542f8fb75SBob Moore object_type1, 48642f8fb75SBob Moore package->ret_info. 48742f8fb75SBob Moore count1, 48842f8fb75SBob Moore package->ret_info. 48942f8fb75SBob Moore object_type2, 49042f8fb75SBob Moore sub_package->package. 49142f8fb75SBob Moore count - 49242f8fb75SBob Moore package->ret_info. 49342f8fb75SBob Moore count1, 0); 49442f8fb75SBob Moore if (ACPI_FAILURE(status)) { 49542f8fb75SBob Moore return (status); 49642f8fb75SBob Moore } 49742f8fb75SBob Moore break; 49842f8fb75SBob Moore 499e34a7813SBob Moore case ACPI_PTYPE2_VAR_VAR: 500e34a7813SBob Moore /* 501e34a7813SBob Moore * Each subpackage has a fixed or variable number of elements 502e34a7813SBob Moore */ 503e34a7813SBob Moore break; 504e34a7813SBob Moore 50542f8fb75SBob Moore case ACPI_PTYPE2_FIXED: 50642f8fb75SBob Moore 5070a16d12aSBob Moore /* Each subpackage has a fixed length */ 50842f8fb75SBob Moore 50942f8fb75SBob Moore expected_count = package->ret_info2.count; 51042f8fb75SBob Moore if (sub_package->package.count < expected_count) { 51142f8fb75SBob Moore goto package_too_small; 51242f8fb75SBob Moore } 51342f8fb75SBob Moore 5140a16d12aSBob Moore /* Check the type of each subpackage element */ 51542f8fb75SBob Moore 51642f8fb75SBob Moore for (j = 0; j < expected_count; j++) { 51742f8fb75SBob Moore status = 51829a241ccSBob Moore acpi_ns_check_object_type(info, 51942f8fb75SBob Moore &sub_elements[j], 52042f8fb75SBob Moore package-> 52142f8fb75SBob Moore ret_info2. 52242f8fb75SBob Moore object_type[j], 52342f8fb75SBob Moore j); 52442f8fb75SBob Moore if (ACPI_FAILURE(status)) { 52542f8fb75SBob Moore return (status); 52642f8fb75SBob Moore } 52742f8fb75SBob Moore } 52842f8fb75SBob Moore break; 52942f8fb75SBob Moore 53042f8fb75SBob Moore case ACPI_PTYPE2_MIN: 53142f8fb75SBob Moore 5320a16d12aSBob Moore /* Each subpackage has a variable but minimum length */ 53342f8fb75SBob Moore 53442f8fb75SBob Moore expected_count = package->ret_info.count1; 53542f8fb75SBob Moore if (sub_package->package.count < expected_count) { 53642f8fb75SBob Moore goto package_too_small; 53742f8fb75SBob Moore } 53842f8fb75SBob Moore 5390a16d12aSBob Moore /* Check the type of each subpackage element */ 54042f8fb75SBob Moore 54142f8fb75SBob Moore status = 54229a241ccSBob Moore acpi_ns_check_package_elements(info, sub_elements, 54342f8fb75SBob Moore package->ret_info. 54442f8fb75SBob Moore object_type1, 54542f8fb75SBob Moore sub_package->package. 54642f8fb75SBob Moore count, 0, 0, 0); 54742f8fb75SBob Moore if (ACPI_FAILURE(status)) { 54842f8fb75SBob Moore return (status); 54942f8fb75SBob Moore } 55042f8fb75SBob Moore break; 55142f8fb75SBob Moore 55242f8fb75SBob Moore case ACPI_PTYPE2_COUNT: 55342f8fb75SBob Moore /* 55442f8fb75SBob Moore * First element is the (Integer) count of elements, including 55542f8fb75SBob Moore * the count field (the ACPI name is num_elements) 55642f8fb75SBob Moore */ 55729a241ccSBob Moore status = acpi_ns_check_object_type(info, sub_elements, 55842f8fb75SBob Moore ACPI_RTYPE_INTEGER, 55942f8fb75SBob Moore 0); 56042f8fb75SBob Moore if (ACPI_FAILURE(status)) { 56142f8fb75SBob Moore return (status); 56242f8fb75SBob Moore } 56342f8fb75SBob Moore 56442f8fb75SBob Moore /* 56542f8fb75SBob Moore * Make sure package is large enough for the Count and is 56642f8fb75SBob Moore * is as large as the minimum size 56742f8fb75SBob Moore */ 56842f8fb75SBob Moore expected_count = (u32)(*sub_elements)->integer.value; 56942f8fb75SBob Moore if (sub_package->package.count < expected_count) { 57042f8fb75SBob Moore goto package_too_small; 57142f8fb75SBob Moore } 57242f8fb75SBob Moore if (sub_package->package.count < 57342f8fb75SBob Moore package->ret_info.count1) { 57442f8fb75SBob Moore expected_count = package->ret_info.count1; 57542f8fb75SBob Moore goto package_too_small; 57642f8fb75SBob Moore } 57742f8fb75SBob Moore if (expected_count == 0) { 57842f8fb75SBob Moore /* 57942f8fb75SBob Moore * Either the num_entries element was originally zero or it was 58042f8fb75SBob Moore * a NULL element and repaired to an Integer of value zero. 58142f8fb75SBob Moore * In either case, repair it by setting num_entries to be the 58242f8fb75SBob Moore * actual size of the subpackage. 58342f8fb75SBob Moore */ 58442f8fb75SBob Moore expected_count = sub_package->package.count; 58542f8fb75SBob Moore (*sub_elements)->integer.value = expected_count; 58642f8fb75SBob Moore } 58742f8fb75SBob Moore 5880a16d12aSBob Moore /* Check the type of each subpackage element */ 58942f8fb75SBob Moore 59042f8fb75SBob Moore status = 59129a241ccSBob Moore acpi_ns_check_package_elements(info, 59242f8fb75SBob Moore (sub_elements + 1), 59342f8fb75SBob Moore package->ret_info. 59442f8fb75SBob Moore object_type1, 59542f8fb75SBob Moore (expected_count - 1), 59642f8fb75SBob Moore 0, 0, 1); 59742f8fb75SBob Moore if (ACPI_FAILURE(status)) { 59842f8fb75SBob Moore return (status); 59942f8fb75SBob Moore } 60042f8fb75SBob Moore break; 60142f8fb75SBob Moore 60242f8fb75SBob Moore default: /* Should not get here, type was validated by caller */ 60342f8fb75SBob Moore 60442f8fb75SBob Moore return (AE_AML_INTERNAL); 60542f8fb75SBob Moore } 60642f8fb75SBob Moore 60742f8fb75SBob Moore elements++; 60842f8fb75SBob Moore } 60942f8fb75SBob Moore 61042f8fb75SBob Moore return (AE_OK); 61142f8fb75SBob Moore 61242f8fb75SBob Moore package_too_small: 61342f8fb75SBob Moore 6140a16d12aSBob Moore /* The subpackage count was smaller than required */ 61542f8fb75SBob Moore 61629a241ccSBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, 6170a16d12aSBob Moore "Return SubPackage[%u] is too small - found %u elements, expected %u", 61842f8fb75SBob Moore i, sub_package->package.count, expected_count)); 61942f8fb75SBob Moore 62042f8fb75SBob Moore return (AE_AML_OPERAND_VALUE); 62142f8fb75SBob Moore } 62242f8fb75SBob Moore 62342f8fb75SBob Moore /******************************************************************************* 62442f8fb75SBob Moore * 62542f8fb75SBob Moore * FUNCTION: acpi_ns_check_package_elements 62642f8fb75SBob Moore * 62729a241ccSBob Moore * PARAMETERS: info - Method execution information block 62842f8fb75SBob Moore * elements - Pointer to the package elements array 62942f8fb75SBob Moore * type1 - Object type for first group 63042f8fb75SBob Moore * count1 - Count for first group 63142f8fb75SBob Moore * type2 - Object type for second group 63242f8fb75SBob Moore * count2 - Count for second group 63342f8fb75SBob Moore * start_index - Start of the first group of elements 63442f8fb75SBob Moore * 63542f8fb75SBob Moore * RETURN: Status 63642f8fb75SBob Moore * 63742f8fb75SBob Moore * DESCRIPTION: Check that all elements of a package are of the correct object 63842f8fb75SBob Moore * type. Supports up to two groups of different object types. 63942f8fb75SBob Moore * 64042f8fb75SBob Moore ******************************************************************************/ 64142f8fb75SBob Moore 64242f8fb75SBob Moore static acpi_status 64329a241ccSBob Moore acpi_ns_check_package_elements(struct acpi_evaluate_info *info, 64442f8fb75SBob Moore union acpi_operand_object **elements, 64542f8fb75SBob Moore u8 type1, 64642f8fb75SBob Moore u32 count1, 64742f8fb75SBob Moore u8 type2, u32 count2, u32 start_index) 64842f8fb75SBob Moore { 64942f8fb75SBob Moore union acpi_operand_object **this_element = elements; 65042f8fb75SBob Moore acpi_status status; 65142f8fb75SBob Moore u32 i; 65242f8fb75SBob Moore 65342f8fb75SBob Moore /* 65442f8fb75SBob Moore * Up to two groups of package elements are supported by the data 65542f8fb75SBob Moore * structure. All elements in each group must be of the same type. 65642f8fb75SBob Moore * The second group can have a count of zero. 65742f8fb75SBob Moore */ 65842f8fb75SBob Moore for (i = 0; i < count1; i++) { 65929a241ccSBob Moore status = acpi_ns_check_object_type(info, this_element, 66042f8fb75SBob Moore type1, i + start_index); 66142f8fb75SBob Moore if (ACPI_FAILURE(status)) { 66242f8fb75SBob Moore return (status); 66342f8fb75SBob Moore } 66442f8fb75SBob Moore this_element++; 66542f8fb75SBob Moore } 66642f8fb75SBob Moore 66742f8fb75SBob Moore for (i = 0; i < count2; i++) { 66829a241ccSBob Moore status = acpi_ns_check_object_type(info, this_element, 66942f8fb75SBob Moore type2, 67042f8fb75SBob Moore (i + count1 + start_index)); 67142f8fb75SBob Moore if (ACPI_FAILURE(status)) { 67242f8fb75SBob Moore return (status); 67342f8fb75SBob Moore } 67442f8fb75SBob Moore this_element++; 67542f8fb75SBob Moore } 67642f8fb75SBob Moore 67742f8fb75SBob Moore return (AE_OK); 67842f8fb75SBob Moore } 679