1 /****************************************************************************** 2 * 3 * Module Name: asllookup- Namespace lookup functions 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 #include <contrib/dev/acpica/compiler/aslcompiler.h> 45 #include "aslcompiler.y.h" 46 #include <contrib/dev/acpica/include/acparser.h> 47 #include <contrib/dev/acpica/include/amlcode.h> 48 #include <contrib/dev/acpica/include/acnamesp.h> 49 #include <contrib/dev/acpica/include/acdispat.h> 50 51 52 #define _COMPONENT ACPI_COMPILER 53 ACPI_MODULE_NAME ("asllookup") 54 55 /* Local prototypes */ 56 57 static ACPI_STATUS 58 LkIsObjectUsed ( 59 ACPI_HANDLE ObjHandle, 60 UINT32 Level, 61 void *Context, 62 void **ReturnValue); 63 64 static ACPI_PARSE_OBJECT * 65 LkGetNameOp ( 66 ACPI_PARSE_OBJECT *Op); 67 68 69 /******************************************************************************* 70 * 71 * FUNCTION: LkFindUnreferencedObjects 72 * 73 * PARAMETERS: None 74 * 75 * RETURN: None 76 * 77 * DESCRIPTION: Namespace walk to find objects that are not referenced in any 78 * way. Must be called after the namespace has been cross 79 * referenced. 80 * 81 ******************************************************************************/ 82 83 void 84 LkFindUnreferencedObjects ( 85 void) 86 { 87 88 /* Walk entire namespace from the supplied root */ 89 90 (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 91 ACPI_UINT32_MAX, FALSE, LkIsObjectUsed, NULL, 92 NULL, NULL); 93 } 94 95 96 /******************************************************************************* 97 * 98 * FUNCTION: LkIsObjectUsed 99 * 100 * PARAMETERS: ACPI_WALK_CALLBACK 101 * 102 * RETURN: Status 103 * 104 * DESCRIPTION: Check for an unreferenced namespace object and emit a warning. 105 * We have to be careful, because some types and names are 106 * typically or always unreferenced, we don't want to issue 107 * excessive warnings. Note: Names that are declared within a 108 * control method are temporary, so we always issue a remark 109 * if they are not referenced. 110 * 111 ******************************************************************************/ 112 113 static ACPI_STATUS 114 LkIsObjectUsed ( 115 ACPI_HANDLE ObjHandle, 116 UINT32 Level, 117 void *Context, 118 void **ReturnValue) 119 { 120 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); 121 ACPI_NAMESPACE_NODE *Next; 122 ASL_METHOD_LOCAL *MethodLocals; 123 ASL_METHOD_LOCAL *MethodArgs; 124 UINT32 i; 125 126 127 if (Node->Type == ACPI_TYPE_METHOD) 128 { 129 if (!Node->Op || !Node->MethodLocals) 130 { 131 return (AE_OK); 132 } 133 134 MethodLocals = (ASL_METHOD_LOCAL *) Node->MethodLocals; 135 MethodArgs = (ASL_METHOD_LOCAL *) Node->MethodArgs; 136 137 /* 138 * Analysis of LocalX variables 139 */ 140 for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) 141 { 142 /* Warn for Locals that are set but never referenced */ 143 144 if ((MethodLocals[i].Flags & ASL_LOCAL_INITIALIZED) && 145 (!(MethodLocals[i].Flags & ASL_LOCAL_REFERENCED))) 146 { 147 sprintf (MsgBuffer, "Local%u", i); 148 AslError (ASL_WARNING, ASL_MSG_LOCAL_NOT_USED, 149 MethodLocals[i].Op, MsgBuffer); 150 } 151 } 152 153 /* 154 * Analysis of ArgX variables (standard method arguments, 155 * and remaining unused ArgX can also be used as locals) 156 */ 157 for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) 158 { 159 if (MethodArgs[i].Flags & ASL_ARG_IS_LOCAL) 160 { 161 /* Warn if ArgX is being used as a local, but not referenced */ 162 163 if ((MethodArgs[i].Flags & ASL_ARG_INITIALIZED) && 164 (!(MethodArgs[i].Flags & ASL_ARG_REFERENCED))) 165 { 166 sprintf (MsgBuffer, "Arg%u", i); 167 AslError (ASL_WARNING, ASL_MSG_ARG_AS_LOCAL_NOT_USED, 168 MethodArgs[i].Op, MsgBuffer); 169 } 170 } 171 else 172 { 173 /* 174 * Remark if a normal method ArgX is not referenced. 175 * We ignore the predefined methods since often, not 176 * all arguments are needed or used. 177 */ 178 if ((Node->Name.Ascii[0] != '_') && 179 (!(MethodArgs[i].Flags & ASL_ARG_REFERENCED))) 180 { 181 sprintf (MsgBuffer, "Arg%u", i); 182 AslError (ASL_REMARK, ASL_MSG_ARG_NOT_USED, 183 MethodArgs[i].Op, MsgBuffer); 184 } 185 } 186 } 187 } 188 189 /* Referenced flag is set during the namespace xref */ 190 191 if (Node->Flags & ANOBJ_IS_REFERENCED) 192 { 193 return (AE_OK); 194 } 195 196 if (!Node->Op) 197 { 198 return (AE_OK); 199 } 200 201 /* These types are typically never directly referenced, ignore them */ 202 203 switch (Node->Type) 204 { 205 case ACPI_TYPE_DEVICE: 206 case ACPI_TYPE_PROCESSOR: 207 case ACPI_TYPE_POWER: 208 case ACPI_TYPE_THERMAL: 209 case ACPI_TYPE_LOCAL_RESOURCE: 210 case ACPI_TYPE_LOCAL_RESOURCE_FIELD: /* Names assigned to descriptor elements */ 211 212 return (AE_OK); 213 214 default: 215 216 break; 217 } 218 219 /* Determine if the name is within a control method */ 220 221 Next = Node->Parent; 222 while (Next) 223 { 224 if (Next->Type == ACPI_TYPE_METHOD) 225 { 226 /* 227 * Name is within a method, therefore it is temporary. 228 * Issue a remark even if it is a reserved name (starts 229 * with an underscore). 230 */ 231 sprintf (MsgBuffer, "Name [%4.4s] is within a method [%4.4s]", 232 Node->Name.Ascii, Next->Name.Ascii); 233 AslError (ASL_REMARK, ASL_MSG_NOT_REFERENCED, 234 LkGetNameOp (Node->Op), MsgBuffer); 235 return (AE_OK); 236 } 237 238 Next = Next->Parent; 239 } 240 241 /* The name is not within a control method */ 242 243 /* 244 * Ignore names that start with an underscore. These are the reserved 245 * ACPI names and are typically not referenced since they are meant 246 * to be called by the host OS. 247 */ 248 if (Node->Name.Ascii[0] == '_') 249 { 250 return (AE_OK); 251 } 252 253 /* 254 * What remains is an unresolved user name that is not within a method. 255 * However, the object could be referenced via another table, so issue 256 * the warning at level 2. 257 */ 258 AslError (ASL_WARNING2, ASL_MSG_NOT_REFERENCED, 259 LkGetNameOp (Node->Op), NULL); 260 return (AE_OK); 261 } 262 263 264 /******************************************************************************* 265 * 266 * FUNCTION: LkGetNameOp 267 * 268 * PARAMETERS: Op - Current Op 269 * 270 * RETURN: NameOp associated with the input op 271 * 272 * DESCRIPTION: Find the name declaration op associated with the operator 273 * 274 ******************************************************************************/ 275 276 static ACPI_PARSE_OBJECT * 277 LkGetNameOp ( 278 ACPI_PARSE_OBJECT *Op) 279 { 280 const ACPI_OPCODE_INFO *OpInfo; 281 ACPI_PARSE_OBJECT *NameOp = Op; 282 283 284 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 285 286 287 /* Get the NamePath from the appropriate place */ 288 289 if (OpInfo->Flags & AML_NAMED) 290 { 291 /* For nearly all NAMED operators, the name reference is the first child */ 292 293 NameOp = Op->Asl.Child; 294 if (Op->Asl.AmlOpcode == AML_ALIAS_OP) 295 { 296 /* 297 * ALIAS is the only oddball opcode, the name declaration 298 * (alias name) is the second operand 299 */ 300 NameOp = Op->Asl.Child->Asl.Next; 301 } 302 } 303 else if (OpInfo->Flags & AML_CREATE) 304 { 305 /* Name must appear as the last parameter */ 306 307 NameOp = Op->Asl.Child; 308 while (!(NameOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) 309 { 310 NameOp = NameOp->Asl.Next; 311 } 312 } 313 314 return (NameOp); 315 } 316