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