1 /******************************************************************************
   2  *
   3  * Module Name: asllookup- Namespace lookup functions
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 
  45 #include "aslcompiler.h"
  46 #include "aslcompiler.y.h"
  47 #include "acparser.h"
  48 #include "amlcode.h"
  49 #include "acnamesp.h"
  50 #include "acdispat.h"
  51 
  52 
  53 #define _COMPONENT          ACPI_COMPILER
  54         ACPI_MODULE_NAME    ("asllookup")
  55 
  56 /* Local prototypes */
  57 
  58 static ACPI_STATUS
  59 LkIsObjectUsed (
  60     ACPI_HANDLE             ObjHandle,
  61     UINT32                  Level,
  62     void                    *Context,
  63     void                    **ReturnValue);
  64 
  65 static ACPI_PARSE_OBJECT *
  66 LkGetNameOp (
  67     ACPI_PARSE_OBJECT       *Op);
  68 
  69 
  70 /*******************************************************************************
  71  *
  72  * FUNCTION:    LkFindUnreferencedObjects
  73  *
  74  * PARAMETERS:  None
  75  *
  76  * RETURN:      None
  77  *
  78  * DESCRIPTION: Namespace walk to find objects that are not referenced in any
  79  *              way. Must be called after the namespace has been cross
  80  *              referenced.
  81  *
  82  ******************************************************************************/
  83 
  84 void
  85 LkFindUnreferencedObjects (
  86     void)
  87 {
  88 
  89     /* Walk entire namespace from the supplied root */
  90 
  91     (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
  92                 ACPI_UINT32_MAX, FALSE, LkIsObjectUsed, NULL,
  93                 NULL, NULL);
  94 }
  95 
  96 
  97 /*******************************************************************************
  98  *
  99  * FUNCTION:    LkIsObjectUsed
 100  *
 101  * PARAMETERS:  ACPI_WALK_CALLBACK
 102  *
 103  * RETURN:      Status
 104  *
 105  * DESCRIPTION: Check for an unreferenced namespace object and emit a warning.
 106  *              We have to be careful, because some types and names are
 107  *              typically or always unreferenced, we don't want to issue
 108  *              excessive warnings. Note: Names that are declared within a
 109  *              control method are temporary, so we always issue a remark
 110  *              if they are not referenced.
 111  *
 112  ******************************************************************************/
 113 
 114 static ACPI_STATUS
 115 LkIsObjectUsed (
 116     ACPI_HANDLE             ObjHandle,
 117     UINT32                  Level,
 118     void                    *Context,
 119     void                    **ReturnValue)
 120 {
 121     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
 122     ACPI_NAMESPACE_NODE     *Next;
 123 
 124 
 125     /* Referenced flag is set during the namespace xref */
 126 
 127     if (Node->Flags & ANOBJ_IS_REFERENCED)
 128     {
 129         return (AE_OK);
 130     }
 131 
 132     if (!Node->Op)
 133     {
 134         return (AE_OK);
 135     }
 136 
 137     /* These types are typically never directly referenced, ignore them */
 138 
 139     switch (Node->Type)
 140     {
 141     case ACPI_TYPE_DEVICE:
 142     case ACPI_TYPE_PROCESSOR:
 143     case ACPI_TYPE_POWER:
 144     case ACPI_TYPE_THERMAL:
 145     case ACPI_TYPE_LOCAL_RESOURCE:
 146 
 147         return (AE_OK);
 148 
 149     default:
 150 
 151         break;
 152     }
 153 
 154     /* Determine if the name is within a control method */
 155 
 156     Next = Node->Parent;
 157     while (Next)
 158     {
 159         if (Next->Type == ACPI_TYPE_METHOD)
 160         {
 161             /*
 162              * Name is within a method, therefore it is temporary.
 163              * Issue a remark even if it is a reserved name (starts
 164              * with an underscore).
 165              */
 166             sprintf (MsgBuffer, "Name is within method [%4.4s]",
 167                 Next->Name.Ascii);
 168             AslError (ASL_REMARK, ASL_MSG_NOT_REFERENCED,
 169                 LkGetNameOp (Node->Op), MsgBuffer);
 170             return (AE_OK);
 171         }
 172 
 173         Next = Next->Parent;
 174     }
 175 
 176     /* The name is not within a control method */
 177 
 178     /*
 179      * Ignore names that start with an underscore. These are the reserved
 180      * ACPI names and are typically not referenced since they are meant
 181      * to be called by the host OS.
 182      */
 183     if (Node->Name.Ascii[0] == '_')
 184     {
 185         return (AE_OK);
 186     }
 187 
 188     /*
 189      * What remains is an unresolved user name that is not within a method.
 190      * However, the object could be referenced via another table, so issue
 191      * the warning at level 2.
 192      */
 193     AslError (ASL_WARNING2, ASL_MSG_NOT_REFERENCED,
 194         LkGetNameOp (Node->Op), NULL);
 195     return (AE_OK);
 196 }
 197 
 198 
 199 /*******************************************************************************
 200  *
 201  * FUNCTION:    LkGetNameOp
 202  *
 203  * PARAMETERS:  Op              - Current Op
 204  *
 205  * RETURN:      NameOp associated with the input op
 206  *
 207  * DESCRIPTION: Find the name declaration op associated with the operator
 208  *
 209  ******************************************************************************/
 210 
 211 static ACPI_PARSE_OBJECT *
 212 LkGetNameOp (
 213     ACPI_PARSE_OBJECT       *Op)
 214 {
 215     const ACPI_OPCODE_INFO  *OpInfo;
 216     ACPI_PARSE_OBJECT       *NameOp = Op;
 217 
 218 
 219     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
 220 
 221 
 222     /* Get the NamePath from the appropriate place */
 223 
 224     if (OpInfo->Flags & AML_NAMED)
 225     {
 226         /* For nearly all NAMED operators, the name reference is the first child */
 227 
 228         NameOp = Op->Asl.Child;
 229         if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
 230         {
 231             /*
 232              * ALIAS is the only oddball opcode, the name declaration
 233              * (alias name) is the second operand
 234              */
 235             NameOp = Op->Asl.Child->Asl.Next;
 236         }
 237     }
 238     else if (OpInfo->Flags & AML_CREATE)
 239     {
 240         /* Name must appear as the last parameter */
 241 
 242         NameOp = Op->Asl.Child;
 243         while (!(NameOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
 244         {
 245             NameOp = NameOp->Asl.Next;
 246         }
 247     }
 248 
 249     return (NameOp);
 250 }