aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/nsrepair.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/nsrepair.c')
-rw-r--r--drivers/acpi/acpica/nsrepair.c403
1 files changed, 327 insertions, 76 deletions
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c
index d563f1a564a7..10629fa55d83 100644
--- a/drivers/acpi/acpica/nsrepair.c
+++ b/drivers/acpi/acpica/nsrepair.c
@@ -45,13 +45,52 @@
45#include "accommon.h" 45#include "accommon.h"
46#include "acnamesp.h" 46#include "acnamesp.h"
47#include "acinterp.h" 47#include "acinterp.h"
48#include "acpredef.h"
49 48
50#define _COMPONENT ACPI_NAMESPACE 49#define _COMPONENT ACPI_NAMESPACE
51ACPI_MODULE_NAME("nsrepair") 50ACPI_MODULE_NAME("nsrepair")
52 51
53/******************************************************************************* 52/*******************************************************************************
54 * 53 *
54 * This module attempts to repair or convert objects returned by the
55 * predefined methods to an object type that is expected, as per the ACPI
56 * specification. The need for this code is dictated by the many machines that
57 * return incorrect types for the standard predefined methods. Performing these
58 * conversions here, in one place, eliminates the need for individual ACPI
59 * device drivers to do the same. Note: Most of these conversions are different
60 * than the internal object conversion routines used for implicit object
61 * conversion.
62 *
63 * The following conversions can be performed as necessary:
64 *
65 * Integer -> String
66 * Integer -> Buffer
67 * String -> Integer
68 * String -> Buffer
69 * Buffer -> Integer
70 * Buffer -> String
71 * Buffer -> Package of Integers
72 * Package -> Package of one Package
73 *
74 ******************************************************************************/
75/* Local prototypes */
76static acpi_status
77acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
78 union acpi_operand_object **return_object);
79
80static acpi_status
81acpi_ns_convert_to_string(union acpi_operand_object *original_object,
82 union acpi_operand_object **return_object);
83
84static acpi_status
85acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
86 union acpi_operand_object **return_object);
87
88static acpi_status
89acpi_ns_convert_to_package(union acpi_operand_object *original_object,
90 union acpi_operand_object **return_object);
91
92/*******************************************************************************
93 *
55 * FUNCTION: acpi_ns_repair_object 94 * FUNCTION: acpi_ns_repair_object
56 * 95 *
57 * PARAMETERS: Data - Pointer to validation data structure 96 * PARAMETERS: Data - Pointer to validation data structure
@@ -68,6 +107,7 @@ ACPI_MODULE_NAME("nsrepair")
68 * not expected. 107 * not expected.
69 * 108 *
70 ******************************************************************************/ 109 ******************************************************************************/
110
71acpi_status 111acpi_status
72acpi_ns_repair_object(struct acpi_predefined_data *data, 112acpi_ns_repair_object(struct acpi_predefined_data *data,
73 u32 expected_btypes, 113 u32 expected_btypes,
@@ -76,32 +116,205 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
76{ 116{
77 union acpi_operand_object *return_object = *return_object_ptr; 117 union acpi_operand_object *return_object = *return_object_ptr;
78 union acpi_operand_object *new_object; 118 union acpi_operand_object *new_object;
79 acpi_size length;
80 acpi_status status; 119 acpi_status status;
81 120
82 /* 121 /*
83 * At this point, we know that the type of the returned object was not 122 * 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 123 * one of the expected types for this predefined name. Attempt to
85 * repair the object. Only a limited number of repairs are possible. 124 * repair the object by converting it to one of the expected object
125 * types for this predefined name.
126 */
127 if (expected_btypes & ACPI_RTYPE_INTEGER) {
128 status = acpi_ns_convert_to_integer(return_object, &new_object);
129 if (ACPI_SUCCESS(status)) {
130 goto object_repaired;
131 }
132 }
133 if (expected_btypes & ACPI_RTYPE_STRING) {
134 status = acpi_ns_convert_to_string(return_object, &new_object);
135 if (ACPI_SUCCESS(status)) {
136 goto object_repaired;
137 }
138 }
139 if (expected_btypes & ACPI_RTYPE_BUFFER) {
140 status = acpi_ns_convert_to_buffer(return_object, &new_object);
141 if (ACPI_SUCCESS(status)) {
142 goto object_repaired;
143 }
144 }
145 if (expected_btypes & ACPI_RTYPE_PACKAGE) {
146 status = acpi_ns_convert_to_package(return_object, &new_object);
147 if (ACPI_SUCCESS(status)) {
148 goto object_repaired;
149 }
150 }
151
152 /* We cannot repair this object */
153
154 return (AE_AML_OPERAND_TYPE);
155
156 object_repaired:
157
158 /* Object was successfully repaired */
159
160 /*
161 * If the original object is a package element, we need to:
162 * 1. Set the reference count of the new object to match the
163 * reference count of the old object.
164 * 2. Decrement the reference count of the original object.
86 */ 165 */
87 switch (return_object->common.type) { 166 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
167 new_object->common.reference_count =
168 return_object->common.reference_count;
169
170 if (return_object->common.reference_count > 1) {
171 return_object->common.reference_count--;
172 }
173
174 ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
175 "Converted %s to expected %s at index %u",
176 acpi_ut_get_object_type_name
177 (return_object),
178 acpi_ut_get_object_type_name(new_object),
179 package_index));
180 } else {
181 ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
182 "Converted %s to expected %s",
183 acpi_ut_get_object_type_name
184 (return_object),
185 acpi_ut_get_object_type_name
186 (new_object)));
187 }
188
189 /* Delete old object, install the new return object */
190
191 acpi_ut_remove_reference(return_object);
192 *return_object_ptr = new_object;
193 data->flags |= ACPI_OBJECT_REPAIRED;
194 return (AE_OK);
195}
196
197/*******************************************************************************
198 *
199 * FUNCTION: acpi_ns_convert_to_integer
200 *
201 * PARAMETERS: original_object - Object to be converted
202 * return_object - Where the new converted object is returned
203 *
204 * RETURN: Status. AE_OK if conversion was successful.
205 *
206 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
207 *
208 ******************************************************************************/
209
210static acpi_status
211acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
212 union acpi_operand_object **return_object)
213{
214 union acpi_operand_object *new_object;
215 acpi_status status;
216 u64 value = 0;
217 u32 i;
218
219 switch (original_object->common.type) {
220 case ACPI_TYPE_STRING:
221
222 /* String-to-Integer conversion */
223
224 status = acpi_ut_strtoul64(original_object->string.pointer,
225 ACPI_ANY_BASE, &value);
226 if (ACPI_FAILURE(status)) {
227 return (status);
228 }
229 break;
230
88 case ACPI_TYPE_BUFFER: 231 case ACPI_TYPE_BUFFER:
89 232
90 /* Does the method/object legally return a string? */ 233 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
91 234
92 if (!(expected_btypes & ACPI_RTYPE_STRING)) { 235 if (original_object->buffer.length > 8) {
93 return (AE_AML_OPERAND_TYPE); 236 return (AE_AML_OPERAND_TYPE);
94 } 237 }
95 238
239 /* Extract each buffer byte to create the integer */
240
241 for (i = 0; i < original_object->buffer.length; i++) {
242 value |=
243 ((u64) original_object->buffer.
244 pointer[i] << (i * 8));
245 }
246 break;
247
248 default:
249 return (AE_AML_OPERAND_TYPE);
250 }
251
252 new_object = acpi_ut_create_integer_object(value);
253 if (!new_object) {
254 return (AE_NO_MEMORY);
255 }
256
257 *return_object = new_object;
258 return (AE_OK);
259}
260
261/*******************************************************************************
262 *
263 * FUNCTION: acpi_ns_convert_to_string
264 *
265 * PARAMETERS: original_object - Object to be converted
266 * return_object - Where the new converted object is returned
267 *
268 * RETURN: Status. AE_OK if conversion was successful.
269 *
270 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
271 *
272 ******************************************************************************/
273
274static acpi_status
275acpi_ns_convert_to_string(union acpi_operand_object *original_object,
276 union acpi_operand_object **return_object)
277{
278 union acpi_operand_object *new_object;
279 acpi_size length;
280 acpi_status status;
281
282 switch (original_object->common.type) {
283 case ACPI_TYPE_INTEGER:
284 /*
285 * Integer-to-String conversion. Commonly, convert
286 * an integer of value 0 to a NULL string. The last element of
287 * _BIF and _BIX packages occasionally need this fix.
288 */
289 if (original_object->integer.value == 0) {
290
291 /* Allocate a new NULL string object */
292
293 new_object = acpi_ut_create_string_object(0);
294 if (!new_object) {
295 return (AE_NO_MEMORY);
296 }
297 } else {
298 status =
299 acpi_ex_convert_to_string(original_object,
300 &new_object,
301 ACPI_IMPLICIT_CONVERT_HEX);
302 if (ACPI_FAILURE(status)) {
303 return (status);
304 }
305 }
306 break;
307
308 case ACPI_TYPE_BUFFER:
96 /* 309 /*
97 * Have a Buffer, expected a String, convert. Use a to_string 310 * Buffer-to-String conversion. Use a to_string
98 * conversion, no transform performed on the buffer data. The best 311 * conversion, no transform performed on the buffer data. The best
99 * example of this is the _BIF method, where the string data from 312 * example of this is the _BIF method, where the string data from
100 * the battery is often (incorrectly) returned as buffer object(s). 313 * the battery is often (incorrectly) returned as buffer object(s).
101 */ 314 */
102 length = 0; 315 length = 0;
103 while ((length < return_object->buffer.length) && 316 while ((length < original_object->buffer.length) &&
104 (return_object->buffer.pointer[length])) { 317 (original_object->buffer.pointer[length])) {
105 length++; 318 length++;
106 } 319 }
107 320
@@ -117,94 +330,132 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
117 * terminated at Length+1. 330 * terminated at Length+1.
118 */ 331 */
119 ACPI_MEMCPY(new_object->string.pointer, 332 ACPI_MEMCPY(new_object->string.pointer,
120 return_object->buffer.pointer, length); 333 original_object->buffer.pointer, length);
121 break; 334 break;
122 335
123 case ACPI_TYPE_INTEGER: 336 default:
337 return (AE_AML_OPERAND_TYPE);
338 }
124 339
125 /* 1) Does the method/object legally return a buffer? */ 340 *return_object = new_object;
341 return (AE_OK);
342}
126 343
127 if (expected_btypes & ACPI_RTYPE_BUFFER) { 344/*******************************************************************************
128 /* 345 *
129 * Convert the Integer to a packed-byte buffer. _MAT needs 346 * FUNCTION: acpi_ns_convert_to_buffer
130 * this sometimes, if a read has been performed on a Field 347 *
131 * object that is less than or equal to the global integer 348 * PARAMETERS: original_object - Object to be converted
132 * size (32 or 64 bits). 349 * return_object - Where the new converted object is returned
133 */ 350 *
134 status = 351 * RETURN: Status. AE_OK if conversion was successful.
135 acpi_ex_convert_to_buffer(return_object, 352 *
136 &new_object); 353 * DESCRIPTION: Attempt to convert a Integer/String object to a Buffer.
137 if (ACPI_FAILURE(status)) { 354 *
138 return (status); 355 ******************************************************************************/
139 }
140 }
141 356
142 /* 2) Does the method/object legally return a string? */ 357static acpi_status
358acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
359 union acpi_operand_object **return_object)
360{
361 union acpi_operand_object *new_object;
362 acpi_status status;
143 363
144 else if (expected_btypes & ACPI_RTYPE_STRING) { 364 switch (original_object->common.type) {
145 /* 365 case ACPI_TYPE_INTEGER:
146 * The only supported Integer-to-String conversion is to convert 366 /*
147 * an integer of value 0 to a NULL string. The last element of 367 * Integer-to-Buffer conversion.
148 * _BIF and _BIX packages occasionally need this fix. 368 * Convert the Integer to a packed-byte buffer. _MAT and other
149 */ 369 * objects need this sometimes, if a read has been performed on a
150 if (return_object->integer.value != 0) { 370 * Field object that is less than or equal to the global integer
151 return (AE_AML_OPERAND_TYPE); 371 * size (32 or 64 bits).
152 } 372 */
373 status =
374 acpi_ex_convert_to_buffer(original_object, &new_object);
375 if (ACPI_FAILURE(status)) {
376 return (status);
377 }
378 break;
153 379
154 /* Allocate a new NULL string object */ 380 case ACPI_TYPE_STRING:
155 381
156 new_object = acpi_ut_create_string_object(0); 382 /* String-to-Buffer conversion. Simple data copy */
157 if (!new_object) { 383
158 return (AE_NO_MEMORY); 384 new_object =
159 } 385 acpi_ut_create_buffer_object(original_object->string.
160 } else { 386 length);
161 return (AE_AML_OPERAND_TYPE); 387 if (!new_object) {
388 return (AE_NO_MEMORY);
162 } 389 }
390
391 ACPI_MEMCPY(new_object->buffer.pointer,
392 original_object->string.pointer,
393 original_object->string.length);
163 break; 394 break;
164 395
165 default: 396 default:
166
167 /* We cannot repair this object */
168
169 return (AE_AML_OPERAND_TYPE); 397 return (AE_AML_OPERAND_TYPE);
170 } 398 }
171 399
172 /* Object was successfully repaired */ 400 *return_object = new_object;
401 return (AE_OK);
402}
173 403
174 /* 404/*******************************************************************************
175 * If the original object is a package element, we need to: 405 *
176 * 1. Set the reference count of the new object to match the 406 * FUNCTION: acpi_ns_convert_to_package
177 * reference count of the old object. 407 *
178 * 2. Decrement the reference count of the original object. 408 * PARAMETERS: original_object - Object to be converted
179 */ 409 * return_object - Where the new converted object is returned
180 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 410 *
181 new_object->common.reference_count = 411 * RETURN: Status. AE_OK if conversion was successful.
182 return_object->common.reference_count; 412 *
413 * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of
414 * the buffer is converted to a single integer package element.
415 *
416 ******************************************************************************/
183 417
184 if (return_object->common.reference_count > 1) { 418static acpi_status
185 return_object->common.reference_count--; 419acpi_ns_convert_to_package(union acpi_operand_object *original_object,
420 union acpi_operand_object **return_object)
421{
422 union acpi_operand_object *new_object;
423 union acpi_operand_object **elements;
424 u32 length;
425 u8 *buffer;
426
427 switch (original_object->common.type) {
428 case ACPI_TYPE_BUFFER:
429
430 /* Buffer-to-Package conversion */
431
432 length = original_object->buffer.length;
433 new_object = acpi_ut_create_package_object(length);
434 if (!new_object) {
435 return (AE_NO_MEMORY);
186 } 436 }
187 437
188 ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, 438 /* Convert each buffer byte to an integer package element */
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)));
201 }
202 439
203 /* Delete old object, install the new return object */ 440 elements = new_object->package.elements;
441 buffer = original_object->buffer.pointer;
204 442
205 acpi_ut_remove_reference(return_object); 443 while (length--) {
206 *return_object_ptr = new_object; 444 *elements = acpi_ut_create_integer_object(*buffer);
207 data->flags |= ACPI_OBJECT_REPAIRED; 445 if (!*elements) {
446 acpi_ut_remove_reference(new_object);
447 return (AE_NO_MEMORY);
448 }
449 elements++;
450 buffer++;
451 }
452 break;
453
454 default:
455 return (AE_AML_OPERAND_TYPE);
456 }
457
458 *return_object = new_object;
208 return (AE_OK); 459 return (AE_OK);
209} 460}
210 461