1 /****************************************************************************** 2 * 3 * Module Name: nsrepair - Repair for objects returned by predefined methods 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2011, 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 #include "acpredef.h" 49 50 #define _COMPONENT ACPI_NAMESPACE 51 ACPI_MODULE_NAME("nsrepair") 52 53 /******************************************************************************* 54 * 55 * This module attempts to repair or convert objects returned by the 56 * predefined methods to an object type that is expected, as per the ACPI 57 * specification. The need for this code is dictated by the many machines that 58 * return incorrect types for the standard predefined methods. Performing these 59 * conversions here, in one place, eliminates the need for individual ACPI 60 * device drivers to do the same. Note: Most of these conversions are different 61 * than the internal object conversion routines used for implicit object 62 * conversion. 63 * 64 * The following conversions can be performed as necessary: 65 * 66 * Integer -> String 67 * Integer -> Buffer 68 * String -> Integer 69 * String -> Buffer 70 * Buffer -> Integer 71 * Buffer -> String 72 * Buffer -> Package of Integers 73 * Package -> Package of one Package 74 * 75 * Additional possible repairs: 76 * 77 * Required package elements that are NULL replaced by Integer/String/Buffer 78 * Incorrect standalone package wrapped with required outer package 79 * 80 ******************************************************************************/ 81 /* Local prototypes */ 82 static acpi_status 83 acpi_ns_convert_to_integer(union acpi_operand_object *original_object, 84 union acpi_operand_object **return_object); 85 86 static acpi_status 87 acpi_ns_convert_to_string(union acpi_operand_object *original_object, 88 union acpi_operand_object **return_object); 89 90 static acpi_status 91 acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, 92 union acpi_operand_object **return_object); 93 94 static acpi_status 95 acpi_ns_convert_to_package(union acpi_operand_object *original_object, 96 union acpi_operand_object **return_object); 97 98 /******************************************************************************* 99 * 100 * FUNCTION: acpi_ns_repair_object 101 * 102 * PARAMETERS: Data - Pointer to validation data structure 103 * expected_btypes - Object types expected 104 * package_index - Index of object within parent package (if 105 * applicable - ACPI_NOT_PACKAGE_ELEMENT 106 * otherwise) 107 * return_object_ptr - Pointer to the object returned from the 108 * evaluation of a method or object 109 * 110 * RETURN: Status. AE_OK if repair was successful. 111 * 112 * DESCRIPTION: Attempt to repair/convert a return object of a type that was 113 * not expected. 114 * 115 ******************************************************************************/ 116 117 acpi_status 118 acpi_ns_repair_object(struct acpi_predefined_data *data, 119 u32 expected_btypes, 120 u32 package_index, 121 union acpi_operand_object **return_object_ptr) 122 { 123 union acpi_operand_object *return_object = *return_object_ptr; 124 union acpi_operand_object *new_object; 125 acpi_status status; 126 127 ACPI_FUNCTION_NAME(ns_repair_object); 128 129 /* 130 * At this point, we know that the type of the returned object was not 131 * one of the expected types for this predefined name. Attempt to 132 * repair the object by converting it to one of the expected object 133 * types for this predefined name. 134 */ 135 if (expected_btypes & ACPI_RTYPE_INTEGER) { 136 status = acpi_ns_convert_to_integer(return_object, &new_object); 137 if (ACPI_SUCCESS(status)) { 138 goto object_repaired; 139 } 140 } 141 if (expected_btypes & ACPI_RTYPE_STRING) { 142 status = acpi_ns_convert_to_string(return_object, &new_object); 143 if (ACPI_SUCCESS(status)) { 144 goto object_repaired; 145 } 146 } 147 if (expected_btypes & ACPI_RTYPE_BUFFER) { 148 status = acpi_ns_convert_to_buffer(return_object, &new_object); 149 if (ACPI_SUCCESS(status)) { 150 goto object_repaired; 151 } 152 } 153 if (expected_btypes & ACPI_RTYPE_PACKAGE) { 154 status = acpi_ns_convert_to_package(return_object, &new_object); 155 if (ACPI_SUCCESS(status)) { 156 goto object_repaired; 157 } 158 } 159 160 /* We cannot repair this object */ 161 162 return (AE_AML_OPERAND_TYPE); 163 164 object_repaired: 165 166 /* Object was successfully repaired */ 167 168 /* 169 * If the original object is a package element, we need to: 170 * 1. Set the reference count of the new object to match the 171 * reference count of the old object. 172 * 2. Decrement the reference count of the original object. 173 */ 174 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 175 new_object->common.reference_count = 176 return_object->common.reference_count; 177 178 if (return_object->common.reference_count > 1) { 179 return_object->common.reference_count--; 180 } 181 182 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 183 "%s: Converted %s to expected %s at index %u\n", 184 data->pathname, 185 acpi_ut_get_object_type_name(return_object), 186 acpi_ut_get_object_type_name(new_object), 187 package_index)); 188 } else { 189 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 190 "%s: Converted %s to expected %s\n", 191 data->pathname, 192 acpi_ut_get_object_type_name(return_object), 193 acpi_ut_get_object_type_name(new_object))); 194 } 195 196 /* Delete old object, install the new return object */ 197 198 acpi_ut_remove_reference(return_object); 199 *return_object_ptr = new_object; 200 data->flags |= ACPI_OBJECT_REPAIRED; 201 return (AE_OK); 202 } 203 204 /******************************************************************************* 205 * 206 * FUNCTION: acpi_ns_convert_to_integer 207 * 208 * PARAMETERS: original_object - Object to be converted 209 * return_object - Where the new converted object is returned 210 * 211 * RETURN: Status. AE_OK if conversion was successful. 212 * 213 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. 214 * 215 ******************************************************************************/ 216 217 static acpi_status 218 acpi_ns_convert_to_integer(union acpi_operand_object *original_object, 219 union acpi_operand_object **return_object) 220 { 221 union acpi_operand_object *new_object; 222 acpi_status status; 223 u64 value = 0; 224 u32 i; 225 226 switch (original_object->common.type) { 227 case ACPI_TYPE_STRING: 228 229 /* String-to-Integer conversion */ 230 231 status = acpi_ut_strtoul64(original_object->string.pointer, 232 ACPI_ANY_BASE, &value); 233 if (ACPI_FAILURE(status)) { 234 return (status); 235 } 236 break; 237 238 case ACPI_TYPE_BUFFER: 239 240 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ 241 242 if (original_object->buffer.length > 8) { 243 return (AE_AML_OPERAND_TYPE); 244 } 245 246 /* Extract each buffer byte to create the integer */ 247 248 for (i = 0; i < original_object->buffer.length; i++) { 249 value |= 250 ((u64) original_object->buffer. 251 pointer[i] << (i * 8)); 252 } 253 break; 254 255 default: 256 return (AE_AML_OPERAND_TYPE); 257 } 258 259 new_object = acpi_ut_create_integer_object(value); 260 if (!new_object) { 261 return (AE_NO_MEMORY); 262 } 263 264 *return_object = new_object; 265 return (AE_OK); 266 } 267 268 /******************************************************************************* 269 * 270 * FUNCTION: acpi_ns_convert_to_string 271 * 272 * PARAMETERS: original_object - Object to be converted 273 * return_object - Where the new converted object is returned 274 * 275 * RETURN: Status. AE_OK if conversion was successful. 276 * 277 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. 278 * 279 ******************************************************************************/ 280 281 static acpi_status 282 acpi_ns_convert_to_string(union acpi_operand_object *original_object, 283 union acpi_operand_object **return_object) 284 { 285 union acpi_operand_object *new_object; 286 acpi_size length; 287 acpi_status status; 288 289 switch (original_object->common.type) { 290 case ACPI_TYPE_INTEGER: 291 /* 292 * Integer-to-String conversion. Commonly, convert 293 * an integer of value 0 to a NULL string. The last element of 294 * _BIF and _BIX packages occasionally need this fix. 295 */ 296 if (original_object->integer.value == 0) { 297 298 /* Allocate a new NULL string object */ 299 300 new_object = acpi_ut_create_string_object(0); 301 if (!new_object) { 302 return (AE_NO_MEMORY); 303 } 304 } else { 305 status = 306 acpi_ex_convert_to_string(original_object, 307 &new_object, 308 ACPI_IMPLICIT_CONVERT_HEX); 309 if (ACPI_FAILURE(status)) { 310 return (status); 311 } 312 } 313 break; 314 315 case ACPI_TYPE_BUFFER: 316 /* 317 * Buffer-to-String conversion. Use a to_string 318 * conversion, no transform performed on the buffer data. The best 319 * example of this is the _BIF method, where the string data from 320 * the battery is often (incorrectly) returned as buffer object(s). 321 */ 322 length = 0; 323 while ((length < original_object->buffer.length) && 324 (original_object->buffer.pointer[length])) { 325 length++; 326 } 327 328 /* Allocate a new string object */ 329 330 new_object = acpi_ut_create_string_object(length); 331 if (!new_object) { 332 return (AE_NO_MEMORY); 333 } 334 335 /* 336 * Copy the raw buffer data with no transform. String is already NULL 337 * terminated at Length+1. 338 */ 339 ACPI_MEMCPY(new_object->string.pointer, 340 original_object->buffer.pointer, length); 341 break; 342 343 default: 344 return (AE_AML_OPERAND_TYPE); 345 } 346 347 *return_object = new_object; 348 return (AE_OK); 349 } 350 351 /******************************************************************************* 352 * 353 * FUNCTION: acpi_ns_convert_to_buffer 354 * 355 * PARAMETERS: original_object - Object to be converted 356 * return_object - Where the new converted object is returned 357 * 358 * RETURN: Status. AE_OK if conversion was successful. 359 * 360 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. 361 * 362 ******************************************************************************/ 363 364 static acpi_status 365 acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, 366 union acpi_operand_object **return_object) 367 { 368 union acpi_operand_object *new_object; 369 acpi_status status; 370 union acpi_operand_object **elements; 371 u32 *dword_buffer; 372 u32 count; 373 u32 i; 374 375 switch (original_object->common.type) { 376 case ACPI_TYPE_INTEGER: 377 /* 378 * Integer-to-Buffer conversion. 379 * Convert the Integer to a packed-byte buffer. _MAT and other 380 * objects need this sometimes, if a read has been performed on a 381 * Field object that is less than or equal to the global integer 382 * size (32 or 64 bits). 383 */ 384 status = 385 acpi_ex_convert_to_buffer(original_object, &new_object); 386 if (ACPI_FAILURE(status)) { 387 return (status); 388 } 389 break; 390 391 case ACPI_TYPE_STRING: 392 393 /* String-to-Buffer conversion. Simple data copy */ 394 395 new_object = 396 acpi_ut_create_buffer_object(original_object->string. 397 length); 398 if (!new_object) { 399 return (AE_NO_MEMORY); 400 } 401 402 ACPI_MEMCPY(new_object->buffer.pointer, 403 original_object->string.pointer, 404 original_object->string.length); 405 break; 406 407 case ACPI_TYPE_PACKAGE: 408 /* 409 * This case is often seen for predefined names that must return a 410 * Buffer object with multiple DWORD integers within. For example, 411 * _FDE and _GTM. The Package can be converted to a Buffer. 412 */ 413 414 /* All elements of the Package must be integers */ 415 416 elements = original_object->package.elements; 417 count = original_object->package.count; 418 419 for (i = 0; i < count; i++) { 420 if ((!*elements) || 421 ((*elements)->common.type != ACPI_TYPE_INTEGER)) { 422 return (AE_AML_OPERAND_TYPE); 423 } 424 elements++; 425 } 426 427 /* Create the new buffer object to replace the Package */ 428 429 new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count)); 430 if (!new_object) { 431 return (AE_NO_MEMORY); 432 } 433 434 /* Copy the package elements (integers) to the buffer as DWORDs */ 435 436 elements = original_object->package.elements; 437 dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer); 438 439 for (i = 0; i < count; i++) { 440 *dword_buffer = (u32) (*elements)->integer.value; 441 dword_buffer++; 442 elements++; 443 } 444 break; 445 446 default: 447 return (AE_AML_OPERAND_TYPE); 448 } 449 450 *return_object = new_object; 451 return (AE_OK); 452 } 453 454 /******************************************************************************* 455 * 456 * FUNCTION: acpi_ns_convert_to_package 457 * 458 * PARAMETERS: original_object - Object to be converted 459 * return_object - Where the new converted object is returned 460 * 461 * RETURN: Status. AE_OK if conversion was successful. 462 * 463 * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of 464 * the buffer is converted to a single integer package element. 465 * 466 ******************************************************************************/ 467 468 static acpi_status 469 acpi_ns_convert_to_package(union acpi_operand_object *original_object, 470 union acpi_operand_object **return_object) 471 { 472 union acpi_operand_object *new_object; 473 union acpi_operand_object **elements; 474 u32 length; 475 u8 *buffer; 476 477 switch (original_object->common.type) { 478 case ACPI_TYPE_BUFFER: 479 480 /* Buffer-to-Package conversion */ 481 482 length = original_object->buffer.length; 483 new_object = acpi_ut_create_package_object(length); 484 if (!new_object) { 485 return (AE_NO_MEMORY); 486 } 487 488 /* Convert each buffer byte to an integer package element */ 489 490 elements = new_object->package.elements; 491 buffer = original_object->buffer.pointer; 492 493 while (length--) { 494 *elements = 495 acpi_ut_create_integer_object((u64) *buffer); 496 if (!*elements) { 497 acpi_ut_remove_reference(new_object); 498 return (AE_NO_MEMORY); 499 } 500 elements++; 501 buffer++; 502 } 503 break; 504 505 default: 506 return (AE_AML_OPERAND_TYPE); 507 } 508 509 *return_object = new_object; 510 return (AE_OK); 511 } 512 513 /******************************************************************************* 514 * 515 * FUNCTION: acpi_ns_repair_null_element 516 * 517 * PARAMETERS: Data - Pointer to validation data structure 518 * expected_btypes - Object types expected 519 * package_index - Index of object within parent package (if 520 * applicable - ACPI_NOT_PACKAGE_ELEMENT 521 * otherwise) 522 * return_object_ptr - Pointer to the object returned from the 523 * evaluation of a method or object 524 * 525 * RETURN: Status. AE_OK if repair was successful. 526 * 527 * DESCRIPTION: Attempt to repair a NULL element of a returned Package object. 528 * 529 ******************************************************************************/ 530 531 acpi_status 532 acpi_ns_repair_null_element(struct acpi_predefined_data *data, 533 u32 expected_btypes, 534 u32 package_index, 535 union acpi_operand_object **return_object_ptr) 536 { 537 union acpi_operand_object *return_object = *return_object_ptr; 538 union acpi_operand_object *new_object; 539 540 ACPI_FUNCTION_NAME(ns_repair_null_element); 541 542 /* No repair needed if return object is non-NULL */ 543 544 if (return_object) { 545 return (AE_OK); 546 } 547 548 /* 549 * Attempt to repair a NULL element of a Package object. This applies to 550 * predefined names that return a fixed-length package and each element 551 * is required. It does not apply to variable-length packages where NULL 552 * elements are allowed, especially at the end of the package. 553 */ 554 if (expected_btypes & ACPI_RTYPE_INTEGER) { 555 556 /* Need an Integer - create a zero-value integer */ 557 558 new_object = acpi_ut_create_integer_object((u64)0); 559 } else if (expected_btypes & ACPI_RTYPE_STRING) { 560 561 /* Need a String - create a NULL string */ 562 563 new_object = acpi_ut_create_string_object(0); 564 } else if (expected_btypes & ACPI_RTYPE_BUFFER) { 565 566 /* Need a Buffer - create a zero-length buffer */ 567 568 new_object = acpi_ut_create_buffer_object(0); 569 } else { 570 /* Error for all other expected types */ 571 572 return (AE_AML_OPERAND_TYPE); 573 } 574 575 if (!new_object) { 576 return (AE_NO_MEMORY); 577 } 578 579 /* Set the reference count according to the parent Package object */ 580 581 new_object->common.reference_count = 582 data->parent_package->common.reference_count; 583 584 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 585 "%s: Converted NULL package element to expected %s at index %u\n", 586 data->pathname, 587 acpi_ut_get_object_type_name(new_object), 588 package_index)); 589 590 *return_object_ptr = new_object; 591 data->flags |= ACPI_OBJECT_REPAIRED; 592 return (AE_OK); 593 } 594 595 /****************************************************************************** 596 * 597 * FUNCTION: acpi_ns_remove_null_elements 598 * 599 * PARAMETERS: Data - Pointer to validation data structure 600 * package_type - An acpi_return_package_types value 601 * obj_desc - A Package object 602 * 603 * RETURN: None. 604 * 605 * DESCRIPTION: Remove all NULL package elements from packages that contain 606 * a variable number of sub-packages. For these types of 607 * packages, NULL elements can be safely removed. 608 * 609 *****************************************************************************/ 610 611 void 612 acpi_ns_remove_null_elements(struct acpi_predefined_data *data, 613 u8 package_type, 614 union acpi_operand_object *obj_desc) 615 { 616 union acpi_operand_object **source; 617 union acpi_operand_object **dest; 618 u32 count; 619 u32 new_count; 620 u32 i; 621 622 ACPI_FUNCTION_NAME(ns_remove_null_elements); 623 624 /* 625 * We can safely remove all NULL elements from these package types: 626 * PTYPE1_VAR packages contain a variable number of simple data types. 627 * PTYPE2 packages contain a variable number of sub-packages. 628 */ 629 switch (package_type) { 630 case ACPI_PTYPE1_VAR: 631 case ACPI_PTYPE2: 632 case ACPI_PTYPE2_COUNT: 633 case ACPI_PTYPE2_PKG_COUNT: 634 case ACPI_PTYPE2_FIXED: 635 case ACPI_PTYPE2_MIN: 636 case ACPI_PTYPE2_REV_FIXED: 637 break; 638 639 default: 640 case ACPI_PTYPE1_FIXED: 641 case ACPI_PTYPE1_OPTION: 642 return; 643 } 644 645 count = obj_desc->package.count; 646 new_count = count; 647 648 source = obj_desc->package.elements; 649 dest = source; 650 651 /* Examine all elements of the package object, remove nulls */ 652 653 for (i = 0; i < count; i++) { 654 if (!*source) { 655 new_count--; 656 } else { 657 *dest = *source; 658 dest++; 659 } 660 source++; 661 } 662 663 /* Update parent package if any null elements were removed */ 664 665 if (new_count < count) { 666 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 667 "%s: Found and removed %u NULL elements\n", 668 data->pathname, (count - new_count))); 669 670 /* NULL terminate list and update the package count */ 671 672 *dest = NULL; 673 obj_desc->package.count = new_count; 674 } 675 } 676 677 /******************************************************************************* 678 * 679 * FUNCTION: acpi_ns_repair_package_list 680 * 681 * PARAMETERS: Data - Pointer to validation data structure 682 * obj_desc_ptr - Pointer to the object to repair. The new 683 * package object is returned here, 684 * overwriting the old object. 685 * 686 * RETURN: Status, new object in *obj_desc_ptr 687 * 688 * DESCRIPTION: Repair a common problem with objects that are defined to return 689 * a variable-length Package of Packages. If the variable-length 690 * is one, some BIOS code mistakenly simply declares a single 691 * Package instead of a Package with one sub-Package. This 692 * function attempts to repair this error by wrapping a Package 693 * object around the original Package, creating the correct 694 * Package with one sub-Package. 695 * 696 * Names that can be repaired in this manner include: 697 * _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS 698 * 699 ******************************************************************************/ 700 701 acpi_status 702 acpi_ns_repair_package_list(struct acpi_predefined_data *data, 703 union acpi_operand_object **obj_desc_ptr) 704 { 705 union acpi_operand_object *pkg_obj_desc; 706 707 ACPI_FUNCTION_NAME(ns_repair_package_list); 708 709 /* 710 * Create the new outer package and populate it. The new package will 711 * have a single element, the lone subpackage. 712 */ 713 pkg_obj_desc = acpi_ut_create_package_object(1); 714 if (!pkg_obj_desc) { 715 return (AE_NO_MEMORY); 716 } 717 718 pkg_obj_desc->package.elements[0] = *obj_desc_ptr; 719 720 /* Return the new object in the object pointer */ 721 722 *obj_desc_ptr = pkg_obj_desc; 723 data->flags |= ACPI_OBJECT_REPAIRED; 724 725 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 726 "%s: Repaired incorrectly formed Package\n", 727 data->pathname)); 728 729 return (AE_OK); 730 } 731