diff options
Diffstat (limited to 'drivers/acpi/acpica/nsrepair.c')
| -rw-r--r-- | drivers/acpi/acpica/nsrepair.c | 159 |
1 files changed, 58 insertions, 101 deletions
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 9c35d20eb52b..5519a64a353f 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c | |||
| @@ -71,11 +71,10 @@ ACPI_MODULE_NAME("nsrepair") | |||
| 71 | * Buffer -> String | 71 | * Buffer -> String |
| 72 | * Buffer -> Package of Integers | 72 | * Buffer -> Package of Integers |
| 73 | * Package -> Package of one Package | 73 | * Package -> Package of one Package |
| 74 | * An incorrect standalone object is wrapped with required outer package | ||
| 74 | * | 75 | * |
| 75 | * Additional possible repairs: | 76 | * Additional possible repairs: |
| 76 | * | ||
| 77 | * Required package elements that are NULL replaced by Integer/String/Buffer | 77 | * Required package elements that are NULL replaced by Integer/String/Buffer |
| 78 | * Incorrect standalone package wrapped with required outer package | ||
| 79 | * | 78 | * |
| 80 | ******************************************************************************/ | 79 | ******************************************************************************/ |
| 81 | /* Local prototypes */ | 80 | /* Local prototypes */ |
| @@ -91,10 +90,6 @@ static acpi_status | |||
| 91 | acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, | 90 | acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, |
| 92 | union acpi_operand_object **return_object); | 91 | union acpi_operand_object **return_object); |
| 93 | 92 | ||
| 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 | /******************************************************************************* | 93 | /******************************************************************************* |
| 99 | * | 94 | * |
| 100 | * FUNCTION: acpi_ns_repair_object | 95 | * FUNCTION: acpi_ns_repair_object |
| @@ -151,9 +146,24 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, | |||
| 151 | } | 146 | } |
| 152 | } | 147 | } |
| 153 | if (expected_btypes & ACPI_RTYPE_PACKAGE) { | 148 | if (expected_btypes & ACPI_RTYPE_PACKAGE) { |
| 154 | status = acpi_ns_convert_to_package(return_object, &new_object); | 149 | /* |
| 150 | * A package is expected. We will wrap the existing object with a | ||
| 151 | * new package object. It is often the case that if a variable-length | ||
| 152 | * package is required, but there is only a single object needed, the | ||
| 153 | * BIOS will return that object instead of wrapping it with a Package | ||
| 154 | * object. Note: after the wrapping, the package will be validated | ||
| 155 | * for correct contents (expected object type or types). | ||
| 156 | */ | ||
| 157 | status = | ||
| 158 | acpi_ns_wrap_with_package(data, return_object, &new_object); | ||
| 155 | if (ACPI_SUCCESS(status)) { | 159 | if (ACPI_SUCCESS(status)) { |
| 156 | goto object_repaired; | 160 | /* |
| 161 | * The original object just had its reference count | ||
| 162 | * incremented for being inserted into the new package. | ||
| 163 | */ | ||
| 164 | *return_object_ptr = new_object; /* New Package object */ | ||
| 165 | data->flags |= ACPI_OBJECT_REPAIRED; | ||
| 166 | return (AE_OK); | ||
| 157 | } | 167 | } |
| 158 | } | 168 | } |
| 159 | 169 | ||
| @@ -165,22 +175,27 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, | |||
| 165 | 175 | ||
| 166 | /* Object was successfully repaired */ | 176 | /* Object was successfully repaired */ |
| 167 | 177 | ||
| 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) { | 178 | if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { |
| 175 | new_object->common.reference_count = | 179 | /* |
| 176 | return_object->common.reference_count; | 180 | * The original object is a package element. We need to |
| 181 | * decrement the reference count of the original object, | ||
| 182 | * for removing it from the package. | ||
| 183 | * | ||
| 184 | * However, if the original object was just wrapped with a | ||
| 185 | * package object as part of the repair, we don't need to | ||
| 186 | * change the reference count. | ||
| 187 | */ | ||
| 188 | if (!(data->flags & ACPI_OBJECT_WRAPPED)) { | ||
| 189 | new_object->common.reference_count = | ||
| 190 | return_object->common.reference_count; | ||
| 177 | 191 | ||
| 178 | if (return_object->common.reference_count > 1) { | 192 | if (return_object->common.reference_count > 1) { |
| 179 | return_object->common.reference_count--; | 193 | return_object->common.reference_count--; |
| 194 | } | ||
| 180 | } | 195 | } |
| 181 | 196 | ||
| 182 | ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, | 197 | ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, |
| 183 | "%s: Converted %s to expected %s at index %u\n", | 198 | "%s: Converted %s to expected %s at Package index %u\n", |
| 184 | data->pathname, | 199 | data->pathname, |
| 185 | acpi_ut_get_object_type_name(return_object), | 200 | acpi_ut_get_object_type_name(return_object), |
| 186 | acpi_ut_get_object_type_name(new_object), | 201 | acpi_ut_get_object_type_name(new_object), |
| @@ -453,65 +468,6 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, | |||
| 453 | 468 | ||
| 454 | /******************************************************************************* | 469 | /******************************************************************************* |
| 455 | * | 470 | * |
| 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 | 471 | * FUNCTION: acpi_ns_repair_null_element |
| 516 | * | 472 | * |
| 517 | * PARAMETERS: Data - Pointer to validation data structure | 473 | * PARAMETERS: Data - Pointer to validation data structure |
| @@ -677,55 +633,56 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, | |||
| 677 | 633 | ||
| 678 | /******************************************************************************* | 634 | /******************************************************************************* |
| 679 | * | 635 | * |
| 680 | * FUNCTION: acpi_ns_repair_package_list | 636 | * FUNCTION: acpi_ns_wrap_with_package |
| 681 | * | 637 | * |
| 682 | * PARAMETERS: Data - Pointer to validation data structure | 638 | * PARAMETERS: Data - Pointer to validation data structure |
| 683 | * obj_desc_ptr - Pointer to the object to repair. The new | 639 | * original_object - Pointer to the object to repair. |
| 684 | * package object is returned here, | 640 | * obj_desc_ptr - The new package object is returned here |
| 685 | * overwriting the old object. | ||
| 686 | * | 641 | * |
| 687 | * RETURN: Status, new object in *obj_desc_ptr | 642 | * RETURN: Status, new object in *obj_desc_ptr |
| 688 | * | 643 | * |
| 689 | * DESCRIPTION: Repair a common problem with objects that are defined to return | 644 | * DESCRIPTION: Repair a common problem with objects that are defined to |
| 690 | * a variable-length Package of Packages. If the variable-length | 645 | * return a variable-length Package of sub-objects. If there is |
| 691 | * is one, some BIOS code mistakenly simply declares a single | 646 | * only one sub-object, some BIOS code mistakenly simply declares |
| 692 | * Package instead of a Package with one sub-Package. This | 647 | * the single object instead of a Package with one sub-object. |
| 693 | * function attempts to repair this error by wrapping a Package | 648 | * This function attempts to repair this error by wrapping a |
| 694 | * object around the original Package, creating the correct | 649 | * Package object around the original object, creating the |
| 695 | * Package with one sub-Package. | 650 | * correct and expected Package with one sub-object. |
| 696 | * | 651 | * |
| 697 | * Names that can be repaired in this manner include: | 652 | * Names that can be repaired in this manner include: |
| 698 | * _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS | 653 | * _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS, |
| 654 | * _BCL, _DOD, _FIX, _Sx | ||
| 699 | * | 655 | * |
| 700 | ******************************************************************************/ | 656 | ******************************************************************************/ |
| 701 | 657 | ||
| 702 | acpi_status | 658 | acpi_status |
| 703 | acpi_ns_repair_package_list(struct acpi_predefined_data *data, | 659 | acpi_ns_wrap_with_package(struct acpi_predefined_data *data, |
| 704 | union acpi_operand_object **obj_desc_ptr) | 660 | union acpi_operand_object *original_object, |
| 661 | union acpi_operand_object **obj_desc_ptr) | ||
| 705 | { | 662 | { |
| 706 | union acpi_operand_object *pkg_obj_desc; | 663 | union acpi_operand_object *pkg_obj_desc; |
| 707 | 664 | ||
| 708 | ACPI_FUNCTION_NAME(ns_repair_package_list); | 665 | ACPI_FUNCTION_NAME(ns_wrap_with_package); |
| 709 | 666 | ||
| 710 | /* | 667 | /* |
| 711 | * Create the new outer package and populate it. The new package will | 668 | * Create the new outer package and populate it. The new package will |
| 712 | * have a single element, the lone subpackage. | 669 | * have a single element, the lone sub-object. |
| 713 | */ | 670 | */ |
| 714 | pkg_obj_desc = acpi_ut_create_package_object(1); | 671 | pkg_obj_desc = acpi_ut_create_package_object(1); |
| 715 | if (!pkg_obj_desc) { | 672 | if (!pkg_obj_desc) { |
| 716 | return (AE_NO_MEMORY); | 673 | return (AE_NO_MEMORY); |
| 717 | } | 674 | } |
| 718 | 675 | ||
| 719 | pkg_obj_desc->package.elements[0] = *obj_desc_ptr; | 676 | pkg_obj_desc->package.elements[0] = original_object; |
| 677 | |||
| 678 | ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, | ||
| 679 | "%s: Wrapped %s with expected Package object\n", | ||
| 680 | data->pathname, | ||
| 681 | acpi_ut_get_object_type_name(original_object))); | ||
| 720 | 682 | ||
| 721 | /* Return the new object in the object pointer */ | 683 | /* Return the new object in the object pointer */ |
| 722 | 684 | ||
| 723 | *obj_desc_ptr = pkg_obj_desc; | 685 | *obj_desc_ptr = pkg_obj_desc; |
| 724 | data->flags |= ACPI_OBJECT_REPAIRED; | 686 | data->flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; |
| 725 | |||
| 726 | ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, | ||
| 727 | "%s: Repaired incorrectly formed Package\n", | ||
| 728 | data->pathname)); | ||
| 729 | |||
| 730 | return (AE_OK); | 687 | return (AE_OK); |
| 731 | } | 688 | } |
