aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2008-11-13 19:44:39 -0500
committerLen Brown <len.brown@intel.com>2008-12-29 22:38:38 -0500
commita647b5c34047560d7efe7e53e756c6692ce67dc7 (patch)
treef5fc81828932810ddaf19cd1f43732af48215433
parentd037c5fd7367548191eab2b376a1d08c4ffaf7ff (diff)
ACPICA: Add Buffer->String conversion for predefined methods
For predefined methods (such as _BIF), add automatic conversion for objects that are required to be a String, but a Buffer was found instead. This can happen when reading string battery data from an operation region, because it used to be difficult to convert the data from buffer to string from within the ASL. Linux BZ 11822. http://bugzilla.kernel.org/show_bug.cgi?id=11822 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>
-rw-r--r--drivers/acpi/namespace/nseval.c3
-rw-r--r--drivers/acpi/namespace/nspredef.c150
-rw-r--r--include/acpi/acnamesp.h2
3 files changed, 125 insertions, 30 deletions
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index 4cdf03ac2b46..738a4517b7c1 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -282,8 +282,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
282 * the method on invalid return object. 282 * the method on invalid return object.
283 */ 283 */
284 (void)acpi_ns_check_predefined_names(node, 284 (void)acpi_ns_check_predefined_names(node,
285 info-> 285 &info->return_object);
286 return_object);
287 } 286 }
288 287
289 /* Mark the node as having been evaluated */ 288 /* Mark the node as having been evaluated */
diff --git a/drivers/acpi/namespace/nspredef.c b/drivers/acpi/namespace/nspredef.c
index 0f17cf0898c9..3df17522117f 100644
--- a/drivers/acpi/namespace/nspredef.c
+++ b/drivers/acpi/namespace/nspredef.c
@@ -72,7 +72,7 @@ ACPI_MODULE_NAME("nspredef")
72/* Local prototypes */ 72/* Local prototypes */
73static acpi_status 73static acpi_status
74acpi_ns_check_package(char *pathname, 74acpi_ns_check_package(char *pathname,
75 union acpi_operand_object *return_object, 75 union acpi_operand_object **return_object_ptr,
76 const union acpi_predefined_info *predefined); 76 const union acpi_predefined_info *predefined);
77 77
78static acpi_status 78static acpi_status
@@ -82,13 +82,18 @@ acpi_ns_check_package_elements(char *pathname,
82 82
83static acpi_status 83static acpi_status
84acpi_ns_check_object_type(char *pathname, 84acpi_ns_check_object_type(char *pathname,
85 union acpi_operand_object *return_object, 85 union acpi_operand_object **return_object_ptr,
86 u32 expected_btypes, u32 package_index); 86 u32 expected_btypes, u32 package_index);
87 87
88static acpi_status 88static acpi_status
89acpi_ns_check_reference(char *pathname, 89acpi_ns_check_reference(char *pathname,
90 union acpi_operand_object *return_object); 90 union acpi_operand_object *return_object);
91 91
92static acpi_status
93acpi_ns_repair_object(u32 expected_btypes,
94 u32 package_index,
95 union acpi_operand_object **return_object_ptr);
96
92/* 97/*
93 * Names for the types that can be returned by the predefined objects. 98 * Names for the types that can be returned by the predefined objects.
94 * Used for warning messages. Must be in the same order as the ACPI_RTYPEs 99 * Used for warning messages. Must be in the same order as the ACPI_RTYPEs
@@ -108,8 +113,8 @@ static const char *acpi_rtype_names[] = {
108 * FUNCTION: acpi_ns_check_predefined_names 113 * FUNCTION: acpi_ns_check_predefined_names
109 * 114 *
110 * PARAMETERS: Node - Namespace node for the method/object 115 * PARAMETERS: Node - Namespace node for the method/object
111 * return_object - Object returned from the evaluation of this 116 * return_object_ptr - Pointer to the object returned from the
112 * method/object 117 * evaluation of a method or object
113 * 118 *
114 * RETURN: Status 119 * RETURN: Status
115 * 120 *
@@ -119,8 +124,9 @@ static const char *acpi_rtype_names[] = {
119 124
120acpi_status 125acpi_status
121acpi_ns_check_predefined_names(struct acpi_namespace_node *node, 126acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
122 union acpi_operand_object *return_object) 127 union acpi_operand_object **return_object_ptr)
123{ 128{
129 union acpi_operand_object *return_object = *return_object_ptr;
124 acpi_status status = AE_OK; 130 acpi_status status = AE_OK;
125 const union acpi_predefined_info *predefined; 131 const union acpi_predefined_info *predefined;
126 char *pathname; 132 char *pathname;
@@ -182,7 +188,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
182 * Check that the type of the return object is what is expected for 188 * Check that the type of the return object is what is expected for
183 * this predefined name 189 * this predefined name
184 */ 190 */
185 status = acpi_ns_check_object_type(pathname, return_object, 191 status = acpi_ns_check_object_type(pathname, return_object_ptr,
186 predefined->info.expected_btypes, 192 predefined->info.expected_btypes,
187 ACPI_NOT_PACKAGE); 193 ACPI_NOT_PACKAGE);
188 if (ACPI_FAILURE(status)) { 194 if (ACPI_FAILURE(status)) {
@@ -193,7 +199,8 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
193 199
194 if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) { 200 if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) {
195 status = 201 status =
196 acpi_ns_check_package(pathname, return_object, predefined); 202 acpi_ns_check_package(pathname, return_object_ptr,
203 predefined);
197 } 204 }
198 205
199 exit: 206 exit:
@@ -307,8 +314,8 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
307 * FUNCTION: acpi_ns_check_package 314 * FUNCTION: acpi_ns_check_package
308 * 315 *
309 * PARAMETERS: Pathname - Full pathname to the node (for error msgs) 316 * PARAMETERS: Pathname - Full pathname to the node (for error msgs)
310 * return_object - Object returned from the evaluation of a 317 * return_object_ptr - Pointer to the object returned from the
311 * method or object 318 * evaluation of a method or object
312 * Predefined - Pointer to entry in predefined name table 319 * Predefined - Pointer to entry in predefined name table
313 * 320 *
314 * RETURN: Status 321 * RETURN: Status
@@ -320,9 +327,10 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
320 327
321static acpi_status 328static acpi_status
322acpi_ns_check_package(char *pathname, 329acpi_ns_check_package(char *pathname,
323 union acpi_operand_object *return_object, 330 union acpi_operand_object **return_object_ptr,
324 const union acpi_predefined_info *predefined) 331 const union acpi_predefined_info *predefined)
325{ 332{
333 union acpi_operand_object *return_object = *return_object_ptr;
326 const union acpi_predefined_info *package; 334 const union acpi_predefined_info *package;
327 union acpi_operand_object *sub_package; 335 union acpi_operand_object *sub_package;
328 union acpi_operand_object **elements; 336 union acpi_operand_object **elements;
@@ -408,7 +416,7 @@ acpi_ns_check_package(char *pathname,
408 * elements must be of the same type 416 * elements must be of the same type
409 */ 417 */
410 for (i = 0; i < count; i++) { 418 for (i = 0; i < count; i++) {
411 status = acpi_ns_check_object_type(pathname, *elements, 419 status = acpi_ns_check_object_type(pathname, elements,
412 package->ret_info. 420 package->ret_info.
413 object_type1, i); 421 object_type1, i);
414 if (ACPI_FAILURE(status)) { 422 if (ACPI_FAILURE(status)) {
@@ -441,7 +449,7 @@ acpi_ns_check_package(char *pathname,
441 449
442 status = 450 status =
443 acpi_ns_check_object_type(pathname, 451 acpi_ns_check_object_type(pathname,
444 *elements, 452 elements,
445 package-> 453 package->
446 ret_info3. 454 ret_info3.
447 object_type[i], 455 object_type[i],
@@ -454,7 +462,7 @@ acpi_ns_check_package(char *pathname,
454 462
455 status = 463 status =
456 acpi_ns_check_object_type(pathname, 464 acpi_ns_check_object_type(pathname,
457 *elements, 465 elements,
458 package-> 466 package->
459 ret_info3. 467 ret_info3.
460 tail_object_type, 468 tail_object_type,
@@ -471,7 +479,7 @@ acpi_ns_check_package(char *pathname,
471 479
472 /* First element is the (Integer) count of sub-packages to follow */ 480 /* First element is the (Integer) count of sub-packages to follow */
473 481
474 status = acpi_ns_check_object_type(pathname, *elements, 482 status = acpi_ns_check_object_type(pathname, elements,
475 ACPI_RTYPE_INTEGER, 0); 483 ACPI_RTYPE_INTEGER, 0);
476 if (ACPI_FAILURE(status)) { 484 if (ACPI_FAILURE(status)) {
477 return (status); 485 return (status);
@@ -509,7 +517,7 @@ acpi_ns_check_package(char *pathname,
509 /* Each sub-object must be of type Package */ 517 /* Each sub-object must be of type Package */
510 518
511 status = 519 status =
512 acpi_ns_check_object_type(pathname, sub_package, 520 acpi_ns_check_object_type(pathname, &sub_package,
513 ACPI_RTYPE_PACKAGE, i); 521 ACPI_RTYPE_PACKAGE, i);
514 if (ACPI_FAILURE(status)) { 522 if (ACPI_FAILURE(status)) {
515 return (status); 523 return (status);
@@ -567,12 +575,8 @@ acpi_ns_check_package(char *pathname,
567 for (j = 0; j < expected_count; j++) { 575 for (j = 0; j < expected_count; j++) {
568 status = 576 status =
569 acpi_ns_check_object_type(pathname, 577 acpi_ns_check_object_type(pathname,
570 sub_elements 578 &sub_elements[j],
571 [j], 579 package->ret_info2.object_type[j], j);
572 package->
573 ret_info2.
574 object_type
575 [j], j);
576 if (ACPI_FAILURE(status)) { 580 if (ACPI_FAILURE(status)) {
577 return (status); 581 return (status);
578 } 582 }
@@ -611,7 +615,7 @@ acpi_ns_check_package(char *pathname,
611 615
612 status = 616 status =
613 acpi_ns_check_object_type(pathname, 617 acpi_ns_check_object_type(pathname,
614 *sub_elements, 618 sub_elements,
615 ACPI_RTYPE_INTEGER, 619 ACPI_RTYPE_INTEGER,
616 0); 620 0);
617 if (ACPI_FAILURE(status)) { 621 if (ACPI_FAILURE(status)) {
@@ -708,7 +712,7 @@ acpi_ns_check_package_elements(char *pathname,
708 * The second group can have a count of zero. 712 * The second group can have a count of zero.
709 */ 713 */
710 for (i = 0; i < count1; i++) { 714 for (i = 0; i < count1; i++) {
711 status = acpi_ns_check_object_type(pathname, *this_element, 715 status = acpi_ns_check_object_type(pathname, this_element,
712 type1, i); 716 type1, i);
713 if (ACPI_FAILURE(status)) { 717 if (ACPI_FAILURE(status)) {
714 return (status); 718 return (status);
@@ -717,7 +721,7 @@ acpi_ns_check_package_elements(char *pathname,
717 } 721 }
718 722
719 for (i = 0; i < count2; i++) { 723 for (i = 0; i < count2; i++) {
720 status = acpi_ns_check_object_type(pathname, *this_element, 724 status = acpi_ns_check_object_type(pathname, this_element,
721 type2, (i + count1)); 725 type2, (i + count1));
722 if (ACPI_FAILURE(status)) { 726 if (ACPI_FAILURE(status)) {
723 return (status); 727 return (status);
@@ -733,8 +737,8 @@ acpi_ns_check_package_elements(char *pathname,
733 * FUNCTION: acpi_ns_check_object_type 737 * FUNCTION: acpi_ns_check_object_type
734 * 738 *
735 * PARAMETERS: Pathname - Full pathname to the node (for error msgs) 739 * PARAMETERS: Pathname - Full pathname to the node (for error msgs)
736 * return_object - Object return from the execution of this 740 * return_object_ptr - Pointer to the object returned from the
737 * method/object 741 * evaluation of a method or object
738 * expected_btypes - Bitmap of expected return type(s) 742 * expected_btypes - Bitmap of expected return type(s)
739 * package_index - Index of object within parent package (if 743 * package_index - Index of object within parent package (if
740 * applicable - ACPI_NOT_PACKAGE otherwise) 744 * applicable - ACPI_NOT_PACKAGE otherwise)
@@ -748,9 +752,10 @@ acpi_ns_check_package_elements(char *pathname,
748 752
749static acpi_status 753static acpi_status
750acpi_ns_check_object_type(char *pathname, 754acpi_ns_check_object_type(char *pathname,
751 union acpi_operand_object *return_object, 755 union acpi_operand_object **return_object_ptr,
752 u32 expected_btypes, u32 package_index) 756 u32 expected_btypes, u32 package_index)
753{ 757{
758 union acpi_operand_object *return_object = *return_object_ptr;
754 acpi_status status = AE_OK; 759 acpi_status status = AE_OK;
755 u32 return_btype; 760 u32 return_btype;
756 char type_buffer[48]; /* Room for 5 types */ 761 char type_buffer[48]; /* Room for 5 types */
@@ -814,6 +819,14 @@ acpi_ns_check_object_type(char *pathname,
814 /* Is the object one of the expected types? */ 819 /* Is the object one of the expected types? */
815 820
816 if (!(return_btype & expected_btypes)) { 821 if (!(return_btype & expected_btypes)) {
822
823 /* Type mismatch -- attempt repair of the returned object */
824
825 status = acpi_ns_repair_object(expected_btypes, package_index,
826 return_object_ptr);
827 if (ACPI_SUCCESS(status)) {
828 return (status);
829 }
817 goto type_error_exit; 830 goto type_error_exit;
818 } 831 }
819 832
@@ -898,3 +911,86 @@ acpi_ns_check_reference(char *pathname,
898 911
899 return (AE_AML_OPERAND_TYPE); 912 return (AE_AML_OPERAND_TYPE);
900} 913}
914
915/*******************************************************************************
916 *
917 * FUNCTION: acpi_ns_repair_object
918 *
919 * PARAMETERS: Pathname - Full pathname to the node (for error msgs)
920 * package_index - Used to determine if target is in a package
921 * return_object_ptr - Pointer to the object returned from the
922 * evaluation of a method or object
923 *
924 * RETURN: Status. AE_OK if repair was successful.
925 *
926 * DESCRIPTION: Attempt to repair/convert a return object of a type that was
927 * not expected.
928 *
929 ******************************************************************************/
930
931static acpi_status
932acpi_ns_repair_object(u32 expected_btypes,
933 u32 package_index,
934 union acpi_operand_object **return_object_ptr)
935{
936 union acpi_operand_object *return_object = *return_object_ptr;
937 union acpi_operand_object *new_object;
938 acpi_size length;
939
940 switch (ACPI_GET_OBJECT_TYPE(return_object)) {
941 case ACPI_TYPE_BUFFER:
942
943 if (!(expected_btypes & ACPI_RTYPE_STRING)) {
944 return (AE_AML_OPERAND_TYPE);
945 }
946
947 /*
948 * Have a Buffer, expected a String, convert. Use a to_string
949 * conversion, no transform performed on the buffer data. The best
950 * example of this is the _BIF method, where the string data from
951 * the battery is often (incorrectly) returned as buffer object(s).
952 */
953 length = 0;
954 while ((length < return_object->buffer.length) &&
955 (return_object->buffer.pointer[length])) {
956 length++;
957 }
958
959 /* Allocate a new string object */
960
961 new_object = acpi_ut_create_string_object(length);
962 if (!new_object) {
963 return (AE_NO_MEMORY);
964 }
965
966 /*
967 * Copy the raw buffer data with no transform. String is already NULL
968 * terminated at Length+1.
969 */
970 ACPI_MEMCPY(new_object->string.pointer,
971 return_object->buffer.pointer, length);
972
973 /* Install the new return object */
974
975 acpi_ut_remove_reference(return_object);
976 *return_object_ptr = new_object;
977
978 /*
979 * If the object is a package element, we need to:
980 * 1. Decrement the reference count of the orignal object, it was
981 * incremented when building the package
982 * 2. Increment the reference count of the new object, it will be
983 * decremented when releasing the package
984 */
985 if (package_index != ACPI_NOT_PACKAGE) {
986 acpi_ut_remove_reference(return_object);
987 acpi_ut_add_reference(new_object);
988 }
989 return (AE_OK);
990
991 default:
992 break;
993 }
994
995 return (AE_AML_OPERAND_TYPE);
996}
diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h
index db4e6f677855..db1e29052077 100644
--- a/include/acpi/acnamesp.h
+++ b/include/acpi/acnamesp.h
@@ -182,7 +182,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
182 */ 182 */
183acpi_status 183acpi_status
184acpi_ns_check_predefined_names(struct acpi_namespace_node *node, 184acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
185 union acpi_operand_object *return_object); 185 union acpi_operand_object **return_object);
186 186
187const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct 187const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
188 acpi_namespace_node 188 acpi_namespace_node