1 /****************************************************************************** 2 * 3 * Module Name: nsrepair - Repair for objects returned by predefined methods 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2009, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <acpi/acpi.h> 45 #include "accommon.h" 46 #include "acnamesp.h" 47 #include "acinterp.h" 48 49 #define _COMPONENT ACPI_NAMESPACE 50 ACPI_MODULE_NAME("nsrepair") 51 52 /******************************************************************************* 53 * 54 * This module attempts to repair or convert objects returned by the 55 * predefined methods to an object type that is expected, as per the ACPI 56 * specification. The need for this code is dictated by the many machines that 57 * return incorrect types for the standard predefined methods. Performing these 58 * conversions here, in one place, eliminates the need for individual ACPI 59 * device drivers to do the same. Note: Most of these conversions are different 60 * than the internal object conversion routines used for implicit object 61 * conversion. 62 * 63 * The following conversions can be performed as necessary: 64 * 65 * Integer -> String 66 * Integer -> Buffer 67 * String -> Integer 68 * String -> Buffer 69 * Buffer -> Integer 70 * Buffer -> String 71 * Buffer -> Package of Integers 72 * Package -> Package of one Package 73 * 74 ******************************************************************************/ 75 /* Local prototypes */ 76 static acpi_status 77 acpi_ns_convert_to_integer(union acpi_operand_object *original_object, 78 union acpi_operand_object **return_object); 79 80 static acpi_status 81 acpi_ns_convert_to_string(union acpi_operand_object *original_object, 82 union acpi_operand_object **return_object); 83 84 static acpi_status 85 acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, 86 union acpi_operand_object **return_object); 87 88 static acpi_status 89 acpi_ns_convert_to_package(union acpi_operand_object *original_object, 90 union acpi_operand_object **return_object); 91 92 /******************************************************************************* 93 * 94 * FUNCTION: acpi_ns_repair_object 95 * 96 * PARAMETERS: Data - Pointer to validation data structure 97 * expected_btypes - Object types expected 98 * package_index - Index of object within parent package (if 99 * applicable - ACPI_NOT_PACKAGE_ELEMENT 100 * otherwise) 101 * return_object_ptr - Pointer to the object returned from the 102 * evaluation of a method or object 103 * 104 * RETURN: Status. AE_OK if repair was successful. 105 * 106 * DESCRIPTION: Attempt to repair/convert a return object of a type that was 107 * not expected. 108 * 109 ******************************************************************************/ 110 111 acpi_status 112 acpi_ns_repair_object(struct acpi_predefined_data *data, 113 u32 expected_btypes, 114 u32 package_index, 115 union acpi_operand_object **return_object_ptr) 116 { 117 union acpi_operand_object *return_object = *return_object_ptr; 118 union acpi_operand_object *new_object; 119 acpi_status status; 120 121 ACPI_FUNCTION_NAME(ns_repair_object); 122 123 /* 124 * At this point, we know that the type of the returned object was not 125 * one of the expected types for this predefined name. Attempt to 126 * repair the object by converting it to one of the expected object 127 * types for this predefined name. 128 */ 129 if (expected_btypes & ACPI_RTYPE_INTEGER) { 130 status = acpi_ns_convert_to_integer(return_object, &new_object); 131 if (ACPI_SUCCESS(status)) { 132 goto object_repaired; 133 } 134 } 135 if (expected_btypes & ACPI_RTYPE_STRING) { 136 status = acpi_ns_convert_to_string(return_object, &new_object); 137 if (ACPI_SUCCESS(status)) { 138 goto object_repaired; 139 } 140 } 141 if (expected_btypes & ACPI_RTYPE_BUFFER) { 142 status = acpi_ns_convert_to_buffer(return_object, &new_object); 143 if (ACPI_SUCCESS(status)) { 144 goto object_repaired; 145 } 146 } 147 if (expected_btypes & ACPI_RTYPE_PACKAGE) { 148 status = acpi_ns_convert_to_package(return_object, &new_object); 149 if (ACPI_SUCCESS(status)) { 150 goto object_repaired; 151 } 152 } 153 154 /* We cannot repair this object */ 155 156 return (AE_AML_OPERAND_TYPE); 157 158 object_repaired: 159 160 /* Object was successfully repaired */ 161 162 /* 163 * If the original object is a package element, we need to: 164 * 1. Set the reference count of the new object to match the 165 * reference count of the old object. 166 * 2. Decrement the reference count of the original object. 167 */ 168 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 169 new_object->common.reference_count = 170 return_object->common.reference_count; 171 172 if (return_object->common.reference_count > 1) { 173 return_object->common.reference_count--; 174 } 175 176 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 177 "%s: Converted %s to expected %s at index %u\n", 178 data->pathname, 179 acpi_ut_get_object_type_name(return_object), 180 acpi_ut_get_object_type_name(new_object), 181 package_index)); 182 } else { 183 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 184 "%s: Converted %s to expected %s\n", 185 data->pathname, 186 acpi_ut_get_object_type_name(return_object), 187 acpi_ut_get_object_type_name(new_object))); 188 } 189 190 /* Delete old object, install the new return object */ 191 192 acpi_ut_remove_reference(return_object); 193 *return_object_ptr = new_object; 194 data->flags |= ACPI_OBJECT_REPAIRED; 195 return (AE_OK); 196 } 197 198 /******************************************************************************* 199 * 200 * FUNCTION: acpi_ns_convert_to_integer 201 * 202 * PARAMETERS: original_object - Object to be converted 203 * return_object - Where the new converted object is returned 204 * 205 * RETURN: Status. AE_OK if conversion was successful. 206 * 207 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. 208 * 209 ******************************************************************************/ 210 211 static acpi_status 212 acpi_ns_convert_to_integer(union acpi_operand_object *original_object, 213 union acpi_operand_object **return_object) 214 { 215 union acpi_operand_object *new_object; 216 acpi_status status; 217 u64 value = 0; 218 u32 i; 219 220 switch (original_object->common.type) { 221 case ACPI_TYPE_STRING: 222 223 /* String-to-Integer conversion */ 224 225 status = acpi_ut_strtoul64(original_object->string.pointer, 226 ACPI_ANY_BASE, &value); 227 if (ACPI_FAILURE(status)) { 228 return (status); 229 } 230 break; 231 232 case ACPI_TYPE_BUFFER: 233 234 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ 235 236 if (original_object->buffer.length > 8) { 237 return (AE_AML_OPERAND_TYPE); 238 } 239 240 /* Extract each buffer byte to create the integer */ 241 242 for (i = 0; i < original_object->buffer.length; i++) { 243 value |= 244 ((u64) original_object->buffer. 245 pointer[i] << (i * 8)); 246 } 247 break; 248 249 default: 250 return (AE_AML_OPERAND_TYPE); 251 } 252 253 new_object = acpi_ut_create_integer_object(value); 254 if (!new_object) { 255 return (AE_NO_MEMORY); 256 } 257 258 *return_object = new_object; 259 return (AE_OK); 260 } 261 262 /******************************************************************************* 263 * 264 * FUNCTION: acpi_ns_convert_to_string 265 * 266 * PARAMETERS: original_object - Object to be converted 267 * return_object - Where the new converted object is returned 268 * 269 * RETURN: Status. AE_OK if conversion was successful. 270 * 271 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. 272 * 273 ******************************************************************************/ 274 275 static acpi_status 276 acpi_ns_convert_to_string(union acpi_operand_object *original_object, 277 union acpi_operand_object **return_object) 278 { 279 union acpi_operand_object *new_object; 280 acpi_size length; 281 acpi_status status; 282 283 switch (original_object->common.type) { 284 case ACPI_TYPE_INTEGER: 285 /* 286 * Integer-to-String conversion. Commonly, convert 287 * an integer of value 0 to a NULL string. The last element of 288 * _BIF and _BIX packages occasionally need this fix. 289 */ 290 if (original_object->integer.value == 0) { 291 292 /* Allocate a new NULL string object */ 293 294 new_object = acpi_ut_create_string_object(0); 295 if (!new_object) { 296 return (AE_NO_MEMORY); 297 } 298 } else { 299 status = 300 acpi_ex_convert_to_string(original_object, 301 &new_object, 302 ACPI_IMPLICIT_CONVERT_HEX); 303 if (ACPI_FAILURE(status)) { 304 return (status); 305 } 306 } 307 break; 308 309 case ACPI_TYPE_BUFFER: 310 /* 311 * Buffer-to-String conversion. Use a to_string 312 * conversion, no transform performed on the buffer data. The best 313 * example of this is the _BIF method, where the string data from 314 * the battery is often (incorrectly) returned as buffer object(s). 315 */ 316 length = 0; 317 while ((length < original_object->buffer.length) && 318 (original_object->buffer.pointer[length])) { 319 length++; 320 } 321 322 /* Allocate a new string object */ 323 324 new_object = acpi_ut_create_string_object(length); 325 if (!new_object) { 326 return (AE_NO_MEMORY); 327 } 328 329 /* 330 * Copy the raw buffer data with no transform. String is already NULL 331 * terminated at Length+1. 332 */ 333 ACPI_MEMCPY(new_object->string.pointer, 334 original_object->buffer.pointer, length); 335 break; 336 337 default: 338 return (AE_AML_OPERAND_TYPE); 339 } 340 341 *return_object = new_object; 342 return (AE_OK); 343 } 344 345 /******************************************************************************* 346 * 347 * FUNCTION: acpi_ns_convert_to_buffer 348 * 349 * PARAMETERS: original_object - Object to be converted 350 * return_object - Where the new converted object is returned 351 * 352 * RETURN: Status. AE_OK if conversion was successful. 353 * 354 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. 355 * 356 ******************************************************************************/ 357 358 static acpi_status 359 acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, 360 union acpi_operand_object **return_object) 361 { 362 union acpi_operand_object *new_object; 363 acpi_status status; 364 union acpi_operand_object **elements; 365 u32 *dword_buffer; 366 u32 count; 367 u32 i; 368 369 switch (original_object->common.type) { 370 case ACPI_TYPE_INTEGER: 371 /* 372 * Integer-to-Buffer conversion. 373 * Convert the Integer to a packed-byte buffer. _MAT and other 374 * objects need this sometimes, if a read has been performed on a 375 * Field object that is less than or equal to the global integer 376 * size (32 or 64 bits). 377 */ 378 status = 379 acpi_ex_convert_to_buffer(original_object, &new_object); 380 if (ACPI_FAILURE(status)) { 381 return (status); 382 } 383 break; 384 385 case ACPI_TYPE_STRING: 386 387 /* String-to-Buffer conversion. Simple data copy */ 388 389 new_object = 390 acpi_ut_create_buffer_object(original_object->string. 391 length); 392 if (!new_object) { 393 return (AE_NO_MEMORY); 394 } 395 396 ACPI_MEMCPY(new_object->buffer.pointer, 397 original_object->string.pointer, 398 original_object->string.length); 399 break; 400 401 case ACPI_TYPE_PACKAGE: 402 /* 403 * This case is often seen for predefined names that must return a 404 * Buffer object with multiple DWORD integers within. For example, 405 * _FDE and _GTM. The Package can be converted to a Buffer. 406 */ 407 408 /* All elements of the Package must be integers */ 409 410 elements = original_object->package.elements; 411 count = original_object->package.count; 412 413 for (i = 0; i < count; i++) { 414 if ((!*elements) || 415 ((*elements)->common.type != ACPI_TYPE_INTEGER)) { 416 return (AE_AML_OPERAND_TYPE); 417 } 418 elements++; 419 } 420 421 /* Create the new buffer object to replace the Package */ 422 423 new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count)); 424 if (!new_object) { 425 return (AE_NO_MEMORY); 426 } 427 428 /* Copy the package elements (integers) to the buffer as DWORDs */ 429 430 elements = original_object->package.elements; 431 dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer); 432 433 for (i = 0; i < count; i++) { 434 *dword_buffer = (u32) (*elements)->integer.value; 435 dword_buffer++; 436 elements++; 437 } 438 break; 439 440 default: 441 return (AE_AML_OPERAND_TYPE); 442 } 443 444 *return_object = new_object; 445 return (AE_OK); 446 } 447 448 /******************************************************************************* 449 * 450 * FUNCTION: acpi_ns_convert_to_package 451 * 452 * PARAMETERS: original_object - Object to be converted 453 * return_object - Where the new converted object is returned 454 * 455 * RETURN: Status. AE_OK if conversion was successful. 456 * 457 * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of 458 * the buffer is converted to a single integer package element. 459 * 460 ******************************************************************************/ 461 462 static acpi_status 463 acpi_ns_convert_to_package(union acpi_operand_object *original_object, 464 union acpi_operand_object **return_object) 465 { 466 union acpi_operand_object *new_object; 467 union acpi_operand_object **elements; 468 u32 length; 469 u8 *buffer; 470 471 switch (original_object->common.type) { 472 case ACPI_TYPE_BUFFER: 473 474 /* Buffer-to-Package conversion */ 475 476 length = original_object->buffer.length; 477 new_object = acpi_ut_create_package_object(length); 478 if (!new_object) { 479 return (AE_NO_MEMORY); 480 } 481 482 /* Convert each buffer byte to an integer package element */ 483 484 elements = new_object->package.elements; 485 buffer = original_object->buffer.pointer; 486 487 while (length--) { 488 *elements = 489 acpi_ut_create_integer_object((u64) *buffer); 490 if (!*elements) { 491 acpi_ut_remove_reference(new_object); 492 return (AE_NO_MEMORY); 493 } 494 elements++; 495 buffer++; 496 } 497 break; 498 499 default: 500 return (AE_AML_OPERAND_TYPE); 501 } 502 503 *return_object = new_object; 504 return (AE_OK); 505 } 506 507 /******************************************************************************* 508 * 509 * FUNCTION: acpi_ns_repair_package_list 510 * 511 * PARAMETERS: Data - Pointer to validation data structure 512 * obj_desc_ptr - Pointer to the object to repair. The new 513 * package object is returned here, 514 * overwriting the old object. 515 * 516 * RETURN: Status, new object in *obj_desc_ptr 517 * 518 * DESCRIPTION: Repair a common problem with objects that are defined to return 519 * a variable-length Package of Packages. If the variable-length 520 * is one, some BIOS code mistakenly simply declares a single 521 * Package instead of a Package with one sub-Package. This 522 * function attempts to repair this error by wrapping a Package 523 * object around the original Package, creating the correct 524 * Package with one sub-Package. 525 * 526 * Names that can be repaired in this manner include: 527 * _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS 528 * 529 ******************************************************************************/ 530 531 acpi_status 532 acpi_ns_repair_package_list(struct acpi_predefined_data *data, 533 union acpi_operand_object **obj_desc_ptr) 534 { 535 union acpi_operand_object *pkg_obj_desc; 536 537 ACPI_FUNCTION_NAME(ns_repair_package_list); 538 539 /* 540 * Create the new outer package and populate it. The new package will 541 * have a single element, the lone subpackage. 542 */ 543 pkg_obj_desc = acpi_ut_create_package_object(1); 544 if (!pkg_obj_desc) { 545 return (AE_NO_MEMORY); 546 } 547 548 pkg_obj_desc->package.elements[0] = *obj_desc_ptr; 549 550 /* Return the new object in the object pointer */ 551 552 *obj_desc_ptr = pkg_obj_desc; 553 data->flags |= ACPI_OBJECT_REPAIRED; 554 555 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 556 "%s: Repaired incorrectly formed Package\n", 557 data->pathname)); 558 559 return (AE_OK); 560 } 561