diff options
author | Bob Moore <robert.moore@intel.com> | 2008-04-10 11:06:39 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-04-22 14:29:24 -0400 |
commit | 5eb691805f7ec5960fe9d5d7fc57a7fc3097bbd0 (patch) | |
tree | bd968bd9717f55a32ff9a30062aad025854c3bc6 /drivers/acpi/executer/exconfig.c | |
parent | 53cf174409a24e8388e1d554d27436275fc81fe7 (diff) |
ACPICA: Fix for fault if Load() fails
Fixed a problem with the Load operator when loading a table from
a buffer object. The input buffer was prematurely zeroed and/or
deleted.
http://www.acpica.org/bugzilla/show_bug.cgi?id=577
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/executer/exconfig.c')
-rw-r--r-- | drivers/acpi/executer/exconfig.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 009aef5fcbfc..8cc410ce9208 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c | |||
@@ -285,16 +285,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
285 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { | 285 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { |
286 | case ACPI_TYPE_REGION: | 286 | case ACPI_TYPE_REGION: |
287 | 287 | ||
288 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", | ||
289 | obj_desc, | ||
290 | acpi_ut_get_object_type_name(obj_desc))); | ||
291 | |||
288 | /* Region must be system_memory (from ACPI spec) */ | 292 | /* Region must be system_memory (from ACPI spec) */ |
289 | 293 | ||
290 | if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { | 294 | if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
291 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 295 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
292 | } | 296 | } |
293 | 297 | ||
294 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", | ||
295 | obj_desc, | ||
296 | acpi_ut_get_object_type_name(obj_desc))); | ||
297 | |||
298 | /* | 298 | /* |
299 | * If the Region Address and Length have not been previously evaluated, | 299 | * If the Region Address and Length have not been previously evaluated, |
300 | * evaluate them now and save the results. | 300 | * evaluate them now and save the results. |
@@ -306,6 +306,11 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
306 | } | 306 | } |
307 | } | 307 | } |
308 | 308 | ||
309 | /* | ||
310 | * We will simply map the memory region for the table. However, the | ||
311 | * memory region is technically not guaranteed to remain stable and | ||
312 | * we may eventually have to copy the table to a local buffer. | ||
313 | */ | ||
309 | table_desc.address = obj_desc->region.address; | 314 | table_desc.address = obj_desc->region.address; |
310 | table_desc.length = obj_desc->region.length; | 315 | table_desc.length = obj_desc->region.length; |
311 | table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; | 316 | table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; |
@@ -313,18 +318,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
313 | 318 | ||
314 | case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ | 319 | case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ |
315 | 320 | ||
316 | /* Simply extract the buffer from the buffer object */ | ||
317 | |||
318 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 321 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
319 | "Load from Buffer or Field %p %s\n", obj_desc, | 322 | "Load from Buffer or Field %p %s\n", obj_desc, |
320 | acpi_ut_get_object_type_name(obj_desc))); | 323 | acpi_ut_get_object_type_name(obj_desc))); |
321 | 324 | ||
322 | table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header, | 325 | /* |
323 | obj_desc->buffer.pointer); | 326 | * We need to copy the buffer since the original buffer could be |
324 | table_desc.length = table_desc.pointer->length; | 327 | * changed or deleted in the future |
325 | table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; | 328 | */ |
329 | table_desc.pointer = ACPI_ALLOCATE(obj_desc->buffer.length); | ||
330 | if (!table_desc.pointer) { | ||
331 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
332 | } | ||
326 | 333 | ||
327 | obj_desc->buffer.pointer = NULL; | 334 | ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer, |
335 | obj_desc->buffer.length); | ||
336 | table_desc.length = obj_desc->buffer.length; | ||
337 | table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; | ||
328 | break; | 338 | break; |
329 | 339 | ||
330 | default: | 340 | default: |
@@ -369,6 +379,9 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
369 | 379 | ||
370 | cleanup: | 380 | cleanup: |
371 | if (ACPI_FAILURE(status)) { | 381 | if (ACPI_FAILURE(status)) { |
382 | |||
383 | /* Delete allocated buffer or mapping */ | ||
384 | |||
372 | acpi_tb_delete_table(&table_desc); | 385 | acpi_tb_delete_table(&table_desc); |
373 | } | 386 | } |
374 | return_ACPI_STATUS(status); | 387 | return_ACPI_STATUS(status); |