Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Bob Moore and committed by
Len Brown
091f4d71 5f8902ac

+209 -92
+1
drivers/acpi/acpica/aclocal.h
··· 374 374 struct acpi_predefined_data { 375 375 char *pathname; 376 376 const union acpi_predefined_info *predefined; 377 + union acpi_operand_object *parent_package; 377 378 u32 flags; 378 379 u8 node_flags; 379 380 };
+11 -5
drivers/acpi/acpica/acnamesp.h
··· 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 ··· 306 295 struct acpi_namespace_node *node, 307 296 acpi_status validate_status, 308 297 union acpi_operand_object **return_object_ptr); 309 - 310 - void 311 - acpi_ns_remove_null_elements(struct acpi_predefined_data *data, 312 - u8 package_type, 313 - union acpi_operand_object *obj_desc); 314 298 315 299 /* 316 300 * nssearch - Namespace searching and entry
+24 -3
drivers/acpi/acpica/nspredef.c
··· 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; ··· 711 710 for (i = 0; i < count; i++) { 712 711 sub_package = *elements; 713 712 sub_elements = sub_package->package.elements; 713 + data->parent_package = sub_package; 714 714 715 715 /* Each sub-object must be of type Package */ 716 716 ··· 723 721 724 722 /* Examine the different types of expected sub-packages */ 725 723 724 + data->parent_package = sub_package; 726 725 switch (package->ret_info.type) { 727 726 case ACPI_PTYPE2: 728 727 case ACPI_PTYPE2_PKG_COUNT: ··· 803 800 804 801 /* 805 802 * First element is the (Integer) count of elements, including 806 - * the count field. 803 + * the count field (the ACPI name is num_elements) 807 804 */ 808 805 status = acpi_ns_check_object_type(data, sub_elements, 809 806 ACPI_RTYPE_INTEGER, ··· 824 821 package->ret_info.count1) { 825 822 expected_count = package->ret_info.count1; 826 823 goto package_too_small; 824 + } 825 + if (expected_count == 0) { 826 + /* 827 + * Either the num_entries element was originally zero or it was 828 + * a NULL element and repaired to an Integer of value zero. 829 + * In either case, repair it by setting num_entries to be the 830 + * actual size of the subpackage. 831 + */ 832 + expected_count = sub_package->package.count; 833 + (*sub_elements)->integer.value = expected_count; 827 834 } 828 835 829 836 /* Check the type of each sub-package element */ ··· 958 945 char type_buffer[48]; /* Room for 5 types */ 959 946 960 947 /* 961 - * If we get a NULL return_object here, it is a NULL package element, 962 - * and this is always an error. 948 + * If we get a NULL return_object here, it is a NULL package element. 949 + * Since all extraneous NULL package elements were removed earlier by a 950 + * call to acpi_ns_remove_null_elements, this is an unexpected NULL element. 951 + * We will attempt to repair it. 963 952 */ 964 953 if (!return_object) { 954 + status = acpi_ns_repair_null_element(data, expected_btypes, 955 + package_index, 956 + return_object_ptr); 957 + if (ACPI_SUCCESS(status)) { 958 + return (AE_OK); /* Repair was successful */ 959 + } 965 960 goto type_error_exit; 966 961 } 967 962
+173
drivers/acpi/acpica/nsrepair.c
··· 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 70 * Buffer -> String 72 71 * Buffer -> Package of Integers 73 72 * Package -> Package of one Package 73 + * 74 + * Additional possible repairs: 75 + * 76 + * Optional/unnecessary NULL package elements removed 77 + * Required package elements that are NULL replaced by Integer/String/Buffer 78 + * Incorrect standalone package wrapped with required outer package 74 79 * 75 80 ******************************************************************************/ 76 81 /* Local prototypes */ ··· 509 502 510 503 *return_object = new_object; 511 504 return (AE_OK); 505 + } 506 + 507 + /******************************************************************************* 508 + * 509 + * FUNCTION: acpi_ns_repair_null_element 510 + * 511 + * PARAMETERS: Data - Pointer to validation data structure 512 + * expected_btypes - Object types expected 513 + * package_index - Index of object within parent package (if 514 + * applicable - ACPI_NOT_PACKAGE_ELEMENT 515 + * otherwise) 516 + * return_object_ptr - Pointer to the object returned from the 517 + * evaluation of a method or object 518 + * 519 + * RETURN: Status. AE_OK if repair was successful. 520 + * 521 + * DESCRIPTION: Attempt to repair a NULL element of a returned Package object. 522 + * 523 + ******************************************************************************/ 524 + 525 + acpi_status 526 + acpi_ns_repair_null_element(struct acpi_predefined_data *data, 527 + u32 expected_btypes, 528 + u32 package_index, 529 + union acpi_operand_object **return_object_ptr) 530 + { 531 + union acpi_operand_object *return_object = *return_object_ptr; 532 + union acpi_operand_object *new_object; 533 + 534 + ACPI_FUNCTION_NAME(ns_repair_null_element); 535 + 536 + /* No repair needed if return object is non-NULL */ 537 + 538 + if (return_object) { 539 + return (AE_OK); 540 + } 541 + 542 + /* 543 + * Attempt to repair a NULL element of a Package object. This applies to 544 + * predefined names that return a fixed-length package and each element 545 + * is required. It does not apply to variable-length packages where NULL 546 + * elements are allowed, especially at the end of the package. 547 + */ 548 + if (expected_btypes & ACPI_RTYPE_INTEGER) { 549 + 550 + /* Need an Integer - create a zero-value integer */ 551 + 552 + new_object = acpi_ut_create_integer_object(0); 553 + } else if (expected_btypes & ACPI_RTYPE_STRING) { 554 + 555 + /* Need a String - create a NULL string */ 556 + 557 + new_object = acpi_ut_create_string_object(0); 558 + } else if (expected_btypes & ACPI_RTYPE_BUFFER) { 559 + 560 + /* Need a Buffer - create a zero-length buffer */ 561 + 562 + new_object = acpi_ut_create_buffer_object(0); 563 + } else { 564 + /* Error for all other expected types */ 565 + 566 + return (AE_AML_OPERAND_TYPE); 567 + } 568 + 569 + if (!new_object) { 570 + return (AE_NO_MEMORY); 571 + } 572 + 573 + /* Set the reference count according to the parent Package object */ 574 + 575 + new_object->common.reference_count = 576 + data->parent_package->common.reference_count; 577 + 578 + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 579 + "%s: Converted NULL package element to expected %s at index %u\n", 580 + data->pathname, 581 + acpi_ut_get_object_type_name(new_object), 582 + package_index)); 583 + 584 + *return_object_ptr = new_object; 585 + data->flags |= ACPI_OBJECT_REPAIRED; 586 + return (AE_OK); 587 + } 588 + 589 + /****************************************************************************** 590 + * 591 + * FUNCTION: acpi_ns_remove_null_elements 592 + * 593 + * PARAMETERS: Data - Pointer to validation data structure 594 + * package_type - An acpi_return_package_types value 595 + * obj_desc - A Package object 596 + * 597 + * RETURN: None. 598 + * 599 + * DESCRIPTION: Remove all NULL package elements from packages that contain 600 + * a variable number of sub-packages. For these types of 601 + * packages, NULL elements can be safely removed. 602 + * 603 + *****************************************************************************/ 604 + 605 + void 606 + acpi_ns_remove_null_elements(struct acpi_predefined_data *data, 607 + u8 package_type, 608 + union acpi_operand_object *obj_desc) 609 + { 610 + union acpi_operand_object **source; 611 + union acpi_operand_object **dest; 612 + u32 count; 613 + u32 new_count; 614 + u32 i; 615 + 616 + ACPI_FUNCTION_NAME(ns_remove_null_elements); 617 + 618 + /* 619 + * PTYPE1 packages contain no subpackages. 620 + * PTYPE2 packages contain a variable number of sub-packages. We can 621 + * safely remove all NULL elements from the PTYPE2 packages. 622 + */ 623 + switch (package_type) { 624 + case ACPI_PTYPE1_FIXED: 625 + case ACPI_PTYPE1_VAR: 626 + case ACPI_PTYPE1_OPTION: 627 + return; 628 + 629 + case ACPI_PTYPE2: 630 + case ACPI_PTYPE2_COUNT: 631 + case ACPI_PTYPE2_PKG_COUNT: 632 + case ACPI_PTYPE2_FIXED: 633 + case ACPI_PTYPE2_MIN: 634 + case ACPI_PTYPE2_REV_FIXED: 635 + break; 636 + 637 + default: 638 + return; 639 + } 640 + 641 + count = obj_desc->package.count; 642 + new_count = count; 643 + 644 + source = obj_desc->package.elements; 645 + dest = source; 646 + 647 + /* Examine all elements of the package object, remove nulls */ 648 + 649 + for (i = 0; i < count; i++) { 650 + if (!*source) { 651 + new_count--; 652 + } else { 653 + *dest = *source; 654 + dest++; 655 + } 656 + source++; 657 + } 658 + 659 + /* Update parent package if any null elements were removed */ 660 + 661 + if (new_count < count) { 662 + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 663 + "%s: Found and removed %u NULL elements\n", 664 + data->pathname, (count - new_count))); 665 + 666 + /* NULL terminate list and update the package count */ 667 + 668 + *dest = NULL; 669 + obj_desc->package.count = new_count; 670 + } 512 671 } 513 672 514 673 /*******************************************************************************
-84
drivers/acpi/acpica/nsrepair2.c
··· 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") ··· 515 516 } 516 517 517 518 return (AE_OK); 518 - } 519 - 520 - /****************************************************************************** 521 - * 522 - * FUNCTION: acpi_ns_remove_null_elements 523 - * 524 - * PARAMETERS: Data - Pointer to validation data structure 525 - * package_type - An acpi_return_package_types value 526 - * obj_desc - A Package object 527 - * 528 - * RETURN: None. 529 - * 530 - * DESCRIPTION: Remove all NULL package elements from packages that contain 531 - * a variable number of sub-packages. 532 - * 533 - *****************************************************************************/ 534 - 535 - void 536 - acpi_ns_remove_null_elements(struct acpi_predefined_data *data, 537 - u8 package_type, 538 - union acpi_operand_object *obj_desc) 539 - { 540 - union acpi_operand_object **source; 541 - union acpi_operand_object **dest; 542 - u32 count; 543 - u32 new_count; 544 - u32 i; 545 - 546 - ACPI_FUNCTION_NAME(ns_remove_null_elements); 547 - 548 - /* 549 - * PTYPE1 packages contain no subpackages. 550 - * PTYPE2 packages contain a variable number of sub-packages. We can 551 - * safely remove all NULL elements from the PTYPE2 packages. 552 - */ 553 - switch (package_type) { 554 - case ACPI_PTYPE1_FIXED: 555 - case ACPI_PTYPE1_VAR: 556 - case ACPI_PTYPE1_OPTION: 557 - return; 558 - 559 - case ACPI_PTYPE2: 560 - case ACPI_PTYPE2_COUNT: 561 - case ACPI_PTYPE2_PKG_COUNT: 562 - case ACPI_PTYPE2_FIXED: 563 - case ACPI_PTYPE2_MIN: 564 - case ACPI_PTYPE2_REV_FIXED: 565 - break; 566 - 567 - default: 568 - return; 569 - } 570 - 571 - count = obj_desc->package.count; 572 - new_count = count; 573 - 574 - source = obj_desc->package.elements; 575 - dest = source; 576 - 577 - /* Examine all elements of the package object, remove nulls */ 578 - 579 - for (i = 0; i < count; i++) { 580 - if (!*source) { 581 - new_count--; 582 - } else { 583 - *dest = *source; 584 - dest++; 585 - } 586 - source++; 587 - } 588 - 589 - /* Update parent package if any null elements were removed */ 590 - 591 - if (new_count < count) { 592 - ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 593 - "%s: Found and removed %u NULL elements\n", 594 - data->pathname, (count - new_count))); 595 - 596 - /* NULL terminate list and update the package count */ 597 - 598 - *dest = NULL; 599 - obj_desc->package.count = new_count; 600 - } 601 519 } 602 520 603 521 /******************************************************************************