1b2deadd5SBob Moore /****************************************************************************** 2b2deadd5SBob Moore * 3b2deadd5SBob Moore * Module Name: nsrepair - Repair for objects returned by predefined methods 4b2deadd5SBob Moore * 5b2deadd5SBob Moore *****************************************************************************/ 6b2deadd5SBob Moore 7b2deadd5SBob Moore /* 825f044e6SBob Moore * Copyright (C) 2000 - 2013, 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[] = { 10196b44cc6SLv Zheng /* Unicode conversions */ 10296b44cc6SLv Zheng 10396b44cc6SLv Zheng {"_MLS", ACPI_RTYPE_STRING, 1, 10496b44cc6SLv Zheng acpi_ns_convert_to_unicode}, 10596b44cc6SLv Zheng {"_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, 10696b44cc6SLv Zheng ACPI_NOT_PACKAGE_ELEMENT, 10796b44cc6SLv Zheng acpi_ns_convert_to_unicode}, 108d5a36100SBob Moore {{0, 0, 0, 0}, 0, 0, NULL} /* Table terminator */ 109d5a36100SBob Moore }; 110d5a36100SBob Moore 11147e11d54SBob Moore /******************************************************************************* 11247e11d54SBob Moore * 113d5a36100SBob Moore * FUNCTION: acpi_ns_simple_repair 114b2deadd5SBob Moore * 115ba494beeSBob Moore * PARAMETERS: data - Pointer to validation data structure 116b2deadd5SBob Moore * expected_btypes - Object types expected 117b2deadd5SBob Moore * package_index - Index of object within parent package (if 118b2deadd5SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 119b2deadd5SBob Moore * otherwise) 120b2deadd5SBob Moore * return_object_ptr - Pointer to the object returned from the 121b2deadd5SBob Moore * evaluation of a method or object 122b2deadd5SBob Moore * 123b2deadd5SBob Moore * RETURN: Status. AE_OK if repair was successful. 124b2deadd5SBob Moore * 125b2deadd5SBob Moore * DESCRIPTION: Attempt to repair/convert a return object of a type that was 126b2deadd5SBob Moore * not expected. 127b2deadd5SBob Moore * 128b2deadd5SBob Moore ******************************************************************************/ 12947e11d54SBob Moore 130b2deadd5SBob Moore acpi_status 131d5a36100SBob Moore acpi_ns_simple_repair(struct acpi_predefined_data *data, 132b2deadd5SBob Moore u32 expected_btypes, 133b2deadd5SBob Moore u32 package_index, 134b2deadd5SBob Moore union acpi_operand_object **return_object_ptr) 135b2deadd5SBob Moore { 136b2deadd5SBob Moore union acpi_operand_object *return_object = *return_object_ptr; 137d5a36100SBob Moore union acpi_operand_object *new_object = NULL; 1380240d7b4SLin Ming acpi_status status; 139d5a36100SBob Moore const struct acpi_simple_repair_info *predefined; 140b2deadd5SBob Moore 141d5a36100SBob Moore ACPI_FUNCTION_NAME(ns_simple_repair); 142d5a36100SBob Moore 143d5a36100SBob Moore /* 144d5a36100SBob Moore * Special repairs for certain names that are in the repair table. 145d5a36100SBob Moore * Check if this name is in the list of repairable names. 146d5a36100SBob Moore */ 147d5a36100SBob Moore predefined = acpi_ns_match_simple_repair(data->node, 148d5a36100SBob Moore data->return_btype, 149d5a36100SBob Moore package_index); 150d5a36100SBob Moore if (predefined) { 151d5a36100SBob Moore if (!return_object) { 152d5a36100SBob Moore ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, 153d5a36100SBob Moore ACPI_WARN_ALWAYS, 154d5a36100SBob Moore "Missing expected return value")); 155d5a36100SBob Moore } 156d5a36100SBob Moore 157d5a36100SBob Moore status = 158d5a36100SBob Moore predefined->object_converter(return_object, &new_object); 159d5a36100SBob Moore if (ACPI_FAILURE(status)) { 160d5a36100SBob Moore 161d5a36100SBob Moore /* A fatal error occurred during a conversion */ 162d5a36100SBob Moore 163d5a36100SBob Moore ACPI_EXCEPTION((AE_INFO, status, 164d5a36100SBob Moore "During return object analysis")); 165d5a36100SBob Moore return (status); 166d5a36100SBob Moore } 167d5a36100SBob Moore if (new_object) { 168d5a36100SBob Moore goto object_repaired; 169d5a36100SBob Moore } 170d5a36100SBob Moore } 171d5a36100SBob Moore 172d5a36100SBob Moore /* 173d5a36100SBob Moore * Do not perform simple object repair unless the return type is not 174d5a36100SBob Moore * expected. 175d5a36100SBob Moore */ 176d5a36100SBob Moore if (data->return_btype & expected_btypes) { 177d5a36100SBob Moore return (AE_OK); 178d5a36100SBob Moore } 1793a58176eSBob Moore 18027526993SBob Moore /* 18127526993SBob Moore * At this point, we know that the type of the returned object was not 18227526993SBob Moore * one of the expected types for this predefined name. Attempt to 18347e11d54SBob Moore * repair the object by converting it to one of the expected object 18447e11d54SBob Moore * types for this predefined name. 18527526993SBob Moore */ 186d5a36100SBob Moore 187d5a36100SBob Moore /* 188d5a36100SBob Moore * If there is no return value, check if we require a return value for 189d5a36100SBob Moore * this predefined name. Either one return value is expected, or none, 190d5a36100SBob Moore * for both methods and other objects. 191d5a36100SBob Moore * 192d5a36100SBob Moore * Exit now if there is no return object. Warning if one was expected. 193d5a36100SBob Moore */ 194d5a36100SBob Moore if (!return_object) { 195d5a36100SBob Moore if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) { 196d5a36100SBob Moore ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, 197d5a36100SBob Moore ACPI_WARN_ALWAYS, 198d5a36100SBob Moore "Missing expected return value")); 199d5a36100SBob Moore 200d5a36100SBob Moore return (AE_AML_NO_RETURN_VALUE); 201d5a36100SBob Moore } 202d5a36100SBob Moore } 203d5a36100SBob Moore 20447e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_INTEGER) { 20547e11d54SBob Moore status = acpi_ns_convert_to_integer(return_object, &new_object); 20647e11d54SBob Moore if (ACPI_SUCCESS(status)) { 20747e11d54SBob Moore goto object_repaired; 208b2deadd5SBob Moore } 209b2deadd5SBob Moore } 21047e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_STRING) { 21147e11d54SBob Moore status = acpi_ns_convert_to_string(return_object, &new_object); 21247e11d54SBob Moore if (ACPI_SUCCESS(status)) { 21347e11d54SBob Moore goto object_repaired; 214b2deadd5SBob Moore } 21547e11d54SBob Moore } 2160240d7b4SLin Ming if (expected_btypes & ACPI_RTYPE_BUFFER) { 21747e11d54SBob Moore status = acpi_ns_convert_to_buffer(return_object, &new_object); 21847e11d54SBob Moore if (ACPI_SUCCESS(status)) { 21947e11d54SBob Moore goto object_repaired; 2200240d7b4SLin Ming } 2210240d7b4SLin Ming } 22247e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_PACKAGE) { 2236a99b1c9SBob Moore /* 2246a99b1c9SBob Moore * A package is expected. We will wrap the existing object with a 2256a99b1c9SBob Moore * new package object. It is often the case that if a variable-length 2266a99b1c9SBob Moore * package is required, but there is only a single object needed, the 2276a99b1c9SBob Moore * BIOS will return that object instead of wrapping it with a Package 2286a99b1c9SBob Moore * object. Note: after the wrapping, the package will be validated 2296a99b1c9SBob Moore * for correct contents (expected object type or types). 2306a99b1c9SBob Moore */ 2316a99b1c9SBob Moore status = 2326a99b1c9SBob Moore acpi_ns_wrap_with_package(data, return_object, &new_object); 23347e11d54SBob Moore if (ACPI_SUCCESS(status)) { 2346a99b1c9SBob Moore /* 2356a99b1c9SBob Moore * The original object just had its reference count 2366a99b1c9SBob Moore * incremented for being inserted into the new package. 2376a99b1c9SBob Moore */ 2386a99b1c9SBob Moore *return_object_ptr = new_object; /* New Package object */ 2396a99b1c9SBob Moore data->flags |= ACPI_OBJECT_REPAIRED; 2406a99b1c9SBob Moore return (AE_OK); 24127526993SBob Moore } 24227526993SBob Moore } 24327526993SBob Moore 24427526993SBob Moore /* We cannot repair this object */ 24527526993SBob Moore 24627526993SBob Moore return (AE_AML_OPERAND_TYPE); 24747e11d54SBob Moore 24847e11d54SBob Moore object_repaired: 24927526993SBob Moore 25027526993SBob Moore /* Object was successfully repaired */ 251b2deadd5SBob Moore 252b2deadd5SBob Moore if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 2536a99b1c9SBob Moore /* 2546a99b1c9SBob Moore * The original object is a package element. We need to 2556a99b1c9SBob Moore * decrement the reference count of the original object, 2566a99b1c9SBob Moore * for removing it from the package. 2576a99b1c9SBob Moore * 2586a99b1c9SBob Moore * However, if the original object was just wrapped with a 2596a99b1c9SBob Moore * package object as part of the repair, we don't need to 2606a99b1c9SBob Moore * change the reference count. 2616a99b1c9SBob Moore */ 2626a99b1c9SBob Moore if (!(data->flags & ACPI_OBJECT_WRAPPED)) { 263b2deadd5SBob Moore new_object->common.reference_count = 264b2deadd5SBob Moore return_object->common.reference_count; 265b2deadd5SBob Moore 266b2deadd5SBob Moore if (return_object->common.reference_count > 1) { 267b2deadd5SBob Moore return_object->common.reference_count--; 268b2deadd5SBob Moore } 2696a99b1c9SBob Moore } 270b2deadd5SBob Moore 2713a58176eSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 2726a99b1c9SBob Moore "%s: Converted %s to expected %s at Package index %u\n", 2733a58176eSBob Moore data->pathname, 2743a58176eSBob Moore acpi_ut_get_object_type_name(return_object), 27527526993SBob Moore acpi_ut_get_object_type_name(new_object), 276b2deadd5SBob Moore package_index)); 277b2deadd5SBob Moore } else { 2783a58176eSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 2793a58176eSBob Moore "%s: Converted %s to expected %s\n", 2803a58176eSBob Moore data->pathname, 2813a58176eSBob Moore acpi_ut_get_object_type_name(return_object), 2823a58176eSBob Moore acpi_ut_get_object_type_name(new_object))); 283b2deadd5SBob Moore } 284b2deadd5SBob Moore 285b2deadd5SBob Moore /* Delete old object, install the new return object */ 286b2deadd5SBob Moore 287b2deadd5SBob Moore acpi_ut_remove_reference(return_object); 288b2deadd5SBob Moore *return_object_ptr = new_object; 289b2deadd5SBob Moore data->flags |= ACPI_OBJECT_REPAIRED; 290b2deadd5SBob Moore return (AE_OK); 291b2deadd5SBob Moore } 292e5f69d6eSBob Moore 293d5a36100SBob Moore /****************************************************************************** 294d5a36100SBob Moore * 295d5a36100SBob Moore * FUNCTION: acpi_ns_match_simple_repair 296d5a36100SBob Moore * 297d5a36100SBob Moore * PARAMETERS: node - Namespace node for the method/object 298d5a36100SBob Moore * return_btype - Object type that was returned 299d5a36100SBob Moore * package_index - Index of object within parent package (if 300d5a36100SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 301d5a36100SBob Moore * otherwise) 302d5a36100SBob Moore * 303d5a36100SBob Moore * RETURN: Pointer to entry in repair table. NULL indicates not found. 304d5a36100SBob Moore * 305d5a36100SBob Moore * DESCRIPTION: Check an object name against the repairable object list. 306d5a36100SBob Moore * 307d5a36100SBob Moore *****************************************************************************/ 308d5a36100SBob Moore 309d5a36100SBob Moore static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct 310d5a36100SBob Moore acpi_namespace_node 311d5a36100SBob Moore *node, 312d5a36100SBob Moore u32 313d5a36100SBob Moore return_btype, 314d5a36100SBob Moore u32 315d5a36100SBob Moore package_index) 316d5a36100SBob Moore { 317d5a36100SBob Moore const struct acpi_simple_repair_info *this_name; 318d5a36100SBob Moore 319d5a36100SBob Moore /* Search info table for a repairable predefined method/object name */ 320d5a36100SBob Moore 321d5a36100SBob Moore this_name = acpi_object_repair_info; 322d5a36100SBob Moore while (this_name->object_converter) { 323d5a36100SBob Moore if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) { 324d5a36100SBob Moore 325d5a36100SBob Moore /* Check if we can actually repair this name/type combination */ 326d5a36100SBob Moore 327d5a36100SBob Moore if ((return_btype & this_name->unexpected_btypes) && 328d5a36100SBob Moore (package_index == this_name->package_index)) { 329d5a36100SBob Moore return (this_name); 330d5a36100SBob Moore } 331d5a36100SBob Moore 332d5a36100SBob Moore return (NULL); 333d5a36100SBob Moore } 334d5a36100SBob Moore this_name++; 335d5a36100SBob Moore } 336d5a36100SBob Moore 337d5a36100SBob Moore return (NULL); /* Name was not found in the repair table */ 338d5a36100SBob Moore } 339d5a36100SBob Moore 340e5f69d6eSBob Moore /******************************************************************************* 341e5f69d6eSBob Moore * 342091f4d71SBob Moore * FUNCTION: acpi_ns_repair_null_element 343091f4d71SBob Moore * 344ba494beeSBob Moore * PARAMETERS: data - Pointer to validation data structure 345091f4d71SBob Moore * expected_btypes - Object types expected 346091f4d71SBob Moore * package_index - Index of object within parent package (if 347091f4d71SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 348091f4d71SBob Moore * otherwise) 349091f4d71SBob Moore * return_object_ptr - Pointer to the object returned from the 350091f4d71SBob Moore * evaluation of a method or object 351091f4d71SBob Moore * 352091f4d71SBob Moore * RETURN: Status. AE_OK if repair was successful. 353091f4d71SBob Moore * 354091f4d71SBob Moore * DESCRIPTION: Attempt to repair a NULL element of a returned Package object. 355091f4d71SBob Moore * 356091f4d71SBob Moore ******************************************************************************/ 357091f4d71SBob Moore 358091f4d71SBob Moore acpi_status 359091f4d71SBob Moore acpi_ns_repair_null_element(struct acpi_predefined_data *data, 360091f4d71SBob Moore u32 expected_btypes, 361091f4d71SBob Moore u32 package_index, 362091f4d71SBob Moore union acpi_operand_object **return_object_ptr) 363091f4d71SBob Moore { 364091f4d71SBob Moore union acpi_operand_object *return_object = *return_object_ptr; 365091f4d71SBob Moore union acpi_operand_object *new_object; 366091f4d71SBob Moore 367091f4d71SBob Moore ACPI_FUNCTION_NAME(ns_repair_null_element); 368091f4d71SBob Moore 369091f4d71SBob Moore /* No repair needed if return object is non-NULL */ 370091f4d71SBob Moore 371091f4d71SBob Moore if (return_object) { 372091f4d71SBob Moore return (AE_OK); 373091f4d71SBob Moore } 374091f4d71SBob Moore 375091f4d71SBob Moore /* 376091f4d71SBob Moore * Attempt to repair a NULL element of a Package object. This applies to 377091f4d71SBob Moore * predefined names that return a fixed-length package and each element 378091f4d71SBob Moore * is required. It does not apply to variable-length packages where NULL 379091f4d71SBob Moore * elements are allowed, especially at the end of the package. 380091f4d71SBob Moore */ 381091f4d71SBob Moore if (expected_btypes & ACPI_RTYPE_INTEGER) { 382091f4d71SBob Moore 383ba494beeSBob Moore /* Need an integer - create a zero-value integer */ 384091f4d71SBob Moore 385150dba38SBob Moore new_object = acpi_ut_create_integer_object((u64)0); 386091f4d71SBob Moore } else if (expected_btypes & ACPI_RTYPE_STRING) { 387091f4d71SBob Moore 388ba494beeSBob Moore /* Need a string - create a NULL string */ 389091f4d71SBob Moore 390091f4d71SBob Moore new_object = acpi_ut_create_string_object(0); 391091f4d71SBob Moore } else if (expected_btypes & ACPI_RTYPE_BUFFER) { 392091f4d71SBob Moore 393ba494beeSBob Moore /* Need a buffer - create a zero-length buffer */ 394091f4d71SBob Moore 395091f4d71SBob Moore new_object = acpi_ut_create_buffer_object(0); 396091f4d71SBob Moore } else { 397091f4d71SBob Moore /* Error for all other expected types */ 398091f4d71SBob Moore 399091f4d71SBob Moore return (AE_AML_OPERAND_TYPE); 400091f4d71SBob Moore } 401091f4d71SBob Moore 402091f4d71SBob Moore if (!new_object) { 403091f4d71SBob Moore return (AE_NO_MEMORY); 404091f4d71SBob Moore } 405091f4d71SBob Moore 406091f4d71SBob Moore /* Set the reference count according to the parent Package object */ 407091f4d71SBob Moore 408091f4d71SBob Moore new_object->common.reference_count = 409091f4d71SBob Moore data->parent_package->common.reference_count; 410091f4d71SBob Moore 411091f4d71SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 412091f4d71SBob Moore "%s: Converted NULL package element to expected %s at index %u\n", 413091f4d71SBob Moore data->pathname, 414091f4d71SBob Moore acpi_ut_get_object_type_name(new_object), 415091f4d71SBob Moore package_index)); 416091f4d71SBob Moore 417091f4d71SBob Moore *return_object_ptr = new_object; 418091f4d71SBob Moore data->flags |= ACPI_OBJECT_REPAIRED; 419091f4d71SBob Moore return (AE_OK); 420091f4d71SBob Moore } 421091f4d71SBob Moore 422091f4d71SBob Moore /****************************************************************************** 423091f4d71SBob Moore * 424091f4d71SBob Moore * FUNCTION: acpi_ns_remove_null_elements 425091f4d71SBob Moore * 426ba494beeSBob Moore * PARAMETERS: data - Pointer to validation data structure 427091f4d71SBob Moore * package_type - An acpi_return_package_types value 428091f4d71SBob Moore * obj_desc - A Package object 429091f4d71SBob Moore * 430091f4d71SBob Moore * RETURN: None. 431091f4d71SBob Moore * 432091f4d71SBob Moore * DESCRIPTION: Remove all NULL package elements from packages that contain 433091f4d71SBob Moore * a variable number of sub-packages. For these types of 434091f4d71SBob Moore * packages, NULL elements can be safely removed. 435091f4d71SBob Moore * 436091f4d71SBob Moore *****************************************************************************/ 437091f4d71SBob Moore 438091f4d71SBob Moore void 439091f4d71SBob Moore acpi_ns_remove_null_elements(struct acpi_predefined_data *data, 440091f4d71SBob Moore u8 package_type, 441091f4d71SBob Moore union acpi_operand_object *obj_desc) 442091f4d71SBob Moore { 443091f4d71SBob Moore union acpi_operand_object **source; 444091f4d71SBob Moore union acpi_operand_object **dest; 445091f4d71SBob Moore u32 count; 446091f4d71SBob Moore u32 new_count; 447091f4d71SBob Moore u32 i; 448091f4d71SBob Moore 449091f4d71SBob Moore ACPI_FUNCTION_NAME(ns_remove_null_elements); 450091f4d71SBob Moore 451091f4d71SBob Moore /* 452945488b9SBob Moore * We can safely remove all NULL elements from these package types: 453945488b9SBob Moore * PTYPE1_VAR packages contain a variable number of simple data types. 454945488b9SBob Moore * PTYPE2 packages contain a variable number of sub-packages. 455091f4d71SBob Moore */ 456091f4d71SBob Moore switch (package_type) { 457091f4d71SBob Moore case ACPI_PTYPE1_VAR: 458091f4d71SBob Moore case ACPI_PTYPE2: 459091f4d71SBob Moore case ACPI_PTYPE2_COUNT: 460091f4d71SBob Moore case ACPI_PTYPE2_PKG_COUNT: 461091f4d71SBob Moore case ACPI_PTYPE2_FIXED: 462091f4d71SBob Moore case ACPI_PTYPE2_MIN: 463091f4d71SBob Moore case ACPI_PTYPE2_REV_FIXED: 4647fce7a4bSBob Moore case ACPI_PTYPE2_FIX_VAR: 465091f4d71SBob Moore break; 466091f4d71SBob Moore 467091f4d71SBob Moore default: 468945488b9SBob Moore case ACPI_PTYPE1_FIXED: 469945488b9SBob Moore case ACPI_PTYPE1_OPTION: 470091f4d71SBob Moore return; 471091f4d71SBob Moore } 472091f4d71SBob Moore 473091f4d71SBob Moore count = obj_desc->package.count; 474091f4d71SBob Moore new_count = count; 475091f4d71SBob Moore 476091f4d71SBob Moore source = obj_desc->package.elements; 477091f4d71SBob Moore dest = source; 478091f4d71SBob Moore 479091f4d71SBob Moore /* Examine all elements of the package object, remove nulls */ 480091f4d71SBob Moore 481091f4d71SBob Moore for (i = 0; i < count; i++) { 482091f4d71SBob Moore if (!*source) { 483091f4d71SBob Moore new_count--; 484091f4d71SBob Moore } else { 485091f4d71SBob Moore *dest = *source; 486091f4d71SBob Moore dest++; 487091f4d71SBob Moore } 488091f4d71SBob Moore source++; 489091f4d71SBob Moore } 490091f4d71SBob Moore 491091f4d71SBob Moore /* Update parent package if any null elements were removed */ 492091f4d71SBob Moore 493091f4d71SBob Moore if (new_count < count) { 494091f4d71SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 495091f4d71SBob Moore "%s: Found and removed %u NULL elements\n", 496091f4d71SBob Moore data->pathname, (count - new_count))); 497091f4d71SBob Moore 498091f4d71SBob Moore /* NULL terminate list and update the package count */ 499091f4d71SBob Moore 500091f4d71SBob Moore *dest = NULL; 501091f4d71SBob Moore obj_desc->package.count = new_count; 502091f4d71SBob Moore } 503091f4d71SBob Moore } 504091f4d71SBob Moore 505091f4d71SBob Moore /******************************************************************************* 506091f4d71SBob Moore * 5076a99b1c9SBob Moore * FUNCTION: acpi_ns_wrap_with_package 508e5f69d6eSBob Moore * 509ba494beeSBob Moore * PARAMETERS: data - Pointer to validation data structure 5106a99b1c9SBob Moore * original_object - Pointer to the object to repair. 5116a99b1c9SBob Moore * obj_desc_ptr - The new package object is returned here 512e5f69d6eSBob Moore * 513e5f69d6eSBob Moore * RETURN: Status, new object in *obj_desc_ptr 514e5f69d6eSBob Moore * 5156a99b1c9SBob Moore * DESCRIPTION: Repair a common problem with objects that are defined to 5166a99b1c9SBob Moore * return a variable-length Package of sub-objects. If there is 5176a99b1c9SBob Moore * only one sub-object, some BIOS code mistakenly simply declares 5186a99b1c9SBob Moore * the single object instead of a Package with one sub-object. 5196a99b1c9SBob Moore * This function attempts to repair this error by wrapping a 5206a99b1c9SBob Moore * Package object around the original object, creating the 5216a99b1c9SBob Moore * correct and expected Package with one sub-object. 522e5f69d6eSBob Moore * 523e5f69d6eSBob Moore * Names that can be repaired in this manner include: 5246a99b1c9SBob Moore * _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS, 5256a99b1c9SBob Moore * _BCL, _DOD, _FIX, _Sx 526e5f69d6eSBob Moore * 527e5f69d6eSBob Moore ******************************************************************************/ 528e5f69d6eSBob Moore 529e5f69d6eSBob Moore acpi_status 5306a99b1c9SBob Moore acpi_ns_wrap_with_package(struct acpi_predefined_data *data, 5316a99b1c9SBob Moore union acpi_operand_object *original_object, 532e5f69d6eSBob Moore union acpi_operand_object **obj_desc_ptr) 533e5f69d6eSBob Moore { 534e5f69d6eSBob Moore union acpi_operand_object *pkg_obj_desc; 535e5f69d6eSBob Moore 5366a99b1c9SBob Moore ACPI_FUNCTION_NAME(ns_wrap_with_package); 5373a58176eSBob Moore 538e5f69d6eSBob Moore /* 539e5f69d6eSBob Moore * Create the new outer package and populate it. The new package will 5406a99b1c9SBob Moore * have a single element, the lone sub-object. 541e5f69d6eSBob Moore */ 542e5f69d6eSBob Moore pkg_obj_desc = acpi_ut_create_package_object(1); 543e5f69d6eSBob Moore if (!pkg_obj_desc) { 544e5f69d6eSBob Moore return (AE_NO_MEMORY); 545e5f69d6eSBob Moore } 546e5f69d6eSBob Moore 5476a99b1c9SBob Moore pkg_obj_desc->package.elements[0] = original_object; 5486a99b1c9SBob Moore 5496a99b1c9SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 5506a99b1c9SBob Moore "%s: Wrapped %s with expected Package object\n", 5516a99b1c9SBob Moore data->pathname, 5526a99b1c9SBob Moore acpi_ut_get_object_type_name(original_object))); 553e5f69d6eSBob Moore 554e5f69d6eSBob Moore /* Return the new object in the object pointer */ 555e5f69d6eSBob Moore 556e5f69d6eSBob Moore *obj_desc_ptr = pkg_obj_desc; 5576a99b1c9SBob Moore data->flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; 558e5f69d6eSBob Moore return (AE_OK); 559e5f69d6eSBob Moore } 560