mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
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>
This commit is contained in:
parent
4bbfb85da2
commit
ac5f98db7b
4 changed files with 50 additions and 46 deletions
|
@ -371,7 +371,6 @@ ACPI_EXTERN char *acpi_gbl_db_buffer;
|
|||
ACPI_EXTERN char *acpi_gbl_db_filename;
|
||||
ACPI_EXTERN u32 acpi_gbl_db_debug_level;
|
||||
ACPI_EXTERN u32 acpi_gbl_db_console_debug_level;
|
||||
ACPI_EXTERN struct acpi_table_header *acpi_gbl_db_table_ptr;
|
||||
ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node;
|
||||
|
||||
/*
|
||||
|
|
|
@ -287,7 +287,10 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length)
|
|||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Install an ACPI table into the global data structure.
|
||||
* DESCRIPTION: Install an ACPI table into the global data structure. The
|
||||
* table override mechanism is implemented here to allow the host
|
||||
* OS to replace any table before it is installed in the root
|
||||
* table array.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
@ -295,7 +298,10 @@ void
|
|||
acpi_tb_install_table(acpi_physical_address address,
|
||||
u8 flags, char *signature, u32 table_index)
|
||||
{
|
||||
struct acpi_table_header *table;
|
||||
acpi_status status;
|
||||
struct acpi_table_header *table_to_install;
|
||||
struct acpi_table_header *mapped_table;
|
||||
struct acpi_table_header *override_table = NULL;
|
||||
|
||||
if (!address) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
|
@ -306,41 +312,68 @@ acpi_tb_install_table(acpi_physical_address address,
|
|||
|
||||
/* Map just the table header */
|
||||
|
||||
table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
|
||||
if (!table) {
|
||||
mapped_table =
|
||||
acpi_os_map_memory(address, sizeof(struct acpi_table_header));
|
||||
if (!mapped_table) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If a particular signature is expected, signature must match */
|
||||
/* If a particular signature is expected (DSDT/FACS), it must match */
|
||||
|
||||
if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) {
|
||||
if (signature && !ACPI_COMPARE_NAME(mapped_table->signature, signature)) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Invalid signature 0x%X for ACPI table [%s]",
|
||||
*ACPI_CAST_PTR(u32, table->signature), signature));
|
||||
"Invalid signature 0x%X for ACPI table, expected [%s]",
|
||||
*ACPI_CAST_PTR(u32, mapped_table->signature),
|
||||
signature));
|
||||
goto unmap_and_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* ACPI Table Override:
|
||||
*
|
||||
* Before we install the table, let the host OS override it with a new
|
||||
* one if desired. Any table within the RSDT/XSDT can be replaced,
|
||||
* including the DSDT which is pointed to by the FADT.
|
||||
*/
|
||||
status = acpi_os_table_override(mapped_table, &override_table);
|
||||
if (ACPI_SUCCESS(status) && override_table) {
|
||||
ACPI_INFO((AE_INFO,
|
||||
"%4.4s @ 0x%p Table override, replaced with:",
|
||||
mapped_table->signature, ACPI_CAST_PTR(void,
|
||||
address)));
|
||||
|
||||
acpi_gbl_root_table_list.tables[table_index].pointer =
|
||||
override_table;
|
||||
flags = ACPI_TABLE_ORIGIN_OVERRIDE;
|
||||
address = ACPI_PTR_TO_PHYSADDR(override_table);
|
||||
|
||||
table_to_install = override_table;
|
||||
} else {
|
||||
table_to_install = mapped_table;
|
||||
}
|
||||
|
||||
/* Initialize the table entry */
|
||||
|
||||
acpi_gbl_root_table_list.tables[table_index].address = address;
|
||||
acpi_gbl_root_table_list.tables[table_index].length = table->length;
|
||||
acpi_gbl_root_table_list.tables[table_index].length =
|
||||
table_to_install->length;
|
||||
acpi_gbl_root_table_list.tables[table_index].flags = flags;
|
||||
|
||||
ACPI_MOVE_32_TO_32(&
|
||||
(acpi_gbl_root_table_list.tables[table_index].
|
||||
signature), table->signature);
|
||||
signature), table_to_install->signature);
|
||||
|
||||
acpi_tb_print_table_header(address, table);
|
||||
acpi_tb_print_table_header(address, table_to_install);
|
||||
|
||||
if (table_index == ACPI_TABLE_INDEX_DSDT) {
|
||||
|
||||
/* Global integer width is based upon revision of the DSDT */
|
||||
|
||||
acpi_ut_set_integer_width(table->revision);
|
||||
acpi_ut_set_integer_width(table_to_install->revision);
|
||||
}
|
||||
|
||||
unmap_and_exit:
|
||||
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
|
||||
acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -491,7 +491,6 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
|
|||
static acpi_status acpi_tb_load_namespace(void)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_table_header *table;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_load_namespace);
|
||||
|
@ -515,41 +514,13 @@ static acpi_status acpi_tb_load_namespace(void)
|
|||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find DSDT table
|
||||
*/
|
||||
status =
|
||||
acpi_os_table_override(acpi_gbl_root_table_list.
|
||||
tables[ACPI_TABLE_INDEX_DSDT].pointer,
|
||||
&table);
|
||||
if (ACPI_SUCCESS(status) && table) {
|
||||
/*
|
||||
* DSDT table has been found
|
||||
*/
|
||||
acpi_tb_delete_table(&acpi_gbl_root_table_list.
|
||||
tables[ACPI_TABLE_INDEX_DSDT]);
|
||||
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer =
|
||||
table;
|
||||
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length =
|
||||
table->length;
|
||||
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags =
|
||||
ACPI_TABLE_ORIGIN_UNKNOWN;
|
||||
|
||||
ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS"));
|
||||
acpi_tb_print_table_header(0, table);
|
||||
|
||||
if (no_auto_ssdt == 0) {
|
||||
printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n");
|
||||
}
|
||||
}
|
||||
/* A valid DSDT is required */
|
||||
|
||||
status =
|
||||
acpi_tb_verify_table(&acpi_gbl_root_table_list.
|
||||
tables[ACPI_TABLE_INDEX_DSDT]);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
||||
/* A valid DSDT is required */
|
||||
|
||||
status = AE_NO_ACPI_TABLES;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
|
|
@ -310,8 +310,9 @@ struct acpi_table_desc {
|
|||
#define ACPI_TABLE_ORIGIN_UNKNOWN (0)
|
||||
#define ACPI_TABLE_ORIGIN_MAPPED (1)
|
||||
#define ACPI_TABLE_ORIGIN_ALLOCATED (2)
|
||||
#define ACPI_TABLE_ORIGIN_MASK (3)
|
||||
#define ACPI_TABLE_IS_LOADED (4)
|
||||
#define ACPI_TABLE_ORIGIN_OVERRIDE (4)
|
||||
#define ACPI_TABLE_ORIGIN_MASK (7)
|
||||
#define ACPI_TABLE_IS_LOADED (8)
|
||||
|
||||
/*
|
||||
* Get the remaining ACPI tables
|
||||
|
|
Loading…
Reference in a new issue