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 <contrib/dev/acpica/include/acpi.h> 47 #include <contrib/dev/acpica/include/accommon.h> 48 #include <contrib/dev/acpica/include/amlcode.h> 49 #include <contrib/dev/acpica/include/acdispat.h> 50 #include <contrib/dev/acpica/include/acinterp.h> 51 #include <contrib/dev/acpica/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 /* 181 * Get the local from the method's state info 182 * Note: this increments the local's object reference count 183 */ 184 Status = AcpiDsMethodDataGetValue (RefType, 185 StackDesc->Reference.Value, WalkState, &ObjDesc); 186 if (ACPI_FAILURE (Status)) 187 { 188 return_ACPI_STATUS (Status); 189 } 190 191 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] ValueObj is %p\n", 192 StackDesc->Reference.Value, ObjDesc)); 193 194 /* 195 * Now we can delete the original Reference Object and 196 * replace it with the resolved value 197 */ 198 AcpiUtRemoveReference (StackDesc); 199 *StackPtr = ObjDesc; 200 break; 201 202 203 case ACPI_REFCLASS_INDEX: 204 205 switch (StackDesc->Reference.TargetType) 206 { 207 case ACPI_TYPE_BUFFER_FIELD: 208 209 /* Just return - do not dereference */ 210 break; 211 212 213 case ACPI_TYPE_PACKAGE: 214 215 /* If method call or CopyObject - do not dereference */ 216 217 if ((WalkState->Opcode == AML_INT_METHODCALL_OP) || 218 (WalkState->Opcode == AML_COPY_OP)) 219 { 220 break; 221 } 222 223 /* Otherwise, dereference the PackageIndex to a package element */ 224 225 ObjDesc = *StackDesc->Reference.Where; 226 if (ObjDesc) 227 { 228 /* 229 * Valid object descriptor, copy pointer to return value 230 * (i.e., dereference the package index) 231 * Delete the ref object, increment the returned object 232 */ 233 AcpiUtRemoveReference (StackDesc); 234 AcpiUtAddReference (ObjDesc); 235 *StackPtr = ObjDesc; 236 } 237 else 238 { 239 /* 240 * A NULL object descriptor means an uninitialized element of 241 * the package, can't dereference it 242 */ 243 ACPI_ERROR ((AE_INFO, 244 "Attempt to dereference an Index to NULL package element Idx=%p", 245 StackDesc)); 246 Status = AE_AML_UNINITIALIZED_ELEMENT; 247 } 248 break; 249 250 251 default: 252 253 /* Invalid reference object */ 254 255 ACPI_ERROR ((AE_INFO, 256 "Unknown TargetType 0x%X in Index/Reference object %p", 257 StackDesc->Reference.TargetType, StackDesc)); 258 Status = AE_AML_INTERNAL; 259 break; 260 } 261 break; 262 263 264 case ACPI_REFCLASS_REFOF: 265 case ACPI_REFCLASS_DEBUG: 266 case ACPI_REFCLASS_TABLE: 267 268 /* Just leave the object as-is, do not dereference */ 269 270 break; 271 272 case ACPI_REFCLASS_NAME: /* Reference to a named object */ 273 274 /* Dereference the name */ 275 276 if ((StackDesc->Reference.Node->Type == ACPI_TYPE_DEVICE) || 277 (StackDesc->Reference.Node->Type == ACPI_TYPE_THERMAL)) 278 { 279 /* These node types do not have 'real' subobjects */ 280 281 *StackPtr = (void *) StackDesc->Reference.Node; 282 } 283 else 284 { 285 /* Get the object pointed to by the namespace node */ 286 287 *StackPtr = (StackDesc->Reference.Node)->Object; 288 AcpiUtAddReference (*StackPtr); 289 } 290 291 AcpiUtRemoveReference (StackDesc); 292 break; 293 294 default: 295 296 ACPI_ERROR ((AE_INFO, 297 "Unknown Reference type 0x%X in %p", RefType, StackDesc)); 298 Status = AE_AML_INTERNAL; 299 break; 300 } 301 break; 302 303 304 case ACPI_TYPE_BUFFER: 305 306 Status = AcpiDsGetBufferArguments (StackDesc); 307 break; 308 309 310 case ACPI_TYPE_PACKAGE: 311 312 Status = AcpiDsGetPackageArguments (StackDesc); 313 break; 314 315 316 case ACPI_TYPE_BUFFER_FIELD: 317 case ACPI_TYPE_LOCAL_REGION_FIELD: 318 case ACPI_TYPE_LOCAL_BANK_FIELD: 319 case ACPI_TYPE_LOCAL_INDEX_FIELD: 320 321 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "FieldRead SourceDesc=%p Type=%X\n", 322 StackDesc, StackDesc->Common.Type)); 323 324 Status = AcpiExReadDataFromField (WalkState, StackDesc, &ObjDesc); 325 326 /* Remove a reference to the original operand, then override */ 327 328 AcpiUtRemoveReference (*StackPtr); 329 *StackPtr = (void *) ObjDesc; 330 break; 331 332 default: 333 break; 334 } 335 336 return_ACPI_STATUS (Status); 337 } 338 339 340 /******************************************************************************* 341 * 342 * FUNCTION: AcpiExResolveMultiple 343 * 344 * PARAMETERS: WalkState - Current state (contains AML opcode) 345 * Operand - Starting point for resolution 346 * ReturnType - Where the object type is returned 347 * ReturnDesc - Where the resolved object is returned 348 * 349 * RETURN: Status 350 * 351 * DESCRIPTION: Return the base object and type. Traverse a reference list if 352 * necessary to get to the base object. 353 * 354 ******************************************************************************/ 355 356 ACPI_STATUS 357 AcpiExResolveMultiple ( 358 ACPI_WALK_STATE *WalkState, 359 ACPI_OPERAND_OBJECT *Operand, 360 ACPI_OBJECT_TYPE *ReturnType, 361 ACPI_OPERAND_OBJECT **ReturnDesc) 362 { 363 ACPI_OPERAND_OBJECT *ObjDesc = (void *) Operand; 364 ACPI_NAMESPACE_NODE *Node; 365 ACPI_OBJECT_TYPE Type; 366 ACPI_STATUS Status; 367 368 369 ACPI_FUNCTION_TRACE (AcpiExResolveMultiple); 370 371 372 /* Operand can be either a namespace node or an operand descriptor */ 373 374 switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) 375 { 376 case ACPI_DESC_TYPE_OPERAND: 377 Type = ObjDesc->Common.Type; 378 break; 379 380 case ACPI_DESC_TYPE_NAMED: 381 Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; 382 ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc); 383 384 /* If we had an Alias node, use the attached object for type info */ 385 386 if (Type == ACPI_TYPE_LOCAL_ALIAS) 387 { 388 Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; 389 ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc); 390 } 391 break; 392 393 default: 394 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 395 } 396 397 /* If type is anything other than a reference, we are done */ 398 399 if (Type != ACPI_TYPE_LOCAL_REFERENCE) 400 { 401 goto Exit; 402 } 403 404 /* 405 * For reference objects created via the RefOf, Index, or Load/LoadTable 406 * operators, we need to get to the base object (as per the ACPI 407 * specification of the ObjectType and SizeOf operators). This means 408 * traversing the list of possibly many nested references. 409 */ 410 while (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) 411 { 412 switch (ObjDesc->Reference.Class) 413 { 414 case ACPI_REFCLASS_REFOF: 415 case ACPI_REFCLASS_NAME: 416 417 /* Dereference the reference pointer */ 418 419 if (ObjDesc->Reference.Class == ACPI_REFCLASS_REFOF) 420 { 421 Node = ObjDesc->Reference.Object; 422 } 423 else /* AML_INT_NAMEPATH_OP */ 424 { 425 Node = ObjDesc->Reference.Node; 426 } 427 428 /* All "References" point to a NS node */ 429 430 if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) 431 { 432 ACPI_ERROR ((AE_INFO, 433 "Not a namespace node %p [%s]", 434 Node, AcpiUtGetDescriptorName (Node))); 435 return_ACPI_STATUS (AE_AML_INTERNAL); 436 } 437 438 /* Get the attached object */ 439 440 ObjDesc = AcpiNsGetAttachedObject (Node); 441 if (!ObjDesc) 442 { 443 /* No object, use the NS node type */ 444 445 Type = AcpiNsGetType (Node); 446 goto Exit; 447 } 448 449 /* Check for circular references */ 450 451 if (ObjDesc == Operand) 452 { 453 return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE); 454 } 455 break; 456 457 458 case ACPI_REFCLASS_INDEX: 459 460 /* Get the type of this reference (index into another object) */ 461 462 Type = ObjDesc->Reference.TargetType; 463 if (Type != ACPI_TYPE_PACKAGE) 464 { 465 goto Exit; 466 } 467 468 /* 469 * The main object is a package, we want to get the type 470 * of the individual package element that is referenced by 471 * the index. 472 * 473 * This could of course in turn be another reference object. 474 */ 475 ObjDesc = *(ObjDesc->Reference.Where); 476 if (!ObjDesc) 477 { 478 /* NULL package elements are allowed */ 479 480 Type = 0; /* Uninitialized */ 481 goto Exit; 482 } 483 break; 484 485 486 case ACPI_REFCLASS_TABLE: 487 488 Type = ACPI_TYPE_DDB_HANDLE; 489 goto Exit; 490 491 492 case ACPI_REFCLASS_LOCAL: 493 case ACPI_REFCLASS_ARG: 494 495 if (ReturnDesc) 496 { 497 Status = AcpiDsMethodDataGetValue (ObjDesc->Reference.Class, 498 ObjDesc->Reference.Value, WalkState, &ObjDesc); 499 if (ACPI_FAILURE (Status)) 500 { 501 return_ACPI_STATUS (Status); 502 } 503 AcpiUtRemoveReference (ObjDesc); 504 } 505 else 506 { 507 Status = AcpiDsMethodDataGetNode (ObjDesc->Reference.Class, 508 ObjDesc->Reference.Value, WalkState, &Node); 509 if (ACPI_FAILURE (Status)) 510 { 511 return_ACPI_STATUS (Status); 512 } 513 514 ObjDesc = AcpiNsGetAttachedObject (Node); 515 if (!ObjDesc) 516 { 517 Type = ACPI_TYPE_ANY; 518 goto Exit; 519 } 520 } 521 break; 522 523 524 case ACPI_REFCLASS_DEBUG: 525 526 /* The Debug Object is of type "DebugObject" */ 527 528 Type = ACPI_TYPE_DEBUG_OBJECT; 529 goto Exit; 530 531 532 default: 533 534 ACPI_ERROR ((AE_INFO, 535 "Unknown Reference Class 0x%2.2X", ObjDesc->Reference.Class)); 536 return_ACPI_STATUS (AE_AML_INTERNAL); 537 } 538 } 539 540 /* 541 * Now we are guaranteed to have an object that has not been created 542 * via the RefOf or Index operators. 543 */ 544 Type = ObjDesc->Common.Type; 545 546 547 Exit: 548 /* Convert internal types to external types */ 549 550 switch (Type) 551 { 552 case ACPI_TYPE_LOCAL_REGION_FIELD: 553 case ACPI_TYPE_LOCAL_BANK_FIELD: 554 case ACPI_TYPE_LOCAL_INDEX_FIELD: 555 556 Type = ACPI_TYPE_FIELD_UNIT; 557 break; 558 559 case ACPI_TYPE_LOCAL_SCOPE: 560 561 /* Per ACPI Specification, Scope is untyped */ 562 563 Type = ACPI_TYPE_ANY; 564 break; 565 566 default: 567 /* No change to Type required */ 568 break; 569 } 570 571 *ReturnType = Type; 572 if (ReturnDesc) 573 { 574 *ReturnDesc = ObjDesc; 575 } 576 return_ACPI_STATUS (AE_OK); 577 } 578