1b2deadd5SBob Moore /****************************************************************************** 2b2deadd5SBob Moore * 3b2deadd5SBob Moore * Module Name: nsrepair - Repair for objects returned by predefined methods 4b2deadd5SBob Moore * 5b2deadd5SBob Moore *****************************************************************************/ 6b2deadd5SBob Moore 7b2deadd5SBob Moore /* 8b2deadd5SBob Moore * Copyright (C) 2000 - 2009, 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" 48b2deadd5SBob Moore #include "acpredef.h" 49b2deadd5SBob Moore 50b2deadd5SBob Moore #define _COMPONENT ACPI_NAMESPACE 51b2deadd5SBob Moore ACPI_MODULE_NAME("nsrepair") 52b2deadd5SBob Moore 53b2deadd5SBob Moore /******************************************************************************* 54b2deadd5SBob Moore * 55b2deadd5SBob Moore * FUNCTION: acpi_ns_repair_object 56b2deadd5SBob Moore * 57b2deadd5SBob Moore * PARAMETERS: Data - Pointer to validation data structure 58b2deadd5SBob Moore * expected_btypes - Object types expected 59b2deadd5SBob Moore * package_index - Index of object within parent package (if 60b2deadd5SBob Moore * applicable - ACPI_NOT_PACKAGE_ELEMENT 61b2deadd5SBob Moore * otherwise) 62b2deadd5SBob Moore * return_object_ptr - Pointer to the object returned from the 63b2deadd5SBob Moore * evaluation of a method or object 64b2deadd5SBob Moore * 65b2deadd5SBob Moore * RETURN: Status. AE_OK if repair was successful. 66b2deadd5SBob Moore * 67b2deadd5SBob Moore * DESCRIPTION: Attempt to repair/convert a return object of a type that was 68b2deadd5SBob Moore * not expected. 69b2deadd5SBob Moore * 70b2deadd5SBob Moore ******************************************************************************/ 71b2deadd5SBob Moore acpi_status 72b2deadd5SBob Moore acpi_ns_repair_object(struct acpi_predefined_data *data, 73b2deadd5SBob Moore u32 expected_btypes, 74b2deadd5SBob Moore u32 package_index, 75b2deadd5SBob Moore union acpi_operand_object **return_object_ptr) 76b2deadd5SBob Moore { 77b2deadd5SBob Moore union acpi_operand_object *return_object = *return_object_ptr; 78b2deadd5SBob Moore union acpi_operand_object *new_object; 79b2deadd5SBob Moore acpi_size length; 800240d7b4SLin Ming acpi_status status; 81b2deadd5SBob Moore 8227526993SBob Moore /* 8327526993SBob Moore * At this point, we know that the type of the returned object was not 8427526993SBob Moore * one of the expected types for this predefined name. Attempt to 8527526993SBob Moore * repair the object. Only a limited number of repairs are possible. 8627526993SBob Moore */ 87b2deadd5SBob Moore switch (return_object->common.type) { 88b2deadd5SBob Moore case ACPI_TYPE_BUFFER: 89b2deadd5SBob Moore 90b2deadd5SBob Moore /* Does the method/object legally return a string? */ 91b2deadd5SBob Moore 92b2deadd5SBob Moore if (!(expected_btypes & ACPI_RTYPE_STRING)) { 93b2deadd5SBob Moore return (AE_AML_OPERAND_TYPE); 94b2deadd5SBob Moore } 95b2deadd5SBob Moore 96b2deadd5SBob Moore /* 97b2deadd5SBob Moore * Have a Buffer, expected a String, convert. Use a to_string 98b2deadd5SBob Moore * conversion, no transform performed on the buffer data. The best 99b2deadd5SBob Moore * example of this is the _BIF method, where the string data from 100b2deadd5SBob Moore * the battery is often (incorrectly) returned as buffer object(s). 101b2deadd5SBob Moore */ 102b2deadd5SBob Moore length = 0; 103b2deadd5SBob Moore while ((length < return_object->buffer.length) && 104b2deadd5SBob Moore (return_object->buffer.pointer[length])) { 105b2deadd5SBob Moore length++; 106b2deadd5SBob Moore } 107b2deadd5SBob Moore 108b2deadd5SBob Moore /* Allocate a new string object */ 109b2deadd5SBob Moore 110b2deadd5SBob Moore new_object = acpi_ut_create_string_object(length); 111b2deadd5SBob Moore if (!new_object) { 112b2deadd5SBob Moore return (AE_NO_MEMORY); 113b2deadd5SBob Moore } 114b2deadd5SBob Moore 115b2deadd5SBob Moore /* 116b2deadd5SBob Moore * Copy the raw buffer data with no transform. String is already NULL 117b2deadd5SBob Moore * terminated at Length+1. 118b2deadd5SBob Moore */ 119b2deadd5SBob Moore ACPI_MEMCPY(new_object->string.pointer, 120b2deadd5SBob Moore return_object->buffer.pointer, length); 12127526993SBob Moore break; 12227526993SBob Moore 12327526993SBob Moore case ACPI_TYPE_INTEGER: 12427526993SBob Moore 1250240d7b4SLin Ming /* 1) Does the method/object legally return a buffer? */ 12627526993SBob Moore 1270240d7b4SLin Ming if (expected_btypes & ACPI_RTYPE_BUFFER) { 1280240d7b4SLin Ming /* 1290240d7b4SLin Ming * Convert the Integer to a packed-byte buffer. _MAT needs 1300240d7b4SLin Ming * this sometimes, if a read has been performed on a Field 1310240d7b4SLin Ming * object that is less than or equal to the global integer 1320240d7b4SLin Ming * size (32 or 64 bits). 1330240d7b4SLin Ming */ 1340240d7b4SLin Ming status = 1350240d7b4SLin Ming acpi_ex_convert_to_buffer(return_object, 1360240d7b4SLin Ming &new_object); 1370240d7b4SLin Ming if (ACPI_FAILURE(status)) { 1380240d7b4SLin Ming return (status); 1390240d7b4SLin Ming } 1400240d7b4SLin Ming } 1410240d7b4SLin Ming 1420240d7b4SLin Ming /* 2) Does the method/object legally return a string? */ 1430240d7b4SLin Ming 1440240d7b4SLin Ming else if (expected_btypes & ACPI_RTYPE_STRING) { 14527526993SBob Moore /* 14627526993SBob Moore * The only supported Integer-to-String conversion is to convert 14727526993SBob Moore * an integer of value 0 to a NULL string. The last element of 14827526993SBob Moore * _BIF and _BIX packages occasionally need this fix. 14927526993SBob Moore */ 15027526993SBob Moore if (return_object->integer.value != 0) { 15127526993SBob Moore return (AE_AML_OPERAND_TYPE); 15227526993SBob Moore } 15327526993SBob Moore 15427526993SBob Moore /* Allocate a new NULL string object */ 15527526993SBob Moore 15627526993SBob Moore new_object = acpi_ut_create_string_object(0); 15727526993SBob Moore if (!new_object) { 15827526993SBob Moore return (AE_NO_MEMORY); 15927526993SBob Moore } 16027526993SBob Moore } else { 16127526993SBob Moore return (AE_AML_OPERAND_TYPE); 16227526993SBob Moore } 16327526993SBob Moore break; 16427526993SBob Moore 16527526993SBob Moore default: 16627526993SBob Moore 16727526993SBob Moore /* We cannot repair this object */ 16827526993SBob Moore 16927526993SBob Moore return (AE_AML_OPERAND_TYPE); 17027526993SBob Moore } 17127526993SBob Moore 17227526993SBob Moore /* Object was successfully repaired */ 173b2deadd5SBob Moore 174b2deadd5SBob Moore /* 175b2deadd5SBob Moore * If the original object is a package element, we need to: 176b2deadd5SBob Moore * 1. Set the reference count of the new object to match the 177b2deadd5SBob Moore * reference count of the old object. 178b2deadd5SBob Moore * 2. Decrement the reference count of the original object. 179b2deadd5SBob Moore */ 180b2deadd5SBob Moore if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 181b2deadd5SBob Moore new_object->common.reference_count = 182b2deadd5SBob Moore return_object->common.reference_count; 183b2deadd5SBob Moore 184b2deadd5SBob Moore if (return_object->common.reference_count > 1) { 185b2deadd5SBob Moore return_object->common.reference_count--; 186b2deadd5SBob Moore } 187b2deadd5SBob Moore 1887df200cdSBob Moore ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, 18927526993SBob Moore "Converted %s to expected %s at index %u", 19027526993SBob Moore acpi_ut_get_object_type_name 19127526993SBob Moore (return_object), 19227526993SBob Moore acpi_ut_get_object_type_name(new_object), 193b2deadd5SBob Moore package_index)); 194b2deadd5SBob Moore } else { 1957df200cdSBob Moore ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, 19627526993SBob Moore "Converted %s to expected %s", 19727526993SBob Moore acpi_ut_get_object_type_name 19827526993SBob Moore (return_object), 19927526993SBob Moore acpi_ut_get_object_type_name 20027526993SBob Moore (new_object))); 201b2deadd5SBob Moore } 202b2deadd5SBob Moore 203b2deadd5SBob Moore /* Delete old object, install the new return object */ 204b2deadd5SBob Moore 205b2deadd5SBob Moore acpi_ut_remove_reference(return_object); 206b2deadd5SBob Moore *return_object_ptr = new_object; 207b2deadd5SBob Moore data->flags |= ACPI_OBJECT_REPAIRED; 208b2deadd5SBob Moore return (AE_OK); 209b2deadd5SBob Moore } 210e5f69d6eSBob Moore 211e5f69d6eSBob Moore /******************************************************************************* 212e5f69d6eSBob Moore * 213e5f69d6eSBob Moore * FUNCTION: acpi_ns_repair_package_list 214e5f69d6eSBob Moore * 215e5f69d6eSBob Moore * PARAMETERS: Data - Pointer to validation data structure 216e5f69d6eSBob Moore * obj_desc_ptr - Pointer to the object to repair. The new 217e5f69d6eSBob Moore * package object is returned here, 218e5f69d6eSBob Moore * overwriting the old object. 219e5f69d6eSBob Moore * 220e5f69d6eSBob Moore * RETURN: Status, new object in *obj_desc_ptr 221e5f69d6eSBob Moore * 222e5f69d6eSBob Moore * DESCRIPTION: Repair a common problem with objects that are defined to return 223e5f69d6eSBob Moore * a variable-length Package of Packages. If the variable-length 224e5f69d6eSBob Moore * is one, some BIOS code mistakenly simply declares a single 225e5f69d6eSBob Moore * Package instead of a Package with one sub-Package. This 226e5f69d6eSBob Moore * function attempts to repair this error by wrapping a Package 227e5f69d6eSBob Moore * object around the original Package, creating the correct 228e5f69d6eSBob Moore * Package with one sub-Package. 229e5f69d6eSBob Moore * 230e5f69d6eSBob Moore * Names that can be repaired in this manner include: 231e5f69d6eSBob Moore * _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS 232e5f69d6eSBob Moore * 233e5f69d6eSBob Moore ******************************************************************************/ 234e5f69d6eSBob Moore 235e5f69d6eSBob Moore acpi_status 236e5f69d6eSBob Moore acpi_ns_repair_package_list(struct acpi_predefined_data *data, 237e5f69d6eSBob Moore union acpi_operand_object **obj_desc_ptr) 238e5f69d6eSBob Moore { 239e5f69d6eSBob Moore union acpi_operand_object *pkg_obj_desc; 240e5f69d6eSBob Moore 241e5f69d6eSBob Moore /* 242e5f69d6eSBob Moore * Create the new outer package and populate it. The new package will 243e5f69d6eSBob Moore * have a single element, the lone subpackage. 244e5f69d6eSBob Moore */ 245e5f69d6eSBob Moore pkg_obj_desc = acpi_ut_create_package_object(1); 246e5f69d6eSBob Moore if (!pkg_obj_desc) { 247e5f69d6eSBob Moore return (AE_NO_MEMORY); 248e5f69d6eSBob Moore } 249e5f69d6eSBob Moore 250e5f69d6eSBob Moore pkg_obj_desc->package.elements[0] = *obj_desc_ptr; 251e5f69d6eSBob Moore 252e5f69d6eSBob Moore /* Return the new object in the object pointer */ 253e5f69d6eSBob Moore 254e5f69d6eSBob Moore *obj_desc_ptr = pkg_obj_desc; 255e5f69d6eSBob Moore data->flags |= ACPI_OBJECT_REPAIRED; 256e5f69d6eSBob Moore 2577df200cdSBob Moore ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, 2587df200cdSBob Moore "Repaired Incorrectly formed Package")); 259e5f69d6eSBob Moore 260e5f69d6eSBob Moore return (AE_OK); 261e5f69d6eSBob Moore } 262