aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2012-03-20 21:51:39 -0400
committerLen Brown <len.brown@intel.com>2012-03-30 01:45:13 -0400
commit6a99b1c94d053b3420eaa4a4bc8b2883dd90a2f9 (patch)
tree6352de44a9cf8d6aff4b5b6674c33a96403c434e /drivers/acpi/acpica
parenta2ef5c4fd44ce3922435139393b89f2cce47f576 (diff)
ACPICA: Object repair code: Support to add Package wrappers
Repair a common problem with objects that are defined to return a variable-length Package of sub-objects. If there is only one sub-object, some BIOS code mistakenly simply declares the single object instead of a Package with one sub-object. This function attempts to repair this error by wrapping a Package object around the original object, creating the correct and expected Package with one sub-object. 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.h5
-rw-r--r--drivers/acpi/acpica/nspredef.c4
-rw-r--r--drivers/acpi/acpica/nsrepair.c159
4 files changed, 64 insertions, 105 deletions
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 3f24068837d5..e3922ca20e7f 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -370,6 +370,7 @@ struct acpi_predefined_data {
370/* Defines for Flags field above */ 370/* Defines for Flags field above */
371 371
372#define ACPI_OBJECT_REPAIRED 1 372#define ACPI_OBJECT_REPAIRED 1
373#define ACPI_OBJECT_WRAPPED 2
373 374
374/* 375/*
375 * Bitmapped return value types 376 * Bitmapped return value types
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index 2c9e0f049523..9b19d4b86424 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -283,8 +283,9 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
283 union acpi_operand_object **return_object_ptr); 283 union acpi_operand_object **return_object_ptr);
284 284
285acpi_status 285acpi_status
286acpi_ns_repair_package_list(struct acpi_predefined_data *data, 286acpi_ns_wrap_with_package(struct acpi_predefined_data *data,
287 union acpi_operand_object **obj_desc_ptr); 287 union acpi_operand_object *original_object,
288 union acpi_operand_object **obj_desc_ptr);
288 289
289acpi_status 290acpi_status
290acpi_ns_repair_null_element(struct acpi_predefined_data *data, 291acpi_ns_repair_null_element(struct acpi_predefined_data *data,
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index bbe46a447d34..23ce09686418 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -638,8 +638,8 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
638 /* Create the new outer package and populate it */ 638 /* Create the new outer package and populate it */
639 639
640 status = 640 status =
641 acpi_ns_repair_package_list(data, 641 acpi_ns_wrap_with_package(data, *elements,
642 return_object_ptr); 642 return_object_ptr);
643 if (ACPI_FAILURE(status)) { 643 if (ACPI_FAILURE(status)) {
644 return (status); 644 return (status);
645 } 645 }
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c
index 9c35d20eb52b..5519a64a353f 100644
--- a/drivers/acpi/acpica/nsrepair.c
+++ b/drivers/acpi/acpica/nsrepair.c
@@ -71,11 +71,10 @@ ACPI_MODULE_NAME("nsrepair")
71 * Buffer -> String 71 * Buffer -> String
72 * Buffer -> Package of Integers 72 * Buffer -> Package of Integers
73 * Package -> Package of one Package 73 * Package -> Package of one Package
74 * An incorrect standalone object is wrapped with required outer package
74 * 75 *
75 * Additional possible repairs: 76 * Additional possible repairs:
76 *
77 * Required package elements that are NULL replaced by Integer/String/Buffer 77 * Required package elements that are NULL replaced by Integer/String/Buffer
78 * Incorrect standalone package wrapped with required outer package
79 * 78 *
80 ******************************************************************************/ 79 ******************************************************************************/
81/* Local prototypes */ 80/* Local prototypes */
@@ -91,10 +90,6 @@ static acpi_status
91acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, 90acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
92 union acpi_operand_object **return_object); 91 union acpi_operand_object **return_object);
93 92
94static acpi_status
95acpi_ns_convert_to_package(union acpi_operand_object *original_object,
96 union acpi_operand_object **return_object);
97
98/******************************************************************************* 93/*******************************************************************************
99 * 94 *
100 * FUNCTION: acpi_ns_repair_object 95 * FUNCTION: acpi_ns_repair_object
@@ -151,9 +146,24 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
151 } 146 }
152 } 147 }
153 if (expected_btypes & ACPI_RTYPE_PACKAGE) { 148 if (expected_btypes & ACPI_RTYPE_PACKAGE) {
154 status = acpi_ns_convert_to_package(return_object, &new_object); 149 /*
150 * A package is expected. We will wrap the existing object with a
151 * new package object. It is often the case that if a variable-length
152 * package is required, but there is only a single object needed, the
153 * BIOS will return that object instead of wrapping it with a Package
154 * object. Note: after the wrapping, the package will be validated
155 * for correct contents (expected object type or types).
156 */
157 status =
158 acpi_ns_wrap_with_package(data, return_object, &new_object);
155 if (ACPI_SUCCESS(status)) { 159 if (ACPI_SUCCESS(status)) {
156 goto object_repaired; 160 /*
161 * The original object just had its reference count
162 * incremented for being inserted into the new package.
163 */
164 *return_object_ptr = new_object; /* New Package object */
165 data->flags |= ACPI_OBJECT_REPAIRED;
166 return (AE_OK);
157 } 167 }
158 } 168 }
159 169
@@ -165,22 +175,27 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
165 175
166 /* Object was successfully repaired */ 176 /* Object was successfully repaired */
167 177
168 /*
169 * If the original object is a package element, we need to:
170 * 1. Set the reference count of the new object to match the
171 * reference count of the old object.
172 * 2. Decrement the reference count of the original object.
173 */
174 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 178 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
175 new_object->common.reference_count = 179 /*
176 return_object->common.reference_count; 180 * The original object is a package element. We need to
181 * decrement the reference count of the original object,
182 * for removing it from the package.
183 *
184 * However, if the original object was just wrapped with a
185 * package object as part of the repair, we don't need to
186 * change the reference count.
187 */
188 if (!(data->flags & ACPI_OBJECT_WRAPPED)) {
189 new_object->common.reference_count =
190 return_object->common.reference_count;
177 191
178 if (return_object->common.reference_count > 1) { 192 if (return_object->common.reference_count > 1) {
179 return_object->common.reference_count--; 193 return_object->common.reference_count--;
194 }
180 } 195 }
181 196
182 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 197 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
183 "%s: Converted %s to expected %s at index %u\n", 198 "%s: Converted %s to expected %s at Package index %u\n",
184 data->pathname, 199 data->pathname,
185 acpi_ut_get_object_type_name(return_object), 200 acpi_ut_get_object_type_name(return_object),
186 acpi_ut_get_object_type_name(new_object), 201 acpi_ut_get_object_type_name(new_object),
@@ -453,65 +468,6 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
453 468
454/******************************************************************************* 469/*******************************************************************************
455 * 470 *
456 * FUNCTION: acpi_ns_convert_to_package
457 *
458 * PARAMETERS: original_object - Object to be converted
459 * return_object - Where the new converted object is returned
460 *
461 * RETURN: Status. AE_OK if conversion was successful.
462 *
463 * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of
464 * the buffer is converted to a single integer package element.
465 *
466 ******************************************************************************/
467
468static acpi_status
469acpi_ns_convert_to_package(union acpi_operand_object *original_object,
470 union acpi_operand_object **return_object)
471{
472 union acpi_operand_object *new_object;
473 union acpi_operand_object **elements;
474 u32 length;
475 u8 *buffer;
476
477 switch (original_object->common.type) {
478 case ACPI_TYPE_BUFFER:
479
480 /* Buffer-to-Package conversion */
481
482 length = original_object->buffer.length;
483 new_object = acpi_ut_create_package_object(length);
484 if (!new_object) {
485 return (AE_NO_MEMORY);
486 }
487
488 /* Convert each buffer byte to an integer package element */
489
490 elements = new_object->package.elements;
491 buffer = original_object->buffer.pointer;
492
493 while (length--) {
494 *elements =
495 acpi_ut_create_integer_object((u64) *buffer);
496 if (!*elements) {
497 acpi_ut_remove_reference(new_object);
498 return (AE_NO_MEMORY);
499 }
500 elements++;
501 buffer++;
502 }
503 break;
504
505 default:
506 return (AE_AML_OPERAND_TYPE);
507 }
508
509 *return_object = new_object;
510 return (AE_OK);
511}
512
513/*******************************************************************************
514 *
515 * FUNCTION: acpi_ns_repair_null_element 471 * FUNCTION: acpi_ns_repair_null_element
516 * 472 *
517 * PARAMETERS: Data - Pointer to validation data structure 473 * PARAMETERS: Data - Pointer to validation data structure
@@ -677,55 +633,56 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
677 633
678/******************************************************************************* 634/*******************************************************************************
679 * 635 *
680 * FUNCTION: acpi_ns_repair_package_list 636 * FUNCTION: acpi_ns_wrap_with_package
681 * 637 *
682 * PARAMETERS: Data - Pointer to validation data structure 638 * PARAMETERS: Data - Pointer to validation data structure
683 * obj_desc_ptr - Pointer to the object to repair. The new 639 * original_object - Pointer to the object to repair.
684 * package object is returned here, 640 * obj_desc_ptr - The new package object is returned here
685 * overwriting the old object.
686 * 641 *
687 * RETURN: Status, new object in *obj_desc_ptr 642 * RETURN: Status, new object in *obj_desc_ptr
688 * 643 *
689 * DESCRIPTION: Repair a common problem with objects that are defined to return 644 * DESCRIPTION: Repair a common problem with objects that are defined to
690 * a variable-length Package of Packages. If the variable-length 645 * return a variable-length Package of sub-objects. If there is
691 * is one, some BIOS code mistakenly simply declares a single 646 * only one sub-object, some BIOS code mistakenly simply declares
692 * Package instead of a Package with one sub-Package. This 647 * the single object instead of a Package with one sub-object.
693 * function attempts to repair this error by wrapping a Package 648 * This function attempts to repair this error by wrapping a
694 * object around the original Package, creating the correct 649 * Package object around the original object, creating the
695 * Package with one sub-Package. 650 * correct and expected Package with one sub-object.
696 * 651 *
697 * Names that can be repaired in this manner include: 652 * Names that can be repaired in this manner include:
698 * _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS 653 * _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS,
654 * _BCL, _DOD, _FIX, _Sx
699 * 655 *
700 ******************************************************************************/ 656 ******************************************************************************/
701 657
702acpi_status 658acpi_status
703acpi_ns_repair_package_list(struct acpi_predefined_data *data, 659acpi_ns_wrap_with_package(struct acpi_predefined_data *data,
704 union acpi_operand_object **obj_desc_ptr) 660 union acpi_operand_object *original_object,
661 union acpi_operand_object **obj_desc_ptr)
705{ 662{
706 union acpi_operand_object *pkg_obj_desc; 663 union acpi_operand_object *pkg_obj_desc;
707 664
708 ACPI_FUNCTION_NAME(ns_repair_package_list); 665 ACPI_FUNCTION_NAME(ns_wrap_with_package);
709 666
710 /* 667 /*
711 * Create the new outer package and populate it. The new package will 668 * Create the new outer package and populate it. The new package will
712 * have a single element, the lone subpackage. 669 * have a single element, the lone sub-object.
713 */ 670 */
714 pkg_obj_desc = acpi_ut_create_package_object(1); 671 pkg_obj_desc = acpi_ut_create_package_object(1);
715 if (!pkg_obj_desc) { 672 if (!pkg_obj_desc) {
716 return (AE_NO_MEMORY); 673 return (AE_NO_MEMORY);
717 } 674 }
718 675
719 pkg_obj_desc->package.elements[0] = *obj_desc_ptr; 676 pkg_obj_desc->package.elements[0] = original_object;
677
678 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
679 "%s: Wrapped %s with expected Package object\n",
680 data->pathname,
681 acpi_ut_get_object_type_name(original_object)));
720 682
721 /* Return the new object in the object pointer */ 683 /* Return the new object in the object pointer */
722 684
723 *obj_desc_ptr = pkg_obj_desc; 685 *obj_desc_ptr = pkg_obj_desc;
724 data->flags |= ACPI_OBJECT_REPAIRED; 686 data->flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED;
725
726 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
727 "%s: Repaired incorrectly formed Package\n",
728 data->pathname));
729
730 return (AE_OK); 687 return (AE_OK);
731} 688}