diff options
author | Bob Moore <robert.moore@intel.com> | 2009-02-03 01:35:25 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-03-26 16:38:19 -0400 |
commit | ac5f98db7be34cefc244026f882cf030debb7431 (patch) | |
tree | 7746bc75e1a8f4344b8673b5d2b54bc07147ca0f /drivers/acpi/acpica | |
parent | 4bbfb85da27c27e9cc9a7fef4bd75df6361152ff (diff) |
ACPICA: Allow OS override of all ACPI tables
Previously, the table override mechanism was implemented for the
DSDT only. Now, any table in the RSDT/XSDT can be replaced by
the host OS. (including the DSDT).
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r-- | drivers/acpi/acpica/acglobal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/tbutils.c | 59 | ||||
-rw-r--r-- | drivers/acpi/acpica/tbxface.c | 31 |
3 files changed, 47 insertions, 44 deletions
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index ddb40f5c68fc..634fb0785e7e 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h | |||
@@ -371,7 +371,6 @@ ACPI_EXTERN char *acpi_gbl_db_buffer; | |||
371 | ACPI_EXTERN char *acpi_gbl_db_filename; | 371 | ACPI_EXTERN char *acpi_gbl_db_filename; |
372 | ACPI_EXTERN u32 acpi_gbl_db_debug_level; | 372 | ACPI_EXTERN u32 acpi_gbl_db_debug_level; |
373 | ACPI_EXTERN u32 acpi_gbl_db_console_debug_level; | 373 | ACPI_EXTERN u32 acpi_gbl_db_console_debug_level; |
374 | ACPI_EXTERN struct acpi_table_header *acpi_gbl_db_table_ptr; | ||
375 | ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node; | 374 | ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node; |
376 | 375 | ||
377 | /* | 376 | /* |
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 22ce48985720..e285bedbb989 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c | |||
@@ -287,7 +287,10 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length) | |||
287 | * | 287 | * |
288 | * RETURN: None | 288 | * RETURN: None |
289 | * | 289 | * |
290 | * DESCRIPTION: Install an ACPI table into the global data structure. | 290 | * DESCRIPTION: Install an ACPI table into the global data structure. The |
291 | * table override mechanism is implemented here to allow the host | ||
292 | * OS to replace any table before it is installed in the root | ||
293 | * table array. | ||
291 | * | 294 | * |
292 | ******************************************************************************/ | 295 | ******************************************************************************/ |
293 | 296 | ||
@@ -295,7 +298,10 @@ void | |||
295 | acpi_tb_install_table(acpi_physical_address address, | 298 | acpi_tb_install_table(acpi_physical_address address, |
296 | u8 flags, char *signature, u32 table_index) | 299 | u8 flags, char *signature, u32 table_index) |
297 | { | 300 | { |
298 | struct acpi_table_header *table; | 301 | acpi_status status; |
302 | struct acpi_table_header *table_to_install; | ||
303 | struct acpi_table_header *mapped_table; | ||
304 | struct acpi_table_header *override_table = NULL; | ||
299 | 305 | ||
300 | if (!address) { | 306 | if (!address) { |
301 | ACPI_ERROR((AE_INFO, | 307 | ACPI_ERROR((AE_INFO, |
@@ -306,41 +312,68 @@ acpi_tb_install_table(acpi_physical_address address, | |||
306 | 312 | ||
307 | /* Map just the table header */ | 313 | /* Map just the table header */ |
308 | 314 | ||
309 | table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); | 315 | mapped_table = |
310 | if (!table) { | 316 | acpi_os_map_memory(address, sizeof(struct acpi_table_header)); |
317 | if (!mapped_table) { | ||
311 | return; | 318 | return; |
312 | } | 319 | } |
313 | 320 | ||
314 | /* If a particular signature is expected, signature must match */ | 321 | /* If a particular signature is expected (DSDT/FACS), it must match */ |
315 | 322 | ||
316 | if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { | 323 | if (signature && !ACPI_COMPARE_NAME(mapped_table->signature, signature)) { |
317 | ACPI_ERROR((AE_INFO, | 324 | ACPI_ERROR((AE_INFO, |
318 | "Invalid signature 0x%X for ACPI table [%s]", | 325 | "Invalid signature 0x%X for ACPI table, expected [%s]", |
319 | *ACPI_CAST_PTR(u32, table->signature), signature)); | 326 | *ACPI_CAST_PTR(u32, mapped_table->signature), |
327 | signature)); | ||
320 | goto unmap_and_exit; | 328 | goto unmap_and_exit; |
321 | } | 329 | } |
322 | 330 | ||
331 | /* | ||
332 | * ACPI Table Override: | ||
333 | * | ||
334 | * Before we install the table, let the host OS override it with a new | ||
335 | * one if desired. Any table within the RSDT/XSDT can be replaced, | ||
336 | * including the DSDT which is pointed to by the FADT. | ||
337 | */ | ||
338 | status = acpi_os_table_override(mapped_table, &override_table); | ||
339 | if (ACPI_SUCCESS(status) && override_table) { | ||
340 | ACPI_INFO((AE_INFO, | ||
341 | "%4.4s @ 0x%p Table override, replaced with:", | ||
342 | mapped_table->signature, ACPI_CAST_PTR(void, | ||
343 | address))); | ||
344 | |||
345 | acpi_gbl_root_table_list.tables[table_index].pointer = | ||
346 | override_table; | ||
347 | flags = ACPI_TABLE_ORIGIN_OVERRIDE; | ||
348 | address = ACPI_PTR_TO_PHYSADDR(override_table); | ||
349 | |||
350 | table_to_install = override_table; | ||
351 | } else { | ||
352 | table_to_install = mapped_table; | ||
353 | } | ||
354 | |||
323 | /* Initialize the table entry */ | 355 | /* Initialize the table entry */ |
324 | 356 | ||
325 | acpi_gbl_root_table_list.tables[table_index].address = address; | 357 | acpi_gbl_root_table_list.tables[table_index].address = address; |
326 | acpi_gbl_root_table_list.tables[table_index].length = table->length; | 358 | acpi_gbl_root_table_list.tables[table_index].length = |
359 | table_to_install->length; | ||
327 | acpi_gbl_root_table_list.tables[table_index].flags = flags; | 360 | acpi_gbl_root_table_list.tables[table_index].flags = flags; |
328 | 361 | ||
329 | ACPI_MOVE_32_TO_32(& | 362 | ACPI_MOVE_32_TO_32(& |
330 | (acpi_gbl_root_table_list.tables[table_index]. | 363 | (acpi_gbl_root_table_list.tables[table_index]. |
331 | signature), table->signature); | 364 | signature), table_to_install->signature); |
332 | 365 | ||
333 | acpi_tb_print_table_header(address, table); | 366 | acpi_tb_print_table_header(address, table_to_install); |
334 | 367 | ||
335 | if (table_index == ACPI_TABLE_INDEX_DSDT) { | 368 | if (table_index == ACPI_TABLE_INDEX_DSDT) { |
336 | 369 | ||
337 | /* Global integer width is based upon revision of the DSDT */ | 370 | /* Global integer width is based upon revision of the DSDT */ |
338 | 371 | ||
339 | acpi_ut_set_integer_width(table->revision); | 372 | acpi_ut_set_integer_width(table_to_install->revision); |
340 | } | 373 | } |
341 | 374 | ||
342 | unmap_and_exit: | 375 | unmap_and_exit: |
343 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); | 376 | acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header)); |
344 | } | 377 | } |
345 | 378 | ||
346 | /******************************************************************************* | 379 | /******************************************************************************* |
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index c3e841f3cde9..f3f95e386334 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c | |||
@@ -491,7 +491,6 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) | |||
491 | static acpi_status acpi_tb_load_namespace(void) | 491 | static acpi_status acpi_tb_load_namespace(void) |
492 | { | 492 | { |
493 | acpi_status status; | 493 | acpi_status status; |
494 | struct acpi_table_header *table; | ||
495 | u32 i; | 494 | u32 i; |
496 | 495 | ||
497 | ACPI_FUNCTION_TRACE(tb_load_namespace); | 496 | ACPI_FUNCTION_TRACE(tb_load_namespace); |
@@ -515,41 +514,13 @@ static acpi_status acpi_tb_load_namespace(void) | |||
515 | goto unlock_and_exit; | 514 | goto unlock_and_exit; |
516 | } | 515 | } |
517 | 516 | ||
518 | /* | 517 | /* A valid DSDT is required */ |
519 | * Find DSDT table | ||
520 | */ | ||
521 | status = | ||
522 | acpi_os_table_override(acpi_gbl_root_table_list. | ||
523 | tables[ACPI_TABLE_INDEX_DSDT].pointer, | ||
524 | &table); | ||
525 | if (ACPI_SUCCESS(status) && table) { | ||
526 | /* | ||
527 | * DSDT table has been found | ||
528 | */ | ||
529 | acpi_tb_delete_table(&acpi_gbl_root_table_list. | ||
530 | tables[ACPI_TABLE_INDEX_DSDT]); | ||
531 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer = | ||
532 | table; | ||
533 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = | ||
534 | table->length; | ||
535 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = | ||
536 | ACPI_TABLE_ORIGIN_UNKNOWN; | ||
537 | |||
538 | ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); | ||
539 | acpi_tb_print_table_header(0, table); | ||
540 | |||
541 | if (no_auto_ssdt == 0) { | ||
542 | printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n"); | ||
543 | } | ||
544 | } | ||
545 | 518 | ||
546 | status = | 519 | status = |
547 | acpi_tb_verify_table(&acpi_gbl_root_table_list. | 520 | acpi_tb_verify_table(&acpi_gbl_root_table_list. |
548 | tables[ACPI_TABLE_INDEX_DSDT]); | 521 | tables[ACPI_TABLE_INDEX_DSDT]); |
549 | if (ACPI_FAILURE(status)) { | 522 | if (ACPI_FAILURE(status)) { |
550 | 523 | ||
551 | /* A valid DSDT is required */ | ||
552 | |||
553 | status = AE_NO_ACPI_TABLES; | 524 | status = AE_NO_ACPI_TABLES; |
554 | goto unlock_and_exit; | 525 | goto unlock_and_exit; |
555 | } | 526 | } |