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:
parent
023e2ee16c
commit
f9d472ee32
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user