aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/executer
diff options
context:
space:
mode:
authorDennis Noordsij <dennis.noordsij@helsinki.fi>2008-08-14 21:37:58 -0400
committerLen Brown <len.brown@intel.com>2008-10-22 23:14:34 -0400
commitf0e0da8a6cca44396c7a711e308d58084e881617 (patch)
tree015422fb82f6a86ac06f328ead51d6bcd6ca1d12 /drivers/acpi/executer
parent3fa8749e584b55f1180411ab1b51117190bac1e5 (diff)
ACPICA: Copy dynamically loaded tables to local buffer
Previously, dynamically loaded tables were simply mapped, but on some machines this memory is corrupted after suspend. Now copy the table to a local buffer. For OpRegion case, added checksum verify. Use the table length from the table header, not the region length. For Buffer case, use the table length also. http://bugzilla.kernel.org/show_bug.cgi?id=10734 Signed-off-by: Dennis Noordsij <dennis.noordsij@helsinki.fi> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/executer')
-rw-r--r--drivers/acpi/executer/exconfig.c113
1 files changed, 82 insertions, 31 deletions
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 8892b9824fae..331a114f42c9 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -280,6 +280,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
280 struct acpi_walk_state *walk_state) 280 struct acpi_walk_state *walk_state)
281{ 281{
282 union acpi_operand_object *ddb_handle; 282 union acpi_operand_object *ddb_handle;
283 struct acpi_table_header *table;
283 struct acpi_table_desc table_desc; 284 struct acpi_table_desc table_desc;
284 u32 table_index; 285 u32 table_index;
285 acpi_status status; 286 acpi_status status;
@@ -294,9 +295,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
294 switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { 295 switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
295 case ACPI_TYPE_REGION: 296 case ACPI_TYPE_REGION:
296 297
297 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", 298 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
298 obj_desc, 299 "Load table from Region %p\n", obj_desc));
299 acpi_ut_get_object_type_name(obj_desc)));
300 300
301 /* Region must be system_memory (from ACPI spec) */ 301 /* Region must be system_memory (from ACPI spec) */
302 302
@@ -316,61 +316,112 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
316 } 316 }
317 317
318 /* 318 /*
319 * We will simply map the memory region for the table. However, the 319 * Map the table header and get the actual table length. The region
320 * memory region is technically not guaranteed to remain stable and 320 * length is not guaranteed to be the same as the table length.
321 * we may eventually have to copy the table to a local buffer. 321 */
322 table = acpi_os_map_memory(obj_desc->region.address,
323 sizeof(struct acpi_table_header));
324 if (!table) {
325 return_ACPI_STATUS(AE_NO_MEMORY);
326 }
327
328 length = table->length;
329 acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
330
331 /* Must have at least an ACPI table header */
332
333 if (length < sizeof(struct acpi_table_header)) {
334 return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
335 }
336
337 /*
338 * The memory region is not guaranteed to remain stable and we must
339 * copy the table to a local buffer. For example, the memory region
340 * is corrupted after suspend on some machines. Dynamically loaded
341 * tables are usually small, so this overhead is minimal.
322 */ 342 */
343
344 /* Allocate a buffer for the table */
345
346 table_desc.pointer = ACPI_ALLOCATE(length);
347 if (!table_desc.pointer) {
348 return_ACPI_STATUS(AE_NO_MEMORY);
349 }
350
351 /* Map the entire table and copy it */
352
353 table = acpi_os_map_memory(obj_desc->region.address, length);
354 if (!table) {
355 ACPI_FREE(table_desc.pointer);
356 return_ACPI_STATUS(AE_NO_MEMORY);
357 }
358
359 ACPI_MEMCPY(table_desc.pointer, table, length);
360 acpi_os_unmap_memory(table, length);
361
323 table_desc.address = obj_desc->region.address; 362 table_desc.address = obj_desc->region.address;
324 table_desc.length = obj_desc->region.length;
325 table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED;
326 break; 363 break;
327 364
328 case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ 365 case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */
329 366
330 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 367 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
331 "Load from Buffer or Field %p %s\n", obj_desc, 368 "Load table from Buffer or Field %p\n",
332 acpi_ut_get_object_type_name(obj_desc))); 369 obj_desc));
333
334 length = obj_desc->buffer.length;
335 370
336 /* Must have at least an ACPI table header */ 371 /* Must have at least an ACPI table header */
337 372
338 if (length < sizeof(struct acpi_table_header)) { 373 if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) {
339 return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); 374 return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
340 } 375 }
341 376
342 /* Validate checksum here. It won't get validated in tb_add_table */ 377 /* Get the actual table length from the table header */
343 378
344 status = 379 table =
345 acpi_tb_verify_checksum(ACPI_CAST_PTR 380 ACPI_CAST_PTR(struct acpi_table_header,
346 (struct acpi_table_header, 381 obj_desc->buffer.pointer);
347 obj_desc->buffer.pointer), length); 382 length = table->length;
348 if (ACPI_FAILURE(status)) { 383
349 return_ACPI_STATUS(status); 384 /* Table cannot extend beyond the buffer */
385
386 if (length > obj_desc->buffer.length) {
387 return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
388 }
389 if (length < sizeof(struct acpi_table_header)) {
390 return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
350 } 391 }
351 392
352 /* 393 /*
353 * We need to copy the buffer since the original buffer could be 394 * Copy the table from the buffer because the buffer could be modified
354 * changed or deleted in the future 395 * or even deleted in the future
355 */ 396 */
356 table_desc.pointer = ACPI_ALLOCATE(length); 397 table_desc.pointer = ACPI_ALLOCATE(length);
357 if (!table_desc.pointer) { 398 if (!table_desc.pointer) {
358 return_ACPI_STATUS(AE_NO_MEMORY); 399 return_ACPI_STATUS(AE_NO_MEMORY);
359 } 400 }
360 401
361 ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer, 402 ACPI_MEMCPY(table_desc.pointer, table, length);
362 length); 403 table_desc.address = ACPI_TO_INTEGER(table_desc.pointer);
363 table_desc.length = length;
364 table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
365 break; 404 break;
366 405
367 default: 406 default:
368 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 407 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
369 } 408 }
370 409
371 /* 410 /* Validate table checksum (will not get validated in tb_add_table) */
372 * Install the new table into the local data structures 411
373 */ 412 status = acpi_tb_verify_checksum(table_desc.pointer, length);
413 if (ACPI_FAILURE(status)) {
414 ACPI_FREE(table_desc.pointer);
415 return_ACPI_STATUS(status);
416 }
417
418 /* Complete the table descriptor */
419
420 table_desc.length = length;
421 table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
422
423 /* Install the new table into the local data structures */
424
374 status = acpi_tb_add_table(&table_desc, &table_index); 425 status = acpi_tb_add_table(&table_desc, &table_index);
375 if (ACPI_FAILURE(status)) { 426 if (ACPI_FAILURE(status)) {
376 goto cleanup; 427 goto cleanup;
@@ -379,7 +430,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
379 /* 430 /*
380 * Add the table to the namespace. 431 * Add the table to the namespace.
381 * 432 *
382 * Note: We load the table objects relative to the root of the namespace. 433 * Note: Load the table objects relative to the root of the namespace.
383 * This appears to go against the ACPI specification, but we do it for 434 * This appears to go against the ACPI specification, but we do it for
384 * compatibility with other ACPI implementations. 435 * compatibility with other ACPI implementations.
385 */ 436 */
@@ -415,7 +466,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
415 cleanup: 466 cleanup:
416 if (ACPI_FAILURE(status)) { 467 if (ACPI_FAILURE(status)) {
417 468
418 /* Delete allocated buffer or mapping */ 469 /* Delete allocated table buffer */
419 470
420 acpi_tb_delete_table(&table_desc); 471 acpi_tb_delete_table(&table_desc);
421 } 472 }