1b2deadd5SBob Moore /****************************************************************************** 2b2deadd5SBob Moore * 3b2deadd5SBob Moore * Module Name: nsrepair - Repair for objects returned by predefined methods 4b2deadd5SBob Moore * 5b2deadd5SBob Moore *****************************************************************************/ 6b2deadd5SBob Moore 7b2deadd5SBob Moore /* 8da6f8320SBob Moore * Copyright (C) 2000 - 2018, Intel Corp. 9b2deadd5SBob Moore * All rights reserved. 10b2deadd5SBob Moore * 11b2deadd5SBob Moore * Redistribution and use in source and binary forms, with or without 12b2deadd5SBob Moore * modification, are permitted provided that the following conditions 13b2deadd5SBob Moore * are met: 14b2deadd5SBob Moore * 1. Redistributions of source code must retain the above copyright 15b2deadd5SBob Moore * notice, this list of conditions, and the following disclaimer, 16b2deadd5SBob Moore * without modification. 17b2deadd5SBob Moore * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18b2deadd5SBob Moore * substantially similar to the "NO WARRANTY" disclaimer below 19b2deadd5SBob Moore * ("Disclaimer") and any redistribution must be conditioned upon 20b2deadd5SBob Moore * including a substantially similar Disclaimer requirement for further 21b2deadd5SBob Moore * binary redistribution. 22b2deadd5SBob Moore * 3. Neither the names of the above-listed copyright holders nor the names 23b2deadd5SBob Moore * of any contributors may be used to endorse or promote products derived 24b2deadd5SBob Moore * from this software without specific prior written permission. 25b2deadd5SBob Moore * 26b2deadd5SBob Moore * Alternatively, this software may be distributed under the terms of the 27b2deadd5SBob Moore * GNU General Public License ("GPL") version 2 as published by the Free 28b2deadd5SBob Moore * Software Foundation. 29b2deadd5SBob Moore * 30b2deadd5SBob Moore * NO WARRANTY 31b2deadd5SBob Moore * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32b2deadd5SBob Moore * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33b2deadd5SBob Moore * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34b2deadd5SBob Moore * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35b2deadd5SBob Moore * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36b2deadd5SBob Moore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37b2deadd5SBob Moore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38b2deadd5SBob Moore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39b2deadd5SBob Moore * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40b2deadd5SBob Moore * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41b2deadd5SBob Moore * POSSIBILITY OF SUCH DAMAGES. 42b2deadd5SBob Moore */ 43b2deadd5SBob Moore 44b2deadd5SBob Moore #include <acpi/acpi.h> 45b2deadd5SBob Moore #include "accommon.h" 46b2deadd5SBob Moore #include "acnamesp.h" 470240d7b4SLin Ming #include "acinterp.h" 48091f4d71SBob Moore #include "acpredef.h" 49d5a36100SBob Moore #include "amlresrc.h" 50b2deadd5SBob Moore 51b2deadd5SBob Moore #define _COMPONENT ACPI_NAMESPACE 52b2deadd5SBob Moore ACPI_MODULE_NAME("nsrepair") 53b2deadd5SBob Moore 54b2deadd5SBob Moore /******************************************************************************* 55b2deadd5SBob Moore * 5647e11d54SBob Moore * This module attempts to repair or convert objects returned by the 5747e11d54SBob Moore * predefined methods to an object type that is expected, as per the ACPI 5847e11d54SBob Moore * specification. The need for this code is dictated by the many machines that 5947e11d54SBob Moore * return incorrect types for the standard predefined methods. Performing these 6047e11d54SBob Moore * conversions here, in one place, eliminates the need for individual ACPI 6147e11d54SBob Moore * device drivers to do the same. Note: Most of these conversions are different 6247e11d54SBob Moore * than the internal object conversion routines used for implicit object 6347e11d54SBob Moore * conversion. 6447e11d54SBob Moore * 6547e11d54SBob Moore * The following conversions can be performed as necessary: 6647e11d54SBob Moore * 6747e11d54SBob Moore * Integer -> String 6847e11d54SBob Moore * Integer -> Buffer 6947e11d54SBob Moore * String -> Integer 7047e11d54SBob Moore * String -> Buffer 7147e11d54SBob Moore * Buffer -> Integer 7247e11d54SBob Moore * Buffer -> String 7347e11d54SBob Moore * Buffer -> Package of Integers 7447e11d54SBob Moore * Package -> Package of one Package 75d5a36100SBob Moore * 76d5a36100SBob Moore * Additional conversions that are available: 77d5a36100SBob Moore * Convert a null return or zero return value to an end_tag descriptor 78d5a36100SBob Moore * Convert an ASCII string to a Unicode buffer 79d5a36100SBob Moore * 806a99b1c9SBob Moore * An incorrect standalone object is wrapped with required outer package 8147e11d54SBob Moore * 82091f4d71SBob Moore * Additional possible repairs: 83091f4d71SBob Moore * Required package elements that are NULL replaced by Integer/String/Buffer 84091f4d71SBob Moore * 8547e11d54SBob Moore ******************************************************************************/ 8647e11d54SBob Moore /* Local prototypes */ 87d5a36100SBob Moore static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct 88d5a36100SBob Moore acpi_namespace_node 89d5a36100SBob Moore *node, 90d5a36100SBob Moore u32 91d5a36100SBob Moore return_btype, 92d5a36100SBob Moore u32 93d5a36100SBob Moore package_index); 94d5a36100SBob Moore 95d5a36100SBob Moore /* 96d5a36100SBob Moore * Special but simple repairs for some names. 97d5a36100SBob Moore * 98d5a36100SBob Moore * 2nd argument: Unexpected types that can be repaired 99d5a36100SBob Moore */ 100d5a36100SBob Moore static const struct acpi_simple_repair_info acpi_object_repair_info[] = { 10188fd0ac8SLv Zheng /* Resource descriptor conversions */ 10288fd0ac8SLv Zheng 10388fd0ac8SLv Zheng {"_CRS", 10488fd0ac8SLv Zheng ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | 10588fd0ac8SLv Zheng ACPI_RTYPE_NONE, 10688fd0ac8SLv Zheng ACPI_NOT_PACKAGE_ELEMENT, 10788fd0ac8SLv Zheng acpi_ns_convert_to_resource}, 10888fd0ac8SLv Zheng {"_DMA", 10988fd0ac8SLv Zheng ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | 11088fd0ac8SLv Zheng ACPI_RTYPE_NONE, 11188fd0ac8SLv Zheng ACPI_NOT_PACKAGE_ELEMENT, 11288fd0ac8SLv Zheng acpi_ns_convert_to_resource}, 11388fd0ac8SLv Zheng {"_PRS", 11488fd0ac8SLv Zheng ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | 11588fd0ac8SLv Zheng ACPI_RTYPE_NONE, 11688fd0ac8SLv Zheng ACPI_NOT_PACKAGE_ELEMENT, 11788fd0ac8SLv Zheng acpi_ns_convert_to_resource}, 11888fd0ac8SLv Zheng 119ee387409SLv Zheng /* Object reference conversions */ 120ee387409SLv Zheng 121ee387409SLv Zheng {"_DEP", ACPI_RTYPE_STRING, ACPI_ALL_PACKAGE_ELEMENTS, 122ee387409SLv Zheng acpi_ns_convert_to_reference}, 123ee387409SLv Zheng 12496b44cc6SLv Zheng /* Unicode conversions */ 12596b44cc6SLv Zheng 12696b44cc6SLv Zheng {"_MLS", ACPI_RTYPE_STRING, 1, 12796b44cc6SLv Zheng acpi_ns_convert_to_unicode}, 12896b44cc6SLv Zheng {"_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, 12996b44cc6SLv Zheng ACPI_NOT_PACKAGE_ELEMENT, 13096b44cc6SLv Zheng acpi_ns_convert_to_unicode}, 131d5a36100SBob Moore {{0, 0, 0, 0}, 0, 0, NULL} /* Table terminator */ 132d5a36100SBob Moore }; 133d5a36100SBob Moore 13447e11d54SBob Moore /******************************************************************************* 13547e11d54SBob Moore * 136d5a36100SBob Moore * FUNCTION: acpi_ns_simple_repair 137b2deadd5SBob Moore * 13829a241ccSBob Moore * PARAMETERS: info - Method execution information block 139b2deadd5SBob Moore * expected_btypes - Object types expected 140b2deadd5SBob Moore * package_index - Index of object within parent package (if 141b2deadd5SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 142b2deadd5SBob Moore * otherwise) 143b2deadd5SBob Moore * return_object_ptr - Pointer to the object returned from the 144b2deadd5SBob Moore * evaluation of a method or object 145b2deadd5SBob Moore * 146b2deadd5SBob Moore * RETURN: Status. AE_OK if repair was successful. 147b2deadd5SBob Moore * 148b2deadd5SBob Moore * DESCRIPTION: Attempt to repair/convert a return object of a type that was 149b2deadd5SBob Moore * not expected. 150b2deadd5SBob Moore * 151b2deadd5SBob Moore ******************************************************************************/ 15247e11d54SBob Moore 153b2deadd5SBob Moore acpi_status 15429a241ccSBob Moore acpi_ns_simple_repair(struct acpi_evaluate_info *info, 155b2deadd5SBob Moore u32 expected_btypes, 156b2deadd5SBob Moore u32 package_index, 157b2deadd5SBob Moore union acpi_operand_object **return_object_ptr) 158b2deadd5SBob Moore { 159b2deadd5SBob Moore union acpi_operand_object *return_object = *return_object_ptr; 160d5a36100SBob Moore union acpi_operand_object *new_object = NULL; 1610240d7b4SLin Ming acpi_status status; 162d5a36100SBob Moore const struct acpi_simple_repair_info *predefined; 163b2deadd5SBob Moore 164d5a36100SBob Moore ACPI_FUNCTION_NAME(ns_simple_repair); 165d5a36100SBob Moore 166d5a36100SBob Moore /* 167d5a36100SBob Moore * Special repairs for certain names that are in the repair table. 168d5a36100SBob Moore * Check if this name is in the list of repairable names. 169d5a36100SBob Moore */ 17029a241ccSBob Moore predefined = acpi_ns_match_simple_repair(info->node, 17129a241ccSBob Moore info->return_btype, 172d5a36100SBob Moore package_index); 173d5a36100SBob Moore if (predefined) { 174d5a36100SBob Moore if (!return_object) { 17529a241ccSBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 176d5a36100SBob Moore ACPI_WARN_ALWAYS, 177d5a36100SBob Moore "Missing expected return value")); 178d5a36100SBob Moore } 179d5a36100SBob Moore 1804debda53SLv Zheng status = predefined->object_converter(info->node, return_object, 1814debda53SLv Zheng &new_object); 182d5a36100SBob Moore if (ACPI_FAILURE(status)) { 183d5a36100SBob Moore 184d5a36100SBob Moore /* A fatal error occurred during a conversion */ 185d5a36100SBob Moore 186d5a36100SBob Moore ACPI_EXCEPTION((AE_INFO, status, 187d5a36100SBob Moore "During return object analysis")); 188d5a36100SBob Moore return (status); 189d5a36100SBob Moore } 190d5a36100SBob Moore if (new_object) { 191d5a36100SBob Moore goto object_repaired; 192d5a36100SBob Moore } 193d5a36100SBob Moore } 194d5a36100SBob Moore 195d5a36100SBob Moore /* 196d5a36100SBob Moore * Do not perform simple object repair unless the return type is not 197d5a36100SBob Moore * expected. 198d5a36100SBob Moore */ 19929a241ccSBob Moore if (info->return_btype & expected_btypes) { 200d5a36100SBob Moore return (AE_OK); 201d5a36100SBob Moore } 2023a58176eSBob Moore 20327526993SBob Moore /* 20427526993SBob Moore * At this point, we know that the type of the returned object was not 20527526993SBob Moore * one of the expected types for this predefined name. Attempt to 20647e11d54SBob Moore * repair the object by converting it to one of the expected object 20747e11d54SBob Moore * types for this predefined name. 20827526993SBob Moore */ 209d5a36100SBob Moore 210d5a36100SBob Moore /* 211d5a36100SBob Moore * If there is no return value, check if we require a return value for 212d5a36100SBob Moore * this predefined name. Either one return value is expected, or none, 213d5a36100SBob Moore * for both methods and other objects. 214d5a36100SBob Moore * 21561db45caSLv Zheng * Try to fix if there was no return object. Warning if failed to fix. 216d5a36100SBob Moore */ 217d5a36100SBob Moore if (!return_object) { 218d5a36100SBob Moore if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) { 21961db45caSLv Zheng if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 22061db45caSLv Zheng ACPI_WARN_PREDEFINED((AE_INFO, 22161db45caSLv Zheng info->full_pathname, 22261db45caSLv Zheng ACPI_WARN_ALWAYS, 22361db45caSLv Zheng "Found unexpected NULL package element")); 22461db45caSLv Zheng 22561db45caSLv Zheng status = 22661db45caSLv Zheng acpi_ns_repair_null_element(info, 22761db45caSLv Zheng expected_btypes, 22861db45caSLv Zheng package_index, 22961db45caSLv Zheng return_object_ptr); 23061db45caSLv Zheng if (ACPI_SUCCESS(status)) { 23161db45caSLv Zheng return (AE_OK); /* Repair was successful */ 23261db45caSLv Zheng } 23361db45caSLv Zheng } else { 23461db45caSLv Zheng ACPI_WARN_PREDEFINED((AE_INFO, 23561db45caSLv Zheng info->full_pathname, 236d5a36100SBob Moore ACPI_WARN_ALWAYS, 237d5a36100SBob Moore "Missing expected return value")); 23861db45caSLv Zheng } 239d5a36100SBob Moore 240d5a36100SBob Moore return (AE_AML_NO_RETURN_VALUE); 241d5a36100SBob Moore } 242d5a36100SBob Moore } 243d5a36100SBob Moore 24447e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_INTEGER) { 24547e11d54SBob Moore status = acpi_ns_convert_to_integer(return_object, &new_object); 24647e11d54SBob Moore if (ACPI_SUCCESS(status)) { 24747e11d54SBob Moore goto object_repaired; 248b2deadd5SBob Moore } 249b2deadd5SBob Moore } 25047e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_STRING) { 25147e11d54SBob Moore status = acpi_ns_convert_to_string(return_object, &new_object); 25247e11d54SBob Moore if (ACPI_SUCCESS(status)) { 25347e11d54SBob Moore goto object_repaired; 254b2deadd5SBob Moore } 25547e11d54SBob Moore } 2560240d7b4SLin Ming if (expected_btypes & ACPI_RTYPE_BUFFER) { 25747e11d54SBob Moore status = acpi_ns_convert_to_buffer(return_object, &new_object); 25847e11d54SBob Moore if (ACPI_SUCCESS(status)) { 25947e11d54SBob Moore goto object_repaired; 2600240d7b4SLin Ming } 2610240d7b4SLin Ming } 26247e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_PACKAGE) { 2636a99b1c9SBob Moore /* 2646a99b1c9SBob Moore * A package is expected. We will wrap the existing object with a 2656a99b1c9SBob Moore * new package object. It is often the case that if a variable-length 2666a99b1c9SBob Moore * package is required, but there is only a single object needed, the 2676a99b1c9SBob Moore * BIOS will return that object instead of wrapping it with a Package 2686a99b1c9SBob Moore * object. Note: after the wrapping, the package will be validated 2696a99b1c9SBob Moore * for correct contents (expected object type or types). 2706a99b1c9SBob Moore */ 2716a99b1c9SBob Moore status = 27229a241ccSBob Moore acpi_ns_wrap_with_package(info, return_object, &new_object); 27347e11d54SBob Moore if (ACPI_SUCCESS(status)) { 2746a99b1c9SBob Moore /* 2756a99b1c9SBob Moore * The original object just had its reference count 2766a99b1c9SBob Moore * incremented for being inserted into the new package. 2776a99b1c9SBob Moore */ 2786a99b1c9SBob Moore *return_object_ptr = new_object; /* New Package object */ 27929a241ccSBob Moore info->return_flags |= ACPI_OBJECT_REPAIRED; 2806a99b1c9SBob Moore return (AE_OK); 28127526993SBob Moore } 28227526993SBob Moore } 28327526993SBob Moore 28427526993SBob Moore /* We cannot repair this object */ 28527526993SBob Moore 28627526993SBob Moore return (AE_AML_OPERAND_TYPE); 28747e11d54SBob Moore 28847e11d54SBob Moore object_repaired: 28927526993SBob Moore 29027526993SBob Moore /* Object was successfully repaired */ 291b2deadd5SBob Moore 292b2deadd5SBob Moore if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 293ed7f8bc9SBob Moore 294ed7f8bc9SBob Moore /* Update reference count of new object */ 295ed7f8bc9SBob Moore 29629a241ccSBob Moore if (!(info->return_flags & ACPI_OBJECT_WRAPPED)) { 297b2deadd5SBob Moore new_object->common.reference_count = 298b2deadd5SBob Moore return_object->common.reference_count; 2996a99b1c9SBob Moore } 300b2deadd5SBob Moore 3013a58176eSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 3026a99b1c9SBob Moore "%s: Converted %s to expected %s at Package index %u\n", 30329a241ccSBob Moore info->full_pathname, 3043a58176eSBob Moore acpi_ut_get_object_type_name(return_object), 30527526993SBob Moore acpi_ut_get_object_type_name(new_object), 306b2deadd5SBob Moore package_index)); 307b2deadd5SBob Moore } else { 3083a58176eSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 3093a58176eSBob Moore "%s: Converted %s to expected %s\n", 31029a241ccSBob Moore info->full_pathname, 3113a58176eSBob Moore acpi_ut_get_object_type_name(return_object), 3123a58176eSBob Moore acpi_ut_get_object_type_name(new_object))); 313b2deadd5SBob Moore } 314b2deadd5SBob Moore 315b2deadd5SBob Moore /* Delete old object, install the new return object */ 316b2deadd5SBob Moore 317b2deadd5SBob Moore acpi_ut_remove_reference(return_object); 318b2deadd5SBob Moore *return_object_ptr = new_object; 31929a241ccSBob Moore info->return_flags |= ACPI_OBJECT_REPAIRED; 320b2deadd5SBob Moore return (AE_OK); 321b2deadd5SBob Moore } 322e5f69d6eSBob Moore 323d5a36100SBob Moore /****************************************************************************** 324d5a36100SBob Moore * 325d5a36100SBob Moore * FUNCTION: acpi_ns_match_simple_repair 326d5a36100SBob Moore * 327d5a36100SBob Moore * PARAMETERS: node - Namespace node for the method/object 328d5a36100SBob Moore * return_btype - Object type that was returned 329d5a36100SBob Moore * package_index - Index of object within parent package (if 330d5a36100SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 331d5a36100SBob Moore * otherwise) 332d5a36100SBob Moore * 333d5a36100SBob Moore * RETURN: Pointer to entry in repair table. NULL indicates not found. 334d5a36100SBob Moore * 335d5a36100SBob Moore * DESCRIPTION: Check an object name against the repairable object list. 336d5a36100SBob Moore * 337d5a36100SBob Moore *****************************************************************************/ 338d5a36100SBob Moore 339d5a36100SBob Moore static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct 340d5a36100SBob Moore acpi_namespace_node 341d5a36100SBob Moore *node, 342d5a36100SBob Moore u32 343d5a36100SBob Moore return_btype, 344d5a36100SBob Moore u32 345d5a36100SBob Moore package_index) 346d5a36100SBob Moore { 347d5a36100SBob Moore const struct acpi_simple_repair_info *this_name; 348d5a36100SBob Moore 349d5a36100SBob Moore /* Search info table for a repairable predefined method/object name */ 350d5a36100SBob Moore 351d5a36100SBob Moore this_name = acpi_object_repair_info; 352d5a36100SBob Moore while (this_name->object_converter) { 353d5a36100SBob Moore if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) { 354d5a36100SBob Moore 355d5a36100SBob Moore /* Check if we can actually repair this name/type combination */ 356d5a36100SBob Moore 357d5a36100SBob Moore if ((return_btype & this_name->unexpected_btypes) && 358ee387409SLv Zheng (this_name->package_index == 359ee387409SLv Zheng ACPI_ALL_PACKAGE_ELEMENTS 360ee387409SLv Zheng || package_index == this_name->package_index)) { 361d5a36100SBob Moore return (this_name); 362d5a36100SBob Moore } 363d5a36100SBob Moore 364d5a36100SBob Moore return (NULL); 365d5a36100SBob Moore } 3661fad8738SBob Moore 367d5a36100SBob Moore this_name++; 368d5a36100SBob Moore } 369d5a36100SBob Moore 370d5a36100SBob Moore return (NULL); /* Name was not found in the repair table */ 371d5a36100SBob Moore } 372d5a36100SBob Moore 373e5f69d6eSBob Moore /******************************************************************************* 374e5f69d6eSBob Moore * 375091f4d71SBob Moore * FUNCTION: acpi_ns_repair_null_element 376091f4d71SBob Moore * 37729a241ccSBob Moore * PARAMETERS: info - Method execution information block 378091f4d71SBob Moore * expected_btypes - Object types expected 379091f4d71SBob Moore * package_index - Index of object within parent package (if 380091f4d71SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 381091f4d71SBob Moore * otherwise) 382091f4d71SBob Moore * return_object_ptr - Pointer to the object returned from the 383091f4d71SBob Moore * evaluation of a method or object 384091f4d71SBob Moore * 385091f4d71SBob Moore * RETURN: Status. AE_OK if repair was successful. 386091f4d71SBob Moore * 387091f4d71SBob Moore * DESCRIPTION: Attempt to repair a NULL element of a returned Package object. 388091f4d71SBob Moore * 389091f4d71SBob Moore ******************************************************************************/ 390091f4d71SBob Moore 391091f4d71SBob Moore acpi_status 39229a241ccSBob Moore acpi_ns_repair_null_element(struct acpi_evaluate_info *info, 393091f4d71SBob Moore u32 expected_btypes, 394091f4d71SBob Moore u32 package_index, 395091f4d71SBob Moore union acpi_operand_object **return_object_ptr) 396091f4d71SBob Moore { 397091f4d71SBob Moore union acpi_operand_object *return_object = *return_object_ptr; 398091f4d71SBob Moore union acpi_operand_object *new_object; 399091f4d71SBob Moore 400091f4d71SBob Moore ACPI_FUNCTION_NAME(ns_repair_null_element); 401091f4d71SBob Moore 402091f4d71SBob Moore /* No repair needed if return object is non-NULL */ 403091f4d71SBob Moore 404091f4d71SBob Moore if (return_object) { 405091f4d71SBob Moore return (AE_OK); 406091f4d71SBob Moore } 407091f4d71SBob Moore 408091f4d71SBob Moore /* 409091f4d71SBob Moore * Attempt to repair a NULL element of a Package object. This applies to 410091f4d71SBob Moore * predefined names that return a fixed-length package and each element 411091f4d71SBob Moore * is required. It does not apply to variable-length packages where NULL 412091f4d71SBob Moore * elements are allowed, especially at the end of the package. 413091f4d71SBob Moore */ 414091f4d71SBob Moore if (expected_btypes & ACPI_RTYPE_INTEGER) { 415091f4d71SBob Moore 416ba494beeSBob Moore /* Need an integer - create a zero-value integer */ 417091f4d71SBob Moore 418150dba38SBob Moore new_object = acpi_ut_create_integer_object((u64)0); 419091f4d71SBob Moore } else if (expected_btypes & ACPI_RTYPE_STRING) { 420091f4d71SBob Moore 421ba494beeSBob Moore /* Need a string - create a NULL string */ 422091f4d71SBob Moore 423091f4d71SBob Moore new_object = acpi_ut_create_string_object(0); 424091f4d71SBob Moore } else if (expected_btypes & ACPI_RTYPE_BUFFER) { 425091f4d71SBob Moore 426ba494beeSBob Moore /* Need a buffer - create a zero-length buffer */ 427091f4d71SBob Moore 428091f4d71SBob Moore new_object = acpi_ut_create_buffer_object(0); 429091f4d71SBob Moore } else { 430091f4d71SBob Moore /* Error for all other expected types */ 431091f4d71SBob Moore 432091f4d71SBob Moore return (AE_AML_OPERAND_TYPE); 433091f4d71SBob Moore } 434091f4d71SBob Moore 435091f4d71SBob Moore if (!new_object) { 436091f4d71SBob Moore return (AE_NO_MEMORY); 437091f4d71SBob Moore } 438091f4d71SBob Moore 439091f4d71SBob Moore /* Set the reference count according to the parent Package object */ 440091f4d71SBob Moore 441091f4d71SBob Moore new_object->common.reference_count = 44229a241ccSBob Moore info->parent_package->common.reference_count; 443091f4d71SBob Moore 444091f4d71SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 445091f4d71SBob Moore "%s: Converted NULL package element to expected %s at index %u\n", 44629a241ccSBob Moore info->full_pathname, 447091f4d71SBob Moore acpi_ut_get_object_type_name(new_object), 448091f4d71SBob Moore package_index)); 449091f4d71SBob Moore 450091f4d71SBob Moore *return_object_ptr = new_object; 45129a241ccSBob Moore info->return_flags |= ACPI_OBJECT_REPAIRED; 452091f4d71SBob Moore return (AE_OK); 453091f4d71SBob Moore } 454091f4d71SBob Moore 455091f4d71SBob Moore /****************************************************************************** 456091f4d71SBob Moore * 457091f4d71SBob Moore * FUNCTION: acpi_ns_remove_null_elements 458091f4d71SBob Moore * 45929a241ccSBob Moore * PARAMETERS: info - Method execution information block 460091f4d71SBob Moore * package_type - An acpi_return_package_types value 461091f4d71SBob Moore * obj_desc - A Package object 462091f4d71SBob Moore * 463091f4d71SBob Moore * RETURN: None. 464091f4d71SBob Moore * 465091f4d71SBob Moore * DESCRIPTION: Remove all NULL package elements from packages that contain 4660a16d12aSBob Moore * a variable number of subpackages. For these types of 467091f4d71SBob Moore * packages, NULL elements can be safely removed. 468091f4d71SBob Moore * 469091f4d71SBob Moore *****************************************************************************/ 470091f4d71SBob Moore 471091f4d71SBob Moore void 47229a241ccSBob Moore acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, 473091f4d71SBob Moore u8 package_type, 474091f4d71SBob Moore union acpi_operand_object *obj_desc) 475091f4d71SBob Moore { 476091f4d71SBob Moore union acpi_operand_object **source; 477091f4d71SBob Moore union acpi_operand_object **dest; 478091f4d71SBob Moore u32 count; 479091f4d71SBob Moore u32 new_count; 480091f4d71SBob Moore u32 i; 481091f4d71SBob Moore 482091f4d71SBob Moore ACPI_FUNCTION_NAME(ns_remove_null_elements); 483091f4d71SBob Moore 484091f4d71SBob Moore /* 485945488b9SBob Moore * We can safely remove all NULL elements from these package types: 486945488b9SBob Moore * PTYPE1_VAR packages contain a variable number of simple data types. 4870a16d12aSBob Moore * PTYPE2 packages contain a variable number of subpackages. 488091f4d71SBob Moore */ 489091f4d71SBob Moore switch (package_type) { 490091f4d71SBob Moore case ACPI_PTYPE1_VAR: 491091f4d71SBob Moore case ACPI_PTYPE2: 492091f4d71SBob Moore case ACPI_PTYPE2_COUNT: 493091f4d71SBob Moore case ACPI_PTYPE2_PKG_COUNT: 494091f4d71SBob Moore case ACPI_PTYPE2_FIXED: 495091f4d71SBob Moore case ACPI_PTYPE2_MIN: 496091f4d71SBob Moore case ACPI_PTYPE2_REV_FIXED: 4977fce7a4bSBob Moore case ACPI_PTYPE2_FIX_VAR: 498091f4d71SBob Moore break; 499091f4d71SBob Moore 500091f4d71SBob Moore default: 501e34a7813SBob Moore case ACPI_PTYPE2_VAR_VAR: 502945488b9SBob Moore case ACPI_PTYPE1_FIXED: 503945488b9SBob Moore case ACPI_PTYPE1_OPTION: 504091f4d71SBob Moore return; 505091f4d71SBob Moore } 506091f4d71SBob Moore 507091f4d71SBob Moore count = obj_desc->package.count; 508091f4d71SBob Moore new_count = count; 509091f4d71SBob Moore 510091f4d71SBob Moore source = obj_desc->package.elements; 511091f4d71SBob Moore dest = source; 512091f4d71SBob Moore 513091f4d71SBob Moore /* Examine all elements of the package object, remove nulls */ 514091f4d71SBob Moore 515091f4d71SBob Moore for (i = 0; i < count; i++) { 516091f4d71SBob Moore if (!*source) { 517091f4d71SBob Moore new_count--; 518091f4d71SBob Moore } else { 519091f4d71SBob Moore *dest = *source; 520091f4d71SBob Moore dest++; 521091f4d71SBob Moore } 5221fad8738SBob Moore 523091f4d71SBob Moore source++; 524091f4d71SBob Moore } 525091f4d71SBob Moore 526091f4d71SBob Moore /* Update parent package if any null elements were removed */ 527091f4d71SBob Moore 528091f4d71SBob Moore if (new_count < count) { 529091f4d71SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 530091f4d71SBob Moore "%s: Found and removed %u NULL elements\n", 53129a241ccSBob Moore info->full_pathname, (count - new_count))); 532091f4d71SBob Moore 533091f4d71SBob Moore /* NULL terminate list and update the package count */ 534091f4d71SBob Moore 535091f4d71SBob Moore *dest = NULL; 536091f4d71SBob Moore obj_desc->package.count = new_count; 537091f4d71SBob Moore } 538091f4d71SBob Moore } 539091f4d71SBob Moore 540091f4d71SBob Moore /******************************************************************************* 541091f4d71SBob Moore * 5426a99b1c9SBob Moore * FUNCTION: acpi_ns_wrap_with_package 543e5f69d6eSBob Moore * 54429a241ccSBob Moore * PARAMETERS: info - Method execution information block 5456a99b1c9SBob Moore * original_object - Pointer to the object to repair. 5466a99b1c9SBob Moore * obj_desc_ptr - The new package object is returned here 547e5f69d6eSBob Moore * 548e5f69d6eSBob Moore * RETURN: Status, new object in *obj_desc_ptr 549e5f69d6eSBob Moore * 5506a99b1c9SBob Moore * DESCRIPTION: Repair a common problem with objects that are defined to 5516a99b1c9SBob Moore * return a variable-length Package of sub-objects. If there is 5526a99b1c9SBob Moore * only one sub-object, some BIOS code mistakenly simply declares 5536a99b1c9SBob Moore * the single object instead of a Package with one sub-object. 5546a99b1c9SBob Moore * This function attempts to repair this error by wrapping a 5556a99b1c9SBob Moore * Package object around the original object, creating the 5566a99b1c9SBob Moore * correct and expected Package with one sub-object. 557e5f69d6eSBob Moore * 558e5f69d6eSBob Moore * Names that can be repaired in this manner include: 5596a99b1c9SBob Moore * _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS, 5606a99b1c9SBob Moore * _BCL, _DOD, _FIX, _Sx 561e5f69d6eSBob Moore * 562e5f69d6eSBob Moore ******************************************************************************/ 563e5f69d6eSBob Moore 564e5f69d6eSBob Moore acpi_status 56529a241ccSBob Moore acpi_ns_wrap_with_package(struct acpi_evaluate_info *info, 5666a99b1c9SBob Moore union acpi_operand_object *original_object, 567e5f69d6eSBob Moore union acpi_operand_object **obj_desc_ptr) 568e5f69d6eSBob Moore { 569e5f69d6eSBob Moore union acpi_operand_object *pkg_obj_desc; 570e5f69d6eSBob Moore 5716a99b1c9SBob Moore ACPI_FUNCTION_NAME(ns_wrap_with_package); 5723a58176eSBob Moore 573e5f69d6eSBob Moore /* 5741fad8738SBob Moore * Create the new outer package and populate it. The new 5751fad8738SBob Moore * package will have a single element, the lone sub-object. 576e5f69d6eSBob Moore */ 577e5f69d6eSBob Moore pkg_obj_desc = acpi_ut_create_package_object(1); 578e5f69d6eSBob Moore if (!pkg_obj_desc) { 579e5f69d6eSBob Moore return (AE_NO_MEMORY); 580e5f69d6eSBob Moore } 581e5f69d6eSBob Moore 5826a99b1c9SBob Moore pkg_obj_desc->package.elements[0] = original_object; 5836a99b1c9SBob Moore 5846a99b1c9SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 5856a99b1c9SBob Moore "%s: Wrapped %s with expected Package object\n", 58629a241ccSBob Moore info->full_pathname, 5876a99b1c9SBob Moore acpi_ut_get_object_type_name(original_object))); 588e5f69d6eSBob Moore 589e5f69d6eSBob Moore /* Return the new object in the object pointer */ 590e5f69d6eSBob Moore 591e5f69d6eSBob Moore *obj_desc_ptr = pkg_obj_desc; 59229a241ccSBob Moore info->return_flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; 593e5f69d6eSBob Moore return (AE_OK); 594e5f69d6eSBob Moore } 595