aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2010-01-20 20:28:32 -0500
committerLen Brown <len.brown@intel.com>2010-01-22 12:30:06 -0500
commit091f4d718620a79698e1c8ca3e9acbf78eb62da3 (patch)
treece971cfdbef02d83cc40911385b74381c1b67331 /drivers/acpi/acpica
parent5f8902acf87aa206ee4b3f633104456d82747ca6 (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.h1
-rw-r--r--drivers/acpi/acpica/acnamesp.h16
-rw-r--r--drivers/acpi/acpica/nspredef.c27
-rw-r--r--drivers/acpi/acpica/nsrepair.c173
-rw-r--r--drivers/acpi/acpica/nsrepair2.c84
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 {
374struct acpi_predefined_data { 374struct 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
286acpi_ns_repair_package_list(struct acpi_predefined_data *data, 286acpi_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
289acpi_status
290acpi_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
295void
296acpi_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
299void
300acpi_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
50ACPI_MODULE_NAME("nsrepair") 51ACPI_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 */
76static acpi_status 83static 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
532acpi_status
533acpi_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
612void
613acpi_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
51ACPI_MODULE_NAME("nsrepair2") 50ACPI_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
536void
537acpi_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