1 /****************************************************************************** 2 * 3 * Module Name: pstree - Parser op tree manipulation/traversal/search 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, 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 "acpi.h" 45 #include "accommon.h" 46 #include "acparser.h" 47 #include "amlcode.h" 48 #include "acconvert.h" 49 50 #define _COMPONENT ACPI_PARSER 51 ACPI_MODULE_NAME ("pstree") 52 53 /* Local prototypes */ 54 55 #ifdef ACPI_OBSOLETE_FUNCTIONS 56 ACPI_PARSE_OBJECT * 57 AcpiPsGetChild ( 58 ACPI_PARSE_OBJECT *op); 59 #endif 60 61 62 /******************************************************************************* 63 * 64 * FUNCTION: AcpiPsGetArg 65 * 66 * PARAMETERS: Op - Get an argument for this op 67 * Argn - Nth argument to get 68 * 69 * RETURN: The argument (as an Op object). NULL if argument does not exist 70 * 71 * DESCRIPTION: Get the specified op's argument. 72 * 73 ******************************************************************************/ 74 75 ACPI_PARSE_OBJECT * 76 AcpiPsGetArg ( 77 ACPI_PARSE_OBJECT *Op, 78 UINT32 Argn) 79 { 80 ACPI_PARSE_OBJECT *Arg = NULL; 81 const ACPI_OPCODE_INFO *OpInfo; 82 83 84 ACPI_FUNCTION_ENTRY (); 85 86 /* 87 if (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP) 88 { 89 return (Op->Common.Value.Arg); 90 } 91 */ 92 /* Get the info structure for this opcode */ 93 94 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 95 if (OpInfo->Class == AML_CLASS_UNKNOWN) 96 { 97 /* Invalid opcode or ASCII character */ 98 99 return (NULL); 100 } 101 102 /* Check if this opcode requires argument sub-objects */ 103 104 if (!(OpInfo->Flags & AML_HAS_ARGS)) 105 { 106 /* Has no linked argument objects */ 107 108 return (NULL); 109 } 110 111 /* Get the requested argument object */ 112 113 Arg = Op->Common.Value.Arg; 114 while (Arg && Argn) 115 { 116 Argn--; 117 Arg = Arg->Common.Next; 118 } 119 120 return (Arg); 121 } 122 123 124 /******************************************************************************* 125 * 126 * FUNCTION: AcpiPsAppendArg 127 * 128 * PARAMETERS: Op - Append an argument to this Op. 129 * Arg - Argument Op to append 130 * 131 * RETURN: None. 132 * 133 * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK) 134 * 135 ******************************************************************************/ 136 137 void 138 AcpiPsAppendArg ( 139 ACPI_PARSE_OBJECT *Op, 140 ACPI_PARSE_OBJECT *Arg) 141 { 142 ACPI_PARSE_OBJECT *PrevArg; 143 const ACPI_OPCODE_INFO *OpInfo; 144 145 146 ACPI_FUNCTION_TRACE (PsAppendArg); 147 148 149 if (!Op) 150 { 151 return_VOID; 152 } 153 154 /* Get the info structure for this opcode */ 155 156 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 157 if (OpInfo->Class == AML_CLASS_UNKNOWN) 158 { 159 /* Invalid opcode */ 160 161 ACPI_ERROR ((AE_INFO, "Invalid AML Opcode: 0x%2.2X", 162 Op->Common.AmlOpcode)); 163 return_VOID; 164 } 165 166 /* Check if this opcode requires argument sub-objects */ 167 168 if (!(OpInfo->Flags & AML_HAS_ARGS)) 169 { 170 /* Has no linked argument objects */ 171 172 return_VOID; 173 } 174 175 /* Append the argument to the linked argument list */ 176 177 if (Op->Common.Value.Arg) 178 { 179 /* Append to existing argument list */ 180 181 PrevArg = Op->Common.Value.Arg; 182 while (PrevArg->Common.Next) 183 { 184 PrevArg = PrevArg->Common.Next; 185 } 186 PrevArg->Common.Next = Arg; 187 } 188 else 189 { 190 /* No argument list, this will be the first argument */ 191 192 Op->Common.Value.Arg = Arg; 193 } 194 195 /* Set the parent in this arg and any args linked after it */ 196 197 while (Arg) 198 { 199 Arg->Common.Parent = Op; 200 Arg = Arg->Common.Next; 201 202 Op->Common.ArgListLength++; 203 } 204 205 return_VOID; 206 } 207 208 209 /******************************************************************************* 210 * 211 * FUNCTION: AcpiPsGetDepthNext 212 * 213 * PARAMETERS: Origin - Root of subtree to search 214 * Op - Last (previous) Op that was found 215 * 216 * RETURN: Next Op found in the search. 217 * 218 * DESCRIPTION: Get next op in tree (walking the tree in depth-first order) 219 * Return NULL when reaching "origin" or when walking up from root 220 * 221 ******************************************************************************/ 222 223 ACPI_PARSE_OBJECT * 224 AcpiPsGetDepthNext ( 225 ACPI_PARSE_OBJECT *Origin, 226 ACPI_PARSE_OBJECT *Op) 227 { 228 ACPI_PARSE_OBJECT *Next = NULL; 229 ACPI_PARSE_OBJECT *Parent; 230 ACPI_PARSE_OBJECT *Arg; 231 232 233 ACPI_FUNCTION_ENTRY (); 234 235 236 if (!Op) 237 { 238 return (NULL); 239 } 240 241 /* Look for an argument or child */ 242 243 Next = AcpiPsGetArg (Op, 0); 244 if (Next) 245 { 246 ASL_CV_LABEL_FILENODE (Next); 247 return (Next); 248 } 249 250 /* Look for a sibling */ 251 252 Next = Op->Common.Next; 253 if (Next) 254 { 255 ASL_CV_LABEL_FILENODE (Next); 256 return (Next); 257 } 258 259 /* Look for a sibling of parent */ 260 261 Parent = Op->Common.Parent; 262 263 while (Parent) 264 { 265 Arg = AcpiPsGetArg (Parent, 0); 266 while (Arg && (Arg != Origin) && (Arg != Op)) 267 { 268 269 ASL_CV_LABEL_FILENODE (Arg); 270 Arg = Arg->Common.Next; 271 } 272 273 if (Arg == Origin) 274 { 275 /* Reached parent of origin, end search */ 276 277 return (NULL); 278 } 279 280 if (Parent->Common.Next) 281 { 282 /* Found sibling of parent */ 283 284 ASL_CV_LABEL_FILENODE (Parent->Common.Next); 285 return (Parent->Common.Next); 286 } 287 288 Op = Parent; 289 Parent = Parent->Common.Parent; 290 } 291 292 ASL_CV_LABEL_FILENODE (Next); 293 return (Next); 294 } 295 296 297 #ifdef ACPI_OBSOLETE_FUNCTIONS 298 /******************************************************************************* 299 * 300 * FUNCTION: AcpiPsGetChild 301 * 302 * PARAMETERS: Op - Get the child of this Op 303 * 304 * RETURN: Child Op, Null if none is found. 305 * 306 * DESCRIPTION: Get op's children or NULL if none 307 * 308 ******************************************************************************/ 309 310 ACPI_PARSE_OBJECT * 311 AcpiPsGetChild ( 312 ACPI_PARSE_OBJECT *Op) 313 { 314 ACPI_PARSE_OBJECT *Child = NULL; 315 316 317 ACPI_FUNCTION_ENTRY (); 318 319 320 switch (Op->Common.AmlOpcode) 321 { 322 case AML_SCOPE_OP: 323 case AML_ELSE_OP: 324 case AML_DEVICE_OP: 325 case AML_THERMAL_ZONE_OP: 326 case AML_INT_METHODCALL_OP: 327 328 Child = AcpiPsGetArg (Op, 0); 329 break; 330 331 case AML_BUFFER_OP: 332 case AML_PACKAGE_OP: 333 case AML_METHOD_OP: 334 case AML_IF_OP: 335 case AML_WHILE_OP: 336 case AML_FIELD_OP: 337 338 Child = AcpiPsGetArg (Op, 1); 339 break; 340 341 case AML_POWER_RESOURCE_OP: 342 case AML_INDEX_FIELD_OP: 343 344 Child = AcpiPsGetArg (Op, 2); 345 break; 346 347 case AML_PROCESSOR_OP: 348 case AML_BANK_FIELD_OP: 349 350 Child = AcpiPsGetArg (Op, 3); 351 break; 352 353 default: 354 355 /* All others have no children */ 356 357 break; 358 } 359 360 return (Child); 361 } 362 #endif 363