diff options
author | Bob Moore <robert.moore@intel.com> | 2012-03-20 21:51:39 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2012-03-30 01:45:13 -0400 |
commit | 6a99b1c94d053b3420eaa4a4bc8b2883dd90a2f9 (patch) | |
tree | 6352de44a9cf8d6aff4b5b6674c33a96403c434e /drivers/acpi | |
parent | a2ef5c4fd44ce3922435139393b89f2cce47f576 (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')
-rw-r--r-- | drivers/acpi/acpica/aclocal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/acnamesp.h | 5 | ||||
-rw-r--r-- | drivers/acpi/acpica/nspredef.c | 4 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsrepair.c | 159 |
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 | ||
285 | acpi_status | 285 | acpi_status |
286 | acpi_ns_repair_package_list(struct acpi_predefined_data *data, | 286 | acpi_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 | ||
289 | acpi_status | 290 | acpi_status |
290 | acpi_ns_repair_null_element(struct acpi_predefined_data *data, | 291 | acpi_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 | |||
91 | acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, | 90 | acpi_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 | ||
94 | static acpi_status | ||
95 | acpi_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 | |||
468 | static acpi_status | ||
469 | acpi_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 | ||
702 | acpi_status | 658 | acpi_status |
703 | acpi_ns_repair_package_list(struct acpi_predefined_data *data, | 659 | acpi_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 | } |