195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2b2deadd5SBob Moore /****************************************************************************** 3b2deadd5SBob Moore * 4b2deadd5SBob Moore * Module Name: nsrepair - Repair for objects returned by predefined methods 5b2deadd5SBob Moore * 6840c02caSBob Moore * Copyright (C) 2000 - 2019, Intel Corp. 7b2deadd5SBob Moore * 895857638SErik Schmauss *****************************************************************************/ 9b2deadd5SBob Moore 10b2deadd5SBob Moore #include <acpi/acpi.h> 11b2deadd5SBob Moore #include "accommon.h" 12b2deadd5SBob Moore #include "acnamesp.h" 130240d7b4SLin Ming #include "acinterp.h" 14091f4d71SBob Moore #include "acpredef.h" 15d5a36100SBob Moore #include "amlresrc.h" 16b2deadd5SBob Moore 17b2deadd5SBob Moore #define _COMPONENT ACPI_NAMESPACE 18b2deadd5SBob Moore ACPI_MODULE_NAME("nsrepair") 19b2deadd5SBob Moore 20b2deadd5SBob Moore /******************************************************************************* 21b2deadd5SBob Moore * 2247e11d54SBob Moore * This module attempts to repair or convert objects returned by the 2347e11d54SBob Moore * predefined methods to an object type that is expected, as per the ACPI 2447e11d54SBob Moore * specification. The need for this code is dictated by the many machines that 2547e11d54SBob Moore * return incorrect types for the standard predefined methods. Performing these 2647e11d54SBob Moore * conversions here, in one place, eliminates the need for individual ACPI 2747e11d54SBob Moore * device drivers to do the same. Note: Most of these conversions are different 2847e11d54SBob Moore * than the internal object conversion routines used for implicit object 2947e11d54SBob Moore * conversion. 3047e11d54SBob Moore * 3147e11d54SBob Moore * The following conversions can be performed as necessary: 3247e11d54SBob Moore * 3347e11d54SBob Moore * Integer -> String 3447e11d54SBob Moore * Integer -> Buffer 3547e11d54SBob Moore * String -> Integer 3647e11d54SBob Moore * String -> Buffer 3747e11d54SBob Moore * Buffer -> Integer 3847e11d54SBob Moore * Buffer -> String 3947e11d54SBob Moore * Buffer -> Package of Integers 4047e11d54SBob Moore * Package -> Package of one Package 41d5a36100SBob Moore * 42d5a36100SBob Moore * Additional conversions that are available: 43d5a36100SBob Moore * Convert a null return or zero return value to an end_tag descriptor 44d5a36100SBob Moore * Convert an ASCII string to a Unicode buffer 45d5a36100SBob Moore * 466a99b1c9SBob Moore * An incorrect standalone object is wrapped with required outer package 4747e11d54SBob Moore * 48091f4d71SBob Moore * Additional possible repairs: 49091f4d71SBob Moore * Required package elements that are NULL replaced by Integer/String/Buffer 50091f4d71SBob Moore * 5147e11d54SBob Moore ******************************************************************************/ 5247e11d54SBob Moore /* Local prototypes */ 53d5a36100SBob Moore static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct 54d5a36100SBob Moore acpi_namespace_node 55d5a36100SBob Moore *node, 56d5a36100SBob Moore u32 57d5a36100SBob Moore return_btype, 58d5a36100SBob Moore u32 59d5a36100SBob Moore package_index); 60d5a36100SBob Moore 61d5a36100SBob Moore /* 62d5a36100SBob Moore * Special but simple repairs for some names. 63d5a36100SBob Moore * 64d5a36100SBob Moore * 2nd argument: Unexpected types that can be repaired 65d5a36100SBob Moore */ 66d5a36100SBob Moore static const struct acpi_simple_repair_info acpi_object_repair_info[] = { 6788fd0ac8SLv Zheng /* Resource descriptor conversions */ 6888fd0ac8SLv Zheng 6988fd0ac8SLv Zheng {"_CRS", 7088fd0ac8SLv Zheng ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | 7188fd0ac8SLv Zheng ACPI_RTYPE_NONE, 7288fd0ac8SLv Zheng ACPI_NOT_PACKAGE_ELEMENT, 7388fd0ac8SLv Zheng acpi_ns_convert_to_resource}, 7488fd0ac8SLv Zheng {"_DMA", 7588fd0ac8SLv Zheng ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | 7688fd0ac8SLv Zheng ACPI_RTYPE_NONE, 7788fd0ac8SLv Zheng ACPI_NOT_PACKAGE_ELEMENT, 7888fd0ac8SLv Zheng acpi_ns_convert_to_resource}, 7988fd0ac8SLv Zheng {"_PRS", 8088fd0ac8SLv Zheng ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | 8188fd0ac8SLv Zheng ACPI_RTYPE_NONE, 8288fd0ac8SLv Zheng ACPI_NOT_PACKAGE_ELEMENT, 8388fd0ac8SLv Zheng acpi_ns_convert_to_resource}, 8488fd0ac8SLv Zheng 85ee387409SLv Zheng /* Object reference conversions */ 86ee387409SLv Zheng 87ee387409SLv Zheng {"_DEP", ACPI_RTYPE_STRING, ACPI_ALL_PACKAGE_ELEMENTS, 88ee387409SLv Zheng acpi_ns_convert_to_reference}, 89ee387409SLv Zheng 9096b44cc6SLv Zheng /* Unicode conversions */ 9196b44cc6SLv Zheng 9296b44cc6SLv Zheng {"_MLS", ACPI_RTYPE_STRING, 1, 9396b44cc6SLv Zheng acpi_ns_convert_to_unicode}, 9496b44cc6SLv Zheng {"_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, 9596b44cc6SLv Zheng ACPI_NOT_PACKAGE_ELEMENT, 9696b44cc6SLv Zheng acpi_ns_convert_to_unicode}, 97d5a36100SBob Moore {{0, 0, 0, 0}, 0, 0, NULL} /* Table terminator */ 98d5a36100SBob Moore }; 99d5a36100SBob Moore 10047e11d54SBob Moore /******************************************************************************* 10147e11d54SBob Moore * 102d5a36100SBob Moore * FUNCTION: acpi_ns_simple_repair 103b2deadd5SBob Moore * 10429a241ccSBob Moore * PARAMETERS: info - Method execution information block 105b2deadd5SBob Moore * expected_btypes - Object types expected 106b2deadd5SBob Moore * package_index - Index of object within parent package (if 107b2deadd5SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 108b2deadd5SBob Moore * otherwise) 109b2deadd5SBob Moore * return_object_ptr - Pointer to the object returned from the 110b2deadd5SBob Moore * evaluation of a method or object 111b2deadd5SBob Moore * 112b2deadd5SBob Moore * RETURN: Status. AE_OK if repair was successful. 113b2deadd5SBob Moore * 114b2deadd5SBob Moore * DESCRIPTION: Attempt to repair/convert a return object of a type that was 115b2deadd5SBob Moore * not expected. 116b2deadd5SBob Moore * 117b2deadd5SBob Moore ******************************************************************************/ 11847e11d54SBob Moore 119b2deadd5SBob Moore acpi_status 12029a241ccSBob Moore acpi_ns_simple_repair(struct acpi_evaluate_info *info, 121b2deadd5SBob Moore u32 expected_btypes, 122b2deadd5SBob Moore u32 package_index, 123b2deadd5SBob Moore union acpi_operand_object **return_object_ptr) 124b2deadd5SBob Moore { 125b2deadd5SBob Moore union acpi_operand_object *return_object = *return_object_ptr; 126d5a36100SBob Moore union acpi_operand_object *new_object = NULL; 1270240d7b4SLin Ming acpi_status status; 128d5a36100SBob Moore const struct acpi_simple_repair_info *predefined; 129b2deadd5SBob Moore 130d5a36100SBob Moore ACPI_FUNCTION_NAME(ns_simple_repair); 131d5a36100SBob Moore 132d5a36100SBob Moore /* 133d5a36100SBob Moore * Special repairs for certain names that are in the repair table. 134d5a36100SBob Moore * Check if this name is in the list of repairable names. 135d5a36100SBob Moore */ 13629a241ccSBob Moore predefined = acpi_ns_match_simple_repair(info->node, 13729a241ccSBob Moore info->return_btype, 138d5a36100SBob Moore package_index); 139d5a36100SBob Moore if (predefined) { 140d5a36100SBob Moore if (!return_object) { 14129a241ccSBob Moore ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 142d5a36100SBob Moore ACPI_WARN_ALWAYS, 143d5a36100SBob Moore "Missing expected return value")); 144d5a36100SBob Moore } 145d5a36100SBob Moore 1464debda53SLv Zheng status = predefined->object_converter(info->node, return_object, 1474debda53SLv Zheng &new_object); 148d5a36100SBob Moore if (ACPI_FAILURE(status)) { 149d5a36100SBob Moore 150d5a36100SBob Moore /* A fatal error occurred during a conversion */ 151d5a36100SBob Moore 152d5a36100SBob Moore ACPI_EXCEPTION((AE_INFO, status, 153d5a36100SBob Moore "During return object analysis")); 154d5a36100SBob Moore return (status); 155d5a36100SBob Moore } 156d5a36100SBob Moore if (new_object) { 157d5a36100SBob Moore goto object_repaired; 158d5a36100SBob Moore } 159d5a36100SBob Moore } 160d5a36100SBob Moore 161d5a36100SBob Moore /* 162d5a36100SBob Moore * Do not perform simple object repair unless the return type is not 163d5a36100SBob Moore * expected. 164d5a36100SBob Moore */ 16529a241ccSBob Moore if (info->return_btype & expected_btypes) { 166d5a36100SBob Moore return (AE_OK); 167d5a36100SBob Moore } 1683a58176eSBob Moore 16927526993SBob Moore /* 17027526993SBob Moore * At this point, we know that the type of the returned object was not 17127526993SBob Moore * one of the expected types for this predefined name. Attempt to 17247e11d54SBob Moore * repair the object by converting it to one of the expected object 17347e11d54SBob Moore * types for this predefined name. 17427526993SBob Moore */ 175d5a36100SBob Moore 176d5a36100SBob Moore /* 177d5a36100SBob Moore * If there is no return value, check if we require a return value for 178d5a36100SBob Moore * this predefined name. Either one return value is expected, or none, 179d5a36100SBob Moore * for both methods and other objects. 180d5a36100SBob Moore * 18161db45caSLv Zheng * Try to fix if there was no return object. Warning if failed to fix. 182d5a36100SBob Moore */ 183d5a36100SBob Moore if (!return_object) { 184d5a36100SBob Moore if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) { 18561db45caSLv Zheng if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 18661db45caSLv Zheng ACPI_WARN_PREDEFINED((AE_INFO, 18761db45caSLv Zheng info->full_pathname, 18861db45caSLv Zheng ACPI_WARN_ALWAYS, 18961db45caSLv Zheng "Found unexpected NULL package element")); 19061db45caSLv Zheng 19161db45caSLv Zheng status = 19261db45caSLv Zheng acpi_ns_repair_null_element(info, 19361db45caSLv Zheng expected_btypes, 19461db45caSLv Zheng package_index, 19561db45caSLv Zheng return_object_ptr); 19661db45caSLv Zheng if (ACPI_SUCCESS(status)) { 19761db45caSLv Zheng return (AE_OK); /* Repair was successful */ 19861db45caSLv Zheng } 19961db45caSLv Zheng } else { 20061db45caSLv Zheng ACPI_WARN_PREDEFINED((AE_INFO, 20161db45caSLv Zheng info->full_pathname, 202d5a36100SBob Moore ACPI_WARN_ALWAYS, 203d5a36100SBob Moore "Missing expected return value")); 20461db45caSLv Zheng } 205d5a36100SBob Moore 206d5a36100SBob Moore return (AE_AML_NO_RETURN_VALUE); 207d5a36100SBob Moore } 208d5a36100SBob Moore } 209d5a36100SBob Moore 21047e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_INTEGER) { 21147e11d54SBob Moore status = acpi_ns_convert_to_integer(return_object, &new_object); 21247e11d54SBob Moore if (ACPI_SUCCESS(status)) { 21347e11d54SBob Moore goto object_repaired; 214b2deadd5SBob Moore } 215b2deadd5SBob Moore } 21647e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_STRING) { 21747e11d54SBob Moore status = acpi_ns_convert_to_string(return_object, &new_object); 21847e11d54SBob Moore if (ACPI_SUCCESS(status)) { 21947e11d54SBob Moore goto object_repaired; 220b2deadd5SBob Moore } 22147e11d54SBob Moore } 2220240d7b4SLin Ming if (expected_btypes & ACPI_RTYPE_BUFFER) { 22347e11d54SBob Moore status = acpi_ns_convert_to_buffer(return_object, &new_object); 22447e11d54SBob Moore if (ACPI_SUCCESS(status)) { 22547e11d54SBob Moore goto object_repaired; 2260240d7b4SLin Ming } 2270240d7b4SLin Ming } 22847e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_PACKAGE) { 2296a99b1c9SBob Moore /* 2306a99b1c9SBob Moore * A package is expected. We will wrap the existing object with a 2316a99b1c9SBob Moore * new package object. It is often the case that if a variable-length 2326a99b1c9SBob Moore * package is required, but there is only a single object needed, the 2336a99b1c9SBob Moore * BIOS will return that object instead of wrapping it with a Package 2346a99b1c9SBob Moore * object. Note: after the wrapping, the package will be validated 2356a99b1c9SBob Moore * for correct contents (expected object type or types). 2366a99b1c9SBob Moore */ 2376a99b1c9SBob Moore status = 23829a241ccSBob Moore acpi_ns_wrap_with_package(info, return_object, &new_object); 23947e11d54SBob Moore if (ACPI_SUCCESS(status)) { 2406a99b1c9SBob Moore /* 2416a99b1c9SBob Moore * The original object just had its reference count 2426a99b1c9SBob Moore * incremented for being inserted into the new package. 2436a99b1c9SBob Moore */ 2446a99b1c9SBob Moore *return_object_ptr = new_object; /* New Package object */ 24529a241ccSBob Moore info->return_flags |= ACPI_OBJECT_REPAIRED; 2466a99b1c9SBob Moore return (AE_OK); 24727526993SBob Moore } 24827526993SBob Moore } 24927526993SBob Moore 25027526993SBob Moore /* We cannot repair this object */ 25127526993SBob Moore 25227526993SBob Moore return (AE_AML_OPERAND_TYPE); 25347e11d54SBob Moore 25447e11d54SBob Moore object_repaired: 25527526993SBob Moore 25627526993SBob Moore /* Object was successfully repaired */ 257b2deadd5SBob Moore 258b2deadd5SBob Moore if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 259ed7f8bc9SBob Moore 260ed7f8bc9SBob Moore /* Update reference count of new object */ 261ed7f8bc9SBob Moore 26229a241ccSBob Moore if (!(info->return_flags & ACPI_OBJECT_WRAPPED)) { 263b2deadd5SBob Moore new_object->common.reference_count = 264b2deadd5SBob Moore return_object->common.reference_count; 2656a99b1c9SBob Moore } 266b2deadd5SBob Moore 2673a58176eSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 2686a99b1c9SBob Moore "%s: Converted %s to expected %s at Package index %u\n", 26929a241ccSBob Moore info->full_pathname, 2703a58176eSBob Moore acpi_ut_get_object_type_name(return_object), 27127526993SBob Moore acpi_ut_get_object_type_name(new_object), 272b2deadd5SBob Moore package_index)); 273b2deadd5SBob Moore } else { 2743a58176eSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 2753a58176eSBob Moore "%s: Converted %s to expected %s\n", 27629a241ccSBob Moore info->full_pathname, 2773a58176eSBob Moore acpi_ut_get_object_type_name(return_object), 2783a58176eSBob Moore acpi_ut_get_object_type_name(new_object))); 279b2deadd5SBob Moore } 280b2deadd5SBob Moore 281b2deadd5SBob Moore /* Delete old object, install the new return object */ 282b2deadd5SBob Moore 283b2deadd5SBob Moore acpi_ut_remove_reference(return_object); 284b2deadd5SBob Moore *return_object_ptr = new_object; 28529a241ccSBob Moore info->return_flags |= ACPI_OBJECT_REPAIRED; 286b2deadd5SBob Moore return (AE_OK); 287b2deadd5SBob Moore } 288e5f69d6eSBob Moore 289d5a36100SBob Moore /****************************************************************************** 290d5a36100SBob Moore * 291d5a36100SBob Moore * FUNCTION: acpi_ns_match_simple_repair 292d5a36100SBob Moore * 293d5a36100SBob Moore * PARAMETERS: node - Namespace node for the method/object 294d5a36100SBob Moore * return_btype - Object type that was returned 295d5a36100SBob Moore * package_index - Index of object within parent package (if 296d5a36100SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 297d5a36100SBob Moore * otherwise) 298d5a36100SBob Moore * 299d5a36100SBob Moore * RETURN: Pointer to entry in repair table. NULL indicates not found. 300d5a36100SBob Moore * 301d5a36100SBob Moore * DESCRIPTION: Check an object name against the repairable object list. 302d5a36100SBob Moore * 303d5a36100SBob Moore *****************************************************************************/ 304d5a36100SBob Moore 305d5a36100SBob Moore static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct 306d5a36100SBob Moore acpi_namespace_node 307d5a36100SBob Moore *node, 308d5a36100SBob Moore u32 309d5a36100SBob Moore return_btype, 310d5a36100SBob Moore u32 311d5a36100SBob Moore package_index) 312d5a36100SBob Moore { 313d5a36100SBob Moore const struct acpi_simple_repair_info *this_name; 314d5a36100SBob Moore 315d5a36100SBob Moore /* Search info table for a repairable predefined method/object name */ 316d5a36100SBob Moore 317d5a36100SBob Moore this_name = acpi_object_repair_info; 318d5a36100SBob Moore while (this_name->object_converter) { 3195599fb69SBob Moore if (ACPI_COMPARE_NAMESEG(node->name.ascii, this_name->name)) { 320d5a36100SBob Moore 321d5a36100SBob Moore /* Check if we can actually repair this name/type combination */ 322d5a36100SBob Moore 323d5a36100SBob Moore if ((return_btype & this_name->unexpected_btypes) && 324ee387409SLv Zheng (this_name->package_index == 325ee387409SLv Zheng ACPI_ALL_PACKAGE_ELEMENTS 326ee387409SLv Zheng || package_index == this_name->package_index)) { 327d5a36100SBob Moore return (this_name); 328d5a36100SBob Moore } 329d5a36100SBob Moore 330d5a36100SBob Moore return (NULL); 331d5a36100SBob Moore } 3321fad8738SBob Moore 333d5a36100SBob Moore this_name++; 334d5a36100SBob Moore } 335d5a36100SBob Moore 336d5a36100SBob Moore return (NULL); /* Name was not found in the repair table */ 337d5a36100SBob Moore } 338d5a36100SBob Moore 339e5f69d6eSBob Moore /******************************************************************************* 340e5f69d6eSBob Moore * 341091f4d71SBob Moore * FUNCTION: acpi_ns_repair_null_element 342091f4d71SBob Moore * 34329a241ccSBob Moore * PARAMETERS: info - Method execution information block 344091f4d71SBob Moore * expected_btypes - Object types expected 345091f4d71SBob Moore * package_index - Index of object within parent package (if 346091f4d71SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 347091f4d71SBob Moore * otherwise) 348091f4d71SBob Moore * return_object_ptr - Pointer to the object returned from the 349091f4d71SBob Moore * evaluation of a method or object 350091f4d71SBob Moore * 351091f4d71SBob Moore * RETURN: Status. AE_OK if repair was successful. 352091f4d71SBob Moore * 353091f4d71SBob Moore * DESCRIPTION: Attempt to repair a NULL element of a returned Package object. 354091f4d71SBob Moore * 355091f4d71SBob Moore ******************************************************************************/ 356091f4d71SBob Moore 357091f4d71SBob Moore acpi_status 35829a241ccSBob Moore acpi_ns_repair_null_element(struct acpi_evaluate_info *info, 359091f4d71SBob Moore u32 expected_btypes, 360091f4d71SBob Moore u32 package_index, 361091f4d71SBob Moore union acpi_operand_object **return_object_ptr) 362091f4d71SBob Moore { 363091f4d71SBob Moore union acpi_operand_object *return_object = *return_object_ptr; 364091f4d71SBob Moore union acpi_operand_object *new_object; 365091f4d71SBob Moore 366091f4d71SBob Moore ACPI_FUNCTION_NAME(ns_repair_null_element); 367091f4d71SBob Moore 368091f4d71SBob Moore /* No repair needed if return object is non-NULL */ 369091f4d71SBob Moore 370091f4d71SBob Moore if (return_object) { 371091f4d71SBob Moore return (AE_OK); 372091f4d71SBob Moore } 373091f4d71SBob Moore 374091f4d71SBob Moore /* 375091f4d71SBob Moore * Attempt to repair a NULL element of a Package object. This applies to 376091f4d71SBob Moore * predefined names that return a fixed-length package and each element 377091f4d71SBob Moore * is required. It does not apply to variable-length packages where NULL 378091f4d71SBob Moore * elements are allowed, especially at the end of the package. 379091f4d71SBob Moore */ 380091f4d71SBob Moore if (expected_btypes & ACPI_RTYPE_INTEGER) { 381091f4d71SBob Moore 382ba494beeSBob Moore /* Need an integer - create a zero-value integer */ 383091f4d71SBob Moore 384150dba38SBob Moore new_object = acpi_ut_create_integer_object((u64)0); 385091f4d71SBob Moore } else if (expected_btypes & ACPI_RTYPE_STRING) { 386091f4d71SBob Moore 387ba494beeSBob Moore /* Need a string - create a NULL string */ 388091f4d71SBob Moore 389091f4d71SBob Moore new_object = acpi_ut_create_string_object(0); 390091f4d71SBob Moore } else if (expected_btypes & ACPI_RTYPE_BUFFER) { 391091f4d71SBob Moore 392ba494beeSBob Moore /* Need a buffer - create a zero-length buffer */ 393091f4d71SBob Moore 394091f4d71SBob Moore new_object = acpi_ut_create_buffer_object(0); 395091f4d71SBob Moore } else { 396091f4d71SBob Moore /* Error for all other expected types */ 397091f4d71SBob Moore 398091f4d71SBob Moore return (AE_AML_OPERAND_TYPE); 399091f4d71SBob Moore } 400091f4d71SBob Moore 401091f4d71SBob Moore if (!new_object) { 402091f4d71SBob Moore return (AE_NO_MEMORY); 403091f4d71SBob Moore } 404091f4d71SBob Moore 405091f4d71SBob Moore /* Set the reference count according to the parent Package object */ 406091f4d71SBob Moore 407091f4d71SBob Moore new_object->common.reference_count = 40829a241ccSBob Moore info->parent_package->common.reference_count; 409091f4d71SBob Moore 410091f4d71SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 411091f4d71SBob Moore "%s: Converted NULL package element to expected %s at index %u\n", 41229a241ccSBob Moore info->full_pathname, 413091f4d71SBob Moore acpi_ut_get_object_type_name(new_object), 414091f4d71SBob Moore package_index)); 415091f4d71SBob Moore 416091f4d71SBob Moore *return_object_ptr = new_object; 41729a241ccSBob Moore info->return_flags |= ACPI_OBJECT_REPAIRED; 418091f4d71SBob Moore return (AE_OK); 419091f4d71SBob Moore } 420091f4d71SBob Moore 421091f4d71SBob Moore /****************************************************************************** 422091f4d71SBob Moore * 423091f4d71SBob Moore * FUNCTION: acpi_ns_remove_null_elements 424091f4d71SBob Moore * 42529a241ccSBob Moore * PARAMETERS: info - Method execution information block 426091f4d71SBob Moore * package_type - An acpi_return_package_types value 427091f4d71SBob Moore * obj_desc - A Package object 428091f4d71SBob Moore * 429091f4d71SBob Moore * RETURN: None. 430091f4d71SBob Moore * 431091f4d71SBob Moore * DESCRIPTION: Remove all NULL package elements from packages that contain 4320a16d12aSBob Moore * a variable number of subpackages. For these types of 433091f4d71SBob Moore * packages, NULL elements can be safely removed. 434091f4d71SBob Moore * 435091f4d71SBob Moore *****************************************************************************/ 436091f4d71SBob Moore 437091f4d71SBob Moore void 43829a241ccSBob Moore acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, 439091f4d71SBob Moore u8 package_type, 440091f4d71SBob Moore union acpi_operand_object *obj_desc) 441091f4d71SBob Moore { 442091f4d71SBob Moore union acpi_operand_object **source; 443091f4d71SBob Moore union acpi_operand_object **dest; 444091f4d71SBob Moore u32 count; 445091f4d71SBob Moore u32 new_count; 446091f4d71SBob Moore u32 i; 447091f4d71SBob Moore 448091f4d71SBob Moore ACPI_FUNCTION_NAME(ns_remove_null_elements); 449091f4d71SBob Moore 450091f4d71SBob Moore /* 451945488b9SBob Moore * We can safely remove all NULL elements from these package types: 452945488b9SBob Moore * PTYPE1_VAR packages contain a variable number of simple data types. 4530a16d12aSBob Moore * PTYPE2 packages contain a variable number of subpackages. 454091f4d71SBob Moore */ 455091f4d71SBob Moore switch (package_type) { 456091f4d71SBob Moore case ACPI_PTYPE1_VAR: 457091f4d71SBob Moore case ACPI_PTYPE2: 458091f4d71SBob Moore case ACPI_PTYPE2_COUNT: 459091f4d71SBob Moore case ACPI_PTYPE2_PKG_COUNT: 460091f4d71SBob Moore case ACPI_PTYPE2_FIXED: 461091f4d71SBob Moore case ACPI_PTYPE2_MIN: 462091f4d71SBob Moore case ACPI_PTYPE2_REV_FIXED: 4637fce7a4bSBob Moore case ACPI_PTYPE2_FIX_VAR: 464091f4d71SBob Moore break; 465091f4d71SBob Moore 466091f4d71SBob Moore default: 467e34a7813SBob Moore case ACPI_PTYPE2_VAR_VAR: 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 } 4881fad8738SBob Moore 489091f4d71SBob Moore source++; 490091f4d71SBob Moore } 491091f4d71SBob Moore 492091f4d71SBob Moore /* Update parent package if any null elements were removed */ 493091f4d71SBob Moore 494091f4d71SBob Moore if (new_count < count) { 495091f4d71SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 496091f4d71SBob Moore "%s: Found and removed %u NULL elements\n", 49729a241ccSBob Moore info->full_pathname, (count - new_count))); 498091f4d71SBob Moore 499091f4d71SBob Moore /* NULL terminate list and update the package count */ 500091f4d71SBob Moore 501091f4d71SBob Moore *dest = NULL; 502091f4d71SBob Moore obj_desc->package.count = new_count; 503091f4d71SBob Moore } 504091f4d71SBob Moore } 505091f4d71SBob Moore 506091f4d71SBob Moore /******************************************************************************* 507091f4d71SBob Moore * 5086a99b1c9SBob Moore * FUNCTION: acpi_ns_wrap_with_package 509e5f69d6eSBob Moore * 51029a241ccSBob Moore * PARAMETERS: info - Method execution information block 5116a99b1c9SBob Moore * original_object - Pointer to the object to repair. 5126a99b1c9SBob Moore * obj_desc_ptr - The new package object is returned here 513e5f69d6eSBob Moore * 514e5f69d6eSBob Moore * RETURN: Status, new object in *obj_desc_ptr 515e5f69d6eSBob Moore * 5166a99b1c9SBob Moore * DESCRIPTION: Repair a common problem with objects that are defined to 5176a99b1c9SBob Moore * return a variable-length Package of sub-objects. If there is 5186a99b1c9SBob Moore * only one sub-object, some BIOS code mistakenly simply declares 5196a99b1c9SBob Moore * the single object instead of a Package with one sub-object. 5206a99b1c9SBob Moore * This function attempts to repair this error by wrapping a 5216a99b1c9SBob Moore * Package object around the original object, creating the 5226a99b1c9SBob Moore * correct and expected Package with one sub-object. 523e5f69d6eSBob Moore * 524e5f69d6eSBob Moore * Names that can be repaired in this manner include: 5256a99b1c9SBob Moore * _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS, 5266a99b1c9SBob Moore * _BCL, _DOD, _FIX, _Sx 527e5f69d6eSBob Moore * 528e5f69d6eSBob Moore ******************************************************************************/ 529e5f69d6eSBob Moore 530e5f69d6eSBob Moore acpi_status 53129a241ccSBob Moore acpi_ns_wrap_with_package(struct acpi_evaluate_info *info, 5326a99b1c9SBob Moore union acpi_operand_object *original_object, 533e5f69d6eSBob Moore union acpi_operand_object **obj_desc_ptr) 534e5f69d6eSBob Moore { 535e5f69d6eSBob Moore union acpi_operand_object *pkg_obj_desc; 536e5f69d6eSBob Moore 5376a99b1c9SBob Moore ACPI_FUNCTION_NAME(ns_wrap_with_package); 5383a58176eSBob Moore 539e5f69d6eSBob Moore /* 5401fad8738SBob Moore * Create the new outer package and populate it. The new 5411fad8738SBob Moore * package will have a single element, the lone sub-object. 542e5f69d6eSBob Moore */ 543e5f69d6eSBob Moore pkg_obj_desc = acpi_ut_create_package_object(1); 544e5f69d6eSBob Moore if (!pkg_obj_desc) { 545e5f69d6eSBob Moore return (AE_NO_MEMORY); 546e5f69d6eSBob Moore } 547e5f69d6eSBob Moore 5486a99b1c9SBob Moore pkg_obj_desc->package.elements[0] = original_object; 5496a99b1c9SBob Moore 5506a99b1c9SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 5516a99b1c9SBob Moore "%s: Wrapped %s with expected Package object\n", 55229a241ccSBob Moore info->full_pathname, 5536a99b1c9SBob Moore acpi_ut_get_object_type_name(original_object))); 554e5f69d6eSBob Moore 555e5f69d6eSBob Moore /* Return the new object in the object pointer */ 556e5f69d6eSBob Moore 557e5f69d6eSBob Moore *obj_desc_ptr = pkg_obj_desc; 55829a241ccSBob Moore info->return_flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; 559e5f69d6eSBob Moore return (AE_OK); 560e5f69d6eSBob Moore } 561