1 /****************************************************************************** 2 * 3 * Module Name: dsargs - Support for execution of dynamic arguments for static 4 * objects (regions, fields, buffer fields, etc.) 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2017, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #include <acpi/acpi.h> 46 #include "accommon.h" 47 #include "acparser.h" 48 #include "amlcode.h" 49 #include "acdispat.h" 50 #include "acnamesp.h" 51 52 #define _COMPONENT ACPI_DISPATCHER 53 ACPI_MODULE_NAME("dsargs") 54 55 /* Local prototypes */ 56 static acpi_status 57 acpi_ds_execute_arguments(struct acpi_namespace_node *node, 58 struct acpi_namespace_node *scope_node, 59 u32 aml_length, u8 *aml_start); 60 61 /******************************************************************************* 62 * 63 * FUNCTION: acpi_ds_execute_arguments 64 * 65 * PARAMETERS: node - Object NS node 66 * scope_node - Parent NS node 67 * aml_length - Length of executable AML 68 * aml_start - Pointer to the AML 69 * 70 * RETURN: Status. 71 * 72 * DESCRIPTION: Late (deferred) execution of region or field arguments 73 * 74 ******************************************************************************/ 75 76 static acpi_status 77 acpi_ds_execute_arguments(struct acpi_namespace_node *node, 78 struct acpi_namespace_node *scope_node, 79 u32 aml_length, u8 *aml_start) 80 { 81 acpi_status status; 82 union acpi_parse_object *op; 83 struct acpi_walk_state *walk_state; 84 85 ACPI_FUNCTION_TRACE(ds_execute_arguments); 86 87 /* Allocate a new parser op to be the root of the parsed tree */ 88 89 op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start); 90 if (!op) { 91 return_ACPI_STATUS(AE_NO_MEMORY); 92 } 93 94 /* Save the Node for use in acpi_ps_parse_aml */ 95 96 op->common.node = scope_node; 97 98 /* Create and initialize a new parser state */ 99 100 walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); 101 if (!walk_state) { 102 status = AE_NO_MEMORY; 103 goto cleanup; 104 } 105 106 status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, 107 aml_length, NULL, ACPI_IMODE_LOAD_PASS1); 108 if (ACPI_FAILURE(status)) { 109 acpi_ds_delete_walk_state(walk_state); 110 goto cleanup; 111 } 112 113 /* Mark this parse as a deferred opcode */ 114 115 walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; 116 walk_state->deferred_node = node; 117 118 /* Pass1: Parse the entire declaration */ 119 120 status = acpi_ps_parse_aml(walk_state); 121 if (ACPI_FAILURE(status)) { 122 goto cleanup; 123 } 124 125 /* Get and init the Op created above */ 126 127 op->common.node = node; 128 acpi_ps_delete_parse_tree(op); 129 130 /* Evaluate the deferred arguments */ 131 132 op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start); 133 if (!op) { 134 return_ACPI_STATUS(AE_NO_MEMORY); 135 } 136 137 op->common.node = scope_node; 138 139 /* Create and initialize a new parser state */ 140 141 walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); 142 if (!walk_state) { 143 status = AE_NO_MEMORY; 144 goto cleanup; 145 } 146 147 /* Execute the opcode and arguments */ 148 149 status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, 150 aml_length, NULL, ACPI_IMODE_EXECUTE); 151 if (ACPI_FAILURE(status)) { 152 acpi_ds_delete_walk_state(walk_state); 153 goto cleanup; 154 } 155 156 /* Mark this execution as a deferred opcode */ 157 158 walk_state->deferred_node = node; 159 status = acpi_ps_parse_aml(walk_state); 160 161 cleanup: 162 acpi_ps_delete_parse_tree(op); 163 return_ACPI_STATUS(status); 164 } 165 166 /******************************************************************************* 167 * 168 * FUNCTION: acpi_ds_get_buffer_field_arguments 169 * 170 * PARAMETERS: obj_desc - A valid buffer_field object 171 * 172 * RETURN: Status. 173 * 174 * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late 175 * evaluation of these field attributes. 176 * 177 ******************************************************************************/ 178 179 acpi_status 180 acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) 181 { 182 union acpi_operand_object *extra_desc; 183 struct acpi_namespace_node *node; 184 acpi_status status; 185 186 ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); 187 188 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { 189 return_ACPI_STATUS(AE_OK); 190 } 191 192 /* Get the AML pointer (method object) and buffer_field node */ 193 194 extra_desc = acpi_ns_get_secondary_object(obj_desc); 195 node = obj_desc->buffer_field.node; 196 197 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname 198 (ACPI_TYPE_BUFFER_FIELD, node, NULL)); 199 200 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", 201 acpi_ut_get_node_name(node))); 202 203 /* Execute the AML code for the term_arg arguments */ 204 205 status = acpi_ds_execute_arguments(node, node->parent, 206 extra_desc->extra.aml_length, 207 extra_desc->extra.aml_start); 208 return_ACPI_STATUS(status); 209 } 210 211 /******************************************************************************* 212 * 213 * FUNCTION: acpi_ds_get_bank_field_arguments 214 * 215 * PARAMETERS: obj_desc - A valid bank_field object 216 * 217 * RETURN: Status. 218 * 219 * DESCRIPTION: Get bank_field bank_value. This implements the late 220 * evaluation of these field attributes. 221 * 222 ******************************************************************************/ 223 224 acpi_status 225 acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) 226 { 227 union acpi_operand_object *extra_desc; 228 struct acpi_namespace_node *node; 229 acpi_status status; 230 231 ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); 232 233 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { 234 return_ACPI_STATUS(AE_OK); 235 } 236 237 /* Get the AML pointer (method object) and bank_field node */ 238 239 extra_desc = acpi_ns_get_secondary_object(obj_desc); 240 node = obj_desc->bank_field.node; 241 242 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname 243 (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); 244 245 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", 246 acpi_ut_get_node_name(node))); 247 248 /* Execute the AML code for the term_arg arguments */ 249 250 status = acpi_ds_execute_arguments(node, node->parent, 251 extra_desc->extra.aml_length, 252 extra_desc->extra.aml_start); 253 if (ACPI_FAILURE(status)) { 254 return_ACPI_STATUS(status); 255 } 256 257 status = acpi_ut_add_address_range(obj_desc->region.space_id, 258 obj_desc->region.address, 259 obj_desc->region.length, node); 260 return_ACPI_STATUS(status); 261 } 262 263 /******************************************************************************* 264 * 265 * FUNCTION: acpi_ds_get_buffer_arguments 266 * 267 * PARAMETERS: obj_desc - A valid Buffer object 268 * 269 * RETURN: Status. 270 * 271 * DESCRIPTION: Get Buffer length and initializer byte list. This implements 272 * the late evaluation of these attributes. 273 * 274 ******************************************************************************/ 275 276 acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) 277 { 278 struct acpi_namespace_node *node; 279 acpi_status status; 280 281 ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); 282 283 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { 284 return_ACPI_STATUS(AE_OK); 285 } 286 287 /* Get the Buffer node */ 288 289 node = obj_desc->buffer.node; 290 if (!node) { 291 ACPI_ERROR((AE_INFO, 292 "No pointer back to namespace node in buffer object %p", 293 obj_desc)); 294 return_ACPI_STATUS(AE_AML_INTERNAL); 295 } 296 297 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); 298 299 /* Execute the AML code for the term_arg arguments */ 300 301 status = acpi_ds_execute_arguments(node, node, 302 obj_desc->buffer.aml_length, 303 obj_desc->buffer.aml_start); 304 return_ACPI_STATUS(status); 305 } 306 307 /******************************************************************************* 308 * 309 * FUNCTION: acpi_ds_get_package_arguments 310 * 311 * PARAMETERS: obj_desc - A valid Package object 312 * 313 * RETURN: Status. 314 * 315 * DESCRIPTION: Get Package length and initializer byte list. This implements 316 * the late evaluation of these attributes. 317 * 318 ******************************************************************************/ 319 320 acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) 321 { 322 struct acpi_namespace_node *node; 323 acpi_status status; 324 325 ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); 326 327 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { 328 return_ACPI_STATUS(AE_OK); 329 } 330 331 /* Get the Package node */ 332 333 node = obj_desc->package.node; 334 if (!node) { 335 ACPI_ERROR((AE_INFO, 336 "No pointer back to namespace node in package %p", 337 obj_desc)); 338 return_ACPI_STATUS(AE_AML_INTERNAL); 339 } 340 341 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); 342 343 /* Execute the AML code for the term_arg arguments */ 344 345 status = acpi_ds_execute_arguments(node, node, 346 obj_desc->package.aml_length, 347 obj_desc->package.aml_start); 348 return_ACPI_STATUS(status); 349 } 350 351 /******************************************************************************* 352 * 353 * FUNCTION: acpi_ds_get_region_arguments 354 * 355 * PARAMETERS: obj_desc - A valid region object 356 * 357 * RETURN: Status. 358 * 359 * DESCRIPTION: Get region address and length. This implements the late 360 * evaluation of these region attributes. 361 * 362 ******************************************************************************/ 363 364 acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) 365 { 366 struct acpi_namespace_node *node; 367 acpi_status status; 368 union acpi_operand_object *extra_desc; 369 370 ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); 371 372 if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { 373 return_ACPI_STATUS(AE_OK); 374 } 375 376 extra_desc = acpi_ns_get_secondary_object(obj_desc); 377 if (!extra_desc) { 378 return_ACPI_STATUS(AE_NOT_EXIST); 379 } 380 381 /* Get the Region node */ 382 383 node = obj_desc->region.node; 384 385 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname 386 (ACPI_TYPE_REGION, node, NULL)); 387 388 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 389 "[%4.4s] OpRegion Arg Init at AML %p\n", 390 acpi_ut_get_node_name(node), 391 extra_desc->extra.aml_start)); 392 393 /* Execute the argument AML */ 394 395 status = acpi_ds_execute_arguments(node, extra_desc->extra.scope_node, 396 extra_desc->extra.aml_length, 397 extra_desc->extra.aml_start); 398 if (ACPI_FAILURE(status)) { 399 return_ACPI_STATUS(status); 400 } 401 402 status = acpi_ut_add_address_range(obj_desc->region.space_id, 403 obj_desc->region.address, 404 obj_desc->region.length, node); 405 return_ACPI_STATUS(status); 406 } 407