1 2 /****************************************************************************** 3 * 4 * Module Name: exresolv - AML Interpreter object resolution 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2008, 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 "amlcode.h" 48 #include "acdispat.h" 49 #include "acinterp.h" 50 #include "acnamesp.h" 51 52 #define _COMPONENT ACPI_EXECUTER 53 ACPI_MODULE_NAME("exresolv") 54 55 /* Local prototypes */ 56 static acpi_status 57 acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, 58 struct acpi_walk_state *walk_state); 59 60 /******************************************************************************* 61 * 62 * FUNCTION: acpi_ex_resolve_to_value 63 * 64 * PARAMETERS: **stack_ptr - Points to entry on obj_stack, which can 65 * be either an (union acpi_operand_object *) 66 * or an acpi_handle. 67 * walk_state - Current method state 68 * 69 * RETURN: Status 70 * 71 * DESCRIPTION: Convert Reference objects to values 72 * 73 ******************************************************************************/ 74 75 acpi_status 76 acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr, 77 struct acpi_walk_state *walk_state) 78 { 79 acpi_status status; 80 81 ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr); 82 83 if (!stack_ptr || !*stack_ptr) { 84 ACPI_ERROR((AE_INFO, "Internal - null pointer")); 85 return_ACPI_STATUS(AE_AML_NO_OPERAND); 86 } 87 88 /* 89 * The entity pointed to by the stack_ptr can be either 90 * 1) A valid union acpi_operand_object, or 91 * 2) A struct acpi_namespace_node (named_obj) 92 */ 93 if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) { 94 status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state); 95 if (ACPI_FAILURE(status)) { 96 return_ACPI_STATUS(status); 97 } 98 99 if (!*stack_ptr) { 100 ACPI_ERROR((AE_INFO, "Internal - null pointer")); 101 return_ACPI_STATUS(AE_AML_NO_OPERAND); 102 } 103 } 104 105 /* 106 * Object on the stack may have changed if acpi_ex_resolve_object_to_value() 107 * was called (i.e., we can't use an _else_ here.) 108 */ 109 if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) { 110 status = 111 acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR 112 (struct acpi_namespace_node, 113 stack_ptr), walk_state); 114 if (ACPI_FAILURE(status)) { 115 return_ACPI_STATUS(status); 116 } 117 } 118 119 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr)); 120 return_ACPI_STATUS(AE_OK); 121 } 122 123 /******************************************************************************* 124 * 125 * FUNCTION: acpi_ex_resolve_object_to_value 126 * 127 * PARAMETERS: stack_ptr - Pointer to an internal object 128 * walk_state - Current method state 129 * 130 * RETURN: Status 131 * 132 * DESCRIPTION: Retrieve the value from an internal object. The Reference type 133 * uses the associated AML opcode to determine the value. 134 * 135 ******************************************************************************/ 136 137 static acpi_status 138 acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, 139 struct acpi_walk_state *walk_state) 140 { 141 acpi_status status = AE_OK; 142 union acpi_operand_object *stack_desc; 143 union acpi_operand_object *obj_desc = NULL; 144 u8 ref_type; 145 146 ACPI_FUNCTION_TRACE(ex_resolve_object_to_value); 147 148 stack_desc = *stack_ptr; 149 150 /* This is a union acpi_operand_object */ 151 152 switch (stack_desc->common.type) { 153 case ACPI_TYPE_LOCAL_REFERENCE: 154 155 ref_type = stack_desc->reference.class; 156 157 switch (ref_type) { 158 case ACPI_REFCLASS_LOCAL: 159 case ACPI_REFCLASS_ARG: 160 161 /* 162 * Get the local from the method's state info 163 * Note: this increments the local's object reference count 164 */ 165 status = acpi_ds_method_data_get_value(ref_type, 166 stack_desc-> 167 reference.value, 168 walk_state, 169 &obj_desc); 170 if (ACPI_FAILURE(status)) { 171 return_ACPI_STATUS(status); 172 } 173 174 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 175 "[Arg/Local %X] ValueObj is %p\n", 176 stack_desc->reference.value, 177 obj_desc)); 178 179 /* 180 * Now we can delete the original Reference Object and 181 * replace it with the resolved value 182 */ 183 acpi_ut_remove_reference(stack_desc); 184 *stack_ptr = obj_desc; 185 break; 186 187 case ACPI_REFCLASS_INDEX: 188 189 switch (stack_desc->reference.target_type) { 190 case ACPI_TYPE_BUFFER_FIELD: 191 192 /* Just return - do not dereference */ 193 break; 194 195 case ACPI_TYPE_PACKAGE: 196 197 /* If method call or copy_object - do not dereference */ 198 199 if ((walk_state->opcode == 200 AML_INT_METHODCALL_OP) 201 || (walk_state->opcode == AML_COPY_OP)) { 202 break; 203 } 204 205 /* Otherwise, dereference the package_index to a package element */ 206 207 obj_desc = *stack_desc->reference.where; 208 if (obj_desc) { 209 /* 210 * Valid object descriptor, copy pointer to return value 211 * (i.e., dereference the package index) 212 * Delete the ref object, increment the returned object 213 */ 214 acpi_ut_remove_reference(stack_desc); 215 acpi_ut_add_reference(obj_desc); 216 *stack_ptr = obj_desc; 217 } else { 218 /* 219 * A NULL object descriptor means an uninitialized element of 220 * the package, can't dereference it 221 */ 222 ACPI_ERROR((AE_INFO, 223 "Attempt to dereference an Index to NULL package element Idx=%p", 224 stack_desc)); 225 status = AE_AML_UNINITIALIZED_ELEMENT; 226 } 227 break; 228 229 default: 230 231 /* Invalid reference object */ 232 233 ACPI_ERROR((AE_INFO, 234 "Unknown TargetType %X in Index/Reference object %p", 235 stack_desc->reference.target_type, 236 stack_desc)); 237 status = AE_AML_INTERNAL; 238 break; 239 } 240 break; 241 242 case ACPI_REFCLASS_REFOF: 243 case ACPI_REFCLASS_DEBUG: 244 case ACPI_REFCLASS_TABLE: 245 246 /* Just leave the object as-is, do not dereference */ 247 248 break; 249 250 case ACPI_REFCLASS_NAME: /* Reference to a named object */ 251 252 /* Dereference the name */ 253 254 if ((stack_desc->reference.node->type == 255 ACPI_TYPE_DEVICE) 256 || (stack_desc->reference.node->type == 257 ACPI_TYPE_THERMAL)) { 258 259 /* These node types do not have 'real' subobjects */ 260 261 *stack_ptr = (void *)stack_desc->reference.node; 262 } else { 263 /* Get the object pointed to by the namespace node */ 264 265 *stack_ptr = 266 (stack_desc->reference.node)->object; 267 acpi_ut_add_reference(*stack_ptr); 268 } 269 270 acpi_ut_remove_reference(stack_desc); 271 break; 272 273 default: 274 275 ACPI_ERROR((AE_INFO, 276 "Unknown Reference type %X in %p", ref_type, 277 stack_desc)); 278 status = AE_AML_INTERNAL; 279 break; 280 } 281 break; 282 283 case ACPI_TYPE_BUFFER: 284 285 status = acpi_ds_get_buffer_arguments(stack_desc); 286 break; 287 288 case ACPI_TYPE_PACKAGE: 289 290 status = acpi_ds_get_package_arguments(stack_desc); 291 break; 292 293 case ACPI_TYPE_BUFFER_FIELD: 294 case ACPI_TYPE_LOCAL_REGION_FIELD: 295 case ACPI_TYPE_LOCAL_BANK_FIELD: 296 case ACPI_TYPE_LOCAL_INDEX_FIELD: 297 298 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 299 "FieldRead SourceDesc=%p Type=%X\n", 300 stack_desc, stack_desc->common.type)); 301 302 status = 303 acpi_ex_read_data_from_field(walk_state, stack_desc, 304 &obj_desc); 305 306 /* Remove a reference to the original operand, then override */ 307 308 acpi_ut_remove_reference(*stack_ptr); 309 *stack_ptr = (void *)obj_desc; 310 break; 311 312 default: 313 break; 314 } 315 316 return_ACPI_STATUS(status); 317 } 318 319 /******************************************************************************* 320 * 321 * FUNCTION: acpi_ex_resolve_multiple 322 * 323 * PARAMETERS: walk_state - Current state (contains AML opcode) 324 * Operand - Starting point for resolution 325 * return_type - Where the object type is returned 326 * return_desc - Where the resolved object is returned 327 * 328 * RETURN: Status 329 * 330 * DESCRIPTION: Return the base object and type. Traverse a reference list if 331 * necessary to get to the base object. 332 * 333 ******************************************************************************/ 334 335 acpi_status 336 acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, 337 union acpi_operand_object *operand, 338 acpi_object_type * return_type, 339 union acpi_operand_object **return_desc) 340 { 341 union acpi_operand_object *obj_desc = (void *)operand; 342 struct acpi_namespace_node *node; 343 acpi_object_type type; 344 acpi_status status; 345 346 ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple); 347 348 /* Operand can be either a namespace node or an operand descriptor */ 349 350 switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { 351 case ACPI_DESC_TYPE_OPERAND: 352 type = obj_desc->common.type; 353 break; 354 355 case ACPI_DESC_TYPE_NAMED: 356 type = ((struct acpi_namespace_node *)obj_desc)->type; 357 obj_desc = 358 acpi_ns_get_attached_object((struct acpi_namespace_node *) 359 obj_desc); 360 361 /* If we had an Alias node, use the attached object for type info */ 362 363 if (type == ACPI_TYPE_LOCAL_ALIAS) { 364 type = ((struct acpi_namespace_node *)obj_desc)->type; 365 obj_desc = 366 acpi_ns_get_attached_object((struct 367 acpi_namespace_node *) 368 obj_desc); 369 } 370 break; 371 372 default: 373 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 374 } 375 376 /* If type is anything other than a reference, we are done */ 377 378 if (type != ACPI_TYPE_LOCAL_REFERENCE) { 379 goto exit; 380 } 381 382 /* 383 * For reference objects created via the ref_of, Index, or Load/load_table 384 * operators, we need to get to the base object (as per the ACPI 385 * specification of the object_type and size_of operators). This means 386 * traversing the list of possibly many nested references. 387 */ 388 while (obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) { 389 switch (obj_desc->reference.class) { 390 case ACPI_REFCLASS_REFOF: 391 case ACPI_REFCLASS_NAME: 392 393 /* Dereference the reference pointer */ 394 395 if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) { 396 node = obj_desc->reference.object; 397 } else { /* AML_INT_NAMEPATH_OP */ 398 399 node = obj_desc->reference.node; 400 } 401 402 /* All "References" point to a NS node */ 403 404 if (ACPI_GET_DESCRIPTOR_TYPE(node) != 405 ACPI_DESC_TYPE_NAMED) { 406 ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]", 407 node, 408 acpi_ut_get_descriptor_name(node))); 409 return_ACPI_STATUS(AE_AML_INTERNAL); 410 } 411 412 /* Get the attached object */ 413 414 obj_desc = acpi_ns_get_attached_object(node); 415 if (!obj_desc) { 416 417 /* No object, use the NS node type */ 418 419 type = acpi_ns_get_type(node); 420 goto exit; 421 } 422 423 /* Check for circular references */ 424 425 if (obj_desc == operand) { 426 return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE); 427 } 428 break; 429 430 case ACPI_REFCLASS_INDEX: 431 432 /* Get the type of this reference (index into another object) */ 433 434 type = obj_desc->reference.target_type; 435 if (type != ACPI_TYPE_PACKAGE) { 436 goto exit; 437 } 438 439 /* 440 * The main object is a package, we want to get the type 441 * of the individual package element that is referenced by 442 * the index. 443 * 444 * This could of course in turn be another reference object. 445 */ 446 obj_desc = *(obj_desc->reference.where); 447 if (!obj_desc) { 448 449 /* NULL package elements are allowed */ 450 451 type = 0; /* Uninitialized */ 452 goto exit; 453 } 454 break; 455 456 case ACPI_REFCLASS_TABLE: 457 458 type = ACPI_TYPE_DDB_HANDLE; 459 goto exit; 460 461 case ACPI_REFCLASS_LOCAL: 462 case ACPI_REFCLASS_ARG: 463 464 if (return_desc) { 465 status = 466 acpi_ds_method_data_get_value(obj_desc-> 467 reference. 468 class, 469 obj_desc-> 470 reference. 471 value, 472 walk_state, 473 &obj_desc); 474 if (ACPI_FAILURE(status)) { 475 return_ACPI_STATUS(status); 476 } 477 acpi_ut_remove_reference(obj_desc); 478 } else { 479 status = 480 acpi_ds_method_data_get_node(obj_desc-> 481 reference. 482 class, 483 obj_desc-> 484 reference. 485 value, 486 walk_state, 487 &node); 488 if (ACPI_FAILURE(status)) { 489 return_ACPI_STATUS(status); 490 } 491 492 obj_desc = acpi_ns_get_attached_object(node); 493 if (!obj_desc) { 494 type = ACPI_TYPE_ANY; 495 goto exit; 496 } 497 } 498 break; 499 500 case ACPI_REFCLASS_DEBUG: 501 502 /* The Debug Object is of type "DebugObject" */ 503 504 type = ACPI_TYPE_DEBUG_OBJECT; 505 goto exit; 506 507 default: 508 509 ACPI_ERROR((AE_INFO, 510 "Unknown Reference Class %2.2X", 511 obj_desc->reference.class)); 512 return_ACPI_STATUS(AE_AML_INTERNAL); 513 } 514 } 515 516 /* 517 * Now we are guaranteed to have an object that has not been created 518 * via the ref_of or Index operators. 519 */ 520 type = obj_desc->common.type; 521 522 exit: 523 /* Convert internal types to external types */ 524 525 switch (type) { 526 case ACPI_TYPE_LOCAL_REGION_FIELD: 527 case ACPI_TYPE_LOCAL_BANK_FIELD: 528 case ACPI_TYPE_LOCAL_INDEX_FIELD: 529 530 type = ACPI_TYPE_FIELD_UNIT; 531 break; 532 533 case ACPI_TYPE_LOCAL_SCOPE: 534 535 /* Per ACPI Specification, Scope is untyped */ 536 537 type = ACPI_TYPE_ANY; 538 break; 539 540 default: 541 /* No change to Type required */ 542 break; 543 } 544 545 *return_type = type; 546 if (return_desc) { 547 *return_desc = obj_desc; 548 } 549 return_ACPI_STATUS(AE_OK); 550 } 551