2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-21 19:53:59 +08:00

ACPICA: Tables: Combine checksum/duplication verification together

ACPICA commit 182bdffc0644f568be614a6d4debd651e29ca587

They are all mechanisms used to verify if a table is qualified to be
installed and controlled by acpi_gbl_enable_table_validation, so combine them
together. By doing so, table duplication check is applied to the statically
loaded tables (however whether it is actually enabled is still determined
by acpi_gbl_enable_table_validation). Lv Zheng.

Link: https://github.com/acpica/acpica/commit/182bdffc
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Lv Zheng 2017-07-10 15:23:50 +08:00 committed by Rafael J. Wysocki
parent 023e2ee16c
commit f9d472ee32
3 changed files with 169 additions and 110 deletions

View File

@ -76,7 +76,8 @@ void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc);
acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc); acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc);
acpi_status acpi_status
acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature); acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc,
char *signature, u32 *table_index);
u8 acpi_tb_is_table_loaded(u32 table_index); u8 acpi_tb_is_table_loaded(u32 table_index);

View File

@ -50,6 +50,57 @@
#define _COMPONENT ACPI_TABLES #define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbdata") ACPI_MODULE_NAME("tbdata")
/* Local prototypes */
static acpi_status
acpi_tb_check_duplication(struct acpi_table_desc *table_desc, u32 *table_index);
static u8
acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index);
/*******************************************************************************
*
* FUNCTION: acpi_tb_compare_tables
*
* PARAMETERS: table_desc - Table 1 descriptor to be compared
* table_index - Index of table 2 to be compared
*
* RETURN: TRUE if both tables are identical.
*
* DESCRIPTION: This function compares a table with another table that has
* already been installed in the root table list.
*
******************************************************************************/
static u8
acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
{
acpi_status status = AE_OK;
u8 is_identical;
struct acpi_table_header *table;
u32 table_length;
u8 table_flags;
status =
acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
&table, &table_length, &table_flags);
if (ACPI_FAILURE(status)) {
return (FALSE);
}
/*
* Check for a table match on the entire table length,
* not just the header.
*/
is_identical = (u8)((table_desc->length != table_length ||
memcmp(table_desc->pointer, table, table_length)) ?
FALSE : TRUE);
/* Release the acquired table */
acpi_tb_release_table(table, table_length, table_flags);
return (is_identical);
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_init_table_descriptor * FUNCTION: acpi_tb_init_table_descriptor
@ -64,6 +115,7 @@ ACPI_MODULE_NAME("tbdata")
* DESCRIPTION: Initialize a new table descriptor * DESCRIPTION: Initialize a new table descriptor
* *
******************************************************************************/ ******************************************************************************/
void void
acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc, acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
acpi_physical_address address, acpi_physical_address address,
@ -354,12 +406,78 @@ acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc)
return (acpi_tb_validate_table(table_desc)); return (acpi_tb_validate_table(table_desc));
} }
/*******************************************************************************
*
* FUNCTION: acpi_tb_check_duplication
*
* PARAMETERS: table_desc - Table descriptor
* table_index - Where the table index is returned
*
* RETURN: Status
*
* DESCRIPTION: Avoid installing duplicated tables. However table override and
* user aided dynamic table load is allowed, thus comparing the
* address of the table is not sufficient, and checking the entire
* table content is required.
*
******************************************************************************/
static acpi_status
acpi_tb_check_duplication(struct acpi_table_desc *table_desc, u32 *table_index)
{
u32 i;
ACPI_FUNCTION_TRACE(tb_check_duplication);
/* Check if table is already registered */
for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
/*
* Check for a table match on the entire table length,
* not just the header.
*/
if (!acpi_tb_compare_tables(table_desc, i)) {
continue;
}
/*
* Note: the current mechanism does not unregister a table if it is
* dynamically unloaded. The related namespace entries are deleted,
* but the table remains in the root table list.
*
* The assumption here is that the number of different tables that
* will be loaded is actually small, and there is minimal overhead
* in just keeping the table in case it is needed again.
*
* If this assumption changes in the future (perhaps on large
* machines with many table load/unload operations), tables will
* need to be unregistered when they are unloaded, and slots in the
* root table list should be reused when empty.
*/
if (acpi_gbl_root_table_list.tables[i].flags &
ACPI_TABLE_IS_LOADED) {
/* Table is still loaded, this is an error */
return_ACPI_STATUS(AE_ALREADY_EXISTS);
} else {
*table_index = i;
return_ACPI_STATUS(AE_CTRL_TERMINATE);
}
}
/* Indicate no duplication to the caller */
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************** /******************************************************************************
* *
* FUNCTION: acpi_tb_verify_temp_table * FUNCTION: acpi_tb_verify_temp_table
* *
* PARAMETERS: table_desc - Table descriptor * PARAMETERS: table_desc - Table descriptor
* signature - Table signature to verify * signature - Table signature to verify
* table_index - Where the table index is returned
* *
* RETURN: Status * RETURN: Status
* *
@ -369,7 +487,8 @@ acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc)
*****************************************************************************/ *****************************************************************************/
acpi_status acpi_status
acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature) acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc,
char *signature, u32 *table_index)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
@ -392,9 +511,10 @@ acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature)
goto invalidate_and_exit; goto invalidate_and_exit;
} }
if (acpi_gbl_enable_table_validation) {
/* Verify the checksum */ /* Verify the checksum */
if (acpi_gbl_enable_table_validation) {
status = status =
acpi_tb_verify_checksum(table_desc->pointer, acpi_tb_verify_checksum(table_desc->pointer,
table_desc->length); table_desc->length);
@ -411,9 +531,32 @@ acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature)
goto invalidate_and_exit; goto invalidate_and_exit;
} }
/* Avoid duplications */
if (table_index) {
status =
acpi_tb_check_duplication(table_desc, table_index);
if (ACPI_FAILURE(status)) {
if (status != AE_CTRL_TERMINATE) {
ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
"%4.4s 0x%8.8X%8.8X"
" Table is duplicated",
acpi_ut_valid_nameseg
(table_desc->signature.
ascii) ? table_desc->
signature.
ascii : "????",
ACPI_FORMAT_UINT64
(table_desc->address)));
} }
return_ACPI_STATUS(AE_OK); goto invalidate_and_exit;
}
}
}
return_ACPI_STATUS(status);
invalidate_and_exit: invalidate_and_exit:
acpi_tb_invalidate_table(table_desc); acpi_tb_invalidate_table(table_desc);

