Commit 4712f71b authored by Bob Moore's avatar Bob Moore Committed by Rafael J. Wysocki

ACPICA: Correctly cleanup after a ACPI table load failure

ACPICA commit ed7769e832de6c7ba90615480d916c85fd100422

If a table load fails, delete all namespace objects created by the
table, otherwise these objects will be uninitialized, causing
problems later. This appears to be a very rare problem.
Also handle the unitialized node problem to prevent possible
faults. ACPICA BZ 1185.

Link: https://github.com/acpica/acpica/commit/ed7769e8Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLv Zheng <lv.zheng@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 40913fe6
...@@ -126,7 +126,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, ...@@ -126,7 +126,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
if (!source_desc) { if (!source_desc) {
ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p", ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p",
node->name.ascii, node)); node->name.ascii, node));
return_ACPI_STATUS(AE_AML_NO_OPERAND); return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
} }
/* /*
......
...@@ -337,8 +337,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, ...@@ -337,8 +337,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
acpi_object_type * return_type, acpi_object_type * return_type,
union acpi_operand_object **return_desc) union acpi_operand_object **return_desc)
{ {
union acpi_operand_object *obj_desc = (void *)operand; union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
struct acpi_namespace_node *node; struct acpi_namespace_node *node =
ACPI_CAST_PTR(struct acpi_namespace_node, operand);
acpi_object_type type; acpi_object_type type;
acpi_status status; acpi_status status;
...@@ -355,9 +356,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, ...@@ -355,9 +356,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
case ACPI_DESC_TYPE_NAMED: case ACPI_DESC_TYPE_NAMED:
type = ((struct acpi_namespace_node *)obj_desc)->type; type = ((struct acpi_namespace_node *)obj_desc)->type;
obj_desc = obj_desc = acpi_ns_get_attached_object(node);
acpi_ns_get_attached_object((struct acpi_namespace_node *)
obj_desc);
/* If we had an Alias node, use the attached object for type info */ /* If we had an Alias node, use the attached object for type info */
...@@ -368,6 +367,13 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, ...@@ -368,6 +367,13 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
acpi_namespace_node *) acpi_namespace_node *)
obj_desc); obj_desc);
} }
if (!obj_desc) {
ACPI_ERROR((AE_INFO,
"[%4.4s] Node is unresolved or uninitialized",
acpi_ut_get_node_name(node)));
return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
}
break; break;
default: default:
......
...@@ -274,6 +274,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) ...@@ -274,6 +274,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
acpi_ex_exit_interpreter(); acpi_ex_exit_interpreter();
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
info->return_object = NULL;
goto cleanup; goto cleanup;
} }
......
...@@ -111,7 +111,21 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) ...@@ -111,7 +111,21 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
acpi_tb_set_table_loaded_flag(table_index, TRUE); acpi_tb_set_table_loaded_flag(table_index, TRUE);
} else { } else {
(void)acpi_tb_release_owner_id(table_index); /*
* On error, delete any namespace objects created by this table.
* We cannot initialize these objects, so delete them. There are
* a couple of expecially bad cases:
* AE_ALREADY_EXISTS - namespace collision.
* AE_NOT_FOUND - the target of a Scope operator does not
* exist. This target of Scope must already exist in the
* namespace, as per the ACPI specification.
*/
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list.
tables[table_index].owner_id);
acpi_tb_release_owner_id(table_index);
return_ACPI_STATUS(status);
} }
unlock: unlock:
......
...@@ -102,6 +102,8 @@ static acpi_status acpi_tb_load_namespace(void) ...@@ -102,6 +102,8 @@ static acpi_status acpi_tb_load_namespace(void)
acpi_status status; acpi_status status;
u32 i; u32 i;
struct acpi_table_header *new_dsdt; struct acpi_table_header *new_dsdt;
u32 tables_loaded = 0;
u32 tables_failed = 0;
ACPI_FUNCTION_TRACE(tb_load_namespace); ACPI_FUNCTION_TRACE(tb_load_namespace);
...@@ -159,7 +161,10 @@ static acpi_status acpi_tb_load_namespace(void) ...@@ -159,7 +161,10 @@ static acpi_status acpi_tb_load_namespace(void)
status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); ACPI_EXCEPTION((AE_INFO, status, "[DSDT] table load failed"));
tables_failed++;
} else {
tables_loaded++;
} }
/* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */
...@@ -187,11 +192,29 @@ static acpi_status acpi_tb_load_namespace(void) ...@@ -187,11 +192,29 @@ static acpi_status acpi_tb_load_namespace(void)
/* Ignore errors while loading tables, get as many as possible */ /* Ignore errors while loading tables, get as many as possible */
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
(void)acpi_ns_load_table(i, acpi_gbl_root_node); status = acpi_ns_load_table(i, acpi_gbl_root_node);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"[%4.4s] table load failed",
&acpi_gbl_root_table_list.tables[i].
signature.ascii[0]));
tables_failed++;
} else {
tables_loaded++;
}
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
} }
ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired")); if (!tables_failed) {
ACPI_INFO((AE_INFO,
"All (%u) ACPI AML tables successfully loaded",
tables_loaded));
} else {
ACPI_ERROR((AE_INFO,
"%u ACPI AML tables loaded, %u failed",
tables_loaded, tables_failed));
}
unlock_and_exit: unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
......
...@@ -192,8 +192,9 @@ struct acpi_exception_info { ...@@ -192,8 +192,9 @@ struct acpi_exception_info {
#define AE_AML_BAD_RESOURCE_LENGTH EXCEP_AML (0x001F) #define AE_AML_BAD_RESOURCE_LENGTH EXCEP_AML (0x001F)
#define AE_AML_ILLEGAL_ADDRESS EXCEP_AML (0x0020) #define AE_AML_ILLEGAL_ADDRESS EXCEP_AML (0x0020)
#define AE_AML_INFINITE_LOOP EXCEP_AML (0x0021) #define AE_AML_INFINITE_LOOP EXCEP_AML (0x0021)
#define AE_AML_UNINITIALIZED_NODE EXCEP_AML (0x0022)
#define AE_CODE_AML_MAX 0x0021 #define AE_CODE_AML_MAX 0x0022
/* /*
* Internal exceptions used for control * Internal exceptions used for control
...@@ -355,7 +356,9 @@ static const struct acpi_exception_info acpi_gbl_exception_names_aml[] = { ...@@ -355,7 +356,9 @@ static const struct acpi_exception_info acpi_gbl_exception_names_aml[] = {
EXCEP_TXT("AE_AML_ILLEGAL_ADDRESS", EXCEP_TXT("AE_AML_ILLEGAL_ADDRESS",
"A memory, I/O, or PCI configuration address is invalid"), "A memory, I/O, or PCI configuration address is invalid"),
EXCEP_TXT("AE_AML_INFINITE_LOOP", EXCEP_TXT("AE_AML_INFINITE_LOOP",
"An apparent infinite AML While loop, method was aborted") "An apparent infinite AML While loop, method was aborted"),
EXCEP_TXT("AE_AML_UNINITIALIZED_NODE",
"A namespace node is uninitialized or unresolved")
}; };
static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = { static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment