Skip to content

Commit

Permalink
Parser: Avoid resolving in-package references
Browse files Browse the repository at this point in the history
This patch changes PackageElement parsing according to the validated
Windows behavior. It seems Windows always converts NameString in Package
into String, so that when an OSPM driver call invokes it later, forward
references can be allowed.

Note, OSPMs like Linux having drivers invoking ACPICA APIs should still
rely on the old ACPICA behaviors where NameString is resolved into
ObjectReference for the external users. While this commit doesn't ensure
such compatibility, thus functional changes in this commit is not directly
enabled but is surrounded by AcpiGbl_ParseTableAsTermList so that after
having done all necessary changes, it can be enabled along with the new MLC
enabling. Reported by Peter Wu, Fixed by Lv Zheng.

Link: https://bugs.acpica.org/show_bug.cgi?id=1333
Link: Bumblebee-Project/bbswitch#142
Reported-by: Peter Wu <peter@lekensteyn.nl>
Tested-by: Peter Wu <peter@lekensteyn.nl>
Tested-by: Bartosz Skrzypczak <Barteks2x@gmail.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
  • Loading branch information
Lv Zheng committed May 4, 2017
1 parent 49f041a commit ce24b4d
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 45 deletions.
128 changes: 85 additions & 43 deletions source/components/dispatcher/dsobject.c
Expand Up @@ -194,12 +194,14 @@ AcpiDsBuildInternalObject (
ACPI_OPERAND_OBJECT *ObjDesc;
ACPI_STATUS Status;
ACPI_OBJECT_TYPE Type;
ACPI_OBJECT_TYPE ObjType;


ACPI_FUNCTION_TRACE (DsBuildInternalObject);


*ObjDescPtr = NULL;
ObjType = (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType;
if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
{
/*
Expand All @@ -209,48 +211,58 @@ AcpiDsBuildInternalObject (
*/
if (!Op->Common.Node)
{
Status = AcpiNsLookup (WalkState->ScopeInfo,
Op->Common.Value.String,
ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &(Op->Common.Node)));
if (ACPI_FAILURE (Status))
{
/* Check if we are resolving a named reference within a package */
/* Special object resolution for elements of a package */

if ((Status == AE_NOT_FOUND) && (AcpiGbl_EnableInterpreterSlack) &&

((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
(Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
{
/*
* We didn't find the target and we are populating elements
* of a package - ignore if slack enabled. Some ASL code
* contains dangling invalid references in packages and
* expects that no exception will be issued. Leave the
* element as a null element. It cannot be used, but it
* can be overwritten by subsequent ASL code - this is
* typically the case.
*/
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
"Ignoring unresolved reference in package [%4.4s]\n",
WalkState->ScopeInfo->Scope.Node->Name.Ascii));

return_ACPI_STATUS (AE_OK);
}
else
if (AcpiGbl_ParseTableAsTermList &&
((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
(Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
{
ObjType = ACPI_TYPE_STRING;
}
else
{
Status = AcpiNsLookup (WalkState->ScopeInfo,
Op->Common.Value.String,
ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &(Op->Common.Node)));
if (ACPI_FAILURE (Status))
{
ACPI_ERROR_NAMESPACE (Op->Common.Value.String, Status);
/* Check if we are resolving a named reference within a package */

if ((Status == AE_NOT_FOUND) && (AcpiGbl_EnableInterpreterSlack) &&
((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
(Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
{
/*
* We didn't find the target and we are populating
* elements of a package - ignore if slack enabled.
* Some ASL code contains dangling invalid references
* in packages and expects that no exception will be
* issued. Leave the element as a null element. It
* cannot be used, but it can be overwritten by
* subsequent ASL code - this is typically the case.
*/
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
"Ignoring unresolved reference in package [%4.4s]\n",
WalkState->ScopeInfo->Scope.Node->Name.Ascii));

return_ACPI_STATUS (AE_OK);
}
else
{
ACPI_ERROR_NAMESPACE (Op->Common.Value.String, Status);
return_ACPI_STATUS (Status);
}
}

return_ACPI_STATUS (Status);
}
}

/* Special object resolution for elements of a package */

if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
(Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
if (!AcpiGbl_ParseTableAsTermList &&
((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
(Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
{
/*
* Attempt to resolve the node to a value before we insert it into
Expand Down Expand Up @@ -329,8 +341,7 @@ AcpiDsBuildInternalObject (

/* Create and init a new internal ACPI object */

ObjDesc = AcpiUtCreateInternalObject (
(AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType);
ObjDesc = AcpiUtCreateInternalObject (ObjType);
if (!ObjDesc)
{
return_ACPI_STATUS (AE_NO_MEMORY);
Expand Down Expand Up @@ -766,6 +777,7 @@ AcpiDsInitObjectFromOp (
const ACPI_OPCODE_INFO *OpInfo;
ACPI_OPERAND_OBJECT *ObjDesc;
ACPI_STATUS Status = AE_OK;
char *Path = NULL;


ACPI_FUNCTION_TRACE (DsInitObjectFromOp);
Expand Down Expand Up @@ -884,14 +896,44 @@ AcpiDsInitObjectFromOp (

case ACPI_TYPE_STRING:

ObjDesc->String.Pointer = Op->Common.Value.String;
ObjDesc->String.Length = (UINT32) strlen (Op->Common.Value.String);
if (AcpiGbl_ParseTableAsTermList &&
Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
{
Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String,
NULL, &Path);
if (ACPI_FAILURE (Status))
{
ACPI_WARNING ((AE_INFO,
"Unresolved name path in package"));
ObjDesc->String.Pointer = "";
ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
}
else
{
ObjDesc->String.Pointer = Path;
}
ObjDesc->String.Length = (UINT32) strlen (ObjDesc->String.Pointer);
if (!WalkState->ScopeInfo || !WalkState->ScopeInfo->Scope.Node)
{
ObjDesc->String.ScopeNode = NULL;
}
else
{
ObjDesc->String.ScopeNode = WalkState->ScopeInfo->Scope.Node;
}
ObjDesc->Common.Flags |= AOPOBJ_NAMESTRING;
}
else
{
ObjDesc->String.Pointer = Op->Common.Value.String;
ObjDesc->String.Length = (UINT32) strlen (Op->Common.Value.String);

/*
* The string is contained in the ACPI table, don't ever try
* to delete it
*/
ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
/*
* The string is contained in the ACPI table, don't ever try
* to delete it
*/
ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
}
break;

case ACPI_TYPE_METHOD:
Expand Down
3 changes: 2 additions & 1 deletion source/components/executer/exdump.c
Expand Up @@ -207,11 +207,12 @@ static ACPI_EXDUMP_INFO AcpiExDumpInteger[2] =
{ACPI_EXD_UINT64, ACPI_EXD_OFFSET (Integer.Value), "Value"}
};

static ACPI_EXDUMP_INFO AcpiExDumpString[4] =
static ACPI_EXDUMP_INFO AcpiExDumpString[5] =
{
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpString), NULL},
{ACPI_EXD_UINT32, ACPI_EXD_OFFSET (String.Length), "Length"},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET (String.Pointer), "Pointer"},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET (String.ScopeNode), "Scope Node"},
{ACPI_EXD_STRING, 0, NULL}
};

Expand Down
20 changes: 19 additions & 1 deletion source/components/parser/psargs.c
Expand Up @@ -387,6 +387,24 @@ AcpiPsGetNextNamepath (
return_ACPI_STATUS (AE_OK);
}

/*
* Named references are stored internally as string objects, as this
* provides compatibility with other ACPI implementations.
* This provides support for:
* 1) Forward references from package object elements, when the
* package is within a module-level code block.
* 2) ObjectType operator compatibility for individual package
* elements that are actually named references.
* 3) Support for named references to External() objects.
*/
if (AcpiGbl_ParseTableAsTermList && Arg->Common.Parent &&
((Arg->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
(Arg->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
{
Arg->Common.Value.Name = Path;
return_ACPI_STATUS (AE_OK);
}

/*
* Lookup the name in the internal namespace, starting with the current
* scope. We don't want to add anything new to the namespace here,
Expand Down Expand Up @@ -488,7 +506,7 @@ AcpiPsGetNextNamepath (
* may flag as an error later if slack mode is not enabled.
* (Some ASL code depends on allowing this behavior)
*/
else if ((Arg->Common.Parent) &&
else if (!AcpiGbl_ParseTableAsTermList && Arg->Common.Parent &&
((Arg->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
(Arg->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
{
Expand Down
2 changes: 2 additions & 0 deletions source/include/acobject.h
Expand Up @@ -206,6 +206,7 @@
#define AOPOBJ_REG_CONNECTED 0x10 /* _REG was run */
#define AOPOBJ_SETUP_COMPLETE 0x20 /* Region setup is complete */
#define AOPOBJ_INVALID 0x40 /* Host OS won't allow a Region address */
#define AOPOBJ_NAMESTRING 0x80 /* String is coverted from a NameString */


/******************************************************************************
Expand Down Expand Up @@ -245,6 +246,7 @@ typedef struct acpi_object_string /* Null terminated, ASCII characters only */
{
ACPI_OBJECT_COMMON_HEADER
ACPI_COMMON_BUFFER_INFO (char) /* String in AML stream or allocated string */
ACPI_NAMESPACE_NODE *ScopeNode; /* Scope node, may not be needed */

} ACPI_OBJECT_STRING;

Expand Down

0 comments on commit ce24b4d

Please sign in to comment.