diff options
Diffstat (limited to 'drivers/acpi/acpica/nsrepair.c')
-rw-r--r-- | drivers/acpi/acpica/nsrepair.c | 114 |
1 files changed, 86 insertions, 28 deletions
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index db2b2a99c3a8..d563f1a564a7 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
45 | #include "accommon.h" | 45 | #include "accommon.h" |
46 | #include "acnamesp.h" | 46 | #include "acnamesp.h" |
47 | #include "acinterp.h" | ||
47 | #include "acpredef.h" | 48 | #include "acpredef.h" |
48 | 49 | ||
49 | #define _COMPONENT ACPI_NAMESPACE | 50 | #define _COMPONENT ACPI_NAMESPACE |
@@ -76,7 +77,13 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, | |||
76 | union acpi_operand_object *return_object = *return_object_ptr; | 77 | union acpi_operand_object *return_object = *return_object_ptr; |
77 | union acpi_operand_object *new_object; | 78 | union acpi_operand_object *new_object; |
78 | acpi_size length; | 79 | acpi_size length; |
80 | acpi_status status; | ||
79 | 81 | ||
82 | /* | ||
83 | * At this point, we know that the type of the returned object was not | ||
84 | * one of the expected types for this predefined name. Attempt to | ||
85 | * repair the object. Only a limited number of repairs are possible. | ||
86 | */ | ||
80 | switch (return_object->common.type) { | 87 | switch (return_object->common.type) { |
81 | case ACPI_TYPE_BUFFER: | 88 | case ACPI_TYPE_BUFFER: |
82 | 89 | ||
@@ -111,43 +118,94 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, | |||
111 | */ | 118 | */ |
112 | ACPI_MEMCPY(new_object->string.pointer, | 119 | ACPI_MEMCPY(new_object->string.pointer, |
113 | return_object->buffer.pointer, length); | 120 | return_object->buffer.pointer, length); |
121 | break; | ||
114 | 122 | ||
115 | /* | 123 | case ACPI_TYPE_INTEGER: |
116 | * If the original object is a package element, we need to: | 124 | |
117 | * 1. Set the reference count of the new object to match the | 125 | /* 1) Does the method/object legally return a buffer? */ |
118 | * reference count of the old object. | 126 | |
119 | * 2. Decrement the reference count of the original object. | 127 | if (expected_btypes & ACPI_RTYPE_BUFFER) { |
120 | */ | 128 | /* |
121 | if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { | 129 | * Convert the Integer to a packed-byte buffer. _MAT needs |
122 | new_object->common.reference_count = | 130 | * this sometimes, if a read has been performed on a Field |
123 | return_object->common.reference_count; | 131 | * object that is less than or equal to the global integer |
132 | * size (32 or 64 bits). | ||
133 | */ | ||
134 | status = | ||
135 | acpi_ex_convert_to_buffer(return_object, | ||
136 | &new_object); | ||
137 | if (ACPI_FAILURE(status)) { | ||
138 | return (status); | ||
139 | } | ||
140 | } | ||
124 | 141 | ||
125 | if (return_object->common.reference_count > 1) { | 142 | /* 2) Does the method/object legally return a string? */ |
126 | return_object->common.reference_count--; | 143 | |
144 | else if (expected_btypes & ACPI_RTYPE_STRING) { | ||
145 | /* | ||
146 | * The only supported Integer-to-String conversion is to convert | ||
147 | * an integer of value 0 to a NULL string. The last element of | ||
148 | * _BIF and _BIX packages occasionally need this fix. | ||
149 | */ | ||
150 | if (return_object->integer.value != 0) { | ||
151 | return (AE_AML_OPERAND_TYPE); | ||
127 | } | 152 | } |
128 | 153 | ||
129 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, | 154 | /* Allocate a new NULL string object */ |
130 | data->node_flags, | 155 | |
131 | "Converted Buffer to expected String at index %u", | 156 | new_object = acpi_ut_create_string_object(0); |
132 | package_index)); | 157 | if (!new_object) { |
158 | return (AE_NO_MEMORY); | ||
159 | } | ||
133 | } else { | 160 | } else { |
134 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, | 161 | return (AE_AML_OPERAND_TYPE); |
135 | data->node_flags, | ||
136 | "Converted Buffer to expected String")); | ||
137 | } | 162 | } |
163 | break; | ||
138 | 164 | ||
139 | /* Delete old object, install the new return object */ | 165 | default: |
140 | 166 | ||
141 | acpi_ut_remove_reference(return_object); | 167 | /* We cannot repair this object */ |
142 | *return_object_ptr = new_object; | ||
143 | data->flags |= ACPI_OBJECT_REPAIRED; | ||
144 | return (AE_OK); | ||
145 | 168 | ||
146 | default: | 169 | return (AE_AML_OPERAND_TYPE); |
147 | break; | 170 | } |
171 | |||
172 | /* Object was successfully repaired */ | ||
173 | |||
174 | /* | ||
175 | * If the original object is a package element, we need to: | ||
176 | * 1. Set the reference count of the new object to match the | ||
177 | * reference count of the old object. | ||
178 | * 2. Decrement the reference count of the original object. | ||
179 | */ | ||
180 | if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { | ||
181 | new_object->common.reference_count = | ||
182 | return_object->common.reference_count; | ||
183 | |||
184 | if (return_object->common.reference_count > 1) { | ||
185 | return_object->common.reference_count--; | ||
186 | } | ||
187 | |||
188 | ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | ||
189 | "Converted %s to expected %s at index %u", | ||
190 | acpi_ut_get_object_type_name | ||
191 | (return_object), | ||
192 | acpi_ut_get_object_type_name(new_object), | ||
193 | package_index)); | ||
194 | } else { | ||
195 | ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | ||
196 | "Converted %s to expected %s", | ||
197 | acpi_ut_get_object_type_name | ||
198 | (return_object), | ||
199 | acpi_ut_get_object_type_name | ||
200 | (new_object))); | ||
148 | } | 201 | } |
149 | 202 | ||
150 | return (AE_AML_OPERAND_TYPE); | 203 | /* Delete old object, install the new return object */ |
204 | |||
205 | acpi_ut_remove_reference(return_object); | ||
206 | *return_object_ptr = new_object; | ||
207 | data->flags |= ACPI_OBJECT_REPAIRED; | ||
208 | return (AE_OK); | ||
151 | } | 209 | } |
152 | 210 | ||
153 | /******************************************************************************* | 211 | /******************************************************************************* |
@@ -196,8 +254,8 @@ acpi_ns_repair_package_list(struct acpi_predefined_data *data, | |||
196 | *obj_desc_ptr = pkg_obj_desc; | 254 | *obj_desc_ptr = pkg_obj_desc; |
197 | data->flags |= ACPI_OBJECT_REPAIRED; | 255 | data->flags |= ACPI_OBJECT_REPAIRED; |
198 | 256 | ||
199 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | 257 | ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, |
200 | "Incorrectly formed Package, attempting repair")); | 258 | "Repaired Incorrectly formed Package")); |
201 | 259 | ||
202 | return (AE_OK); | 260 | return (AE_OK); |
203 | } | 261 | } |