diff options
Diffstat (limited to 'drivers/acpi/executer/exconfig.c')
-rw-r--r-- | drivers/acpi/executer/exconfig.c | 105 |
1 files changed, 85 insertions, 20 deletions
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 25802f302ffe..24da921d13e3 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -45,7 +45,6 @@ | |||
45 | #include <acpi/acinterp.h> | 45 | #include <acpi/acinterp.h> |
46 | #include <acpi/amlcode.h> | 46 | #include <acpi/amlcode.h> |
47 | #include <acpi/acnamesp.h> | 47 | #include <acpi/acnamesp.h> |
48 | #include <acpi/acevents.h> | ||
49 | #include <acpi/actables.h> | 48 | #include <acpi/actables.h> |
50 | #include <acpi/acdispat.h> | 49 | #include <acpi/acdispat.h> |
51 | 50 | ||
@@ -138,6 +137,14 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
138 | 137 | ||
139 | ACPI_FUNCTION_TRACE(ex_load_table_op); | 138 | ACPI_FUNCTION_TRACE(ex_load_table_op); |
140 | 139 | ||
140 | /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */ | ||
141 | |||
142 | if ((operand[0]->string.length > ACPI_NAME_SIZE) || | ||
143 | (operand[1]->string.length > ACPI_OEM_ID_SIZE) || | ||
144 | (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) { | ||
145 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
146 | } | ||
147 | |||
141 | /* Find the ACPI table in the RSDT/XSDT */ | 148 | /* Find the ACPI table in the RSDT/XSDT */ |
142 | 149 | ||
143 | status = acpi_tb_find_table(operand[0]->string.pointer, | 150 | status = acpi_tb_find_table(operand[0]->string.pointer, |
@@ -229,11 +236,18 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
229 | status = acpi_get_table_by_index(table_index, &table); | 236 | status = acpi_get_table_by_index(table_index, &table); |
230 | if (ACPI_SUCCESS(status)) { | 237 | if (ACPI_SUCCESS(status)) { |
231 | ACPI_INFO((AE_INFO, | 238 | ACPI_INFO((AE_INFO, |
232 | "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]", | 239 | "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]", |
233 | table->signature, table->oem_id, | 240 | table->signature, table->oem_id, |
234 | table->oem_table_id)); | 241 | table->oem_table_id)); |
235 | } | 242 | } |
236 | 243 | ||
244 | /* Invoke table handler if present */ | ||
245 | |||
246 | if (acpi_gbl_table_handler) { | ||
247 | (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, | ||
248 | acpi_gbl_table_handler_context); | ||
249 | } | ||
250 | |||
237 | *return_desc = ddb_handle; | 251 | *return_desc = ddb_handle; |
238 | return_ACPI_STATUS(status); | 252 | return_ACPI_STATUS(status); |
239 | } | 253 | } |
@@ -268,6 +282,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
268 | struct acpi_table_desc table_desc; | 282 | struct acpi_table_desc table_desc; |
269 | acpi_native_uint table_index; | 283 | acpi_native_uint table_index; |
270 | acpi_status status; | 284 | acpi_status status; |
285 | u32 length; | ||
271 | 286 | ||
272 | ACPI_FUNCTION_TRACE(ex_load_op); | 287 | ACPI_FUNCTION_TRACE(ex_load_op); |
273 | 288 | ||
@@ -278,16 +293,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
278 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { | 293 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { |
279 | case ACPI_TYPE_REGION: | 294 | case ACPI_TYPE_REGION: |
280 | 295 | ||
296 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", | ||
297 | obj_desc, | ||
298 | acpi_ut_get_object_type_name(obj_desc))); | ||
299 | |||
281 | /* Region must be system_memory (from ACPI spec) */ | 300 | /* Region must be system_memory (from ACPI spec) */ |
282 | 301 | ||
283 | if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { | 302 | if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
284 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 303 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
285 | } | 304 | } |
286 | 305 | ||
287 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", | ||
288 | obj_desc, | ||
289 | acpi_ut_get_object_type_name(obj_desc))); | ||
290 | |||
291 | /* | 306 | /* |
292 | * If the Region Address and Length have not been previously evaluated, | 307 | * If the Region Address and Length have not been previously evaluated, |
293 | * evaluate them now and save the results. | 308 | * evaluate them now and save the results. |
@@ -299,6 +314,11 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
299 | } | 314 | } |
300 | } | 315 | } |
301 | 316 | ||
317 | /* | ||
318 | * We will simply map the memory region for the table. However, the | ||
319 | * memory region is technically not guaranteed to remain stable and | ||
320 | * we may eventually have to copy the table to a local buffer. | ||
321 | */ | ||
302 | table_desc.address = obj_desc->region.address; | 322 | table_desc.address = obj_desc->region.address; |
303 | table_desc.length = obj_desc->region.length; | 323 | table_desc.length = obj_desc->region.length; |
304 | table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; | 324 | table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; |
@@ -306,18 +326,41 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
306 | 326 | ||
307 | case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ | 327 | case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ |
308 | 328 | ||
309 | /* Simply extract the buffer from the buffer object */ | ||
310 | |||
311 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 329 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
312 | "Load from Buffer or Field %p %s\n", obj_desc, | 330 | "Load from Buffer or Field %p %s\n", obj_desc, |
313 | acpi_ut_get_object_type_name(obj_desc))); | 331 | acpi_ut_get_object_type_name(obj_desc))); |
314 | 332 | ||
315 | table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header, | 333 | length = obj_desc->buffer.length; |
316 | obj_desc->buffer.pointer); | 334 | |
317 | table_desc.length = table_desc.pointer->length; | 335 | /* Must have at least an ACPI table header */ |
318 | table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; | 336 | |
337 | if (length < sizeof(struct acpi_table_header)) { | ||
338 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); | ||
339 | } | ||
340 | |||
341 | /* Validate checksum here. It won't get validated in tb_add_table */ | ||
319 | 342 | ||
320 | obj_desc->buffer.pointer = NULL; | 343 | status = |
344 | acpi_tb_verify_checksum(ACPI_CAST_PTR | ||
345 | (struct acpi_table_header, | ||
346 | obj_desc->buffer.pointer), length); | ||
347 | if (ACPI_FAILURE(status)) { | ||
348 | return_ACPI_STATUS(status); | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * We need to copy the buffer since the original buffer could be | ||
353 | * changed or deleted in the future | ||
354 | */ | ||
355 | table_desc.pointer = ACPI_ALLOCATE(length); | ||
356 | if (!table_desc.pointer) { | ||
357 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
358 | } | ||
359 | |||
360 | ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer, | ||
361 | length); | ||
362 | table_desc.length = length; | ||
363 | table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; | ||
321 | break; | 364 | break; |
322 | 365 | ||
323 | default: | 366 | default: |
@@ -333,7 +376,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
333 | } | 376 | } |
334 | 377 | ||
335 | status = | 378 | status = |
336 | acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); | 379 | acpi_ex_add_table(table_index, walk_state->scope_info->scope.node, |
380 | &ddb_handle); | ||
337 | if (ACPI_FAILURE(status)) { | 381 | if (ACPI_FAILURE(status)) { |
338 | 382 | ||
339 | /* On error, table_ptr was deallocated above */ | 383 | /* On error, table_ptr was deallocated above */ |
@@ -349,11 +393,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
349 | 393 | ||
350 | /* table_ptr was deallocated above */ | 394 | /* table_ptr was deallocated above */ |
351 | 395 | ||
396 | acpi_ut_remove_reference(ddb_handle); | ||
352 | return_ACPI_STATUS(status); | 397 | return_ACPI_STATUS(status); |
353 | } | 398 | } |
354 | 399 | ||
400 | /* Invoke table handler if present */ | ||
401 | |||
402 | if (acpi_gbl_table_handler) { | ||
403 | (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, | ||
404 | table_desc.pointer, | ||
405 | acpi_gbl_table_handler_context); | ||
406 | } | ||
407 | |||
355 | cleanup: | 408 | cleanup: |
356 | if (ACPI_FAILURE(status)) { | 409 | if (ACPI_FAILURE(status)) { |
410 | |||
411 | /* Delete allocated buffer or mapping */ | ||
412 | |||
357 | acpi_tb_delete_table(&table_desc); | 413 | acpi_tb_delete_table(&table_desc); |
358 | } | 414 | } |
359 | return_ACPI_STATUS(status); | 415 | return_ACPI_STATUS(status); |
@@ -376,6 +432,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) | |||
376 | acpi_status status = AE_OK; | 432 | acpi_status status = AE_OK; |
377 | union acpi_operand_object *table_desc = ddb_handle; | 433 | union acpi_operand_object *table_desc = ddb_handle; |
378 | acpi_native_uint table_index; | 434 | acpi_native_uint table_index; |
435 | struct acpi_table_header *table; | ||
379 | 436 | ||
380 | ACPI_FUNCTION_TRACE(ex_unload_table); | 437 | ACPI_FUNCTION_TRACE(ex_unload_table); |
381 | 438 | ||
@@ -395,17 +452,25 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) | |||
395 | 452 | ||
396 | table_index = (acpi_native_uint) table_desc->reference.object; | 453 | table_index = (acpi_native_uint) table_desc->reference.object; |
397 | 454 | ||
455 | /* Invoke table handler if present */ | ||
456 | |||
457 | if (acpi_gbl_table_handler) { | ||
458 | status = acpi_get_table_by_index(table_index, &table); | ||
459 | if (ACPI_SUCCESS(status)) { | ||
460 | (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, | ||
461 | table, | ||
462 | acpi_gbl_table_handler_context); | ||
463 | } | ||
464 | } | ||
465 | |||
398 | /* | 466 | /* |
399 | * Delete the entire namespace under this table Node | 467 | * Delete the entire namespace under this table Node |
400 | * (Offset contains the table_id) | 468 | * (Offset contains the table_id) |
401 | */ | 469 | */ |
402 | acpi_tb_delete_namespace_by_owner(table_index); | 470 | acpi_tb_delete_namespace_by_owner(table_index); |
403 | acpi_tb_release_owner_id(table_index); | 471 | (void)acpi_tb_release_owner_id(table_index); |
404 | 472 | ||
405 | acpi_tb_set_table_loaded_flag(table_index, FALSE); | 473 | acpi_tb_set_table_loaded_flag(table_index, FALSE); |
406 | 474 | ||
407 | /* Delete the table descriptor (ddb_handle) */ | 475 | return_ACPI_STATUS(AE_OK); |
408 | |||
409 | acpi_ut_remove_reference(table_desc); | ||
410 | return_ACPI_STATUS(status); | ||
411 | } | 476 | } |