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