1b2deadd5SBob Moore /****************************************************************************** 2b2deadd5SBob Moore * 3b2deadd5SBob Moore * Module Name: nsrepair - Repair for objects returned by predefined methods 4b2deadd5SBob Moore * 5b2deadd5SBob Moore *****************************************************************************/ 6b2deadd5SBob Moore 7b2deadd5SBob Moore /* 8a8357b0cSBob Moore * Copyright (C) 2000 - 2010, 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" 49b2deadd5SBob Moore 50b2deadd5SBob Moore #define _COMPONENT ACPI_NAMESPACE 51b2deadd5SBob Moore ACPI_MODULE_NAME("nsrepair") 52b2deadd5SBob Moore 53b2deadd5SBob Moore /******************************************************************************* 54b2deadd5SBob Moore * 5547e11d54SBob Moore * This module attempts to repair or convert objects returned by the 5647e11d54SBob Moore * predefined methods to an object type that is expected, as per the ACPI 5747e11d54SBob Moore * specification. The need for this code is dictated by the many machines that 5847e11d54SBob Moore * return incorrect types for the standard predefined methods. Performing these 5947e11d54SBob Moore * conversions here, in one place, eliminates the need for individual ACPI 6047e11d54SBob Moore * device drivers to do the same. Note: Most of these conversions are different 6147e11d54SBob Moore * than the internal object conversion routines used for implicit object 6247e11d54SBob Moore * conversion. 6347e11d54SBob Moore * 6447e11d54SBob Moore * The following conversions can be performed as necessary: 6547e11d54SBob Moore * 6647e11d54SBob Moore * Integer -> String 6747e11d54SBob Moore * Integer -> Buffer 6847e11d54SBob Moore * String -> Integer 6947e11d54SBob Moore * String -> Buffer 7047e11d54SBob Moore * Buffer -> Integer 7147e11d54SBob Moore * Buffer -> String 7247e11d54SBob Moore * Buffer -> Package of Integers 7347e11d54SBob Moore * Package -> Package of one Package 7447e11d54SBob Moore * 75091f4d71SBob Moore * Additional possible repairs: 76091f4d71SBob Moore * 77091f4d71SBob Moore * Optional/unnecessary NULL package elements removed 78091f4d71SBob Moore * Required package elements that are NULL replaced by Integer/String/Buffer 79091f4d71SBob Moore * Incorrect standalone package wrapped with required outer package 80091f4d71SBob Moore * 8147e11d54SBob Moore ******************************************************************************/ 8247e11d54SBob Moore /* Local prototypes */ 8347e11d54SBob Moore static acpi_status 8447e11d54SBob Moore acpi_ns_convert_to_integer(union acpi_operand_object *original_object, 8547e11d54SBob Moore union acpi_operand_object **return_object); 8647e11d54SBob Moore 8747e11d54SBob Moore static acpi_status 8847e11d54SBob Moore acpi_ns_convert_to_string(union acpi_operand_object *original_object, 8947e11d54SBob Moore union acpi_operand_object **return_object); 9047e11d54SBob Moore 9147e11d54SBob Moore static acpi_status 9247e11d54SBob Moore acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, 9347e11d54SBob Moore union acpi_operand_object **return_object); 9447e11d54SBob Moore 9547e11d54SBob Moore static acpi_status 9647e11d54SBob Moore acpi_ns_convert_to_package(union acpi_operand_object *original_object, 9747e11d54SBob Moore union acpi_operand_object **return_object); 9847e11d54SBob Moore 9947e11d54SBob Moore /******************************************************************************* 10047e11d54SBob Moore * 101b2deadd5SBob Moore * FUNCTION: acpi_ns_repair_object 102b2deadd5SBob Moore * 103b2deadd5SBob Moore * PARAMETERS: Data - Pointer to validation data structure 104b2deadd5SBob Moore * expected_btypes - Object types expected 105b2deadd5SBob Moore * package_index - Index of object within parent package (if 106b2deadd5SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 107b2deadd5SBob Moore * otherwise) 108b2deadd5SBob Moore * return_object_ptr - Pointer to the object returned from the 109b2deadd5SBob Moore * evaluation of a method or object 110b2deadd5SBob Moore * 111b2deadd5SBob Moore * RETURN: Status. AE_OK if repair was successful. 112b2deadd5SBob Moore * 113b2deadd5SBob Moore * DESCRIPTION: Attempt to repair/convert a return object of a type that was 114b2deadd5SBob Moore * not expected. 115b2deadd5SBob Moore * 116b2deadd5SBob Moore ******************************************************************************/ 11747e11d54SBob Moore 118b2deadd5SBob Moore acpi_status 119b2deadd5SBob Moore acpi_ns_repair_object(struct acpi_predefined_data *data, 120b2deadd5SBob Moore u32 expected_btypes, 121b2deadd5SBob Moore u32 package_index, 122b2deadd5SBob Moore union acpi_operand_object **return_object_ptr) 123b2deadd5SBob Moore { 124b2deadd5SBob Moore union acpi_operand_object *return_object = *return_object_ptr; 125b2deadd5SBob Moore union acpi_operand_object *new_object; 1260240d7b4SLin Ming acpi_status status; 127b2deadd5SBob Moore 1283a58176eSBob Moore ACPI_FUNCTION_NAME(ns_repair_object); 1293a58176eSBob Moore 13027526993SBob Moore /* 13127526993SBob Moore * At this point, we know that the type of the returned object was not 13227526993SBob Moore * one of the expected types for this predefined name. Attempt to 13347e11d54SBob Moore * repair the object by converting it to one of the expected object 13447e11d54SBob Moore * types for this predefined name. 13527526993SBob Moore */ 13647e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_INTEGER) { 13747e11d54SBob Moore status = acpi_ns_convert_to_integer(return_object, &new_object); 13847e11d54SBob Moore if (ACPI_SUCCESS(status)) { 13947e11d54SBob Moore goto object_repaired; 140b2deadd5SBob Moore } 141b2deadd5SBob Moore } 14247e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_STRING) { 14347e11d54SBob Moore status = acpi_ns_convert_to_string(return_object, &new_object); 14447e11d54SBob Moore if (ACPI_SUCCESS(status)) { 14547e11d54SBob Moore goto object_repaired; 146b2deadd5SBob Moore } 14747e11d54SBob Moore } 1480240d7b4SLin Ming if (expected_btypes & ACPI_RTYPE_BUFFER) { 14947e11d54SBob Moore status = acpi_ns_convert_to_buffer(return_object, &new_object); 15047e11d54SBob Moore if (ACPI_SUCCESS(status)) { 15147e11d54SBob Moore goto object_repaired; 1520240d7b4SLin Ming } 1530240d7b4SLin Ming } 15447e11d54SBob Moore if (expected_btypes & ACPI_RTYPE_PACKAGE) { 15547e11d54SBob Moore status = acpi_ns_convert_to_package(return_object, &new_object); 15647e11d54SBob Moore if (ACPI_SUCCESS(status)) { 15747e11d54SBob Moore goto object_repaired; 15827526993SBob Moore } 15927526993SBob Moore } 16027526993SBob Moore 16127526993SBob Moore /* We cannot repair this object */ 16227526993SBob Moore 16327526993SBob Moore return (AE_AML_OPERAND_TYPE); 16447e11d54SBob Moore 16547e11d54SBob Moore object_repaired: 16627526993SBob Moore 16727526993SBob Moore /* Object was successfully repaired */ 168b2deadd5SBob Moore 169b2deadd5SBob Moore /* 170b2deadd5SBob Moore * If the original object is a package element, we need to: 171b2deadd5SBob Moore * 1. Set the reference count of the new object to match the 172b2deadd5SBob Moore * reference count of the old object. 173b2deadd5SBob Moore * 2. Decrement the reference count of the original object. 174b2deadd5SBob Moore */ 175b2deadd5SBob Moore if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 176b2deadd5SBob Moore new_object->common.reference_count = 177b2deadd5SBob Moore return_object->common.reference_count; 178b2deadd5SBob Moore 179b2deadd5SBob Moore if (return_object->common.reference_count > 1) { 180b2deadd5SBob Moore return_object->common.reference_count--; 181b2deadd5SBob Moore } 182b2deadd5SBob Moore 1833a58176eSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 1843a58176eSBob Moore "%s: Converted %s to expected %s at index %u\n", 1853a58176eSBob Moore data->pathname, 1863a58176eSBob Moore acpi_ut_get_object_type_name(return_object), 18727526993SBob Moore acpi_ut_get_object_type_name(new_object), 188b2deadd5SBob Moore package_index)); 189b2deadd5SBob Moore } else { 1903a58176eSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 1913a58176eSBob Moore "%s: Converted %s to expected %s\n", 1923a58176eSBob Moore data->pathname, 1933a58176eSBob Moore acpi_ut_get_object_type_name(return_object), 1943a58176eSBob Moore acpi_ut_get_object_type_name(new_object))); 195b2deadd5SBob Moore } 196b2deadd5SBob Moore 197b2deadd5SBob Moore /* Delete old object, install the new return object */ 198b2deadd5SBob Moore 199b2deadd5SBob Moore acpi_ut_remove_reference(return_object); 200b2deadd5SBob Moore *return_object_ptr = new_object; 201b2deadd5SBob Moore data->flags |= ACPI_OBJECT_REPAIRED; 202b2deadd5SBob Moore return (AE_OK); 203b2deadd5SBob Moore } 204e5f69d6eSBob Moore 205e5f69d6eSBob Moore /******************************************************************************* 206e5f69d6eSBob Moore * 20747e11d54SBob Moore * FUNCTION: acpi_ns_convert_to_integer 20847e11d54SBob Moore * 20947e11d54SBob Moore * PARAMETERS: original_object - Object to be converted 21047e11d54SBob Moore * return_object - Where the new converted object is returned 21147e11d54SBob Moore * 21247e11d54SBob Moore * RETURN: Status. AE_OK if conversion was successful. 21347e11d54SBob Moore * 21447e11d54SBob Moore * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. 21547e11d54SBob Moore * 21647e11d54SBob Moore ******************************************************************************/ 21747e11d54SBob Moore 21847e11d54SBob Moore static acpi_status 21947e11d54SBob Moore acpi_ns_convert_to_integer(union acpi_operand_object *original_object, 22047e11d54SBob Moore union acpi_operand_object **return_object) 22147e11d54SBob Moore { 22247e11d54SBob Moore union acpi_operand_object *new_object; 22347e11d54SBob Moore acpi_status status; 22447e11d54SBob Moore u64 value = 0; 22547e11d54SBob Moore u32 i; 22647e11d54SBob Moore 22747e11d54SBob Moore switch (original_object->common.type) { 22847e11d54SBob Moore case ACPI_TYPE_STRING: 22947e11d54SBob Moore 23047e11d54SBob Moore /* String-to-Integer conversion */ 23147e11d54SBob Moore 23247e11d54SBob Moore status = acpi_ut_strtoul64(original_object->string.pointer, 23347e11d54SBob Moore ACPI_ANY_BASE, &value); 23447e11d54SBob Moore if (ACPI_FAILURE(status)) { 23547e11d54SBob Moore return (status); 23647e11d54SBob Moore } 23747e11d54SBob Moore break; 23847e11d54SBob Moore 23947e11d54SBob Moore case ACPI_TYPE_BUFFER: 24047e11d54SBob Moore 24147e11d54SBob Moore /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ 24247e11d54SBob Moore 24347e11d54SBob Moore if (original_object->buffer.length > 8) { 24447e11d54SBob Moore return (AE_AML_OPERAND_TYPE); 24547e11d54SBob Moore } 24647e11d54SBob Moore 24747e11d54SBob Moore /* Extract each buffer byte to create the integer */ 24847e11d54SBob Moore 24947e11d54SBob Moore for (i = 0; i < original_object->buffer.length; i++) { 25047e11d54SBob Moore value |= 25147e11d54SBob Moore ((u64) original_object->buffer. 25247e11d54SBob Moore pointer[i] << (i * 8)); 25347e11d54SBob Moore } 25447e11d54SBob Moore break; 25547e11d54SBob Moore 25647e11d54SBob Moore default: 25747e11d54SBob Moore return (AE_AML_OPERAND_TYPE); 25847e11d54SBob Moore } 25947e11d54SBob Moore 26047e11d54SBob Moore new_object = acpi_ut_create_integer_object(value); 26147e11d54SBob Moore if (!new_object) { 26247e11d54SBob Moore return (AE_NO_MEMORY); 26347e11d54SBob Moore } 26447e11d54SBob Moore 26547e11d54SBob Moore *return_object = new_object; 26647e11d54SBob Moore return (AE_OK); 26747e11d54SBob Moore } 26847e11d54SBob Moore 26947e11d54SBob Moore /******************************************************************************* 27047e11d54SBob Moore * 27147e11d54SBob Moore * FUNCTION: acpi_ns_convert_to_string 27247e11d54SBob Moore * 27347e11d54SBob Moore * PARAMETERS: original_object - Object to be converted 27447e11d54SBob Moore * return_object - Where the new converted object is returned 27547e11d54SBob Moore * 27647e11d54SBob Moore * RETURN: Status. AE_OK if conversion was successful. 27747e11d54SBob Moore * 27847e11d54SBob Moore * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. 27947e11d54SBob Moore * 28047e11d54SBob Moore ******************************************************************************/ 28147e11d54SBob Moore 28247e11d54SBob Moore static acpi_status 28347e11d54SBob Moore acpi_ns_convert_to_string(union acpi_operand_object *original_object, 28447e11d54SBob Moore union acpi_operand_object **return_object) 28547e11d54SBob Moore { 28647e11d54SBob Moore union acpi_operand_object *new_object; 28747e11d54SBob Moore acpi_size length; 28847e11d54SBob Moore acpi_status status; 28947e11d54SBob Moore 29047e11d54SBob Moore switch (original_object->common.type) { 29147e11d54SBob Moore case ACPI_TYPE_INTEGER: 29247e11d54SBob Moore /* 29347e11d54SBob Moore * Integer-to-String conversion. Commonly, convert 29447e11d54SBob Moore * an integer of value 0 to a NULL string. The last element of 29547e11d54SBob Moore * _BIF and _BIX packages occasionally need this fix. 29647e11d54SBob Moore */ 29747e11d54SBob Moore if (original_object->integer.value == 0) { 29847e11d54SBob Moore 29947e11d54SBob Moore /* Allocate a new NULL string object */ 30047e11d54SBob Moore 30147e11d54SBob Moore new_object = acpi_ut_create_string_object(0); 30247e11d54SBob Moore if (!new_object) { 30347e11d54SBob Moore return (AE_NO_MEMORY); 30447e11d54SBob Moore } 30547e11d54SBob Moore } else { 30647e11d54SBob Moore status = 30747e11d54SBob Moore acpi_ex_convert_to_string(original_object, 30847e11d54SBob Moore &new_object, 30947e11d54SBob Moore ACPI_IMPLICIT_CONVERT_HEX); 31047e11d54SBob Moore if (ACPI_FAILURE(status)) { 31147e11d54SBob Moore return (status); 31247e11d54SBob Moore } 31347e11d54SBob Moore } 31447e11d54SBob Moore break; 31547e11d54SBob Moore 31647e11d54SBob Moore case ACPI_TYPE_BUFFER: 31747e11d54SBob Moore /* 31847e11d54SBob Moore * Buffer-to-String conversion. Use a to_string 31947e11d54SBob Moore * conversion, no transform performed on the buffer data. The best 32047e11d54SBob Moore * example of this is the _BIF method, where the string data from 32147e11d54SBob Moore * the battery is often (incorrectly) returned as buffer object(s). 32247e11d54SBob Moore */ 32347e11d54SBob Moore length = 0; 32447e11d54SBob Moore while ((length < original_object->buffer.length) && 32547e11d54SBob Moore (original_object->buffer.pointer[length])) { 32647e11d54SBob Moore length++; 32747e11d54SBob Moore } 32847e11d54SBob Moore 32947e11d54SBob Moore /* Allocate a new string object */ 33047e11d54SBob Moore 33147e11d54SBob Moore new_object = acpi_ut_create_string_object(length); 33247e11d54SBob Moore if (!new_object) { 33347e11d54SBob Moore return (AE_NO_MEMORY); 33447e11d54SBob Moore } 33547e11d54SBob Moore 33647e11d54SBob Moore /* 33747e11d54SBob Moore * Copy the raw buffer data with no transform. String is already NULL 33847e11d54SBob Moore * terminated at Length+1. 33947e11d54SBob Moore */ 34047e11d54SBob Moore ACPI_MEMCPY(new_object->string.pointer, 34147e11d54SBob Moore original_object->buffer.pointer, length); 34247e11d54SBob Moore break; 34347e11d54SBob Moore 34447e11d54SBob Moore default: 34547e11d54SBob Moore return (AE_AML_OPERAND_TYPE); 34647e11d54SBob Moore } 34747e11d54SBob Moore 34847e11d54SBob Moore *return_object = new_object; 34947e11d54SBob Moore return (AE_OK); 35047e11d54SBob Moore } 35147e11d54SBob Moore 35247e11d54SBob Moore /******************************************************************************* 35347e11d54SBob Moore * 35447e11d54SBob Moore * FUNCTION: acpi_ns_convert_to_buffer 35547e11d54SBob Moore * 35647e11d54SBob Moore * PARAMETERS: original_object - Object to be converted 35747e11d54SBob Moore * return_object - Where the new converted object is returned 35847e11d54SBob Moore * 35947e11d54SBob Moore * RETURN: Status. AE_OK if conversion was successful. 36047e11d54SBob Moore * 361ea7c5ec1SBob Moore * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. 36247e11d54SBob Moore * 36347e11d54SBob Moore ******************************************************************************/ 36447e11d54SBob Moore 36547e11d54SBob Moore static acpi_status 36647e11d54SBob Moore acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, 36747e11d54SBob Moore union acpi_operand_object **return_object) 36847e11d54SBob Moore { 36947e11d54SBob Moore union acpi_operand_object *new_object; 37047e11d54SBob Moore acpi_status status; 371ea7c5ec1SBob Moore union acpi_operand_object **elements; 372ea7c5ec1SBob Moore u32 *dword_buffer; 373ea7c5ec1SBob Moore u32 count; 374ea7c5ec1SBob Moore u32 i; 37547e11d54SBob Moore 37647e11d54SBob Moore switch (original_object->common.type) { 37747e11d54SBob Moore case ACPI_TYPE_INTEGER: 37847e11d54SBob Moore /* 37947e11d54SBob Moore * Integer-to-Buffer conversion. 38047e11d54SBob Moore * Convert the Integer to a packed-byte buffer. _MAT and other 38147e11d54SBob Moore * objects need this sometimes, if a read has been performed on a 38247e11d54SBob Moore * Field object that is less than or equal to the global integer 38347e11d54SBob Moore * size (32 or 64 bits). 38447e11d54SBob Moore */ 38547e11d54SBob Moore status = 38647e11d54SBob Moore acpi_ex_convert_to_buffer(original_object, &new_object); 38747e11d54SBob Moore if (ACPI_FAILURE(status)) { 38847e11d54SBob Moore return (status); 38947e11d54SBob Moore } 39047e11d54SBob Moore break; 39147e11d54SBob Moore 39247e11d54SBob Moore case ACPI_TYPE_STRING: 39347e11d54SBob Moore 39447e11d54SBob Moore /* String-to-Buffer conversion. Simple data copy */ 39547e11d54SBob Moore 39647e11d54SBob Moore new_object = 39747e11d54SBob Moore acpi_ut_create_buffer_object(original_object->string. 39847e11d54SBob Moore length); 39947e11d54SBob Moore if (!new_object) { 40047e11d54SBob Moore return (AE_NO_MEMORY); 40147e11d54SBob Moore } 40247e11d54SBob Moore 40347e11d54SBob Moore ACPI_MEMCPY(new_object->buffer.pointer, 40447e11d54SBob Moore original_object->string.pointer, 40547e11d54SBob Moore original_object->string.length); 40647e11d54SBob Moore break; 40747e11d54SBob Moore 408ea7c5ec1SBob Moore case ACPI_TYPE_PACKAGE: 40943420bbbSBob Moore /* 41043420bbbSBob Moore * This case is often seen for predefined names that must return a 41143420bbbSBob Moore * Buffer object with multiple DWORD integers within. For example, 41243420bbbSBob Moore * _FDE and _GTM. The Package can be converted to a Buffer. 41343420bbbSBob Moore */ 414ea7c5ec1SBob Moore 415ea7c5ec1SBob Moore /* All elements of the Package must be integers */ 416ea7c5ec1SBob Moore 417ea7c5ec1SBob Moore elements = original_object->package.elements; 418ea7c5ec1SBob Moore count = original_object->package.count; 419ea7c5ec1SBob Moore 420ea7c5ec1SBob Moore for (i = 0; i < count; i++) { 421ea7c5ec1SBob Moore if ((!*elements) || 422ea7c5ec1SBob Moore ((*elements)->common.type != ACPI_TYPE_INTEGER)) { 423ea7c5ec1SBob Moore return (AE_AML_OPERAND_TYPE); 424ea7c5ec1SBob Moore } 425ea7c5ec1SBob Moore elements++; 426ea7c5ec1SBob Moore } 427ea7c5ec1SBob Moore 428ea7c5ec1SBob Moore /* Create the new buffer object to replace the Package */ 429ea7c5ec1SBob Moore 430ea7c5ec1SBob Moore new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count)); 431ea7c5ec1SBob Moore if (!new_object) { 432ea7c5ec1SBob Moore return (AE_NO_MEMORY); 433ea7c5ec1SBob Moore } 434ea7c5ec1SBob Moore 435ea7c5ec1SBob Moore /* Copy the package elements (integers) to the buffer as DWORDs */ 436ea7c5ec1SBob Moore 437ea7c5ec1SBob Moore elements = original_object->package.elements; 438ea7c5ec1SBob Moore dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer); 439ea7c5ec1SBob Moore 440ea7c5ec1SBob Moore for (i = 0; i < count; i++) { 441ea7c5ec1SBob Moore *dword_buffer = (u32) (*elements)->integer.value; 442ea7c5ec1SBob Moore dword_buffer++; 443ea7c5ec1SBob Moore elements++; 444ea7c5ec1SBob Moore } 445ea7c5ec1SBob Moore break; 446ea7c5ec1SBob Moore 44747e11d54SBob Moore default: 44847e11d54SBob Moore return (AE_AML_OPERAND_TYPE); 44947e11d54SBob Moore } 45047e11d54SBob Moore 45147e11d54SBob Moore *return_object = new_object; 45247e11d54SBob Moore return (AE_OK); 45347e11d54SBob Moore } 45447e11d54SBob Moore 45547e11d54SBob Moore /******************************************************************************* 45647e11d54SBob Moore * 45747e11d54SBob Moore * FUNCTION: acpi_ns_convert_to_package 45847e11d54SBob Moore * 45947e11d54SBob Moore * PARAMETERS: original_object - Object to be converted 46047e11d54SBob Moore * return_object - Where the new converted object is returned 46147e11d54SBob Moore * 46247e11d54SBob Moore * RETURN: Status. AE_OK if conversion was successful. 46347e11d54SBob Moore * 46447e11d54SBob Moore * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of 46547e11d54SBob Moore * the buffer is converted to a single integer package element. 46647e11d54SBob Moore * 46747e11d54SBob Moore ******************************************************************************/ 46847e11d54SBob Moore 46947e11d54SBob Moore static acpi_status 47047e11d54SBob Moore acpi_ns_convert_to_package(union acpi_operand_object *original_object, 47147e11d54SBob Moore union acpi_operand_object **return_object) 47247e11d54SBob Moore { 47347e11d54SBob Moore union acpi_operand_object *new_object; 47447e11d54SBob Moore union acpi_operand_object **elements; 47547e11d54SBob Moore u32 length; 47647e11d54SBob Moore u8 *buffer; 47747e11d54SBob Moore 47847e11d54SBob Moore switch (original_object->common.type) { 47947e11d54SBob Moore case ACPI_TYPE_BUFFER: 48047e11d54SBob Moore 48147e11d54SBob Moore /* Buffer-to-Package conversion */ 48247e11d54SBob Moore 48347e11d54SBob Moore length = original_object->buffer.length; 48447e11d54SBob Moore new_object = acpi_ut_create_package_object(length); 48547e11d54SBob Moore if (!new_object) { 48647e11d54SBob Moore return (AE_NO_MEMORY); 48747e11d54SBob Moore } 48847e11d54SBob Moore 48947e11d54SBob Moore /* Convert each buffer byte to an integer package element */ 49047e11d54SBob Moore 49147e11d54SBob Moore elements = new_object->package.elements; 49247e11d54SBob Moore buffer = original_object->buffer.pointer; 49347e11d54SBob Moore 49447e11d54SBob Moore while (length--) { 495ea7c5ec1SBob Moore *elements = 496ea7c5ec1SBob Moore acpi_ut_create_integer_object((u64) *buffer); 49747e11d54SBob Moore if (!*elements) { 49847e11d54SBob Moore acpi_ut_remove_reference(new_object); 49947e11d54SBob Moore return (AE_NO_MEMORY); 50047e11d54SBob Moore } 50147e11d54SBob Moore elements++; 50247e11d54SBob Moore buffer++; 50347e11d54SBob Moore } 50447e11d54SBob Moore break; 50547e11d54SBob Moore 50647e11d54SBob Moore default: 50747e11d54SBob Moore return (AE_AML_OPERAND_TYPE); 50847e11d54SBob Moore } 50947e11d54SBob Moore 51047e11d54SBob Moore *return_object = new_object; 51147e11d54SBob Moore return (AE_OK); 51247e11d54SBob Moore } 51347e11d54SBob Moore 51447e11d54SBob Moore /******************************************************************************* 51547e11d54SBob Moore * 516091f4d71SBob Moore * FUNCTION: acpi_ns_repair_null_element 517091f4d71SBob Moore * 518091f4d71SBob Moore * PARAMETERS: Data - Pointer to validation data structure 519091f4d71SBob Moore * expected_btypes - Object types expected 520091f4d71SBob Moore * package_index - Index of object within parent package (if 521091f4d71SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 522091f4d71SBob Moore * otherwise) 523091f4d71SBob Moore * return_object_ptr - Pointer to the object returned from the 524091f4d71SBob Moore * evaluation of a method or object 525091f4d71SBob Moore * 526091f4d71SBob Moore * RETURN: Status. AE_OK if repair was successful. 527091f4d71SBob Moore * 528091f4d71SBob Moore * DESCRIPTION: Attempt to repair a NULL element of a returned Package object. 529091f4d71SBob Moore * 530091f4d71SBob Moore ******************************************************************************/ 531091f4d71SBob Moore 532091f4d71SBob Moore acpi_status 533091f4d71SBob Moore acpi_ns_repair_null_element(struct acpi_predefined_data *data, 534091f4d71SBob Moore u32 expected_btypes, 535091f4d71SBob Moore u32 package_index, 536091f4d71SBob Moore union acpi_operand_object **return_object_ptr) 537091f4d71SBob Moore { 538091f4d71SBob Moore union acpi_operand_object *return_object = *return_object_ptr; 539091f4d71SBob Moore union acpi_operand_object *new_object; 540091f4d71SBob Moore 541091f4d71SBob Moore ACPI_FUNCTION_NAME(ns_repair_null_element); 542091f4d71SBob Moore 543091f4d71SBob Moore /* No repair needed if return object is non-NULL */ 544091f4d71SBob Moore 545091f4d71SBob Moore if (return_object) { 546091f4d71SBob Moore return (AE_OK); 547091f4d71SBob Moore } 548091f4d71SBob Moore 549091f4d71SBob Moore /* 550091f4d71SBob Moore * Attempt to repair a NULL element of a Package object. This applies to 551091f4d71SBob Moore * predefined names that return a fixed-length package and each element 552091f4d71SBob Moore * is required. It does not apply to variable-length packages where NULL 553091f4d71SBob Moore * elements are allowed, especially at the end of the package. 554091f4d71SBob Moore */ 555091f4d71SBob Moore if (expected_btypes & ACPI_RTYPE_INTEGER) { 556091f4d71SBob Moore 557091f4d71SBob Moore /* Need an Integer - create a zero-value integer */ 558091f4d71SBob Moore 559091f4d71SBob Moore new_object = acpi_ut_create_integer_object(0); 560091f4d71SBob Moore } else if (expected_btypes & ACPI_RTYPE_STRING) { 561091f4d71SBob Moore 562091f4d71SBob Moore /* Need a String - create a NULL string */ 563091f4d71SBob Moore 564091f4d71SBob Moore new_object = acpi_ut_create_string_object(0); 565091f4d71SBob Moore } else if (expected_btypes & ACPI_RTYPE_BUFFER) { 566091f4d71SBob Moore 567091f4d71SBob Moore /* Need a Buffer - create a zero-length buffer */ 568091f4d71SBob Moore 569091f4d71SBob Moore new_object = acpi_ut_create_buffer_object(0); 570091f4d71SBob Moore } else { 571091f4d71SBob Moore /* Error for all other expected types */ 572091f4d71SBob Moore 573091f4d71SBob Moore return (AE_AML_OPERAND_TYPE); 574091f4d71SBob Moore } 575091f4d71SBob Moore 576091f4d71SBob Moore if (!new_object) { 577091f4d71SBob Moore return (AE_NO_MEMORY); 578091f4d71SBob Moore } 579091f4d71SBob Moore 580091f4d71SBob Moore /* Set the reference count according to the parent Package object */ 581091f4d71SBob Moore 582091f4d71SBob Moore new_object->common.reference_count = 583091f4d71SBob Moore data->parent_package->common.reference_count; 584091f4d71SBob Moore 585091f4d71SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 586091f4d71SBob Moore "%s: Converted NULL package element to expected %s at index %u\n", 587091f4d71SBob Moore data->pathname, 588091f4d71SBob Moore acpi_ut_get_object_type_name(new_object), 589091f4d71SBob Moore package_index)); 590091f4d71SBob Moore 591091f4d71SBob Moore *return_object_ptr = new_object; 592091f4d71SBob Moore data->flags |= ACPI_OBJECT_REPAIRED; 593091f4d71SBob Moore return (AE_OK); 594091f4d71SBob Moore } 595091f4d71SBob Moore 596091f4d71SBob Moore /****************************************************************************** 597091f4d71SBob Moore * 598091f4d71SBob Moore * FUNCTION: acpi_ns_remove_null_elements 599091f4d71SBob Moore * 600091f4d71SBob Moore * PARAMETERS: Data - Pointer to validation data structure 601091f4d71SBob Moore * package_type - An acpi_return_package_types value 602091f4d71SBob Moore * obj_desc - A Package object 603091f4d71SBob Moore * 604091f4d71SBob Moore * RETURN: None. 605091f4d71SBob Moore * 606091f4d71SBob Moore * DESCRIPTION: Remove all NULL package elements from packages that contain 607091f4d71SBob Moore * a variable number of sub-packages. For these types of 608091f4d71SBob Moore * packages, NULL elements can be safely removed. 609091f4d71SBob Moore * 610091f4d71SBob Moore *****************************************************************************/ 611091f4d71SBob Moore 612091f4d71SBob Moore void 613091f4d71SBob Moore acpi_ns_remove_null_elements(struct acpi_predefined_data *data, 614091f4d71SBob Moore u8 package_type, 615091f4d71SBob Moore union acpi_operand_object *obj_desc) 616091f4d71SBob Moore { 617091f4d71SBob Moore union acpi_operand_object **source; 618091f4d71SBob Moore union acpi_operand_object **dest; 619091f4d71SBob Moore u32 count; 620091f4d71SBob Moore u32 new_count; 621091f4d71SBob Moore u32 i; 622091f4d71SBob Moore 623091f4d71SBob Moore ACPI_FUNCTION_NAME(ns_remove_null_elements); 624091f4d71SBob Moore 625091f4d71SBob Moore /* 626091f4d71SBob Moore * PTYPE1 packages contain no subpackages. 627091f4d71SBob Moore * PTYPE2 packages contain a variable number of sub-packages. We can 628091f4d71SBob Moore * safely remove all NULL elements from the PTYPE2 packages. 629091f4d71SBob Moore */ 630091f4d71SBob Moore switch (package_type) { 631091f4d71SBob Moore case ACPI_PTYPE1_FIXED: 632091f4d71SBob Moore case ACPI_PTYPE1_VAR: 633091f4d71SBob Moore case ACPI_PTYPE1_OPTION: 634091f4d71SBob Moore return; 635091f4d71SBob Moore 636091f4d71SBob Moore case ACPI_PTYPE2: 637091f4d71SBob Moore case ACPI_PTYPE2_COUNT: 638091f4d71SBob Moore case ACPI_PTYPE2_PKG_COUNT: 639091f4d71SBob Moore case ACPI_PTYPE2_FIXED: 640091f4d71SBob Moore case ACPI_PTYPE2_MIN: 641091f4d71SBob Moore case ACPI_PTYPE2_REV_FIXED: 642091f4d71SBob Moore break; 643091f4d71SBob Moore 644091f4d71SBob Moore default: 645091f4d71SBob Moore return; 646091f4d71SBob Moore } 647091f4d71SBob Moore 648091f4d71SBob Moore count = obj_desc->package.count; 649091f4d71SBob Moore new_count = count; 650091f4d71SBob Moore 651091f4d71SBob Moore source = obj_desc->package.elements; 652091f4d71SBob Moore dest = source; 653091f4d71SBob Moore 654091f4d71SBob Moore /* Examine all elements of the package object, remove nulls */ 655091f4d71SBob Moore 656091f4d71SBob Moore for (i = 0; i < count; i++) { 657091f4d71SBob Moore if (!*source) { 658091f4d71SBob Moore new_count--; 659091f4d71SBob Moore } else { 660091f4d71SBob Moore *dest = *source; 661091f4d71SBob Moore dest++; 662091f4d71SBob Moore } 663091f4d71SBob Moore source++; 664091f4d71SBob Moore } 665091f4d71SBob Moore 666091f4d71SBob Moore /* Update parent package if any null elements were removed */ 667091f4d71SBob Moore 668091f4d71SBob Moore if (new_count < count) { 669091f4d71SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 670091f4d71SBob Moore "%s: Found and removed %u NULL elements\n", 671091f4d71SBob Moore data->pathname, (count - new_count))); 672091f4d71SBob Moore 673091f4d71SBob Moore /* NULL terminate list and update the package count */ 674091f4d71SBob Moore 675091f4d71SBob Moore *dest = NULL; 676091f4d71SBob Moore obj_desc->package.count = new_count; 677091f4d71SBob Moore } 678091f4d71SBob Moore } 679091f4d71SBob Moore 680091f4d71SBob Moore /******************************************************************************* 681091f4d71SBob Moore * 682e5f69d6eSBob Moore * FUNCTION: acpi_ns_repair_package_list 683e5f69d6eSBob Moore * 684e5f69d6eSBob Moore * PARAMETERS: Data - Pointer to validation data structure 685e5f69d6eSBob Moore * obj_desc_ptr - Pointer to the object to repair. The new 686e5f69d6eSBob Moore * package object is returned here, 687e5f69d6eSBob Moore * overwriting the old object. 688e5f69d6eSBob Moore * 689e5f69d6eSBob Moore * RETURN: Status, new object in *obj_desc_ptr 690e5f69d6eSBob Moore * 691e5f69d6eSBob Moore * DESCRIPTION: Repair a common problem with objects that are defined to return 692e5f69d6eSBob Moore * a variable-length Package of Packages. If the variable-length 693e5f69d6eSBob Moore * is one, some BIOS code mistakenly simply declares a single 694e5f69d6eSBob Moore * Package instead of a Package with one sub-Package. This 695e5f69d6eSBob Moore * function attempts to repair this error by wrapping a Package 696e5f69d6eSBob Moore * object around the original Package, creating the correct 697e5f69d6eSBob Moore * Package with one sub-Package. 698e5f69d6eSBob Moore * 699e5f69d6eSBob Moore * Names that can be repaired in this manner include: 700e5f69d6eSBob Moore * _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS 701e5f69d6eSBob Moore * 702e5f69d6eSBob Moore ******************************************************************************/ 703e5f69d6eSBob Moore 704e5f69d6eSBob Moore acpi_status 705e5f69d6eSBob Moore acpi_ns_repair_package_list(struct acpi_predefined_data *data, 706e5f69d6eSBob Moore union acpi_operand_object **obj_desc_ptr) 707e5f69d6eSBob Moore { 708e5f69d6eSBob Moore union acpi_operand_object *pkg_obj_desc; 709e5f69d6eSBob Moore 7103a58176eSBob Moore ACPI_FUNCTION_NAME(ns_repair_package_list); 7113a58176eSBob Moore 712e5f69d6eSBob Moore /* 713e5f69d6eSBob Moore * Create the new outer package and populate it. The new package will 714e5f69d6eSBob Moore * have a single element, the lone subpackage. 715e5f69d6eSBob Moore */ 716e5f69d6eSBob Moore pkg_obj_desc = acpi_ut_create_package_object(1); 717e5f69d6eSBob Moore if (!pkg_obj_desc) { 718e5f69d6eSBob Moore return (AE_NO_MEMORY); 719e5f69d6eSBob Moore } 720e5f69d6eSBob Moore 721e5f69d6eSBob Moore pkg_obj_desc->package.elements[0] = *obj_desc_ptr; 722e5f69d6eSBob Moore 723e5f69d6eSBob Moore /* Return the new object in the object pointer */ 724e5f69d6eSBob Moore 725e5f69d6eSBob Moore *obj_desc_ptr = pkg_obj_desc; 726e5f69d6eSBob Moore data->flags |= ACPI_OBJECT_REPAIRED; 727e5f69d6eSBob Moore 7283a58176eSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 7293a58176eSBob Moore "%s: Repaired incorrectly formed Package\n", 7303a58176eSBob Moore data->pathname)); 731e5f69d6eSBob Moore 732e5f69d6eSBob Moore return (AE_OK); 733e5f69d6eSBob Moore } 734