View File

@ -48,54 +48,6 @@
#define _COMPONENT ACPI_TABLES #define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbinstal") ACPI_MODULE_NAME("tbinstal")
/* Local prototypes */
static u8
acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index);
/*******************************************************************************
*
* FUNCTION: acpi_tb_compare_tables
*
* PARAMETERS: table_desc - Table 1 descriptor to be compared
* table_index - Index of table 2 to be compared
*
* RETURN: TRUE if both tables are identical.
*
* DESCRIPTION: This function compares a table with another table that has
* already been installed in the root table list.
*
******************************************************************************/
static u8
acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
{
acpi_status status = AE_OK;
u8 is_identical;
struct acpi_table_header *table;
u32 table_length;
u8 table_flags;
status =
acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
&table, &table_length, &table_flags);
if (ACPI_FAILURE(status)) {
return (FALSE);
}
/*
* Check for a table match on the entire table length,
* not just the header.
*/
is_identical = (u8)((table_desc->length != table_length ||
memcmp(table_desc->pointer, table, table_length)) ?
FALSE : TRUE);
/* Release the acquired table */
acpi_tb_release_table(table, table_length, table_flags);
return (is_identical);
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_install_table_with_override * FUNCTION: acpi_tb_install_table_with_override
@ -112,7 +64,6 @@ acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
* table array. * table array.
* *
******************************************************************************/ ******************************************************************************/
void void
acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc, acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
u8 override, u32 *table_index) u8 override, u32 *table_index)
@ -210,53 +161,15 @@ acpi_tb_install_standard_table(acpi_physical_address address,
goto release_and_exit; goto release_and_exit;
} }
/* Validate and verify a table before installation */
status = acpi_tb_verify_temp_table(&new_table_desc, NULL);
if (ACPI_FAILURE(status)) {
goto release_and_exit;
}
/* Acquire the table lock */ /* Acquire the table lock */
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
if (acpi_gbl_enable_table_validation) { /* Validate and verify a table before installation */
/* Check if table is already registered */ status = acpi_tb_verify_temp_table(&new_table_desc, NULL, &i);
if (ACPI_FAILURE(status)) {
for (i = 0; i < acpi_gbl_root_table_list.current_table_count; if (status == AE_CTRL_TERMINATE) {
++i) {
/*
* Check for a table match on the entire table length,
* not just the header.
*/
if (!acpi_tb_compare_tables(&new_table_desc, i)) {
continue;
}
/*
* Note: the current mechanism does not unregister a table if it is
* dynamically unloaded. The related namespace entries are deleted,
* but the table remains in the root table list.
*
* The assumption here is that the number of different tables that
* will be loaded is actually small, and there is minimal overhead
* in just keeping the table in case it is needed again.
*
* If this assumption changes in the future (perhaps on large
* machines with many table load/unload operations), tables will
* need to be unregistered when they are unloaded, and slots in the
* root table list should be reused when empty.
*/
if (acpi_gbl_root_table_list.tables[i].flags &
ACPI_TABLE_IS_LOADED) {
/* Table is still loaded, this is an error */
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
} else {
/* /*
* Table was unloaded, allow it to be reloaded. * Table was unloaded, allow it to be reloaded.
* As we are going to return AE_OK to the caller, we should * As we are going to return AE_OK to the caller, we should
@ -270,7 +183,7 @@ acpi_tb_install_standard_table(acpi_physical_address address,
*table_index = i; *table_index = i;
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
} goto unlock_and_exit;
} }
/* Add the table to the global root table list */ /* Add the table to the global root table list */
@ -350,9 +263,11 @@ void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
finish_override: finish_override:
/* Validate and verify a table before overriding */ /*
* Validate and verify a table before overriding, no nested table
status = acpi_tb_verify_temp_table(&new_table_desc, NULL); * duplication check as it's too complicated and unnecessary.
*/
status = acpi_tb_verify_temp_table(&new_table_desc, NULL, NULL);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return; return;
} }