diff options
Diffstat (limited to 'drivers/acpi/executer/exconfig.c')
-rw-r--r-- | drivers/acpi/executer/exconfig.c | 123 |
1 files changed, 86 insertions, 37 deletions
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 8892b9824fae..74da6fa52ef1 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c | |||
@@ -43,7 +43,6 @@ | |||
43 | 43 | ||
44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
45 | #include <acpi/acinterp.h> | 45 | #include <acpi/acinterp.h> |
46 | #include <acpi/amlcode.h> | ||
47 | #include <acpi/acnamesp.h> | 46 | #include <acpi/acnamesp.h> |
48 | #include <acpi/actables.h> | 47 | #include <acpi/actables.h> |
49 | #include <acpi/acdispat.h> | 48 | #include <acpi/acdispat.h> |
@@ -91,13 +90,12 @@ acpi_ex_add_table(u32 table_index, | |||
91 | 90 | ||
92 | /* Init the table handle */ | 91 | /* Init the table handle */ |
93 | 92 | ||
94 | obj_desc->reference.opcode = AML_LOAD_OP; | 93 | obj_desc->reference.class = ACPI_REFCLASS_TABLE; |
95 | *ddb_handle = obj_desc; | 94 | *ddb_handle = obj_desc; |
96 | 95 | ||
97 | /* Install the new table into the local data structures */ | 96 | /* Install the new table into the local data structures */ |
98 | 97 | ||
99 | obj_desc->reference.object = ACPI_CAST_PTR(void, | 98 | obj_desc->reference.value = table_index; |
100 | (unsigned long)table_index); | ||
101 | 99 | ||
102 | /* Add the table to the namespace */ | 100 | /* Add the table to the namespace */ |
103 | 101 | ||
@@ -280,6 +278,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
280 | struct acpi_walk_state *walk_state) | 278 | struct acpi_walk_state *walk_state) |
281 | { | 279 | { |
282 | union acpi_operand_object *ddb_handle; | 280 | union acpi_operand_object *ddb_handle; |
281 | struct acpi_table_header *table; | ||
283 | struct acpi_table_desc table_desc; | 282 | struct acpi_table_desc table_desc; |
284 | u32 table_index; | 283 | u32 table_index; |
285 | acpi_status status; | 284 | acpi_status status; |
@@ -294,9 +293,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
294 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { | 293 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { |
295 | case ACPI_TYPE_REGION: | 294 | case ACPI_TYPE_REGION: |
296 | 295 | ||
297 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", | 296 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
298 | obj_desc, | 297 | "Load table from Region %p\n", obj_desc)); |
299 | acpi_ut_get_object_type_name(obj_desc))); | ||
300 | 298 | ||
301 | /* Region must be system_memory (from ACPI spec) */ | 299 | /* Region must be system_memory (from ACPI spec) */ |
302 | 300 | ||
@@ -316,61 +314,112 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
316 | } | 314 | } |
317 | 315 | ||
318 | /* | 316 | /* |
319 | * We will simply map the memory region for the table. However, the | 317 | * Map the table header and get the actual table length. The region |
320 | * memory region is technically not guaranteed to remain stable and | 318 | * 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. | 319 | */ |
320 | table = acpi_os_map_memory(obj_desc->region.address, | ||
321 | sizeof(struct acpi_table_header)); | ||
322 | if (!table) { | ||
323 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
324 | } | ||
325 | |||
326 | length = table->length; | ||
327 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); | ||
328 | |||
329 | /* Must have at least an ACPI table header */ | ||
330 | |||
331 | if (length < sizeof(struct acpi_table_header)) { | ||
332 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); | ||
333 | } | ||
334 | |||
335 | /* | ||
336 | * The memory region is not guaranteed to remain stable and we must | ||
337 | * copy the table to a local buffer. For example, the memory region | ||
338 | * is corrupted after suspend on some machines. Dynamically loaded | ||
339 | * tables are usually small, so this overhead is minimal. | ||
322 | */ | 340 | */ |
341 | |||
342 | /* Allocate a buffer for the table */ | ||
343 | |||
344 | table_desc.pointer = ACPI_ALLOCATE(length); | ||
345 | if (!table_desc.pointer) { | ||
346 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
347 | } | ||
348 | |||
349 | /* Map the entire table and copy it */ | ||
350 | |||
351 | table = acpi_os_map_memory(obj_desc->region.address, length); | ||
352 | if (!table) { | ||
353 | ACPI_FREE(table_desc.pointer); | ||
354 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
355 | } | ||
356 | |||
357 | ACPI_MEMCPY(table_desc.pointer, table, length); | ||
358 | acpi_os_unmap_memory(table, length); | ||
359 | |||
323 | table_desc.address = obj_desc->region.address; | 360 | 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; | 361 | break; |
327 | 362 | ||
328 | case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ | 363 | case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ |
329 | 364 | ||
330 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 365 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
331 | "Load from Buffer or Field %p %s\n", obj_desc, | 366 | "Load table from Buffer or Field %p\n", |
332 | acpi_ut_get_object_type_name(obj_desc))); | 367 | obj_desc)); |
333 | |||
334 | length = obj_desc->buffer.length; | ||
335 | 368 | ||
336 | /* Must have at least an ACPI table header */ | 369 | /* Must have at least an ACPI table header */ |
337 | 370 | ||
338 | if (length < sizeof(struct acpi_table_header)) { | 371 | if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) { |
339 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); | 372 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); |
340 | } | 373 | } |
341 | 374 | ||
342 | /* Validate checksum here. It won't get validated in tb_add_table */ | 375 | /* Get the actual table length from the table header */ |
343 | 376 | ||
344 | status = | 377 | table = |
345 | acpi_tb_verify_checksum(ACPI_CAST_PTR | 378 | ACPI_CAST_PTR(struct acpi_table_header, |
346 | (struct acpi_table_header, | 379 | obj_desc->buffer.pointer); |
347 | obj_desc->buffer.pointer), length); | 380 | length = table->length; |
348 | if (ACPI_FAILURE(status)) { | 381 | |
349 | return_ACPI_STATUS(status); | 382 | /* Table cannot extend beyond the buffer */ |
383 | |||
384 | if (length > obj_desc->buffer.length) { | ||
385 | return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); | ||
386 | } | ||
387 | if (length < sizeof(struct acpi_table_header)) { | ||
388 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); | ||
350 | } | 389 | } |
351 | 390 | ||
352 | /* | 391 | /* |
353 | * We need to copy the buffer since the original buffer could be | 392 | * Copy the table from the buffer because the buffer could be modified |
354 | * changed or deleted in the future | 393 | * or even deleted in the future |
355 | */ | 394 | */ |
356 | table_desc.pointer = ACPI_ALLOCATE(length); | 395 | table_desc.pointer = ACPI_ALLOCATE(length); |
357 | if (!table_desc.pointer) { | 396 | if (!table_desc.pointer) { |
358 | return_ACPI_STATUS(AE_NO_MEMORY); | 397 | return_ACPI_STATUS(AE_NO_MEMORY); |
359 | } | 398 | } |
360 | 399 | ||
361 | ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer, | 400 | ACPI_MEMCPY(table_desc.pointer, table, length); |
362 | length); | 401 | table_desc.address = ACPI_TO_INTEGER(table_desc.pointer); |
363 | table_desc.length = length; | ||
364 | table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; | ||
365 | break; | 402 | break; |
366 | 403 | ||
367 | default: | 404 | default: |
368 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 405 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
369 | } | 406 | } |
370 | 407 | ||
371 | /* | 408 | /* Validate table checksum (will not get validated in tb_add_table) */ |
372 | * Install the new table into the local data structures | 409 | |
373 | */ | 410 | status = acpi_tb_verify_checksum(table_desc.pointer, length); |
411 | if (ACPI_FAILURE(status)) { | ||
412 | ACPI_FREE(table_desc.pointer); | ||
413 | return_ACPI_STATUS(status); | ||
414 | } | ||
415 | |||
416 | /* Complete the table descriptor */ | ||
417 | |||
418 | table_desc.length = length; | ||
419 | table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; | ||
420 | |||
421 | /* Install the new table into the local data structures */ | ||
422 | |||
374 | status = acpi_tb_add_table(&table_desc, &table_index); | 423 | status = acpi_tb_add_table(&table_desc, &table_index); |
375 | if (ACPI_FAILURE(status)) { | 424 | if (ACPI_FAILURE(status)) { |
376 | goto cleanup; | 425 | goto cleanup; |
@@ -379,7 +428,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
379 | /* | 428 | /* |
380 | * Add the table to the namespace. | 429 | * Add the table to the namespace. |
381 | * | 430 | * |
382 | * Note: We load the table objects relative to the root of the namespace. | 431 | * 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 | 432 | * This appears to go against the ACPI specification, but we do it for |
384 | * compatibility with other ACPI implementations. | 433 | * compatibility with other ACPI implementations. |
385 | */ | 434 | */ |
@@ -415,7 +464,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
415 | cleanup: | 464 | cleanup: |
416 | if (ACPI_FAILURE(status)) { | 465 | if (ACPI_FAILURE(status)) { |
417 | 466 | ||
418 | /* Delete allocated buffer or mapping */ | 467 | /* Delete allocated table buffer */ |
419 | 468 | ||
420 | acpi_tb_delete_table(&table_desc); | 469 | acpi_tb_delete_table(&table_desc); |
421 | } | 470 | } |
@@ -455,9 +504,9 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) | |||
455 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 504 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
456 | } | 505 | } |
457 | 506 | ||
458 | /* Get the table index from the ddb_handle (acpi_size for 64-bit case) */ | 507 | /* Get the table index from the ddb_handle */ |
459 | 508 | ||
460 | table_index = (u32) (acpi_size) table_desc->reference.object; | 509 | table_index = table_desc->reference.value; |
461 | 510 | ||
462 | /* Invoke table handler if present */ | 511 | /* Invoke table handler if present */ |
463 | 512 | ||