diff options
author | Bob Moore <robert.moore@intel.com> | 2010-01-20 20:28:32 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-01-22 12:30:06 -0500 |
commit | 091f4d718620a79698e1c8ca3e9acbf78eb62da3 (patch) | |
tree | ce971cfdbef02d83cc40911385b74381c1b67331 /drivers/acpi/acpica | |
parent | 5f8902acf87aa206ee4b3f633104456d82747ca6 (diff) |
ACPICA: Predefined name repair: fix NULL package elements
For the predefined methods that return fixed-length packages
(or subpackages), attempt repair for a NULL element. Create an
Integer of value 0, a NULL String, or a zero-length buffer as
appropriate.
http://www.acpica.org/bugzilla/show_bug.cgi?id=818
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica')
-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 |