1 /****************************************************************************** 2 * 3 * Module Name: dsopcode - Dispatcher support for regions and fields 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, 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 #include "acpi.h" 45 #include "accommon.h" 46 #include "acparser.h" 47 #include "amlcode.h" 48 #include "acdispat.h" 49 #include "acinterp.h" 50 #include "acnamesp.h" 51 #include "acevents.h" 52 #include "actables.h" 53 54 #define _COMPONENT ACPI_DISPATCHER 55 ACPI_MODULE_NAME ("dsopcode") 56 57 /* Local prototypes */ 58 59 static ACPI_STATUS 60 AcpiDsInitBufferField ( 61 UINT16 AmlOpcode, 62 ACPI_OPERAND_OBJECT *ObjDesc, 63 ACPI_OPERAND_OBJECT *BufferDesc, 64 ACPI_OPERAND_OBJECT *OffsetDesc, 65 ACPI_OPERAND_OBJECT *LengthDesc, 66 ACPI_OPERAND_OBJECT *ResultDesc); 67 68 69 /******************************************************************************* 70 * 71 * FUNCTION: AcpiDsInitializeRegion 72 * 73 * PARAMETERS: ObjHandle - Region namespace node 74 * 75 * RETURN: Status 76 * 77 * DESCRIPTION: Front end to EvInitializeRegion 78 * 79 ******************************************************************************/ 80 81 ACPI_STATUS 82 AcpiDsInitializeRegion ( 83 ACPI_HANDLE ObjHandle) 84 { 85 ACPI_OPERAND_OBJECT *ObjDesc; 86 ACPI_STATUS Status; 87 88 89 ObjDesc = AcpiNsGetAttachedObject (ObjHandle); 90 91 /* Namespace is NOT locked */ 92 93 Status = AcpiEvInitializeRegion (ObjDesc); 94 return (Status); 95 } 96 97 98 /******************************************************************************* 99 * 100 * FUNCTION: AcpiDsInitBufferField 101 * 102 * PARAMETERS: AmlOpcode - CreateXxxField 103 * ObjDesc - BufferField object 104 * BufferDesc - Host Buffer 105 * OffsetDesc - Offset into buffer 106 * LengthDesc - Length of field (CREATE_FIELD_OP only) 107 * ResultDesc - Where to store the result 108 * 109 * RETURN: Status 110 * 111 * DESCRIPTION: Perform actual initialization of a buffer field 112 * 113 ******************************************************************************/ 114 115 static ACPI_STATUS 116 AcpiDsInitBufferField ( 117 UINT16 AmlOpcode, 118 ACPI_OPERAND_OBJECT *ObjDesc, 119 ACPI_OPERAND_OBJECT *BufferDesc, 120 ACPI_OPERAND_OBJECT *OffsetDesc, 121 ACPI_OPERAND_OBJECT *LengthDesc, 122 ACPI_OPERAND_OBJECT *ResultDesc) 123 { 124 UINT32 Offset; 125 UINT32 BitOffset; 126 UINT32 BitCount; 127 UINT8 FieldFlags; 128 ACPI_STATUS Status; 129 130 131 ACPI_FUNCTION_TRACE_PTR (DsInitBufferField, ObjDesc); 132 133 134 /* Host object must be a Buffer */ 135 136 if (BufferDesc->Common.Type != ACPI_TYPE_BUFFER) 137 { 138 ACPI_ERROR ((AE_INFO, 139 "Target of Create Field is not a Buffer object - %s", 140 AcpiUtGetObjectTypeName (BufferDesc))); 141 142 Status = AE_AML_OPERAND_TYPE; 143 goto Cleanup; 144 } 145 146 /* 147 * The last parameter to all of these opcodes (ResultDesc) started 148 * out as a NameString, and should therefore now be a NS node 149 * after resolution in AcpiExResolveOperands(). 150 */ 151 if (ACPI_GET_DESCRIPTOR_TYPE (ResultDesc) != ACPI_DESC_TYPE_NAMED) 152 { 153 ACPI_ERROR ((AE_INFO, 154 "(%s) destination not a NS Node [%s]", 155 AcpiPsGetOpcodeName (AmlOpcode), 156 AcpiUtGetDescriptorName (ResultDesc))); 157 158 Status = AE_AML_OPERAND_TYPE; 159 goto Cleanup; 160 } 161 162 Offset = (UINT32) OffsetDesc->Integer.Value; 163 164 /* 165 * Setup the Bit offsets and counts, according to the opcode 166 */ 167 switch (AmlOpcode) 168 { 169 case AML_CREATE_FIELD_OP: 170 171 /* Offset is in bits, count is in bits */ 172 173 FieldFlags = AML_FIELD_ACCESS_BYTE; 174 BitOffset = Offset; 175 BitCount = (UINT32) LengthDesc->Integer.Value; 176 177 /* Must have a valid (>0) bit count */ 178 179 if (BitCount == 0) 180 { 181 ACPI_ERROR ((AE_INFO, 182 "Attempt to CreateField of length zero")); 183 Status = AE_AML_OPERAND_VALUE; 184 goto Cleanup; 185 } 186 break; 187 188 case AML_CREATE_BIT_FIELD_OP: 189 190 /* Offset is in bits, Field is one bit */ 191 192 BitOffset = Offset; 193 BitCount = 1; 194 FieldFlags = AML_FIELD_ACCESS_BYTE; 195 break; 196 197 case AML_CREATE_BYTE_FIELD_OP: 198 199 /* Offset is in bytes, field is one byte */ 200 201 BitOffset = 8 * Offset; 202 BitCount = 8; 203 FieldFlags = AML_FIELD_ACCESS_BYTE; 204 break; 205 206 case AML_CREATE_WORD_FIELD_OP: 207 208 /* Offset is in bytes, field is one word */ 209 210 BitOffset = 8 * Offset; 211 BitCount = 16; 212 FieldFlags = AML_FIELD_ACCESS_WORD; 213 break; 214 215 case AML_CREATE_DWORD_FIELD_OP: 216 217 /* Offset is in bytes, field is one dword */ 218 219 BitOffset = 8 * Offset; 220 BitCount = 32; 221 FieldFlags = AML_FIELD_ACCESS_DWORD; 222 break; 223 224 case AML_CREATE_QWORD_FIELD_OP: 225 226 /* Offset is in bytes, field is one qword */ 227 228 BitOffset = 8 * Offset; 229 BitCount = 64; 230 FieldFlags = AML_FIELD_ACCESS_QWORD; 231 break; 232 233 default: 234 235 ACPI_ERROR ((AE_INFO, 236 "Unknown field creation opcode 0x%02X", 237 AmlOpcode)); 238 Status = AE_AML_BAD_OPCODE; 239 goto Cleanup; 240 } 241 242 /* Entire field must fit within the current length of the buffer */ 243 244 if ((BitOffset + BitCount) > 245 (8 * (UINT32) BufferDesc->Buffer.Length)) 246 { 247 ACPI_ERROR ((AE_INFO, 248 "Field [%4.4s] at bit offset/length %u/%u " 249 "exceeds size of target Buffer (%u bits)", 250 AcpiUtGetNodeName (ResultDesc), BitOffset, BitCount, 251 8 * (UINT32) BufferDesc->Buffer.Length)); 252 Status = AE_AML_BUFFER_LIMIT; 253 goto Cleanup; 254 } 255 256 /* 257 * Initialize areas of the field object that are common to all fields 258 * For FieldFlags, use LOCK_RULE = 0 (NO_LOCK), 259 * UPDATE_RULE = 0 (UPDATE_PRESERVE) 260 */ 261 Status = AcpiExPrepCommonFieldObject ( 262 ObjDesc, FieldFlags, 0, BitOffset, BitCount); 263 if (ACPI_FAILURE (Status)) 264 { 265 goto Cleanup; 266 } 267 268 ObjDesc->BufferField.BufferObj = BufferDesc; 269 270 /* Reference count for BufferDesc inherits ObjDesc count */ 271 272 BufferDesc->Common.ReferenceCount = (UINT16) 273 (BufferDesc->Common.ReferenceCount + ObjDesc->Common.ReferenceCount); 274 275 276 Cleanup: 277 278 /* Always delete the operands */ 279 280 AcpiUtRemoveReference (OffsetDesc); 281 AcpiUtRemoveReference (BufferDesc); 282 283 if (AmlOpcode == AML_CREATE_FIELD_OP) 284 { 285 AcpiUtRemoveReference (LengthDesc); 286 } 287 288 /* On failure, delete the result descriptor */ 289 290 if (ACPI_FAILURE (Status)) 291 { 292 AcpiUtRemoveReference (ResultDesc); /* Result descriptor */ 293 } 294 else 295 { 296 /* Now the address and length are valid for this BufferField */ 297 298 ObjDesc->BufferField.Flags |= AOPOBJ_DATA_VALID; 299 } 300 301 return_ACPI_STATUS (Status); 302 } 303 304 305 /******************************************************************************* 306 * 307 * FUNCTION: AcpiDsEvalBufferFieldOperands 308 * 309 * PARAMETERS: WalkState - Current walk 310 * Op - A valid BufferField Op object 311 * 312 * RETURN: Status 313 * 314 * DESCRIPTION: Get BufferField Buffer and Index 315 * Called from AcpiDsExecEndOp during BufferField parse tree walk 316 * 317 ******************************************************************************/ 318 319 ACPI_STATUS 320 AcpiDsEvalBufferFieldOperands ( 321 ACPI_WALK_STATE *WalkState, 322 ACPI_PARSE_OBJECT *Op) 323 { 324 ACPI_STATUS Status; 325 ACPI_OPERAND_OBJECT *ObjDesc; 326 ACPI_NAMESPACE_NODE *Node; 327 ACPI_PARSE_OBJECT *NextOp; 328 329 330 ACPI_FUNCTION_TRACE_PTR (DsEvalBufferFieldOperands, Op); 331 332 333 /* 334 * This is where we evaluate the address and length fields of the 335 * CreateXxxField declaration 336 */ 337 Node = Op->Common.Node; 338 339 /* NextOp points to the op that holds the Buffer */ 340 341 NextOp = Op->Common.Value.Arg; 342 343 /* Evaluate/create the address and length operands */ 344 345 Status = AcpiDsCreateOperands (WalkState, NextOp); 346 if (ACPI_FAILURE (Status)) 347 { 348 return_ACPI_STATUS (Status); 349 } 350 351 ObjDesc = AcpiNsGetAttachedObject (Node); 352 if (!ObjDesc) 353 { 354 return_ACPI_STATUS (AE_NOT_EXIST); 355 } 356 357 /* Resolve the operands */ 358 359 Status = AcpiExResolveOperands ( 360 Op->Common.AmlOpcode, ACPI_WALK_OPERANDS, WalkState); 361 if (ACPI_FAILURE (Status)) 362 { 363 ACPI_ERROR ((AE_INFO, "(%s) bad operand(s), status 0x%X", 364 AcpiPsGetOpcodeName (Op->Common.AmlOpcode), Status)); 365 366 return_ACPI_STATUS (Status); 367 } 368 369 /* Initialize the Buffer Field */ 370 371 if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP) 372 { 373 /* NOTE: Slightly different operands for this opcode */ 374 375 Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc, 376 WalkState->Operands[0], WalkState->Operands[1], 377 WalkState->Operands[2], WalkState->Operands[3]); 378 } 379 else 380 { 381 /* All other, CreateXxxField opcodes */ 382 383 Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc, 384 WalkState->Operands[0], WalkState->Operands[1], 385 NULL, WalkState->Operands[2]); 386 } 387 388 return_ACPI_STATUS (Status); 389 } 390 391 392 /******************************************************************************* 393 * 394 * FUNCTION: AcpiDsEvalRegionOperands 395 * 396 * PARAMETERS: WalkState - Current walk 397 * Op - A valid region Op object 398 * 399 * RETURN: Status 400 * 401 * DESCRIPTION: Get region address and length 402 * Called from AcpiDsExecEndOp during OpRegion parse tree walk 403 * 404 ******************************************************************************/ 405 406 ACPI_STATUS 407 AcpiDsEvalRegionOperands ( 408 ACPI_WALK_STATE *WalkState, 409 ACPI_PARSE_OBJECT *Op) 410 { 411 ACPI_STATUS Status; 412 ACPI_OPERAND_OBJECT *ObjDesc; 413 ACPI_OPERAND_OBJECT *OperandDesc; 414 ACPI_NAMESPACE_NODE *Node; 415 ACPI_PARSE_OBJECT *NextOp; 416 417 418 ACPI_FUNCTION_TRACE_PTR (DsEvalRegionOperands, Op); 419 420 421 /* 422 * This is where we evaluate the address and length fields of the 423 * OpRegion declaration 424 */ 425 Node = Op->Common.Node; 426 427 /* NextOp points to the op that holds the SpaceID */ 428 429 NextOp = Op->Common.Value.Arg; 430 431 /* NextOp points to address op */ 432 433 NextOp = NextOp->Common.Next; 434 435 /* Evaluate/create the address and length operands */ 436 437 Status = AcpiDsCreateOperands (WalkState, NextOp); 438 if (ACPI_FAILURE (Status)) 439 { 440 return_ACPI_STATUS (Status); 441 } 442 443 /* Resolve the length and address operands to numbers */ 444 445 Status = AcpiExResolveOperands ( 446 Op->Common.AmlOpcode, ACPI_WALK_OPERANDS, WalkState); 447 if (ACPI_FAILURE (Status)) 448 { 449 return_ACPI_STATUS (Status); 450 } 451 452 ObjDesc = AcpiNsGetAttachedObject (Node); 453 if (!ObjDesc) 454 { 455 return_ACPI_STATUS (AE_NOT_EXIST); 456 } 457 458 /* 459 * Get the length operand and save it 460 * (at Top of stack) 461 */ 462 OperandDesc = WalkState->Operands[WalkState->NumOperands - 1]; 463 464 ObjDesc->Region.Length = (UINT32) OperandDesc->Integer.Value; 465 AcpiUtRemoveReference (OperandDesc); 466 467 /* 468 * Get the address and save it 469 * (at top of stack - 1) 470 */ 471 OperandDesc = WalkState->Operands[WalkState->NumOperands - 2]; 472 473 ObjDesc->Region.Address = (ACPI_PHYSICAL_ADDRESS) 474 OperandDesc->Integer.Value; 475 AcpiUtRemoveReference (OperandDesc); 476 477 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", 478 ObjDesc, ACPI_FORMAT_UINT64 (ObjDesc->Region.Address), 479 ObjDesc->Region.Length)); 480 481 /* Now the address and length are valid for this opregion */ 482 483 ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID; 484 return_ACPI_STATUS (Status); 485 } 486 487 488 /******************************************************************************* 489 * 490 * FUNCTION: AcpiDsEvalTableRegionOperands 491 * 492 * PARAMETERS: WalkState - Current walk 493 * Op - A valid region Op object 494 * 495 * RETURN: Status 496 * 497 * DESCRIPTION: Get region address and length. 498 * Called from AcpiDsExecEndOp during DataTableRegion parse 499 * tree walk. 500 * 501 ******************************************************************************/ 502 503 ACPI_STATUS 504 AcpiDsEvalTableRegionOperands ( 505 ACPI_WALK_STATE *WalkState, 506 ACPI_PARSE_OBJECT *Op) 507 { 508 ACPI_STATUS Status; 509 ACPI_OPERAND_OBJECT *ObjDesc; 510 ACPI_OPERAND_OBJECT **Operand; 511 ACPI_NAMESPACE_NODE *Node; 512 ACPI_PARSE_OBJECT *NextOp; 513 ACPI_TABLE_HEADER *Table; 514 UINT32 TableIndex; 515 516 517 ACPI_FUNCTION_TRACE_PTR (DsEvalTableRegionOperands, Op); 518 519 520 /* 521 * This is where we evaluate the Signature string, OemId string, 522 * and OemTableId string of the Data Table Region declaration 523 */ 524 Node = Op->Common.Node; 525 526 /* NextOp points to Signature string op */ 527 528 NextOp = Op->Common.Value.Arg; 529 530 /* 531 * Evaluate/create the Signature string, OemId string, 532 * and OemTableId string operands 533 */ 534 Status = AcpiDsCreateOperands (WalkState, NextOp); 535 if (ACPI_FAILURE (Status)) 536 { 537 return_ACPI_STATUS (Status); 538 } 539 540 Operand = &WalkState->Operands[0]; 541 542 /* 543 * Resolve the Signature string, OemId string, 544 * and OemTableId string operands 545 */ 546 Status = AcpiExResolveOperands ( 547 Op->Common.AmlOpcode, ACPI_WALK_OPERANDS, WalkState); 548 if (ACPI_FAILURE (Status)) 549 { 550 goto Cleanup; 551 } 552 553 /* Find the ACPI table */ 554 555 Status = AcpiTbFindTable ( 556 Operand[0]->String.Pointer, 557 Operand[1]->String.Pointer, 558 Operand[2]->String.Pointer, &TableIndex); 559 if (ACPI_FAILURE (Status)) 560 { 561 if (Status == AE_NOT_FOUND) 562 { 563 ACPI_ERROR ((AE_INFO, 564 "ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT", 565 Operand[0]->String.Pointer, 566 Operand[1]->String.Pointer, 567 Operand[2]->String.Pointer)); 568 } 569 goto Cleanup; 570 } 571 572 Status = AcpiGetTableByIndex (TableIndex, &Table); 573 if (ACPI_FAILURE (Status)) 574 { 575 goto Cleanup; 576 } 577 578 ObjDesc = AcpiNsGetAttachedObject (Node); 579 if (!ObjDesc) 580 { 581 Status = AE_NOT_EXIST; 582 goto Cleanup; 583 } 584 585 ObjDesc->Region.Address = ACPI_PTR_TO_PHYSADDR (Table); 586 ObjDesc->Region.Length = Table->Length; 587 588 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", 589 ObjDesc, ACPI_FORMAT_UINT64 (ObjDesc->Region.Address), 590 ObjDesc->Region.Length)); 591 592 /* Now the address and length are valid for this opregion */ 593 594 ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID; 595 596 Cleanup: 597 AcpiUtRemoveReference (Operand[0]); 598 AcpiUtRemoveReference (Operand[1]); 599 AcpiUtRemoveReference (Operand[2]); 600 601 return_ACPI_STATUS (Status); 602 } 603 604 605 /******************************************************************************* 606 * 607 * FUNCTION: AcpiDsEvalDataObjectOperands 608 * 609 * PARAMETERS: WalkState - Current walk 610 * Op - A valid DataObject Op object 611 * ObjDesc - DataObject 612 * 613 * RETURN: Status 614 * 615 * DESCRIPTION: Get the operands and complete the following data object types: 616 * Buffer, Package. 617 * 618 ******************************************************************************/ 619 620 ACPI_STATUS 621 AcpiDsEvalDataObjectOperands ( 622 ACPI_WALK_STATE *WalkState, 623 ACPI_PARSE_OBJECT *Op, 624 ACPI_OPERAND_OBJECT *ObjDesc) 625 { 626 ACPI_STATUS Status; 627 ACPI_OPERAND_OBJECT *ArgDesc; 628 UINT32 Length; 629 630 631 ACPI_FUNCTION_TRACE (DsEvalDataObjectOperands); 632 633 634 /* The first operand (for all of these data objects) is the length */ 635 636 /* 637 * Set proper index into operand stack for AcpiDsObjStackPush 638 * invoked inside AcpiDsCreateOperand. 639 */ 640 WalkState->OperandIndex = WalkState->NumOperands; 641 642 /* Ignore if child is not valid */ 643 644 if (!Op->Common.Value.Arg) 645 { 646 ACPI_ERROR ((AE_INFO, 647 "Dispatch: Missing child while executing TermArg for %X", 648 Op->Common.AmlOpcode)); 649 return_ACPI_STATUS (AE_OK); 650 } 651 652 Status = AcpiDsCreateOperand (WalkState, Op->Common.Value.Arg, 1); 653 if (ACPI_FAILURE (Status)) 654 { 655 return_ACPI_STATUS (Status); 656 } 657 658 Status = AcpiExResolveOperands (WalkState->Opcode, 659 &(WalkState->Operands [WalkState->NumOperands -1]), 660 WalkState); 661 if (ACPI_FAILURE (Status)) 662 { 663 return_ACPI_STATUS (Status); 664 } 665 666 /* Extract length operand */ 667 668 ArgDesc = WalkState->Operands [WalkState->NumOperands - 1]; 669 Length = (UINT32) ArgDesc->Integer.Value; 670 671 /* Cleanup for length operand */ 672 673 Status = AcpiDsObjStackPop (1, WalkState); 674 if (ACPI_FAILURE (Status)) 675 { 676 return_ACPI_STATUS (Status); 677 } 678 679 AcpiUtRemoveReference (ArgDesc); 680 681 /* 682 * Create the actual data object 683 */ 684 switch (Op->Common.AmlOpcode) 685 { 686 case AML_BUFFER_OP: 687 688 Status = AcpiDsBuildInternalBufferObj ( 689 WalkState, Op, Length, &ObjDesc); 690 break; 691 692 case AML_PACKAGE_OP: 693 case AML_VARIABLE_PACKAGE_OP: 694 695 Status = AcpiDsBuildInternalPackageObj ( 696 WalkState, Op, Length, &ObjDesc); 697 break; 698 699 default: 700 701 return_ACPI_STATUS (AE_AML_BAD_OPCODE); 702 } 703 704 if (ACPI_SUCCESS (Status)) 705 { 706 /* 707 * Return the object in the WalkState, unless the parent is a package - 708 * in this case, the return object will be stored in the parse tree 709 * for the package. 710 */ 711 if ((!Op->Common.Parent) || 712 ((Op->Common.Parent->Common.AmlOpcode != AML_PACKAGE_OP) && 713 (Op->Common.Parent->Common.AmlOpcode != AML_VARIABLE_PACKAGE_OP) && 714 (Op->Common.Parent->Common.AmlOpcode != AML_NAME_OP))) 715 { 716 WalkState->ResultObj = ObjDesc; 717 } 718 } 719 720 return_ACPI_STATUS (Status); 721 } 722 723 724 /******************************************************************************* 725 * 726 * FUNCTION: AcpiDsEvalBankFieldOperands 727 * 728 * PARAMETERS: WalkState - Current walk 729 * Op - A valid BankField Op object 730 * 731 * RETURN: Status 732 * 733 * DESCRIPTION: Get BankField BankValue 734 * Called from AcpiDsExecEndOp during BankField parse tree walk 735 * 736 ******************************************************************************/ 737 738 ACPI_STATUS 739 AcpiDsEvalBankFieldOperands ( 740 ACPI_WALK_STATE *WalkState, 741 ACPI_PARSE_OBJECT *Op) 742 { 743 ACPI_STATUS Status; 744 ACPI_OPERAND_OBJECT *ObjDesc; 745 ACPI_OPERAND_OBJECT *OperandDesc; 746 ACPI_NAMESPACE_NODE *Node; 747 ACPI_PARSE_OBJECT *NextOp; 748 ACPI_PARSE_OBJECT *Arg; 749 750 751 ACPI_FUNCTION_TRACE_PTR (DsEvalBankFieldOperands, Op); 752 753 754 /* 755 * This is where we evaluate the BankValue field of the 756 * BankField declaration 757 */ 758 759 /* NextOp points to the op that holds the Region */ 760 761 NextOp = Op->Common.Value.Arg; 762 763 /* NextOp points to the op that holds the Bank Register */ 764 765 NextOp = NextOp->Common.Next; 766 767 /* NextOp points to the op that holds the Bank Value */ 768 769 NextOp = NextOp->Common.Next; 770 771 /* 772 * Set proper index into operand stack for AcpiDsObjStackPush 773 * invoked inside AcpiDsCreateOperand. 774 * 775 * We use WalkState->Operands[0] to store the evaluated BankValue 776 */ 777 WalkState->OperandIndex = 0; 778 779 Status = AcpiDsCreateOperand (WalkState, NextOp, 0); 780 if (ACPI_FAILURE (Status)) 781 { 782 return_ACPI_STATUS (Status); 783 } 784 785 Status = AcpiExResolveToValue (&WalkState->Operands[0], WalkState); 786 if (ACPI_FAILURE (Status)) 787 { 788 return_ACPI_STATUS (Status); 789 } 790 791 ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, 792 AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 1); 793 /* 794 * Get the BankValue operand and save it 795 * (at Top of stack) 796 */ 797 OperandDesc = WalkState->Operands[0]; 798 799 /* Arg points to the start Bank Field */ 800 801 Arg = AcpiPsGetArg (Op, 4); 802 while (Arg) 803 { 804 /* Ignore OFFSET and ACCESSAS terms here */ 805 806 if (Arg->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) 807 { 808 Node = Arg->Common.Node; 809 810 ObjDesc = AcpiNsGetAttachedObject (Node); 811 if (!ObjDesc) 812 { 813 return_ACPI_STATUS (AE_NOT_EXIST); 814 } 815 816 ObjDesc->BankField.Value = (UINT32) OperandDesc->Integer.Value; 817 } 818 819 /* Move to next field in the list */ 820 821 Arg = Arg->Common.Next; 822 } 823 824 AcpiUtRemoveReference (OperandDesc); 825 return_ACPI_STATUS (Status); 826 } 827