aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2009-12-11 02:29:44 -0500
committerLen Brown <len.brown@intel.com>2009-12-15 17:29:37 -0500
commitd4085a3ffee8828f7f1bae7fa3cf5e58f59ba627 (patch)
tree4c2397ce902284b20c21c3b96d393707311c46d4 /drivers/acpi/acpica
parente31c32cfe52e98344dad28853c3331879f72c4b0 (diff)
ACPICA: Predefined name repair: automatically remove null package elements
This change will automatically remove embedded and trailing NULL package elements from returned package objects that are defined to containe a variable number of sub-packages. The driver is then presented with a package with no null elements to deal with. ACPICA BZ 819. http://www.acpica.org/bugzilla/show_bug.cgi?id=819 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/acnamesp.h5
-rw-r--r--drivers/acpi/acpica/nspredef.c59
-rw-r--r--drivers/acpi/acpica/nsrepair2.c79
3 files changed, 65 insertions, 78 deletions
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index 14cef45bd6c4..61edb156e8d0 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -296,6 +296,11 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
296 acpi_status validate_status, 296 acpi_status validate_status,
297 union acpi_operand_object **return_object_ptr); 297 union acpi_operand_object **return_object_ptr);
298 298
299void
300acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
301 u8 package_type,
302 union acpi_operand_object *obj_desc);
303
299/* 304/*
300 * nssearch - Namespace searching and entry 305 * nssearch - Namespace searching and entry
301 */ 306 */
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index 239fa2f731ca..d34fa59548f7 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -231,9 +231,6 @@ 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
235 /* TBD: For variable-length Packages, remove NULL elements here */
236
237 status = acpi_ns_check_package(data, return_object_ptr); 234 status = acpi_ns_check_package(data, return_object_ptr);
238 if (ACPI_FAILURE(status)) { 235 if (ACPI_FAILURE(status)) {
239 goto exit; 236 goto exit;
@@ -439,6 +436,13 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
439 data->pathname, package->ret_info.type, 436 data->pathname, package->ret_info.type,
440 return_object->package.count)); 437 return_object->package.count));
441 438
439 /*
440 * For variable-length Packages, we can safely remove all embedded
441 * and trailing NULL package elements
442 */
443 acpi_ns_remove_null_elements(data, package->ret_info.type,
444 return_object);
445
442 /* Extract package count and elements array */ 446 /* Extract package count and elements array */
443 447
444 elements = return_object->package.elements; 448 elements = return_object->package.elements;
@@ -692,53 +696,18 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
692 union acpi_operand_object *sub_package; 696 union acpi_operand_object *sub_package;
693 union acpi_operand_object **sub_elements; 697 union acpi_operand_object **sub_elements;
694 acpi_status status; 698 acpi_status status;
695 u8 non_trailing_null = FALSE;
696 u32 expected_count; 699 u32 expected_count;
697 u32 i; 700 u32 i;
698 u32 j; 701 u32 j;
699 702
700 /* Validate each sub-Package in the parent Package */ 703 /*
701 704 * Validate each sub-Package in the parent Package
705 *
706 * NOTE: assumes list of sub-packages contains no NULL elements.
707 * Any NULL elements should have been removed by earlier call
708 * to acpi_ns_remove_null_elements.
709 */
702 for (i = 0; i < count; i++) { 710 for (i = 0; i < count; i++) {
703 /*
704 * Handling for NULL package elements. For now, we will simply allow
705 * a parent package with trailing NULL elements. This can happen if
706 * the package was defined to be longer than the initializer list.
707 * This is legal as per the ACPI specification. It is often used
708 * to allow for dynamic initialization of a Package.
709 *
710 * A future enhancement may be to simply truncate the package to
711 * remove the trailing NULL elements.
712 */
713 if (!(*elements)) {
714 if (!non_trailing_null) {
715
716 /* Ensure the remaining elements are all NULL */
717
718 for (j = 1; j < (count - i + 1); j++) {
719 if (elements[j]) {
720 non_trailing_null = TRUE;
721 }
722 }
723
724 if (!non_trailing_null) {
725
726 /* Ignore the trailing NULL elements */
727
728 return (AE_OK);
729 }
730 }
731
732 /* There are trailing non-null elements, issue warning */
733
734 ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
735 data->node_flags,
736 "Found NULL element at package index %u",
737 i));
738 elements++;
739 continue;
740 }
741
742 sub_package = *elements; 711 sub_package = *elements;
743 sub_elements = sub_package->package.elements; 712 sub_elements = sub_package->package.elements;
744 713
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c
index e7373eb6cfa5..f13691c1cca5 100644
--- a/drivers/acpi/acpica/nsrepair2.c
+++ b/drivers/acpi/acpica/nsrepair2.c
@@ -45,6 +45,7 @@
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"
48 49
49#define _COMPONENT ACPI_NAMESPACE 50#define _COMPONENT ACPI_NAMESPACE
50ACPI_MODULE_NAME("nsrepair2") 51ACPI_MODULE_NAME("nsrepair2")
@@ -93,9 +94,6 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
93 u8 sort_direction, char *sort_key_name); 94 u8 sort_direction, char *sort_key_name);
94 95
95static acpi_status 96static acpi_status
96acpi_ns_remove_null_elements(union acpi_operand_object *package);
97
98static acpi_status
99acpi_ns_sort_list(union acpi_operand_object **elements, 97acpi_ns_sort_list(union acpi_operand_object **elements,
100 u32 count, u32 index, u8 sort_direction); 98 u32 count, u32 index, u8 sort_direction);
101 99
@@ -456,25 +454,10 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
456 } 454 }
457 455
458 /* 456 /*
459 * Detect any NULL package elements and remove them from the 457 * NOTE: assumes list of sub-packages contains no NULL elements.
460 * package. 458 * Any NULL elements should have been removed by earlier call
461 * 459 * to acpi_ns_remove_null_elements.
462 * TBD: We may want to do this for all predefined names that
463 * return a variable-length package of packages.
464 */ 460 */
465 status = acpi_ns_remove_null_elements(return_object);
466 if (status == AE_NULL_ENTRY) {
467 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
468 "%s: NULL elements removed from package\n",
469 data->pathname));
470
471 /* Exit if package is now zero length */
472
473 if (!return_object->package.count) {
474 return (AE_NULL_ENTRY);
475 }
476 }
477
478 outer_elements = return_object->package.elements; 461 outer_elements = return_object->package.elements;
479 outer_element_count = return_object->package.count; 462 outer_element_count = return_object->package.count;
480 if (!outer_element_count) { 463 if (!outer_element_count) {
@@ -544,36 +527,63 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
544 * 527 *
545 * FUNCTION: acpi_ns_remove_null_elements 528 * FUNCTION: acpi_ns_remove_null_elements
546 * 529 *
547 * PARAMETERS: obj_desc - A Package object 530 * PARAMETERS: Data - Pointer to validation data structure
531 * package_type - An acpi_return_package_types value
532 * obj_desc - A Package object
548 * 533 *
549 * RETURN: Status. AE_NULL_ENTRY means that one or more elements were 534 * RETURN: None.
550 * removed.
551 * 535 *
552 * DESCRIPTION: Remove all NULL package elements and update the package count. 536 * DESCRIPTION: Remove all NULL package elements from packages that contain
537 * a variable number of sub-packages.
553 * 538 *
554 *****************************************************************************/ 539 *****************************************************************************/
555 540
556static acpi_status 541void
557acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc) 542acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
543 u8 package_type,
544 union acpi_operand_object *obj_desc)
558{ 545{
559 union acpi_operand_object **source; 546 union acpi_operand_object **source;
560 union acpi_operand_object **dest; 547 union acpi_operand_object **dest;
561 acpi_status status = AE_OK;
562 u32 count; 548 u32 count;
563 u32 new_count; 549 u32 new_count;
564 u32 i; 550 u32 i;
565 551
552 ACPI_FUNCTION_NAME(ns_remove_null_elements);
553
554 /*
555 * PTYPE1 packages contain no subpackages.
556 * PTYPE2 packages contain a variable number of sub-packages. We can
557 * safely remove all NULL elements from the PTYPE2 packages.
558 */
559 switch (package_type) {
560 case ACPI_PTYPE1_FIXED:
561 case ACPI_PTYPE1_VAR:
562 case ACPI_PTYPE1_OPTION:
563 return;
564
565 case ACPI_PTYPE2:
566 case ACPI_PTYPE2_COUNT:
567 case ACPI_PTYPE2_PKG_COUNT:
568 case ACPI_PTYPE2_FIXED:
569 case ACPI_PTYPE2_MIN:
570 case ACPI_PTYPE2_REV_FIXED:
571 break;
572
573 default:
574 return;
575 }
576
566 count = obj_desc->package.count; 577 count = obj_desc->package.count;
567 new_count = count; 578 new_count = count;
568 579
569 source = obj_desc->package.elements; 580 source = obj_desc->package.elements;
570 dest = source; 581 dest = source;
571 582
572 /* Examine all elements of the package object */ 583 /* Examine all elements of the package object, remove nulls */
573 584
574 for (i = 0; i < count; i++) { 585 for (i = 0; i < count; i++) {
575 if (!*source) { 586 if (!*source) {
576 status = AE_NULL_ENTRY;
577 new_count--; 587 new_count--;
578 } else { 588 } else {
579 *dest = *source; 589 *dest = *source;
@@ -582,15 +592,18 @@ acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc)
582 source++; 592 source++;
583 } 593 }
584 594
585 if (status == AE_NULL_ENTRY) { 595 /* Update parent package if any null elements were removed */
596
597 if (new_count < count) {
598 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
599 "%s: Found and removed %u NULL elements\n",
600 data->pathname, (count - new_count)));
586 601
587 /* NULL terminate list and update the package count */ 602 /* NULL terminate list and update the package count */
588 603
589 *dest = NULL; 604 *dest = NULL;
590 obj_desc->package.count = new_count; 605 obj_desc->package.count = new_count;
591 } 606 }
592
593 return (status);
594} 607}
595 608
596/****************************************************************************** 609/******************************************************************************