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