diff options
Diffstat (limited to 'drivers/acpi/namespace/nspredef.c')
-rw-r--r-- | drivers/acpi/namespace/nspredef.c | 150 |
1 files changed, 123 insertions, 27 deletions
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 */ |
73 | static acpi_status | 73 | static acpi_status |
74 | acpi_ns_check_package(char *pathname, | 74 | acpi_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 | ||
78 | static acpi_status | 78 | static acpi_status |
@@ -82,13 +82,18 @@ acpi_ns_check_package_elements(char *pathname, | |||
82 | 82 | ||
83 | static acpi_status | 83 | static acpi_status |
84 | acpi_ns_check_object_type(char *pathname, | 84 | acpi_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 | ||
88 | static acpi_status | 88 | static acpi_status |
89 | acpi_ns_check_reference(char *pathname, | 89 | acpi_ns_check_reference(char *pathname, |
90 | union acpi_operand_object *return_object); | 90 | union acpi_operand_object *return_object); |
91 | 91 | ||
92 | static acpi_status | ||
93 | acpi_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 | ||
120 | acpi_status | 125 | acpi_status |
121 | acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | 126 | acpi_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 | ||
321 | static acpi_status | 328 | static acpi_status |
322 | acpi_ns_check_package(char *pathname, | 329 | acpi_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 | ||
749 | static acpi_status | 753 | static acpi_status |
750 | acpi_ns_check_object_type(char *pathname, | 754 | acpi_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 | |||
931 | static acpi_status | ||
932 | acpi_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 | } | ||