aslxref.c revision 199767f8919635c4928607450d9e0abb932109ce
/******************************************************************************
*
* Module Name: aslxref - Namespace cross-reference
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include "aslcompiler.y.h"
#define _COMPONENT ACPI_COMPILER
ACPI_MODULE_NAME ("aslxref")
/* Local prototypes */
static ACPI_STATUS
void *Context);
static ACPI_STATUS
void *Context);
static ACPI_PARSE_OBJECT *
static BOOLEAN
char *Name);
static ACPI_STATUS
void *Context,
void **ReturnValue);
static void
#ifdef __UNDER_DEVELOPMENT
static ACPI_PARSE_OBJECT *
static void
static BOOLEAN
#endif
/*******************************************************************************
*
* FUNCTION: XfCrossReferenceNamespace
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Perform a cross reference check of the parse tree against the
* namespace. Every named referenced within the parse tree
* should be get resolved with a namespace lookup. If not, the
* original reference in the ASL code is invalid -- i.e., refers
* to a non-existent object.
*
* NOTE: The ASL "External" operator causes the name to be inserted into the
* namespace so that references to the external name will be resolved
* correctly here.
*
******************************************************************************/
void)
{
/*
* Create a new walk state for use when looking up names
* within the namespace (Passed as context to the callbacks)
*/
if (!WalkState)
{
return (AE_NO_MEMORY);
}
/* Walk the entire parse tree */
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: XfObjectExists
*
* PARAMETERS: Name - 4 char ACPI name
*
* RETURN: TRUE if name exists in namespace
*
* DESCRIPTION: Walk the namespace to find an object
*
******************************************************************************/
static BOOLEAN
char *Name)
{
/* Walk entire namespace from the supplied root */
if (Status == AE_CTRL_TRUE)
{
/* At least one instance of the name was found */
return (TRUE);
}
return (FALSE);
}
/*******************************************************************************
*
* FUNCTION: XfCompareOneNamespaceObject
*
* PARAMETERS: ACPI_WALK_CALLBACK
*
* RETURN: Status
*
* DESCRIPTION: Compare name of one object.
*
******************************************************************************/
static ACPI_STATUS
void *Context,
void **ReturnValue)
{
/* Simply check the name */
{
/* Abort walk if we found one instance */
return (AE_CTRL_TRUE);
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: XfCheckFieldRange
*
* PARAMETERS: RegionBitLength - Length of entire parent region
* FieldBitOffset - Start of the field unit (within region)
* FieldBitLength - Entire length of field unit
* AccessBitWidth - Access width of the field unit
*
* RETURN: None
*
* DESCRIPTION: Check one field unit to make sure it fits in the parent
* op region.
*
* Note: AccessBitWidth must be either 8,16,32, or 64
*
******************************************************************************/
static void
{
/*
* Check each field unit against the region size. The entire
* field unit (start offset plus length) must fit within the
* region.
*/
if (FieldEndBitOffset > RegionBitLength)
{
/* Field definition itself is beyond the end-of-region */
return;
}
/*
* Now check that the field plus AccessWidth doesn't go beyond
* the end-of-region. Assumes AccessBitWidth is a power of 2
*/
if (FieldEndBitOffset > RegionBitLength)
{
/* Field definition combined with the access is beyond EOR */
}
}
/*******************************************************************************
*
* FUNCTION: XfGetParentMethod
*
* PARAMETERS: Op - Parse Op to be checked
*
* RETURN: Control method Op if found. NULL otherwise
*
* DESCRIPTION: Find the control method parent of a parse op. Returns NULL if
* the input Op is not within a control method.
*
******************************************************************************/
static ACPI_PARSE_OBJECT *
{
while (NextOp)
{
{
return (NextOp);
}
}
return (NULL); /* No parent method found */
}
/*******************************************************************************
*
* FUNCTION: XfNamespaceLocateBegin
*
* PARAMETERS: ASL_WALK_CALLBACK
*
* RETURN: Status
*
* DESCRIPTION: Descending callback used during cross-reference. For named
* object references, attempt to locate the name in the
* namespace.
*
* NOTE: ASL references to named fields within resource descriptors are
* resolved to integer values here. Therefore, this step is an
* important part of the code generation. We don't know that the
* name refers to a resource descriptor until now.
*
******************************************************************************/
static ACPI_STATUS
void *Context)
{
char *Path;
const ACPI_OPCODE_INFO *OpInfo;
int RegisterNumber;
UINT32 i;
{
if (!Node->MethodLocals)
{
sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS);
sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_ARGS);
/*
* Get the method argument count
* First, get the name node
*/
/* Get the NumArguments node */
/* We will track all posible ArgXs */
for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
{
{
/* Real Args are always "initialized" */
}
else
{
/* Other ArgXs can be used as locals */
}
}
}
}
/*
* If this node is the actual declaration of a name
* [such as the XXXX name in "Method (XXXX)"],
* we are not interested in it here. We only care about names that are
* references to other objects within the namespace and the parent objects
* of name declarations
*/
{
}
/* Check method LocalX variables */
{
/* Find parent method Op */
if (!NextOp)
{
}
/* Get method node */
{
/* Local is being initialized */
}
/* Mark this Local as referenced */
}
/* Check method ArgX variables */
{
/* Find parent method Op */
if (!NextOp)
{
}
/* Get method node */
/* Get Arg # */
{
/* Arg is being initialized */
}
/* Mark this Arg as referenced */
}
/*
* After method ArgX and LocalX, we are only interested in opcodes
* that have an associated name
*/
{
}
/*
* One special case: CondRefOf operator - we don't care if the name exists
* or not at this point, just ignore it, the point of the operator is to
* determine if the name exists at runtime.
*/
{
}
/*
* We must enable the "search-to-root" for single NameSegs, but
* we have to be very careful about opening up scopes
*/
{
/*
* These are name references, do not push the scope stack
* for them.
*/
}
/* Get the NamePath from the appropriate place */
{
/* For nearly all NAMED operators, the name reference is the first child */
{
/*
* ALIAS is the only oddball opcode, the name declaration
* (alias name) is the second operand
*/
}
}
{
/* Name must appear as the last parameter */
{
}
}
else
{
}
/*
* Lookup the name in the namespace. Name must exist at this point, or it
* is an invalid reference.
*
* The namespace is also used as a lookup table for references to resource
* descriptors and the fields within them.
*/
if (ACPI_FAILURE (Status))
{
if (Status == AE_NOT_FOUND)
{
/*
* We didn't find the name reference by path -- we can qualify this
* a little better before we print an error message
*/
{
/* A simple, one-segment ACPI name */
if (XfObjectExists (Path))
{
/*
* There exists such a name, but we couldn't get to it
* from this scope
*/
}
else
{
/* The name doesn't exist, period */
}
}
else
{
/* Check for a fully qualified path */
if (Path[0] == AML_ROOT_PREFIX)
{
/* Gave full path, the object does not exist */
}
else
{
/*
* We can't tell whether it doesn't exist or just
* can't be reached.
*/
}
}
}
}
/* Check for a reference vs. name declaration */
{
/* This node has been referenced, mark it for reference check */
#ifdef __UNDER_DEVELOPMENT
/* Check for an illegal reference */
#endif
}
/* Attempt to optimize the NamePath */
/*
* 1) Dereference an alias (A name reference that is an alias)
* Aliases are not nested, the alias always points to the final object
*/
{
/* This node points back to the original PARSEOP_ALIAS */
/* The first child is the alias target op */
/* That in turn points back to original target alias node */
{
}
/* Else - forward reference to alias, will be resolved later */
}
/* 2) Check for a reference to a resource descriptor */
{
/*
* This was a reference to a field within a resource descriptor.
* Extract the associated field offset (either a bit or byte
* offset depending on the field type) and change the named
* reference into an integer for AML code generation
*/
/*
* If a field is being created, generate the length (in bits) of
* the field. Note: Opcodes other than CreateXxxField and Index
* can come through here. For other opcodes, we just need to
* convert the resource tag reference to an integer offset.
*/
{
case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
/*
* We know the length operand is an integer constant because
* we know that it contains a reference to a resource
* descriptor tag.
*/
break;
case AML_CREATE_BIT_FIELD_OP:
FieldBitLength = 1;
break;
case AML_CREATE_BYTE_FIELD_OP:
case AML_INDEX_OP:
FieldBitLength = 8;
break;
case AML_CREATE_WORD_FIELD_OP:
FieldBitLength = 16;
break;
FieldBitLength = 32;
break;
FieldBitLength = 64;
break;
default:
FieldBitLength = 0;
break;
}
/* Check the field length against the length of the resource tag */
if (FieldBitLength)
{
if (TagBitLength < FieldBitLength)
{
}
else if (TagBitLength > FieldBitLength)
{
}
if (Message)
{
}
}
/* Convert the BitOffset to a ByteOffset for certain opcodes */
{
case AML_CREATE_BYTE_FIELD_OP:
case AML_CREATE_WORD_FIELD_OP:
case AML_INDEX_OP:
break;
default:
break;
}
/* Now convert this node to an integer whose value is the field offset */
}
/* 3) Check for a method invocation */
else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
{
/*
* A reference to a method within one of these opcodes is not an
* invocation of the method, it is simply a reference to the method.
*/
{
}
/*
* There are two types of method invocation:
* 1) Invocation with arguments -- the parser recognizes this
* as a METHODCALL.
* 2) Invocation with no arguments --the parser cannot determine that
* this is a method invocation, therefore we have to figure it out
* here.
*/
{
}
/* Save the method node in the caller's op */
{
}
/*
* This is a method invocation, with or without arguments.
* Count the number of arguments, each appears as a child
* under the parent node
*/
PassedArgs = 0;
while (NextOp)
{
PassedArgs++;
}
{
/*
* Check the parsed arguments with the number expected by the
* method declaration itself
*/
{
{
}
else
{
}
}
}
}
/* 4) Check for an ASL Field definition */
{
/*
* Offset checking for fields. If the parent operation region has a
* constant length (known at compile time), we can check fields
* defined in that region against the region length. This will catch
* fields and field units that cannot possibly fit within the region.
*
* Note: Index fields do not directly reference an operation region,
* thus they are not included in this check.
*/
{
/*
* This is the first child of the field node, which is
* the name of the region. Get the parse node for the
* region -- which contains the length of the region.
*/
/* Examine the field access width */
{
case AML_FIELD_ACCESS_ANY:
case AML_FIELD_ACCESS_BYTE:
case AML_FIELD_ACCESS_BUFFER:
default:
MinimumLength = 1;
break;
case AML_FIELD_ACCESS_WORD:
MinimumLength = 2;
break;
case AML_FIELD_ACCESS_DWORD:
MinimumLength = 4;
break;
case AML_FIELD_ACCESS_QWORD:
MinimumLength = 8;
break;
}
/*
* Is the region at least as big as the access width?
* Note: DataTableRegions have 0 length
*/
{
}
/*
*/
{
case ACPI_ADR_SPACE_EC:
case ACPI_ADR_SPACE_CMOS:
case ACPI_ADR_SPACE_GPIO:
{
}
break;
case ACPI_ADR_SPACE_SMBUS:
case ACPI_ADR_SPACE_IPMI:
case ACPI_ADR_SPACE_GSBUS:
{
}
break;
default:
/* Nothing to do for other address spaces */
break;
}
}
else
{
/*
* This is one element of the field list. Check to make sure
* that it does not go beyond the end of the parent operation region.
*
* In the code below:
* Op->Asl.Parent->Asl.ExtraValue - Region Length (bits)
* Op->Asl.ExtraValue - Field start offset (bits)
* Op->Asl.Child->Asl.Value.Integer32 - Field length (bits)
* Op->Asl.Child->Asl.ExtraValue - Field access width (bits)
*/
{
}
}
}
/* 5) Check for a connection object */
#if 0
{
}
#endif
}
/*******************************************************************************
*
* FUNCTION: XfNamespaceLocateEnd
*
* PARAMETERS: ASL_WALK_CALLBACK
*
* RETURN: Status
*
* DESCRIPTION: Ascending callback used during cross reference. We only
* need to worry about scope management here.
*
******************************************************************************/
static ACPI_STATUS
void *Context)
{
const ACPI_OPCODE_INFO *OpInfo;
/* We are only interested in opcodes that have an associated name */
{
}
/* Not interested in name references, we did not open a scope for them */
{
}
/* Pop the scope stack if necessary */
{
"%s: Popping scope for Op %p\n",
(void) AcpiDsScopeStackPop (WalkState);
}
}
#ifdef __UNDER_DEVELOPMENT
/*******************************************************************************
*
* 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
{
/* Search upwards through the tree for possible parent */
while (ParentOp)
{
if (ParentOp == PossibleParentOp)
{
return (TRUE);
}
}
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 *
{
if (!Op)
{
return (NULL);
}
{
return (NULL);
}
/* Walk upwards through the parse tree, up to the root if necessary */
while (ParentOp)
{
{
return (ParentOp);
}
}
/* 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
{
/*
* 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.
*/
/* Are both objects within control method(s)? */
{
return;
}
/* Objects not in the same method? */
{
/*
* 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
*/
{
}
}
/*
* 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.
*/
{
}
}
#endif