diff options
author | jkim <jkim@FreeBSD.org> | 2014-09-11 21:38:09 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2014-09-11 21:38:09 +0000 |
commit | 9f91b0b83a53651519b3bbe3b8c1f2a324da984e (patch) | |
tree | 67d2b76905535d056ba6911186285d0325dc703f /source/compiler/aslxref.c | |
parent | b4cfb84e01b0a37b535b69118259bb16e9614b0f (diff) | |
download | FreeBSD-src-9f91b0b83a53651519b3bbe3b8c1f2a324da984e.zip FreeBSD-src-9f91b0b83a53651519b3bbe3b8c1f2a324da984e.tar.gz |
Import ACPICA 20140828.
Diffstat (limited to 'source/compiler/aslxref.c')
-rw-r--r-- | source/compiler/aslxref.c | 193 |
1 files changed, 192 insertions, 1 deletions
diff --git a/source/compiler/aslxref.c b/source/compiler/aslxref.c index ee3a0f8..1cbd6e0 100644 --- a/source/compiler/aslxref.c +++ b/source/compiler/aslxref.c @@ -41,7 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ - #include "aslcompiler.h" #include "aslcompiler.y.h" #include "acparser.h" @@ -86,6 +85,20 @@ XfCheckFieldRange ( UINT32 FieldBitLength, UINT32 AccessBitWidth); +static BOOLEAN +XfIsObjectParental ( + ACPI_PARSE_OBJECT *MethodOp1, + ACPI_PARSE_OBJECT *MethodOp2); + +static ACPI_PARSE_OBJECT * +XfGetParentMethod ( + ACPI_PARSE_OBJECT *Op); + +static void +XfCheckIllegalReference ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *Node); + /******************************************************************************* * @@ -130,6 +143,8 @@ XfCrossReferenceNamespace ( TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, XfNamespaceLocateBegin, XfNamespaceLocateEnd, WalkState); + + ACPI_FREE (WalkState); return (AE_OK); } @@ -262,6 +277,178 @@ XfCheckFieldRange ( } } + +/******************************************************************************* + * + * FUNCTION: XfIsObjectParental + * + * PARAMETERS: ChildOp - Op to be checked + * PossibleParentOp - Determine if this op is in the family + * + * RETURN: TRUE if ChildOp is a descendent of PossibleParentOp + * + * DESCRIPTION: Determine if an Op is a descendent of another Op. Used to + * detect if a method is declared within another method. + * + ******************************************************************************/ + +static BOOLEAN +XfIsObjectParental ( + ACPI_PARSE_OBJECT *ChildOp, + ACPI_PARSE_OBJECT *PossibleParentOp) +{ + ACPI_PARSE_OBJECT *ParentOp; + + + /* Search upwards through the tree for possible parent */ + + ParentOp = ChildOp; + while (ParentOp) + { + if (ParentOp == PossibleParentOp) + { + return (TRUE); + } + + ParentOp = ParentOp->Asl.Parent; + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: XfGetParentMethod + * + * PARAMETERS: Op - Op to be checked + * + * RETURN: Op for parent method. NULL if object is not within a method. + * + * DESCRIPTION: Determine if an object is within a control method. Used to + * implement special rules for named references from within a + * control method. + * + * NOTE: It would be better to have the parser set a flag in the Op if possible. + * + ******************************************************************************/ + +static ACPI_PARSE_OBJECT * +XfGetParentMethod ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *ParentOp; + + + if (!Op) + { + return (NULL); + } + + if (Op->Asl.ParseOpcode == PARSEOP_METHOD) + { + return (NULL); + } + + /* Walk upwards through the parse tree, up to the root if necessary */ + + ParentOp = Op; + while (ParentOp) + { + if (ParentOp->Asl.ParseOpcode == PARSEOP_METHOD) + { + return (ParentOp); + } + + ParentOp = ParentOp->Asl.Parent; + } + + /* Object is not within a method */ + + return (NULL); +} + +/******************************************************************************* + * + * FUNCTION: XfCheckIllegalReference + * + * PARAMETERS: Op - Op referring to the target + * TargetNode - Target of the reference + * + * RETURN: None. Emits error message for an illegal reference + * + * DESCRIPTION: Determine if a named reference is legal. A "named" reference + * is something like: Store(ABCD, ...), where ABCD is an AML + * Nameseg or Namepath. + * + * NOTE: Caller must ensure that the name Op is in fact a reference, and not + * an actual name declaration (creation of a named object). + * + ******************************************************************************/ + +static void +XfCheckIllegalReference ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *TargetNode) +{ + ACPI_PARSE_OBJECT *MethodOp1; + ACPI_PARSE_OBJECT *MethodOp2; + ACPI_PARSE_OBJECT *TargetOp; + + + /* + * Check for an illegal reference to a named object: + * + * 1) References from one control method to another, non-parent + * method are not allowed, they will fail at runtime. + * + * 2) Forward references within a control method are not allowed. + * AML interpreters use a one-pass parse of control methods + * so these forward references will fail at runtime. + */ + TargetOp = TargetNode->Op; + + MethodOp1 = XfGetParentMethod (Op); + MethodOp2 = XfGetParentMethod (TargetOp); + + /* Are both objects within control method(s)? */ + + if (!MethodOp1 || !MethodOp2) + { + return; + } + + /* Objects not in the same method? */ + + if (MethodOp1 != MethodOp2) + { + /* + * 1) Cross-method named reference + * + * This is OK if and only if the target reference is within in a + * method that is a parent of current method + */ + if (!XfIsObjectParental (MethodOp1, MethodOp2)) + { + AslError (ASL_ERROR, ASL_MSG_ILLEGAL_METHOD_REF, Op, + Op->Asl.ExternalName); + } + } + + /* + * 2) Both reference and target are in the same method. Check if this is + * an (illegal) forward reference by examining the exact source code + * location of each (the referenced object and the object declaration). + * This is a bit nasty, yet effective. + */ + else if (Op->Asl.LogicalByteOffset < TargetOp->Asl.LogicalByteOffset) + { + AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op, + Op->Asl.ExternalName); + } +} + + /******************************************************************************* * * FUNCTION: XfNamespaceLocateBegin @@ -471,6 +658,10 @@ XfNamespaceLocateBegin ( /* This node has been referenced, mark it for reference check */ Node->Flags |= ANOBJ_IS_REFERENCED; + + /* Check for an illegal reference */ + + XfCheckIllegalReference (Op, Node); } /* Attempt to optimize the NamePath */ |