diff options
author | Bob Moore <robert.moore@intel.com> | 2009-12-11 01:53:11 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-12-15 17:29:35 -0500 |
commit | 34c39c755347c1ca3d06284bad2273c6a9c3108a (patch) | |
tree | 3e46f996ff85a9888162cde30dc7b12749cd156c | |
parent | ebdca3edd5ac61e37f2f5e7c11006c1a68d3cc7e (diff) |
ACPICA: Add repair for bad _FDE/_GTM buffers
The expected return value for both names is a Buffer of 5 DWORDS.
This repair fixes two possible problems (both seen in the field):
A package of integers is returned, or a buffer of BYTEs is returned.
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/acpica/nspredef.c | 14 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsrepair2.c | 149 |
2 files changed, 152 insertions, 11 deletions
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index b05f42903c86..1782c3d85ba2 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c | |||
@@ -222,23 +222,21 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | |||
222 | status = acpi_ns_check_object_type(data, return_object_ptr, | 222 | status = acpi_ns_check_object_type(data, return_object_ptr, |
223 | predefined->info.expected_btypes, | 223 | predefined->info.expected_btypes, |
224 | ACPI_NOT_PACKAGE_ELEMENT); | 224 | ACPI_NOT_PACKAGE_ELEMENT); |
225 | if (ACPI_FAILURE(status)) { | 225 | if (ACPI_SUCCESS(status)) { |
226 | goto check_validation_status; | ||
227 | } | ||
228 | 226 | ||
229 | /* For returned Package objects, check the type of all sub-objects */ | 227 | /* For returned Package objects, check the type of all sub-objects */ |
230 | 228 | ||
231 | if (return_object->common.type == ACPI_TYPE_PACKAGE) { | 229 | if (return_object->common.type == ACPI_TYPE_PACKAGE) { |
232 | status = acpi_ns_check_package(data, return_object_ptr); | 230 | status = acpi_ns_check_package(data, return_object_ptr); |
231 | } | ||
233 | } | 232 | } |
234 | 233 | ||
235 | /* | 234 | /* |
236 | * Perform additional, more complicated repairs on a per-name | 235 | * Perform additional, more complicated repairs on a per-name |
237 | * basis. | 236 | * basis. Do this regardless of the status from above. |
238 | */ | 237 | */ |
239 | status = acpi_ns_complex_repairs(data, node, status, return_object_ptr); | 238 | status = acpi_ns_complex_repairs(data, node, status, return_object_ptr); |
240 | 239 | ||
241 | check_validation_status: | ||
242 | /* | 240 | /* |
243 | * If the object validation failed or if we successfully repaired one | 241 | * If the object validation failed or if we successfully repaired one |
244 | * or more objects, mark the parent node to suppress further warning | 242 | * or more objects, mark the parent node to suppress further warning |
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index d07b68613818..6c35b57a7fd0 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c | |||
@@ -74,6 +74,10 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data, | |||
74 | union acpi_operand_object **return_object_ptr); | 74 | union acpi_operand_object **return_object_ptr); |
75 | 75 | ||
76 | static acpi_status | 76 | static acpi_status |
77 | acpi_ns_repair_FDE(struct acpi_predefined_data *data, | ||
78 | union acpi_operand_object **return_object_ptr); | ||
79 | |||
80 | static acpi_status | ||
77 | acpi_ns_repair_PSS(struct acpi_predefined_data *data, | 81 | acpi_ns_repair_PSS(struct acpi_predefined_data *data, |
78 | union acpi_operand_object **return_object_ptr); | 82 | union acpi_operand_object **return_object_ptr); |
79 | 83 | ||
@@ -104,17 +108,27 @@ acpi_ns_sort_list(union acpi_operand_object **elements, | |||
104 | * This table contains the names of the predefined methods for which we can | 108 | * This table contains the names of the predefined methods for which we can |
105 | * perform more complex repairs. | 109 | * perform more complex repairs. |
106 | * | 110 | * |
107 | * _ALR: Sort the list ascending by ambient_illuminance if necessary | 111 | * As necessary: |
108 | * _PSS: Sort the list descending by Power if necessary | 112 | * |
109 | * _TSS: Sort the list descending by Power if necessary | 113 | * _ALR: Sort the list ascending by ambient_illuminance |
114 | * _FDE: Convert a Package or Buffer of BYTEs to a Buffer of DWORDs | ||
115 | * _GTM: Convert a Package or Buffer of BYTEs to a Buffer of DWORDs | ||
116 | * _PSS: Sort the list descending by Power | ||
117 | * _TSS: Sort the list descending by Power | ||
110 | */ | 118 | */ |
111 | static const struct acpi_repair_info acpi_ns_repairable_names[] = { | 119 | static const struct acpi_repair_info acpi_ns_repairable_names[] = { |
112 | {"_ALR", acpi_ns_repair_ALR}, | 120 | {"_ALR", acpi_ns_repair_ALR}, |
121 | {"_FDE", acpi_ns_repair_FDE}, | ||
122 | {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ | ||
113 | {"_PSS", acpi_ns_repair_PSS}, | 123 | {"_PSS", acpi_ns_repair_PSS}, |
114 | {"_TSS", acpi_ns_repair_TSS}, | 124 | {"_TSS", acpi_ns_repair_TSS}, |
115 | {{0, 0, 0, 0}, NULL} /* Table terminator */ | 125 | {{0, 0, 0, 0}, NULL} /* Table terminator */ |
116 | }; | 126 | }; |
117 | 127 | ||
128 | #define ACPI_FDE_FIELD_COUNT 5 | ||
129 | #define ACPI_FDE_BYTE_BUFFER_SIZE 5 | ||
130 | #define ACPI_FDE_DWORD_BUFFER_SIZE (ACPI_FDE_FIELD_COUNT * sizeof (u32)) | ||
131 | |||
118 | /****************************************************************************** | 132 | /****************************************************************************** |
119 | * | 133 | * |
120 | * FUNCTION: acpi_ns_complex_repairs | 134 | * FUNCTION: acpi_ns_complex_repairs |
@@ -215,6 +229,135 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data, | |||
215 | 229 | ||
216 | /****************************************************************************** | 230 | /****************************************************************************** |
217 | * | 231 | * |
232 | * FUNCTION: acpi_ns_repair_FDE | ||
233 | * | ||
234 | * PARAMETERS: Data - Pointer to validation data structure | ||
235 | * return_object_ptr - Pointer to the object returned from the | ||
236 | * evaluation of a method or object | ||
237 | * | ||
238 | * RETURN: Status. AE_OK if object is OK or was repaired successfully | ||
239 | * | ||
240 | * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return | ||
241 | * value is a Buffer of 5 DWORDs. This function repairs two | ||
242 | * possible problems: | ||
243 | * 1) The return value is a Buffer of BYTEs, not DWORDs | ||
244 | * 2) The return value is a Package of Integer objects | ||
245 | * | ||
246 | *****************************************************************************/ | ||
247 | |||
248 | static acpi_status | ||
249 | acpi_ns_repair_FDE(struct acpi_predefined_data *data, | ||
250 | union acpi_operand_object **return_object_ptr) | ||
251 | { | ||
252 | union acpi_operand_object *return_object = *return_object_ptr; | ||
253 | union acpi_operand_object **elements; | ||
254 | union acpi_operand_object *buffer_object; | ||
255 | u8 *byte_buffer; | ||
256 | u32 *dword_buffer; | ||
257 | u32 count; | ||
258 | u32 i; | ||
259 | |||
260 | switch (return_object->common.type) { | ||
261 | case ACPI_TYPE_BUFFER: | ||
262 | |||
263 | /* This is the expected type. Length should be (at least) 5 DWORDs */ | ||
264 | |||
265 | if (return_object->buffer.length >= ACPI_FDE_DWORD_BUFFER_SIZE) { | ||
266 | return (AE_OK); | ||
267 | } | ||
268 | |||
269 | /* We can only repair if we have exactly 5 BYTEs */ | ||
270 | |||
271 | if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) { | ||
272 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, | ||
273 | data->node_flags, | ||
274 | "Incorrect return buffer length %u, expected %u", | ||
275 | return_object->buffer.length, | ||
276 | ACPI_FDE_DWORD_BUFFER_SIZE)); | ||
277 | |||
278 | return (AE_AML_OPERAND_TYPE); | ||
279 | } | ||
280 | |||
281 | /* Create the new (larger) buffer object */ | ||
282 | |||
283 | buffer_object = | ||
284 | acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE); | ||
285 | if (!buffer_object) { | ||
286 | return (AE_NO_MEMORY); | ||
287 | } | ||
288 | |||
289 | /* Expand each byte to a DWORD */ | ||
290 | |||
291 | byte_buffer = return_object->buffer.pointer; | ||
292 | dword_buffer = | ||
293 | ACPI_CAST_PTR(u32, buffer_object->buffer.pointer); | ||
294 | |||
295 | for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) { | ||
296 | *dword_buffer = (u32) *byte_buffer; | ||
297 | dword_buffer++; | ||
298 | byte_buffer++; | ||
299 | } | ||
300 | |||
301 | ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | ||
302 | "Expanded Byte Buffer to expected DWord Buffer")); | ||
303 | break; | ||
304 | |||
305 | case ACPI_TYPE_PACKAGE: | ||
306 | |||
307 | /* All elements of the Package must be integers */ | ||
308 | |||
309 | elements = return_object->package.elements; | ||
310 | count = | ||
311 | ACPI_MIN(ACPI_FDE_FIELD_COUNT, | ||
312 | return_object->package.count); | ||
313 | |||
314 | for (i = 0; i < count; i++) { | ||
315 | if ((!*elements) || | ||
316 | ((*elements)->common.type != ACPI_TYPE_INTEGER)) { | ||
317 | return (AE_AML_OPERAND_TYPE); | ||
318 | } | ||
319 | elements++; | ||
320 | } | ||
321 | |||
322 | /* Create the new buffer object to replace the Package */ | ||
323 | |||
324 | buffer_object = | ||
325 | acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE); | ||
326 | if (!buffer_object) { | ||
327 | return (AE_NO_MEMORY); | ||
328 | } | ||
329 | |||
330 | /* Copy the package elements (integers) to the buffer */ | ||
331 | |||
332 | elements = return_object->package.elements; | ||
333 | dword_buffer = | ||
334 | ACPI_CAST_PTR(u32, buffer_object->buffer.pointer); | ||
335 | |||
336 | for (i = 0; i < count; i++) { | ||
337 | *dword_buffer = (u32) (*elements)->integer.value; | ||
338 | dword_buffer++; | ||
339 | elements++; | ||
340 | } | ||
341 | |||
342 | ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | ||
343 | "Converted Package to expected Buffer")); | ||
344 | break; | ||
345 | |||
346 | default: | ||
347 | return (AE_AML_OPERAND_TYPE); | ||
348 | } | ||
349 | |||
350 | /* Delete the original return object, return the new buffer object */ | ||
351 | |||
352 | acpi_ut_remove_reference(return_object); | ||
353 | *return_object_ptr = buffer_object; | ||
354 | |||
355 | data->flags |= ACPI_OBJECT_REPAIRED; | ||
356 | return (AE_OK); | ||
357 | } | ||
358 | |||
359 | /****************************************************************************** | ||
360 | * | ||
218 | * FUNCTION: acpi_ns_repair_TSS | 361 | * FUNCTION: acpi_ns_repair_TSS |
219 | * | 362 | * |
220 | * PARAMETERS: Data - Pointer to validation data structure | 363 | * PARAMETERS: Data - Pointer to validation data structure |