Commit 091f4d718620a79698e1c8ca3e9acbf78eb62da3
Committed by
Len Brown
1 parent
5f8902acf8
Exists in
master
and in
7 other branches
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>
Showing 5 changed files with 209 additions and 92 deletions Side-by-side Diff
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acnamesp.h
... | ... | @@ -286,6 +286,17 @@ |
286 | 286 | acpi_ns_repair_package_list(struct acpi_predefined_data *data, |
287 | 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 | 301 | * nsrepair2 - Return object repair for specific |
291 | 302 | * predefined methods/objects |
... | ... | @@ -295,11 +306,6 @@ |
295 | 306 | struct acpi_namespace_node *node, |
296 | 307 | acpi_status validate_status, |
297 | 308 | union acpi_operand_object **return_object_ptr); |
298 | - | |
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 | 309 | |
304 | 310 | /* |
305 | 311 | * nssearch - Namespace searching and entry |
drivers/acpi/acpica/nspredef.c
... | ... | @@ -231,6 +231,7 @@ |
231 | 231 | * Note: Package may have been newly created by call above. |
232 | 232 | */ |
233 | 233 | if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { |
234 | + data->parent_package = *return_object_ptr; | |
234 | 235 | status = acpi_ns_check_package(data, return_object_ptr); |
235 | 236 | if (ACPI_FAILURE(status)) { |
236 | 237 | goto exit; |
... | ... | @@ -710,6 +711,7 @@ |
710 | 711 | for (i = 0; i < count; i++) { |
711 | 712 | sub_package = *elements; |
712 | 713 | sub_elements = sub_package->package.elements; |
714 | + data->parent_package = sub_package; | |
713 | 715 | |
714 | 716 | /* Each sub-object must be of type Package */ |
715 | 717 | |
... | ... | @@ -721,6 +723,7 @@ |
721 | 723 | |
722 | 724 | /* Examine the different types of expected sub-packages */ |
723 | 725 | |
726 | + data->parent_package = sub_package; | |
724 | 727 | switch (package->ret_info.type) { |
725 | 728 | case ACPI_PTYPE2: |
726 | 729 | case ACPI_PTYPE2_PKG_COUNT: |
... | ... | @@ -800,7 +803,7 @@ |
800 | 803 | |
801 | 804 | /* |
802 | 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 | 808 | status = acpi_ns_check_object_type(data, sub_elements, |
806 | 809 | ACPI_RTYPE_INTEGER, |
... | ... | @@ -822,6 +825,16 @@ |
822 | 825 | expected_count = package->ret_info.count1; |
823 | 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 | 839 | /* Check the type of each sub-package element */ |
827 | 840 | |
828 | 841 | |
... | ... | @@ -945,10 +958,18 @@ |
945 | 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, | |
949 | - * and this is always an error. | |
961 | + * If we get a NULL return_object here, it is a NULL package element. | |
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 | 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 | 973 | goto type_error_exit; |
953 | 974 | } |
954 | 975 |
drivers/acpi/acpica/nsrepair.c
... | ... | @@ -45,6 +45,7 @@ |
45 | 45 | #include "accommon.h" |
46 | 46 | #include "acnamesp.h" |
47 | 47 | #include "acinterp.h" |
48 | +#include "acpredef.h" | |
48 | 49 | |
49 | 50 | #define _COMPONENT ACPI_NAMESPACE |
50 | 51 | ACPI_MODULE_NAME("nsrepair") |
... | ... | @@ -71,6 +72,12 @@ |
71 | 72 | * Buffer -> Package of Integers |
72 | 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 | 82 | /* Local prototypes */ |
76 | 83 | static acpi_status |
... | ... | @@ -502,6 +509,172 @@ |
502 | 509 | |
503 | 510 | *return_object = new_object; |
504 | 511 | return (AE_OK); |
512 | +} | |
513 | + | |
514 | +/******************************************************************************* | |
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 | + } | |
505 | 678 | } |
506 | 679 | |
507 | 680 | /******************************************************************************* |
drivers/acpi/acpica/nsrepair2.c
... | ... | @@ -45,7 +45,6 @@ |
45 | 45 | #include <acpi/acpi.h> |
46 | 46 | #include "accommon.h" |
47 | 47 | #include "acnamesp.h" |
48 | -#include "acpredef.h" | |
49 | 48 | |
50 | 49 | #define _COMPONENT ACPI_NAMESPACE |
51 | 50 | ACPI_MODULE_NAME("nsrepair2") |
... | ... | @@ -516,89 +515,6 @@ |
516 | 515 | } |
517 | 516 | |
518 | 517 | return (AE_OK); |
519 | -} | |
520 | - | |
521 | -/****************************************************************************** | |
522 | - * | |
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 | 518 | } |
603 | 519 | |
604 | 520 | /****************************************************************************** |