Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Bob Moore and committed by
Len Brown
ac5f98db 4bbfb85d

+50 -46
-1
drivers/acpi/acpica/acglobal.h
··· 371 371 ACPI_EXTERN char *acpi_gbl_db_filename; 372 372 ACPI_EXTERN u32 acpi_gbl_db_debug_level; 373 373 ACPI_EXTERN u32 acpi_gbl_db_console_debug_level; 374 - ACPI_EXTERN struct acpi_table_header *acpi_gbl_db_table_ptr; 375 374 ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node; 376 375 377 376 /*
+46 -13
drivers/acpi/acpica/tbutils.c
··· 287 287 * 288 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 ··· 298 295 acpi_tb_install_table(acpi_physical_address address, 299 296 u8 flags, char *signature, u32 table_index) 300 297 { 301 - struct acpi_table_header *table; 298 + acpi_status status; 299 + struct acpi_table_header *table_to_install; 300 + struct acpi_table_header *mapped_table; 301 + struct acpi_table_header *override_table = NULL; 302 302 303 303 if (!address) { 304 304 ACPI_ERROR((AE_INFO, ··· 312 306 313 307 /* Map just the table header */ 314 308 315 - table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); 316 - if (!table) { 309 + mapped_table = 310 + acpi_os_map_memory(address, sizeof(struct acpi_table_header)); 311 + if (!mapped_table) { 317 312 return; 318 313 } 319 314 320 - /* If a particular signature is expected, signature must match */ 315 + /* If a particular signature is expected (DSDT/FACS), it must match */ 321 316 322 - if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { 317 + if (signature && !ACPI_COMPARE_NAME(mapped_table->signature, signature)) { 323 318 ACPI_ERROR((AE_INFO, 324 - "Invalid signature 0x%X for ACPI table [%s]", 325 - *ACPI_CAST_PTR(u32, table->signature), signature)); 319 + "Invalid signature 0x%X for ACPI table, expected [%s]", 320 + *ACPI_CAST_PTR(u32, mapped_table->signature), 321 + signature)); 326 322 goto unmap_and_exit; 323 + } 324 + 325 + /* 326 + * ACPI Table Override: 327 + * 328 + * Before we install the table, let the host OS override it with a new 329 + * one if desired. Any table within the RSDT/XSDT can be replaced, 330 + * including the DSDT which is pointed to by the FADT. 331 + */ 332 + status = acpi_os_table_override(mapped_table, &override_table); 333 + if (ACPI_SUCCESS(status) && override_table) { 334 + ACPI_INFO((AE_INFO, 335 + "%4.4s @ 0x%p Table override, replaced with:", 336 + mapped_table->signature, ACPI_CAST_PTR(void, 337 + address))); 338 + 339 + acpi_gbl_root_table_list.tables[table_index].pointer = 340 + override_table; 341 + flags = ACPI_TABLE_ORIGIN_OVERRIDE; 342 + address = ACPI_PTR_TO_PHYSADDR(override_table); 343 + 344 + table_to_install = override_table; 345 + } else { 346 + table_to_install = mapped_table; 327 347 } 328 348 329 349 /* Initialize the table entry */ 330 350 331 351 acpi_gbl_root_table_list.tables[table_index].address = address; 332 - acpi_gbl_root_table_list.tables[table_index].length = table->length; 352 + acpi_gbl_root_table_list.tables[table_index].length = 353 + table_to_install->length; 333 354 acpi_gbl_root_table_list.tables[table_index].flags = flags; 334 355 335 356 ACPI_MOVE_32_TO_32(& 336 357 (acpi_gbl_root_table_list.tables[table_index]. 337 - signature), table->signature); 358 + signature), table_to_install->signature); 338 359 339 - acpi_tb_print_table_header(address, table); 360 + acpi_tb_print_table_header(address, table_to_install); 340 361 341 362 if (table_index == ACPI_TABLE_INDEX_DSDT) { 342 363 343 364 /* Global integer width is based upon revision of the DSDT */ 344 365 345 - acpi_ut_set_integer_width(table->revision); 366 + acpi_ut_set_integer_width(table_to_install->revision); 346 367 } 347 368 348 369 unmap_and_exit: 349 - acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); 370 + acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header)); 350 371 } 351 372 352 373 /*******************************************************************************
+1 -30
drivers/acpi/acpica/tbxface.c
··· 491 491 static acpi_status acpi_tb_load_namespace(void) 492 492 { 493 493 acpi_status status; 494 - struct acpi_table_header *table; 495 494 u32 i; 496 495 497 496 ACPI_FUNCTION_TRACE(tb_load_namespace); ··· 514 515 goto unlock_and_exit; 515 516 } 516 517 517 - /* 518 - * Find DSDT table 519 - */ 520 - status = 521 - acpi_os_table_override(acpi_gbl_root_table_list. 522 - tables[ACPI_TABLE_INDEX_DSDT].pointer, 523 - &table); 524 - if (ACPI_SUCCESS(status) && table) { 525 - /* 526 - * DSDT table has been found 527 - */ 528 - acpi_tb_delete_table(&acpi_gbl_root_table_list. 529 - tables[ACPI_TABLE_INDEX_DSDT]); 530 - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer = 531 - table; 532 - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = 533 - table->length; 534 - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = 535 - ACPI_TABLE_ORIGIN_UNKNOWN; 536 - 537 - ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); 538 - acpi_tb_print_table_header(0, table); 539 - 540 - if (no_auto_ssdt == 0) { 541 - printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n"); 542 - } 543 - } 518 + /* A valid DSDT is required */ 544 519 545 520 status = 546 521 acpi_tb_verify_table(&acpi_gbl_root_table_list. 547 522 tables[ACPI_TABLE_INDEX_DSDT]); 548 523 if (ACPI_FAILURE(status)) { 549 - 550 - /* A valid DSDT is required */ 551 524 552 525 status = AE_NO_ACPI_TABLES; 553 526 goto unlock_and_exit;
+3 -2
include/acpi/actbl.h
··· 310 310 #define ACPI_TABLE_ORIGIN_UNKNOWN (0) 311 311 #define ACPI_TABLE_ORIGIN_MAPPED (1) 312 312 #define ACPI_TABLE_ORIGIN_ALLOCATED (2) 313 - #define ACPI_TABLE_ORIGIN_MASK (3) 314 - #define ACPI_TABLE_IS_LOADED (4) 313 + #define ACPI_TABLE_ORIGIN_OVERRIDE (4) 314 + #define ACPI_TABLE_ORIGIN_MASK (7) 315 + #define ACPI_TABLE_IS_LOADED (8) 315 316 316 317 /* 317 318 * Get the remaining ACPI tables