[PATCH 01/20] ACPICA: Correctly cleanup after a ACPI table load failure.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Bob Moore <robert.moore@xxxxxxxxx>

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/ed7769e8
Signed-off-by: Bob Moore <robert.moore@xxxxxxxxx>
Signed-off-by: Lv Zheng <lv.zheng@xxxxxxxxx>
---
 drivers/acpi/acpica/exresnte.c |    2 +-
 drivers/acpi/acpica/exresolv.c |   16 +++++++++++-----
 drivers/acpi/acpica/nseval.c   |    1 +
 drivers/acpi/acpica/nsload.c   |   16 +++++++++++++++-
 drivers/acpi/acpica/tbxfload.c |   29 ++++++++++++++++++++++++++---
 include/acpi/acexcep.h         |    7 +++++--
 6 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c
index c7e3b92..1b372ef 100644
--- a/drivers/acpi/acpica/exresnte.c
+++ b/drivers/acpi/acpica/exresnte.c
@@ -126,7 +126,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
 	if (!source_desc) {
 		ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p",
 			    node->name.ascii, node));
-		return_ACPI_STATUS(AE_AML_NO_OPERAND);
+		return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
 	}
 
 	/*
diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c
index b6b7f3a..7b10912 100644
--- a/drivers/acpi/acpica/exresolv.c
+++ b/drivers/acpi/acpica/exresolv.c
@@ -337,8 +337,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
 			 acpi_object_type * return_type,
 			 union acpi_operand_object **return_desc)
 {
-	union acpi_operand_object *obj_desc = (void *)operand;
-	struct acpi_namespace_node *node;
+	union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
+	struct acpi_namespace_node *node =
+	    ACPI_CAST_PTR(struct acpi_namespace_node, operand);
 	acpi_object_type type;
 	acpi_status status;
 
@@ -355,9 +356,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
 	case ACPI_DESC_TYPE_NAMED:
 
 		type = ((struct acpi_namespace_node *)obj_desc)->type;
-		obj_desc =
-		    acpi_ns_get_attached_object((struct acpi_namespace_node *)
-						obj_desc);
+		obj_desc = acpi_ns_get_attached_object(node);
 
 		/* 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,
 							 acpi_namespace_node *)
 							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;
 
 	default:
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
index 80670cb..88822b7a 100644
--- a/drivers/acpi/acpica/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -274,6 +274,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
 		acpi_ex_exit_interpreter();
 
 		if (ACPI_FAILURE(status)) {
+			info->return_object = NULL;
 			goto cleanup;
 		}
 
diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c
index bd6cd4a..14ab836 100644
--- a/drivers/acpi/acpica/nsload.c
+++ b/drivers/acpi/acpica/nsload.c
@@ -111,7 +111,21 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
 	if (ACPI_SUCCESS(status)) {
 		acpi_tb_set_table_loaded_flag(table_index, TRUE);
 	} 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:
diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c
index 9682d40..7862cf0 100644
--- a/drivers/acpi/acpica/tbxfload.c
+++ b/drivers/acpi/acpica/tbxfload.c
@@ -102,6 +102,8 @@ static acpi_status acpi_tb_load_namespace(void)
 	acpi_status status;
 	u32 i;
 	struct acpi_table_header *new_dsdt;
+	u32 tables_loaded = 0;
+	u32 tables_failed = 0;
 
 	ACPI_FUNCTION_TRACE(tb_load_namespace);
 
@@ -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);
 	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 */
@@ -187,11 +192,29 @@ static acpi_status acpi_tb_load_namespace(void)
 		/* Ignore errors while loading tables, get as many as possible */
 
 		(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);
 	}
 
-	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:
 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 11c3a01..9f20eb4a 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -192,8 +192,9 @@ struct acpi_exception_info {
 #define AE_AML_BAD_RESOURCE_LENGTH      EXCEP_AML (0x001F)
 #define AE_AML_ILLEGAL_ADDRESS          EXCEP_AML (0x0020)
 #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
@@ -355,7 +356,9 @@ static const struct acpi_exception_info acpi_gbl_exception_names_aml[] = {
 	EXCEP_TXT("AE_AML_ILLEGAL_ADDRESS",
 		  "A memory, I/O, or PCI configuration address is invalid"),
 	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[] = {
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux