Skip to content

Commit

Permalink
Correctly cleanup after a ACPI table load failure.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
acpibob committed Jul 22, 2015
1 parent 36bb9b3 commit ed7769e
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 10 deletions.
2 changes: 1 addition & 1 deletion source/components/executer/exresnte.c
Expand Up @@ -206,7 +206,7 @@ AcpiExResolveNodeToValue (
{
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);
}

/*
Expand Down
14 changes: 11 additions & 3 deletions source/components/executer/exresolv.c
Expand Up @@ -423,8 +423,8 @@ AcpiExResolveMultiple (
ACPI_OBJECT_TYPE *ReturnType,
ACPI_OPERAND_OBJECT **ReturnDesc)
{
ACPI_OPERAND_OBJECT *ObjDesc = (void *) Operand;
ACPI_NAMESPACE_NODE *Node;
ACPI_OPERAND_OBJECT *ObjDesc = ACPI_CAST_PTR (void, Operand);
ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Operand);
ACPI_OBJECT_TYPE Type;
ACPI_STATUS Status;

Expand All @@ -444,7 +444,7 @@ AcpiExResolveMultiple (
case ACPI_DESC_TYPE_NAMED:

Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type;
ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc);
ObjDesc = AcpiNsGetAttachedObject (Node);

/* If we had an Alias node, use the attached object for type info */

Expand All @@ -453,6 +453,14 @@ AcpiExResolveMultiple (
Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type;
ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc);
}

if (!ObjDesc)
{
ACPI_ERROR ((AE_INFO,
"[%4.4s] Node is unresolved or uninitialized",
AcpiUtGetNodeName (Node)));
return_ACPI_STATUS (AE_AML_UNINITIALIZED_NODE);
}
break;

default:
Expand Down
1 change: 1 addition & 0 deletions source/components/namespace/nseval.c
Expand Up @@ -357,6 +357,7 @@ AcpiNsEvaluate (

if (ACPI_FAILURE (Status))
{
Info->ReturnObject = NULL;
goto Cleanup;
}

Expand Down
16 changes: 15 additions & 1 deletion source/components/namespace/nsload.c
Expand Up @@ -200,7 +200,21 @@ AcpiNsLoadTable (
}
else
{
(void) AcpiTbReleaseOwnerId (TableIndex);
/*
* 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) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
AcpiNsDeleteNamespaceByOwner (
AcpiGbl_RootTableList.Tables[TableIndex].OwnerId);
AcpiTbReleaseOwnerId (TableIndex);

return_ACPI_STATUS (Status);
}

Unlock:
Expand Down
35 changes: 32 additions & 3 deletions source/components/tables/tbxfload.c
Expand Up @@ -187,6 +187,8 @@ AcpiTbLoadNamespace (
ACPI_STATUS Status;
UINT32 i;
ACPI_TABLE_HEADER *NewDsdt;
UINT32 TablesLoaded = 0;
UINT32 TablesFailed = 0;


ACPI_FUNCTION_TRACE (TbLoadNamespace);
Expand Down Expand Up @@ -246,7 +248,12 @@ AcpiTbLoadNamespace (
Status = AcpiNsLoadTable (ACPI_TABLE_INDEX_DSDT, AcpiGbl_RootNode);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
ACPI_EXCEPTION ((AE_INFO, Status, "[DSDT] table load failed"));
TablesFailed++;
}
else
{
TablesLoaded++;
}

/* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */
Expand All @@ -270,11 +277,33 @@ AcpiTbLoadNamespace (
/* Ignore errors while loading tables, get as many as possible */

(void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
(void) AcpiNsLoadTable (i, AcpiGbl_RootNode);
Status = AcpiNsLoadTable (i, AcpiGbl_RootNode);
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status, "[%4.4s] table load failed",
&AcpiGbl_RootTableList.Tables[i].Signature.Ascii[0]));
TablesFailed++;
}
else
{
TablesLoaded++;
}

(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
}

ACPI_INFO ((AE_INFO, "All ACPI Tables successfully acquired"));
if (!TablesFailed)
{
ACPI_INFO ((AE_INFO,
"All (%u) ACPI AML tables successfully loaded",
TablesLoaded));
}
else
{
ACPI_ERROR ((AE_INFO,
"%u ACPI AML tables loaded, %u failed",
TablesLoaded, TablesFailed));
}

UnlockAndExit:
(void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
Expand Down
6 changes: 4 additions & 2 deletions source/include/acexcep.h
Expand Up @@ -269,8 +269,9 @@ typedef 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


/*
Expand Down Expand Up @@ -394,7 +395,8 @@ static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Aml[] =
EXCEP_TXT ("AE_AML_CIRCULAR_REFERENCE", "Two references refer to each other"),
EXCEP_TXT ("AE_AML_BAD_RESOURCE_LENGTH", "The length of a Resource Descriptor in the AML is incorrect"),
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")
EXCEP_TXT ("AE_AML_INFINITE_LOOP", "An apparent infinite AML While loop, method was aborted"),
EXCEP_TXT ("AE_AML_UNINITIALIZED_NODE", "A namespace node is uninitialized or unresolved")
};

static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Ctrl[] =
Expand Down

0 comments on commit ed7769e

Please sign in to comment.