diff options
| -rw-r--r-- | drivers/acpi/acpica/aclocal.h | 1 | ||||
| -rw-r--r-- | drivers/acpi/acpica/acnamesp.h | 16 | ||||
| -rw-r--r-- | drivers/acpi/acpica/nspredef.c | 27 | ||||
| -rw-r--r-- | drivers/acpi/acpica/nsrepair.c | 173 | ||||
| -rw-r--r-- | drivers/acpi/acpica/nsrepair2.c | 84 |
5 files changed, 209 insertions, 92 deletions
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 2caf141076fc..681205c75563 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
| @@ -374,6 +374,7 @@ union acpi_predefined_info { | |||
| 374 | struct acpi_predefined_data { | 374 | struct acpi_predefined_data { |
| 375 | char *pathname; | 375 | char *pathname; |
| 376 | const union acpi_predefined_info *predefined; | 376 | const union acpi_predefined_info *predefined; |
| 377 | union acpi_operand_object *parent_package; | ||
| 377 | u32 flags; | 378 | u32 flags; |
| 378 | u8 node_flags; | 379 | u8 node_flags; |
| 379 | }; | 380 | }; |
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 73f9b0c88dd8..258159cfcdfa 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h | |||
| @@ -286,6 +286,17 @@ acpi_status | |||
| 286 | acpi_ns_repair_package_list(struct acpi_predefined_data *data, | 286 | acpi_ns_repair_package_list(struct acpi_predefined_data *data, |
| 287 | union acpi_operand_object **obj_desc_ptr); | 287 | union acpi_operand_object **obj_desc_ptr); |
| 288 | 288 | ||
| 289 | acpi_status | ||
| 290 | acpi_ns_repair_null_element(struct acpi_predefined_data *data, | ||
| 291 | u32 expected_btypes, | ||
| 292 | u32 package_index, | ||
| 293 | union acpi_operand_object **return_object_ptr); | ||
| 294 | |||
| 295 | void | ||
| 296 | acpi_ns_remove_null_elements(struct acpi_predefined_data *data, | ||
| 297 | u8 package_type, | ||
| 298 | union acpi_operand_object *obj_desc); | ||
| 299 | |||
| 289 | /* | 300 | /* |
| 290 | * nsrepair2 - Return object repair for specific | 301 | * nsrepair2 - Return object repair for specific |
| 291 | * predefined methods/objects | 302 | * predefined methods/objects |
| @@ -296,11 +307,6 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data, | |||
| 296 | acpi_status validate_status, | 307 | acpi_status validate_status, |
| 297 | union acpi_operand_object **return_object_ptr); | 308 | union acpi_operand_object **return_object_ptr); |
| 298 | 309 | ||
| 299 | void | ||
| 300 | acpi_ns_remove_null_elements(struct acpi_predefined_data *data, | ||
| 301 | u8 package_type, | ||
| 302 | union acpi_operand_object *obj_desc); | ||
| 303 | |||
| 304 | /* | 310 | /* |
| 305 | * nssearch - Namespace searching and entry | 311 | * nssearch - Namespace searching and entry |
| 306 | */ | 312 | */ |
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index ba1072fb0daa..7096bcda0c72 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c | |||
| @@ -231,6 +231,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | |||
| 231 | * Note: Package may have been newly created by call above. | 231 | * Note: Package may have been newly created by call above. |
| 232 | */ | 232 | */ |
| 233 | if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { | 233 | if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { |
| 234 | data->parent_package = *return_object_ptr; | ||
| 234 | status = acpi_ns_check_package(data, return_object_ptr); | 235 | status = acpi_ns_check_package(data, return_object_ptr); |
| 235 | if (ACPI_FAILURE(status)) { | 236 | if (ACPI_FAILURE(status)) { |
| 236 | goto exit; | 237 | goto exit; |
| @@ -710,6 +711,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, | |||
| 710 | for (i = 0; i < count; i++) { | 711 | for (i = 0; i < count; i++) { |
| 711 | sub_package = *elements; | 712 | sub_package = *elements; |
| 712 | sub_elements = sub_package->package.elements; | 713 | sub_elements = sub_package->package.elements; |
| 714 | data->parent_package = sub_package; | ||
| 713 | 715 | ||
| 714 | /* Each sub-object must be of type Package */ | 716 | /* Each sub-object must be of type Package */ |
| 715 | 717 | ||
| @@ -721,6 +723,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, | |||
| 721 | 723 | ||
| 722 | /* Examine the different types of expected sub-packages */ | 724 | /* Examine the different types of expected sub-packages */ |
| 723 | 725 | ||
| 726 | data->parent_package = sub_package; | ||
| 724 | switch (package->ret_info.type) { | 727 | switch (package->ret_info.type) { |
| 725 | case ACPI_PTYPE2: | 728 | case ACPI_PTYPE2: |
| 726 | case ACPI_PTYPE2_PKG_COUNT: | 729 | case ACPI_PTYPE2_PKG_COUNT: |
| @@ -800,7 +803,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, | |||
| 800 | 803 | ||
| 801 | /* | 804 | /* |
| 802 | * First element is the (Integer) count of elements, including | 805 | * First element is the (Integer) count of elements, including |
| 803 | * the count field. | 806 | * the count field (the ACPI name is num_elements) |
| 804 | */ | 807 | */ |
| 805 | status = acpi_ns_check_object_type(data, sub_elements, | 808 | status = acpi_ns_check_object_type(data, sub_elements, |
| 806 | ACPI_RTYPE_INTEGER, | 809 | ACPI_RTYPE_INTEGER, |
| @@ -822,6 +825,16 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, | |||
| 822 | expected_count = package->ret_info.count1; | 825 | expected_count = package->ret_info.count1; |
| 823 | goto package_too_small; | 826 | goto package_too_small; |
| 824 | } | 827 | } |
| 828 | if (expected_count == 0) { | ||
| 829 | /* | ||
| 830 | * Either the num_entries element was originally zero or it was | ||
| 831 | * a NULL element and repaired to an Integer of value zero. | ||
| 832 | * In either case, repair it by setting num_entries to be the | ||
| 833 | * actual size of the subpackage. | ||
| 834 | */ | ||
| 835 | expected_count = sub_package->package.count; | ||
| 836 | (*sub_elements)->integer.value = expected_count; | ||
| 837 | } | ||
| 825 | 838 | ||
| 826 | /* Check the type of each sub-package element */ | 839 | /* Check the type of each sub-package element */ |
| 827 | 840 | ||
| @@ -945,10 +958,18 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, | |||
| 945 | char type_buffer[48]; /* Room for 5 types */ | 958 | char type_buffer[48]; /* Room for 5 types */ |
| 946 | 959 | ||
| 947 | /* | 960 | /* |
| 948 | * If we get a NULL return_object here, it is a NULL package element, | 961 | * If we get a NULL return_object here, it is a NULL package element. |
| 949 | * and this is always an error. | 962 | * Since all extraneous NULL package elements were removed earlier by a |
| 963 | * call to acpi_ns_remove_null_elements, this is an unexpected NULL element. | ||
| 964 | * We will attempt to repair it. | ||
| 950 | */ | 965 | */ |
| 951 | if (!return_object) { | 966 | if (!return_object) { |
| 967 | status = acpi_ns_repair_null_element(data, expected_btypes, | ||
| 968 | package_index, | ||
| 969 | return_object_ptr); | ||
| 970 | if (ACPI_SUCCESS(status)) { | ||
| 971 | return (AE_OK); /* Repair was successful */ | ||
| 972 | } | ||
| 952 | goto type_error_exit; | 973 | goto type_error_exit; |
| 953 | } | 974 | } |
| 954 | 975 | ||
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index c82060fd3821..d4be37751be4 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | #include "accommon.h" | 45 | #include "accommon.h" |
| 46 | #include "acnamesp.h" | 46 | #include "acnamesp.h" |
| 47 | #include "acinterp.h" | 47 | #include "acinterp.h" |
| 48 | #include "acpredef.h" | ||
| 48 | 49 | ||
| 49 | #define _COMPONENT ACPI_NAMESPACE | 50 | #define _COMPONENT ACPI_NAMESPACE |
| 50 | ACPI_MODULE_NAME("nsrepair") | 51 | ACPI_MODULE_NAME("nsrepair") |
| @@ -71,6 +72,12 @@ ACPI_MODULE_NAME("nsrepair") | |||
| 71 | * Buffer -> Package of Integers | 72 | * Buffer -> Package of Integers |
| 72 | * Package -> Package of one Package | 73 | * Package -> Package of one Package |
| 73 | * | 74 | * |
| 75 | * Additional possible repairs: | ||
| 76 | * | ||
| 77 | * Optional/unnecessary NULL package elements removed | ||
| 78 | * Required package elements that are NULL replaced by Integer/String/Buffer | ||
| 79 | * Incorrect standalone package wrapped with required outer package | ||
| 80 | * | ||
| 74 | ******************************************************************************/ | 81 | ******************************************************************************/ |
| 75 | /* Local prototypes */ | 82 | /* Local prototypes */ |
| 76 | static acpi_status | 83 | static acpi_status |
| @@ -506,6 +513,172 @@ acpi_ns_convert_to_package(union acpi_operand_object *original_object, | |||
| 506 | 513 | ||
| 507 | /******************************************************************************* | 514 | /******************************************************************************* |
| 508 | * | 515 | * |
| 516 | * FUNCTION: acpi_ns_repair_null_element | ||
| 517 | * | ||
| 518 | * PARAMETERS: Data - Pointer to validation data structure | ||
| 519 | * expected_btypes - Object types expected | ||
| 520 | * package_index - Index of object within parent package (if | ||
| 521 | * applicable - ACPI_NOT_PACKAGE_ELEMENT | ||
| 522 | * otherwise) | ||
| 523 | * return_object_ptr - Pointer to the object returned from the | ||
| 524 | * evaluation of a method or object | ||
| 525 | * | ||
| 526 | * RETURN: Status. AE_OK if repair was successful. | ||
| 527 | * | ||
| 528 | * DESCRIPTION: Attempt to repair a NULL element of a returned Package object. | ||
| 529 | * | ||
| 530 | ******************************************************************************/ | ||
| 531 | |||
| 532 | acpi_status | ||
| 533 | acpi_ns_repair_null_element(struct acpi_predefined_data *data, | ||
| 534 | u32 expected_btypes, | ||
| 535 | u32 package_index, | ||
| 536 | union acpi_operand_object **return_object_ptr) | ||
| 537 | { | ||
| 538 | union acpi_operand_object *return_object = *return_object_ptr; | ||
| 539 | union acpi_operand_object *new_object; | ||
| 540 | |||
| 541 | ACPI_FUNCTION_NAME(ns_repair_null_element); | ||
| 542 | |||
| 543 | /* No repair needed if return object is non-NULL */ | ||
| 544 | |||
| 545 | if (return_object) { | ||
| 546 | return (AE_OK); | ||
| 547 | } | ||
| 548 | |||
| 549 | /* | ||
| 550 | * Attempt to repair a NULL element of a Package object. This applies to | ||
| 551 | * predefined names that return a fixed-length package and each element | ||
| 552 | * is required. It does not apply to variable-length packages where NULL | ||
| 553 | * elements are allowed, especially at the end of the package. | ||
| 554 | */ | ||
| 555 | if (expected_btypes & ACPI_RTYPE_INTEGER) { | ||
| 556 | |||
| 557 | /* Need an Integer - create a zero-value integer */ | ||
| 558 | |||
| 559 | new_object = acpi_ut_create_integer_object(0); | ||
| 560 | } else if (expected_btypes & ACPI_RTYPE_STRING) { | ||
| 561 | |||
| 562 | /* Need a String - create a NULL string */ | ||
| 563 | |||
| 564 | new_object = acpi_ut_create_string_object(0); | ||
| 565 | } else if (expected_btypes & ACPI_RTYPE_BUFFER) { | ||
| 566 | |||
| 567 | /* Need a Buffer - create a zero-length buffer */ | ||
| 568 | |||
| 569 | new_object = acpi_ut_create_buffer_object(0); | ||
| 570 | } else { | ||
| 571 | /* Error for all other expected types */ | ||
| 572 | |||
| 573 | return (AE_AML_OPERAND_TYPE); | ||
| 574 | } | ||
| 575 | |||
| 576 | if (!new_object) { | ||
| 577 | return (AE_NO_MEMORY); | ||
| 578 | } | ||
| 579 | |||
| 580 | /* Set the reference count according to the parent Package object */ | ||
| 581 | |||
| 582 | new_object->common.reference_count = | ||
| 583 | data->parent_package->common.reference_count; | ||
| 584 | |||
| 585 | ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, | ||
| 586 | "%s: Converted NULL package element to expected %s at index %u\n", | ||
| 587 | data->pathname, | ||
| 588 | acpi_ut_get_object_type_name(new_object), | ||
| 589 | package_index)); | ||
| 590 | |||
| 591 | *return_object_ptr = new_object; | ||
| 592 | data->flags |= ACPI_OBJECT_REPAIRED; | ||
| 593 | return (AE_OK); | ||
| 594 | } | ||
| 595 | |||
| 596 | /****************************************************************************** | ||
| 597 | * | ||
| 598 | * FUNCTION: acpi_ns_remove_null_elements | ||
| 599 | * | ||
| 600 | * PARAMETERS: Data - Pointer to validation data structure | ||
| 601 | * package_type - An acpi_return_package_types value | ||
| 602 | * obj_desc - A Package object | ||
| 603 | * | ||
| 604 | * RETURN: None. | ||
| 605 | * | ||
| 606 | * DESCRIPTION: Remove all NULL package elements from packages that contain | ||
| 607 | * a variable number of sub-packages. For these types of | ||
| 608 | * packages, NULL elements can be safely removed. | ||
| 609 | * | ||
| 610 | *****************************************************************************/ | ||
| 611 | |||
| 612 | void | ||
| 613 | acpi_ns_remove_null_elements(struct acpi_predefined_data *data, | ||
| 614 | u8 package_type, | ||
| 615 | union acpi_operand_object *obj_desc) | ||
| 616 | { | ||
| 617 | union acpi_operand_object **source; | ||
| 618 | union acpi_operand_object **dest; | ||
| 619 | u32 count; | ||
| 620 | u32 new_count; | ||
| 621 | u32 i; | ||
| 622 | |||
| 623 | ACPI_FUNCTION_NAME(ns_remove_null_elements); | ||
| 624 | |||
| 625 | /* | ||
| 626 | * PTYPE1 packages contain no subpackages. | ||
| 627 | * PTYPE2 packages contain a variable number of sub-packages. We can | ||
| 628 | * safely remove all NULL elements from the PTYPE2 packages. | ||
| 629 | */ | ||
| 630 | switch (package_type) { | ||
| 631 | case ACPI_PTYPE1_FIXED: | ||
| 632 | case ACPI_PTYPE1_VAR: | ||
| 633 | case ACPI_PTYPE1_OPTION: | ||
| 634 | return; | ||
| 635 | |||
| 636 | case ACPI_PTYPE2: | ||
| 637 | case ACPI_PTYPE2_COUNT: | ||
| 638 | case ACPI_PTYPE2_PKG_COUNT: | ||
| 639 | case ACPI_PTYPE2_FIXED: | ||
| 640 | case ACPI_PTYPE2_MIN: | ||
| 641 | case ACPI_PTYPE2_REV_FIXED: | ||
| 642 | break; | ||
| 643 | |||
| 644 | default: | ||
| 645 | return; | ||
| 646 | } | ||
| 647 | |||
| 648 | count = obj_desc->package.count; | ||
| 649 | new_count = count; | ||
| 650 | |||
| 651 | source = obj_desc->package.elements; | ||
| 652 | dest = source; | ||
| 653 | |||
| 654 | /* Examine all elements of the package object, remove nulls */ | ||
| 655 | |||
| 656 | for (i = 0; i < count; i++) { | ||
| 657 | if (!*source) { | ||
| 658 | new_count--; | ||
| 659 | } else { | ||
| 660 | *dest = *source; | ||
| 661 | dest++; | ||
| 662 | } | ||
| 663 | source++; | ||
| 664 | } | ||
| 665 | |||
| 666 | /* Update parent package if any null elements were removed */ | ||
| 667 | |||
| 668 | if (new_count < count) { | ||
| 669 | ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, | ||
| 670 | "%s: Found and removed %u NULL elements\n", | ||
| 671 | data->pathname, (count - new_count))); | ||
| 672 | |||
| 673 | /* NULL terminate list and update the package count */ | ||
| 674 | |||
| 675 | *dest = NULL; | ||
| 676 | obj_desc->package.count = new_count; | ||
| 677 | } | ||
| 678 | } | ||
| 679 | |||
| 680 | /******************************************************************************* | ||
| 681 | * | ||
| 509 | * FUNCTION: acpi_ns_repair_package_list | 682 | * FUNCTION: acpi_ns_repair_package_list |
| 510 | * | 683 | * |
| 511 | * PARAMETERS: Data - Pointer to validation data structure | 684 | * PARAMETERS: Data - Pointer to validation data structure |
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 29ff5d14e1d5..61bd0f6755d2 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c | |||
| @@ -45,7 +45,6 @@ | |||
| 45 | #include <acpi/acpi.h> | 45 | #include <acpi/acpi.h> |
| 46 | #include "accommon.h" | 46 | #include "accommon.h" |
| 47 | #include "acnamesp.h" | 47 | #include "acnamesp.h" |
| 48 | #include "acpredef.h" | ||
| 49 | 48 | ||
| 50 | #define _COMPONENT ACPI_NAMESPACE | 49 | #define _COMPONENT ACPI_NAMESPACE |
| 51 | ACPI_MODULE_NAME("nsrepair2") | 50 | ACPI_MODULE_NAME("nsrepair2") |
| @@ -520,89 +519,6 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, | |||
| 520 | 519 | ||
| 521 | /****************************************************************************** | 520 | /****************************************************************************** |
| 522 | * | 521 | * |
| 523 | * FUNCTION: acpi_ns_remove_null_elements | ||
| 524 | * | ||
| 525 | * PARAMETERS: Data - Pointer to validation data structure | ||
| 526 | * package_type - An acpi_return_package_types value | ||
| 527 | * obj_desc - A Package object | ||
| 528 | * | ||
| 529 | * RETURN: None. | ||
| 530 | * | ||
| 531 | * DESCRIPTION: Remove all NULL package elements from packages that contain | ||
| 532 | * a variable number of sub-packages. | ||
| 533 | * | ||
| 534 | *****************************************************************************/ | ||
| 535 | |||
| 536 | void | ||
| 537 | acpi_ns_remove_null_elements(struct acpi_predefined_data *data, | ||
| 538 | u8 package_type, | ||
| 539 | union acpi_operand_object *obj_desc) | ||
| 540 | { | ||
| 541 | union acpi_operand_object **source; | ||
| 542 | union acpi_operand_object **dest; | ||
| 543 | u32 count; | ||
| 544 | u32 new_count; | ||
| 545 | u32 i; | ||
| 546 | |||
| 547 | ACPI_FUNCTION_NAME(ns_remove_null_elements); | ||
| 548 | |||
| 549 | /* | ||
| 550 | * PTYPE1 packages contain no subpackages. | ||
| 551 | * PTYPE2 packages contain a variable number of sub-packages. We can | ||
| 552 | * safely remove all NULL elements from the PTYPE2 packages. | ||
| 553 | */ | ||
| 554 | switch (package_type) { | ||
| 555 | case ACPI_PTYPE1_FIXED: | ||
| 556 | case ACPI_PTYPE1_VAR: | ||
| 557 | case ACPI_PTYPE1_OPTION: | ||
| 558 | return; | ||
| 559 | |||
| 560 | case ACPI_PTYPE2: | ||
| 561 | case ACPI_PTYPE2_COUNT: | ||
| 562 | case ACPI_PTYPE2_PKG_COUNT: | ||
| 563 | case ACPI_PTYPE2_FIXED: | ||
| 564 | case ACPI_PTYPE2_MIN: | ||
| 565 | case ACPI_PTYPE2_REV_FIXED: | ||
| 566 | break; | ||
| 567 | |||
| 568 | default: | ||
| 569 | return; | ||
| 570 | } | ||
| 571 | |||
| 572 | count = obj_desc->package.count; | ||
| 573 | new_count = count; | ||
| 574 | |||
| 575 | source = obj_desc->package.elements; | ||
| 576 | dest = source; | ||
| 577 | |||
| 578 | /* Examine all elements of the package object, remove nulls */ | ||
| 579 | |||
| 580 | for (i = 0; i < count; i++) { | ||
| 581 | if (!*source) { | ||
| 582 | new_count--; | ||
| 583 | } else { | ||
| 584 | *dest = *source; | ||
| 585 | dest++; | ||
| 586 | } | ||
| 587 | source++; | ||
| 588 | } | ||
| 589 | |||
| 590 | /* Update parent package if any null elements were removed */ | ||
| 591 | |||
| 592 | if (new_count < count) { | ||
| 593 | ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, | ||
| 594 | "%s: Found and removed %u NULL elements\n", | ||
| 595 | data->pathname, (count - new_count))); | ||
| 596 | |||
| 597 | /* NULL terminate list and update the package count */ | ||
| 598 | |||
| 599 | *dest = NULL; | ||
| 600 | obj_desc->package.count = new_count; | ||
| 601 | } | ||
| 602 | } | ||
| 603 | |||
| 604 | /****************************************************************************** | ||
| 605 | * | ||
| 606 | * FUNCTION: acpi_ns_sort_list | 522 | * FUNCTION: acpi_ns_sort_list |
| 607 | * | 523 | * |
| 608 | * PARAMETERS: Elements - Package object element list | 524 | * PARAMETERS: Elements - Package object element list |
