aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/executer/exconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/executer/exconfig.c')
-rw-r--r--drivers/acpi/executer/exconfig.c105
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}