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