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