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 __DSWLOAD2_C__ 45 46#include <contrib/dev/acpica/include/acpi.h> 47#include <contrib/dev/acpica/include/accommon.h> 48#include <contrib/dev/acpica/include/acparser.h> 49#include <contrib/dev/acpica/include/amlcode.h> 50#include <contrib/dev/acpica/include/acdispat.h> 51#include <contrib/dev/acpica/include/acinterp.h> 52#include <contrib/dev/acpica/include/acnamesp.h> 53#include <contrib/dev/acpica/include/acevents.h> 54 55#define _COMPONENT ACPI_DISPATCHER 56 ACPI_MODULE_NAME ("dswload2") 57 58 59/******************************************************************************* 60 * 61 * FUNCTION: AcpiDsLoad2BeginOp 62 * 63 * PARAMETERS: WalkState - Current state of the parse tree walk 64 * OutOp - Wher to return op if a new one is created 65 * 66 * RETURN: Status 67 * 68 * DESCRIPTION: Descending callback used during the loading of ACPI tables. 69 * 70 ******************************************************************************/ 71 72ACPI_STATUS 73AcpiDsLoad2BeginOp ( 74 ACPI_WALK_STATE *WalkState, 75 ACPI_PARSE_OBJECT **OutOp) 76{ 77 ACPI_PARSE_OBJECT *Op; 78 ACPI_NAMESPACE_NODE *Node; 79 ACPI_STATUS Status; 80 ACPI_OBJECT_TYPE ObjectType; 81 char *BufferPtr; 82 UINT32 Flags; 83 84 85 ACPI_FUNCTION_TRACE (DsLoad2BeginOp); 86 87 88 Op = WalkState->Op; 89 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState)); 90 91 if (Op) 92 { 93 if ((WalkState->ControlState) && 94 (WalkState->ControlState->Common.State == 95 ACPI_CONTROL_CONDITIONAL_EXECUTING)) 96 { 97 /* We are executing a while loop outside of a method */ 98 99 Status = AcpiDsExecBeginOp (WalkState, OutOp); 100 return_ACPI_STATUS (Status); 101 } 102 103 /* We only care about Namespace opcodes here */ 104 105 if ((!(WalkState->OpInfo->Flags & AML_NSOPCODE) && 106 (WalkState->Opcode != AML_INT_NAMEPATH_OP)) || 107 (!(WalkState->OpInfo->Flags & AML_NAMED))) 108 { 109 return_ACPI_STATUS (AE_OK); 110 } 111 112 /* Get the name we are going to enter or lookup in the namespace */ 113 114 if (WalkState->Opcode == AML_INT_NAMEPATH_OP) 115 { 116 /* For Namepath op, get the path string */ 117 118 BufferPtr = Op->Common.Value.String; 119 if (!BufferPtr) 120 { 121 /* No name, just exit */ 122 123 return_ACPI_STATUS (AE_OK); 124 } 125 } 126 else 127 { 128 /* Get name from the op */ 129 130 BufferPtr = ACPI_CAST_PTR (char, &Op->Named.Name); 131 } 132 } 133 else 134 { 135 /* Get the namestring from the raw AML */ 136 137 BufferPtr = AcpiPsGetNextNamestring (&WalkState->ParserState); 138 } 139 140 /* Map the opcode into an internal object type */ 141 142 ObjectType = WalkState->OpInfo->ObjectType; 143 144 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 145 "State=%p Op=%p Type=%X\n", WalkState, Op, ObjectType)); 146 147 switch (WalkState->Opcode) 148 { 149 case AML_FIELD_OP: 150 case AML_BANK_FIELD_OP: 151 case AML_INDEX_FIELD_OP: 152 153 Node = NULL; 154 Status = AE_OK; 155 break; 156 157 case AML_INT_NAMEPATH_OP: 158 /* 159 * The NamePath is an object reference to an existing object. 160 * Don't enter the name into the namespace, but look it up 161 * for use later. 162 */ 163 Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType, 164 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 165 WalkState, &(Node)); 166 break; 167 168 case AML_SCOPE_OP: 169 170 /* Special case for Scope(\) -> refers to the Root node */ 171 172 if (Op && (Op->Named.Node == AcpiGbl_RootNode)) 173 { 174 Node = Op->Named.Node; 175 176 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 177 if (ACPI_FAILURE (Status)) 178 { 179 return_ACPI_STATUS (Status); 180 } 181 } 182 else 183 { 184 /* 185 * The Path is an object reference to an existing object. 186 * Don't enter the name into the namespace, but look it up 187 * for use later. 188 */ 189 Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType, 190 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 191 WalkState, &(Node)); 192 if (ACPI_FAILURE (Status)) 193 { 194#ifdef ACPI_ASL_COMPILER 195 if (Status == AE_NOT_FOUND) 196 { 197 Status = AE_OK; 198 } 199 else 200 { 201 ACPI_ERROR_NAMESPACE (BufferPtr, Status); 202 } 203#else 204 ACPI_ERROR_NAMESPACE (BufferPtr, Status); 205#endif 206 return_ACPI_STATUS (Status); 207 } 208 } 209 210 /* 211 * We must check to make sure that the target is 212 * one of the opcodes that actually opens a scope 213 */ 214 switch (Node->Type) 215 { 216 case ACPI_TYPE_ANY: 217 case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ 218 case ACPI_TYPE_DEVICE: 219 case ACPI_TYPE_POWER: 220 case ACPI_TYPE_PROCESSOR: 221 case ACPI_TYPE_THERMAL: 222 223 /* These are acceptable types */ 224 break; 225 226 case ACPI_TYPE_INTEGER: 227 case ACPI_TYPE_STRING: 228 case ACPI_TYPE_BUFFER: 229 230 /* 231 * These types we will allow, but we will change the type. 232 * This enables some existing code of the form: 233 * 234 * Name (DEB, 0) 235 * Scope (DEB) { ... } 236 */ 237 ACPI_WARNING ((AE_INFO, 238 "Type override - [%4.4s] had invalid type (%s) " 239 "for Scope operator, changed to type ANY\n", 240 AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type))); 241 242 Node->Type = ACPI_TYPE_ANY; 243 WalkState->ScopeInfo->Common.Value = ACPI_TYPE_ANY; 244 break; 245 246 default: 247 248 /* All other types are an error */ 249 250 ACPI_ERROR ((AE_INFO, 251 "Invalid type (%s) for target of " 252 "Scope operator [%4.4s] (Cannot override)", 253 AcpiUtGetTypeName (Node->Type), AcpiUtGetNodeName (Node))); 254 255 return (AE_AML_OPERAND_TYPE); 256 } 257 break; 258 259 default: 260 261 /* All other opcodes */ 262 263 if (Op && Op->Common.Node) 264 { 265 /* This op/node was previously entered into the namespace */ 266 267 Node = Op->Common.Node; 268 269 if (AcpiNsOpensScope (ObjectType)) 270 { 271 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 272 if (ACPI_FAILURE (Status)) 273 { 274 return_ACPI_STATUS (Status); 275 } 276 } 277 278 return_ACPI_STATUS (AE_OK); 279 } 280 281 /* 282 * Enter the named type into the internal namespace. We enter the name 283 * as we go downward in the parse tree. Any necessary subobjects that 284 * involve arguments to the opcode must be created as we go back up the 285 * parse tree later. 286 * 287 * Note: Name may already exist if we are executing a deferred opcode. 288 */ 289 if (WalkState->DeferredNode) 290 { 291 /* This name is already in the namespace, get the node */ 292 293 Node = WalkState->DeferredNode; 294 Status = AE_OK; 295 break; 296 } 297 298 Flags = ACPI_NS_NO_UPSEARCH; 299 if (WalkState->PassNumber == ACPI_IMODE_EXECUTE) 300 { 301 /* Execution mode, node cannot already exist, node is temporary */ 302 303 Flags |= ACPI_NS_ERROR_IF_FOUND; 304 305 if (!(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) 306 { 307 Flags |= ACPI_NS_TEMPORARY; 308 } 309 } 310 311 /* Add new entry or lookup existing entry */ 312 313 Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType, 314 ACPI_IMODE_LOAD_PASS2, Flags, WalkState, &Node); 315 316 if (ACPI_SUCCESS (Status) && (Flags & ACPI_NS_TEMPORARY)) 317 { 318 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 319 "***New Node [%4.4s] %p is temporary\n", 320 AcpiUtGetNodeName (Node), Node)); 321 } 322 break; 323 } 324 325 if (ACPI_FAILURE (Status)) 326 { 327 ACPI_ERROR_NAMESPACE (BufferPtr, Status); 328 return_ACPI_STATUS (Status); 329 } 330 331 if (!Op) 332 { 333 /* Create a new op */ 334 335 Op = AcpiPsAllocOp (WalkState->Opcode); 336 if (!Op) 337 { 338 return_ACPI_STATUS (AE_NO_MEMORY); 339 } 340 341 /* Initialize the new op */ 342 343 if (Node) 344 { 345 Op->Named.Name = Node->Name.Integer; 346 } 347 *OutOp = Op; 348 } 349 350 /* 351 * Put the Node in the "op" object that the parser uses, so we 352 * can get it again quickly when this scope is closed 353 */ 354 Op->Common.Node = Node; 355 return_ACPI_STATUS (Status); 356} 357 358 359/******************************************************************************* 360 * 361 * FUNCTION: AcpiDsLoad2EndOp 362 * 363 * PARAMETERS: WalkState - Current state of the parse tree walk 364 * 365 * RETURN: Status 366 * 367 * DESCRIPTION: Ascending callback used during the loading of the namespace, 368 * both control methods and everything else. 369 * 370 ******************************************************************************/ 371 372ACPI_STATUS 373AcpiDsLoad2EndOp ( 374 ACPI_WALK_STATE *WalkState) 375{ 376 ACPI_PARSE_OBJECT *Op; 377 ACPI_STATUS Status = AE_OK; 378 ACPI_OBJECT_TYPE ObjectType; 379 ACPI_NAMESPACE_NODE *Node; 380 ACPI_PARSE_OBJECT *Arg; 381 ACPI_NAMESPACE_NODE *NewNode; 382#ifndef ACPI_NO_METHOD_EXECUTION 383 UINT32 i; 384 UINT8 RegionSpace; 385#endif 386 387 388 ACPI_FUNCTION_TRACE (DsLoad2EndOp); 389 390 Op = WalkState->Op; 391 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", 392 WalkState->OpInfo->Name, Op, WalkState)); 393 394 /* Check if opcode had an associated namespace object */ 395 396 if (!(WalkState->OpInfo->Flags & AML_NSOBJECT)) 397 { 398 return_ACPI_STATUS (AE_OK); 399 } 400 401 if (Op->Common.AmlOpcode == AML_SCOPE_OP) 402 { 403 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 404 "Ending scope Op=%p State=%p\n", Op, WalkState)); 405 } 406 407 ObjectType = WalkState->OpInfo->ObjectType; 408 409 /* 410 * Get the Node/name from the earlier lookup 411 * (It was saved in the *op structure) 412 */ 413 Node = Op->Common.Node; 414 415 /* 416 * Put the Node on the object stack (Contains the ACPI Name of 417 * this object) 418 */ 419 WalkState->Operands[0] = (void *) Node; 420 WalkState->NumOperands = 1; 421 422 /* Pop the scope stack */ 423 424 if (AcpiNsOpensScope (ObjectType) && 425 (Op->Common.AmlOpcode != AML_INT_METHODCALL_OP)) 426 { 427 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n", 428 AcpiUtGetTypeName (ObjectType), Op)); 429 430 Status = AcpiDsScopeStackPop (WalkState); 431 if (ACPI_FAILURE (Status)) 432 { 433 goto Cleanup; 434 } 435 } 436 437 /* 438 * Named operations are as follows: 439 * 440 * AML_ALIAS 441 * AML_BANKFIELD 442 * AML_CREATEBITFIELD 443 * AML_CREATEBYTEFIELD 444 * AML_CREATEDWORDFIELD 445 * AML_CREATEFIELD 446 * AML_CREATEQWORDFIELD 447 * AML_CREATEWORDFIELD 448 * AML_DATA_REGION 449 * AML_DEVICE 450 * AML_EVENT 451 * AML_FIELD 452 * AML_INDEXFIELD 453 * AML_METHOD 454 * AML_METHODCALL 455 * AML_MUTEX 456 * AML_NAME 457 * AML_NAMEDFIELD 458 * AML_OPREGION 459 * AML_POWERRES 460 * AML_PROCESSOR 461 * AML_SCOPE 462 * AML_THERMALZONE 463 */ 464 465 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 466 "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", 467 AcpiPsGetOpcodeName (Op->Common.AmlOpcode), WalkState, Op, Node)); 468 469 /* Decode the opcode */ 470 471 Arg = Op->Common.Value.Arg; 472 473 switch (WalkState->OpInfo->Type) 474 { 475#ifndef ACPI_NO_METHOD_EXECUTION 476 477 case AML_TYPE_CREATE_FIELD: 478 /* 479 * Create the field object, but the field buffer and index must 480 * be evaluated later during the execution phase 481 */ 482 Status = AcpiDsCreateBufferField (Op, WalkState); 483 break; 484 485 486 case AML_TYPE_NAMED_FIELD: 487 /* 488 * If we are executing a method, initialize the field 489 */ 490 if (WalkState->MethodNode) 491 { 492 Status = AcpiDsInitFieldObjects (Op, WalkState); 493 } 494 495 switch (Op->Common.AmlOpcode) 496 { 497 case AML_INDEX_FIELD_OP: 498 499 Status = AcpiDsCreateIndexField (Op, (ACPI_HANDLE) Arg->Common.Node, 500 WalkState); 501 break; 502 503 case AML_BANK_FIELD_OP: 504 505 Status = AcpiDsCreateBankField (Op, Arg->Common.Node, WalkState); 506 break; 507 508 case AML_FIELD_OP: 509 510 Status = AcpiDsCreateField (Op, Arg->Common.Node, WalkState); 511 break; 512 513 default: 514 /* All NAMED_FIELD opcodes must be handled above */ 515 break; 516 } 517 break; 518 519 520 case AML_TYPE_NAMED_SIMPLE: 521 522 Status = AcpiDsCreateOperands (WalkState, Arg); 523 if (ACPI_FAILURE (Status)) 524 { 525 goto Cleanup; 526 } 527 528 switch (Op->Common.AmlOpcode) 529 { 530 case AML_PROCESSOR_OP: 531 532 Status = AcpiExCreateProcessor (WalkState); 533 break; 534 535 case AML_POWER_RES_OP: 536 537 Status = AcpiExCreatePowerResource (WalkState); 538 break; 539 540 case AML_MUTEX_OP: 541 542 Status = AcpiExCreateMutex (WalkState); 543 break; 544 545 case AML_EVENT_OP: 546 547 Status = AcpiExCreateEvent (WalkState); 548 break; 549 550 551 case AML_ALIAS_OP: 552 553 Status = AcpiExCreateAlias (WalkState); 554 break; 555 556 default: 557 /* Unknown opcode */ 558 559 Status = AE_OK; 560 goto Cleanup; 561 } 562 563 /* Delete operands */ 564 565 for (i = 1; i < WalkState->NumOperands; i++) 566 { 567 AcpiUtRemoveReference (WalkState->Operands[i]); 568 WalkState->Operands[i] = NULL; 569 } 570 571 break; 572#endif /* ACPI_NO_METHOD_EXECUTION */ 573 574 case AML_TYPE_NAMED_COMPLEX: 575 576 switch (Op->Common.AmlOpcode) 577 { 578#ifndef ACPI_NO_METHOD_EXECUTION 579 case AML_REGION_OP: 580 case AML_DATA_REGION_OP: 581 582 if (Op->Common.AmlOpcode == AML_REGION_OP) 583 { 584 RegionSpace = (ACPI_ADR_SPACE_TYPE) 585 ((Op->Common.Value.Arg)->Common.Value.Integer); 586 } 587 else 588 { 589 RegionSpace = ACPI_ADR_SPACE_DATA_TABLE; 590 } 591 592 /* 593 * The OpRegion is not fully parsed at this time. The only valid 594 * argument is the SpaceId. (We must save the address of the 595 * AML of the address and length operands) 596 * 597 * If we have a valid region, initialize it. The namespace is 598 * unlocked at this point. 599 * 600 * Need to unlock interpreter if it is locked (if we are running 601 * a control method), in order to allow _REG methods to be run 602 * during AcpiEvInitializeRegion. 603 */ 604 if (WalkState->MethodNode) 605 { 606 /* 607 * Executing a method: initialize the region and unlock 608 * the interpreter 609 */ 610 Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length, 611 RegionSpace, WalkState); 612 if (ACPI_FAILURE (Status)) 613 { 614 return (Status); 615 } 616 617 AcpiExExitInterpreter (); 618 } 619 620 Status = AcpiEvInitializeRegion (AcpiNsGetAttachedObject (Node), 621 FALSE); 622 if (WalkState->MethodNode) 623 { 624 AcpiExEnterInterpreter (); 625 } 626 627 if (ACPI_FAILURE (Status)) 628 { 629 /* 630 * If AE_NOT_EXIST is returned, it is not fatal 631 * because many regions get created before a handler 632 * is installed for said region. 633 */ 634 if (AE_NOT_EXIST == Status) 635 { 636 Status = AE_OK; 637 } 638 } 639 break; 640 641 642 case AML_NAME_OP: 643 644 Status = AcpiDsCreateNode (WalkState, Node, Op); 645 break; 646 647 648 case AML_METHOD_OP: 649 /* 650 * MethodOp PkgLength NameString MethodFlags TermList 651 * 652 * Note: We must create the method node/object pair as soon as we 653 * see the method declaration. This allows later pass1 parsing 654 * of invocations of the method (need to know the number of 655 * arguments.) 656 */ 657 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 658 "LOADING-Method: State=%p Op=%p NamedObj=%p\n", 659 WalkState, Op, Op->Named.Node)); 660 661 if (!AcpiNsGetAttachedObject (Op->Named.Node)) 662 { 663 WalkState->Operands[0] = ACPI_CAST_PTR (void, Op->Named.Node); 664 WalkState->NumOperands = 1; 665 666 Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg); 667 if (ACPI_SUCCESS (Status)) 668 { 669 Status = AcpiExCreateMethod (Op->Named.Data, 670 Op->Named.Length, WalkState); 671 } 672 WalkState->Operands[0] = NULL; 673 WalkState->NumOperands = 0; 674 675 if (ACPI_FAILURE (Status)) 676 { 677 return_ACPI_STATUS (Status); 678 } 679 } 680 break; 681 682#endif /* ACPI_NO_METHOD_EXECUTION */ 683 684 default: 685 /* All NAMED_COMPLEX opcodes must be handled above */ 686 break; 687 } 688 break; 689 690 691 case AML_CLASS_INTERNAL: 692 693 /* case AML_INT_NAMEPATH_OP: */ 694 break; 695 696 697 case AML_CLASS_METHOD_CALL: 698 699 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 700 "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", 701 WalkState, Op, Node)); 702 703 /* 704 * Lookup the method name and save the Node 705 */ 706 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String, 707 ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS2, 708 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 709 WalkState, &(NewNode)); 710 if (ACPI_SUCCESS (Status)) 711 { 712 /* 713 * Make sure that what we found is indeed a method 714 * We didn't search for a method on purpose, to see if the name 715 * would resolve 716 */ 717 if (NewNode->Type != ACPI_TYPE_METHOD) 718 { 719 Status = AE_AML_OPERAND_TYPE; 720 } 721 722 /* We could put the returned object (Node) on the object stack for 723 * later, but for now, we will put it in the "op" object that the 724 * parser uses, so we can get it again at the end of this scope 725 */ 726 Op->Common.Node = NewNode; 727 } 728 else 729 { 730 ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status); 731 } 732 break; 733 734 735 default: 736 break; 737 } 738 739Cleanup: 740 741 /* Remove the Node pushed at the very beginning */ 742 743 WalkState->Operands[0] = NULL; 744 WalkState->NumOperands = 0; 745 return_ACPI_STATUS (Status); 746} 747
| 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 __DSWLOAD2_C__ 45 46#include <contrib/dev/acpica/include/acpi.h> 47#include <contrib/dev/acpica/include/accommon.h> 48#include <contrib/dev/acpica/include/acparser.h> 49#include <contrib/dev/acpica/include/amlcode.h> 50#include <contrib/dev/acpica/include/acdispat.h> 51#include <contrib/dev/acpica/include/acinterp.h> 52#include <contrib/dev/acpica/include/acnamesp.h> 53#include <contrib/dev/acpica/include/acevents.h> 54 55#define _COMPONENT ACPI_DISPATCHER 56 ACPI_MODULE_NAME ("dswload2") 57 58 59/******************************************************************************* 60 * 61 * FUNCTION: AcpiDsLoad2BeginOp 62 * 63 * PARAMETERS: WalkState - Current state of the parse tree walk 64 * OutOp - Wher to return op if a new one is created 65 * 66 * RETURN: Status 67 * 68 * DESCRIPTION: Descending callback used during the loading of ACPI tables. 69 * 70 ******************************************************************************/ 71 72ACPI_STATUS 73AcpiDsLoad2BeginOp ( 74 ACPI_WALK_STATE *WalkState, 75 ACPI_PARSE_OBJECT **OutOp) 76{ 77 ACPI_PARSE_OBJECT *Op; 78 ACPI_NAMESPACE_NODE *Node; 79 ACPI_STATUS Status; 80 ACPI_OBJECT_TYPE ObjectType; 81 char *BufferPtr; 82 UINT32 Flags; 83 84 85 ACPI_FUNCTION_TRACE (DsLoad2BeginOp); 86 87 88 Op = WalkState->Op; 89 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState)); 90 91 if (Op) 92 { 93 if ((WalkState->ControlState) && 94 (WalkState->ControlState->Common.State == 95 ACPI_CONTROL_CONDITIONAL_EXECUTING)) 96 { 97 /* We are executing a while loop outside of a method */ 98 99 Status = AcpiDsExecBeginOp (WalkState, OutOp); 100 return_ACPI_STATUS (Status); 101 } 102 103 /* We only care about Namespace opcodes here */ 104 105 if ((!(WalkState->OpInfo->Flags & AML_NSOPCODE) && 106 (WalkState->Opcode != AML_INT_NAMEPATH_OP)) || 107 (!(WalkState->OpInfo->Flags & AML_NAMED))) 108 { 109 return_ACPI_STATUS (AE_OK); 110 } 111 112 /* Get the name we are going to enter or lookup in the namespace */ 113 114 if (WalkState->Opcode == AML_INT_NAMEPATH_OP) 115 { 116 /* For Namepath op, get the path string */ 117 118 BufferPtr = Op->Common.Value.String; 119 if (!BufferPtr) 120 { 121 /* No name, just exit */ 122 123 return_ACPI_STATUS (AE_OK); 124 } 125 } 126 else 127 { 128 /* Get name from the op */ 129 130 BufferPtr = ACPI_CAST_PTR (char, &Op->Named.Name); 131 } 132 } 133 else 134 { 135 /* Get the namestring from the raw AML */ 136 137 BufferPtr = AcpiPsGetNextNamestring (&WalkState->ParserState); 138 } 139 140 /* Map the opcode into an internal object type */ 141 142 ObjectType = WalkState->OpInfo->ObjectType; 143 144 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 145 "State=%p Op=%p Type=%X\n", WalkState, Op, ObjectType)); 146 147 switch (WalkState->Opcode) 148 { 149 case AML_FIELD_OP: 150 case AML_BANK_FIELD_OP: 151 case AML_INDEX_FIELD_OP: 152 153 Node = NULL; 154 Status = AE_OK; 155 break; 156 157 case AML_INT_NAMEPATH_OP: 158 /* 159 * The NamePath is an object reference to an existing object. 160 * Don't enter the name into the namespace, but look it up 161 * for use later. 162 */ 163 Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType, 164 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 165 WalkState, &(Node)); 166 break; 167 168 case AML_SCOPE_OP: 169 170 /* Special case for Scope(\) -> refers to the Root node */ 171 172 if (Op && (Op->Named.Node == AcpiGbl_RootNode)) 173 { 174 Node = Op->Named.Node; 175 176 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 177 if (ACPI_FAILURE (Status)) 178 { 179 return_ACPI_STATUS (Status); 180 } 181 } 182 else 183 { 184 /* 185 * The Path is an object reference to an existing object. 186 * Don't enter the name into the namespace, but look it up 187 * for use later. 188 */ 189 Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType, 190 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 191 WalkState, &(Node)); 192 if (ACPI_FAILURE (Status)) 193 { 194#ifdef ACPI_ASL_COMPILER 195 if (Status == AE_NOT_FOUND) 196 { 197 Status = AE_OK; 198 } 199 else 200 { 201 ACPI_ERROR_NAMESPACE (BufferPtr, Status); 202 } 203#else 204 ACPI_ERROR_NAMESPACE (BufferPtr, Status); 205#endif 206 return_ACPI_STATUS (Status); 207 } 208 } 209 210 /* 211 * We must check to make sure that the target is 212 * one of the opcodes that actually opens a scope 213 */ 214 switch (Node->Type) 215 { 216 case ACPI_TYPE_ANY: 217 case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ 218 case ACPI_TYPE_DEVICE: 219 case ACPI_TYPE_POWER: 220 case ACPI_TYPE_PROCESSOR: 221 case ACPI_TYPE_THERMAL: 222 223 /* These are acceptable types */ 224 break; 225 226 case ACPI_TYPE_INTEGER: 227 case ACPI_TYPE_STRING: 228 case ACPI_TYPE_BUFFER: 229 230 /* 231 * These types we will allow, but we will change the type. 232 * This enables some existing code of the form: 233 * 234 * Name (DEB, 0) 235 * Scope (DEB) { ... } 236 */ 237 ACPI_WARNING ((AE_INFO, 238 "Type override - [%4.4s] had invalid type (%s) " 239 "for Scope operator, changed to type ANY\n", 240 AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type))); 241 242 Node->Type = ACPI_TYPE_ANY; 243 WalkState->ScopeInfo->Common.Value = ACPI_TYPE_ANY; 244 break; 245 246 default: 247 248 /* All other types are an error */ 249 250 ACPI_ERROR ((AE_INFO, 251 "Invalid type (%s) for target of " 252 "Scope operator [%4.4s] (Cannot override)", 253 AcpiUtGetTypeName (Node->Type), AcpiUtGetNodeName (Node))); 254 255 return (AE_AML_OPERAND_TYPE); 256 } 257 break; 258 259 default: 260 261 /* All other opcodes */ 262 263 if (Op && Op->Common.Node) 264 { 265 /* This op/node was previously entered into the namespace */ 266 267 Node = Op->Common.Node; 268 269 if (AcpiNsOpensScope (ObjectType)) 270 { 271 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 272 if (ACPI_FAILURE (Status)) 273 { 274 return_ACPI_STATUS (Status); 275 } 276 } 277 278 return_ACPI_STATUS (AE_OK); 279 } 280 281 /* 282 * Enter the named type into the internal namespace. We enter the name 283 * as we go downward in the parse tree. Any necessary subobjects that 284 * involve arguments to the opcode must be created as we go back up the 285 * parse tree later. 286 * 287 * Note: Name may already exist if we are executing a deferred opcode. 288 */ 289 if (WalkState->DeferredNode) 290 { 291 /* This name is already in the namespace, get the node */ 292 293 Node = WalkState->DeferredNode; 294 Status = AE_OK; 295 break; 296 } 297 298 Flags = ACPI_NS_NO_UPSEARCH; 299 if (WalkState->PassNumber == ACPI_IMODE_EXECUTE) 300 { 301 /* Execution mode, node cannot already exist, node is temporary */ 302 303 Flags |= ACPI_NS_ERROR_IF_FOUND; 304 305 if (!(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) 306 { 307 Flags |= ACPI_NS_TEMPORARY; 308 } 309 } 310 311 /* Add new entry or lookup existing entry */ 312 313 Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType, 314 ACPI_IMODE_LOAD_PASS2, Flags, WalkState, &Node); 315 316 if (ACPI_SUCCESS (Status) && (Flags & ACPI_NS_TEMPORARY)) 317 { 318 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 319 "***New Node [%4.4s] %p is temporary\n", 320 AcpiUtGetNodeName (Node), Node)); 321 } 322 break; 323 } 324 325 if (ACPI_FAILURE (Status)) 326 { 327 ACPI_ERROR_NAMESPACE (BufferPtr, Status); 328 return_ACPI_STATUS (Status); 329 } 330 331 if (!Op) 332 { 333 /* Create a new op */ 334 335 Op = AcpiPsAllocOp (WalkState->Opcode); 336 if (!Op) 337 { 338 return_ACPI_STATUS (AE_NO_MEMORY); 339 } 340 341 /* Initialize the new op */ 342 343 if (Node) 344 { 345 Op->Named.Name = Node->Name.Integer; 346 } 347 *OutOp = Op; 348 } 349 350 /* 351 * Put the Node in the "op" object that the parser uses, so we 352 * can get it again quickly when this scope is closed 353 */ 354 Op->Common.Node = Node; 355 return_ACPI_STATUS (Status); 356} 357 358 359/******************************************************************************* 360 * 361 * FUNCTION: AcpiDsLoad2EndOp 362 * 363 * PARAMETERS: WalkState - Current state of the parse tree walk 364 * 365 * RETURN: Status 366 * 367 * DESCRIPTION: Ascending callback used during the loading of the namespace, 368 * both control methods and everything else. 369 * 370 ******************************************************************************/ 371 372ACPI_STATUS 373AcpiDsLoad2EndOp ( 374 ACPI_WALK_STATE *WalkState) 375{ 376 ACPI_PARSE_OBJECT *Op; 377 ACPI_STATUS Status = AE_OK; 378 ACPI_OBJECT_TYPE ObjectType; 379 ACPI_NAMESPACE_NODE *Node; 380 ACPI_PARSE_OBJECT *Arg; 381 ACPI_NAMESPACE_NODE *NewNode; 382#ifndef ACPI_NO_METHOD_EXECUTION 383 UINT32 i; 384 UINT8 RegionSpace; 385#endif 386 387 388 ACPI_FUNCTION_TRACE (DsLoad2EndOp); 389 390 Op = WalkState->Op; 391 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", 392 WalkState->OpInfo->Name, Op, WalkState)); 393 394 /* Check if opcode had an associated namespace object */ 395 396 if (!(WalkState->OpInfo->Flags & AML_NSOBJECT)) 397 { 398 return_ACPI_STATUS (AE_OK); 399 } 400 401 if (Op->Common.AmlOpcode == AML_SCOPE_OP) 402 { 403 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 404 "Ending scope Op=%p State=%p\n", Op, WalkState)); 405 } 406 407 ObjectType = WalkState->OpInfo->ObjectType; 408 409 /* 410 * Get the Node/name from the earlier lookup 411 * (It was saved in the *op structure) 412 */ 413 Node = Op->Common.Node; 414 415 /* 416 * Put the Node on the object stack (Contains the ACPI Name of 417 * this object) 418 */ 419 WalkState->Operands[0] = (void *) Node; 420 WalkState->NumOperands = 1; 421 422 /* Pop the scope stack */ 423 424 if (AcpiNsOpensScope (ObjectType) && 425 (Op->Common.AmlOpcode != AML_INT_METHODCALL_OP)) 426 { 427 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n", 428 AcpiUtGetTypeName (ObjectType), Op)); 429 430 Status = AcpiDsScopeStackPop (WalkState); 431 if (ACPI_FAILURE (Status)) 432 { 433 goto Cleanup; 434 } 435 } 436 437 /* 438 * Named operations are as follows: 439 * 440 * AML_ALIAS 441 * AML_BANKFIELD 442 * AML_CREATEBITFIELD 443 * AML_CREATEBYTEFIELD 444 * AML_CREATEDWORDFIELD 445 * AML_CREATEFIELD 446 * AML_CREATEQWORDFIELD 447 * AML_CREATEWORDFIELD 448 * AML_DATA_REGION 449 * AML_DEVICE 450 * AML_EVENT 451 * AML_FIELD 452 * AML_INDEXFIELD 453 * AML_METHOD 454 * AML_METHODCALL 455 * AML_MUTEX 456 * AML_NAME 457 * AML_NAMEDFIELD 458 * AML_OPREGION 459 * AML_POWERRES 460 * AML_PROCESSOR 461 * AML_SCOPE 462 * AML_THERMALZONE 463 */ 464 465 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 466 "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", 467 AcpiPsGetOpcodeName (Op->Common.AmlOpcode), WalkState, Op, Node)); 468 469 /* Decode the opcode */ 470 471 Arg = Op->Common.Value.Arg; 472 473 switch (WalkState->OpInfo->Type) 474 { 475#ifndef ACPI_NO_METHOD_EXECUTION 476 477 case AML_TYPE_CREATE_FIELD: 478 /* 479 * Create the field object, but the field buffer and index must 480 * be evaluated later during the execution phase 481 */ 482 Status = AcpiDsCreateBufferField (Op, WalkState); 483 break; 484 485 486 case AML_TYPE_NAMED_FIELD: 487 /* 488 * If we are executing a method, initialize the field 489 */ 490 if (WalkState->MethodNode) 491 { 492 Status = AcpiDsInitFieldObjects (Op, WalkState); 493 } 494 495 switch (Op->Common.AmlOpcode) 496 { 497 case AML_INDEX_FIELD_OP: 498 499 Status = AcpiDsCreateIndexField (Op, (ACPI_HANDLE) Arg->Common.Node, 500 WalkState); 501 break; 502 503 case AML_BANK_FIELD_OP: 504 505 Status = AcpiDsCreateBankField (Op, Arg->Common.Node, WalkState); 506 break; 507 508 case AML_FIELD_OP: 509 510 Status = AcpiDsCreateField (Op, Arg->Common.Node, WalkState); 511 break; 512 513 default: 514 /* All NAMED_FIELD opcodes must be handled above */ 515 break; 516 } 517 break; 518 519 520 case AML_TYPE_NAMED_SIMPLE: 521 522 Status = AcpiDsCreateOperands (WalkState, Arg); 523 if (ACPI_FAILURE (Status)) 524 { 525 goto Cleanup; 526 } 527 528 switch (Op->Common.AmlOpcode) 529 { 530 case AML_PROCESSOR_OP: 531 532 Status = AcpiExCreateProcessor (WalkState); 533 break; 534 535 case AML_POWER_RES_OP: 536 537 Status = AcpiExCreatePowerResource (WalkState); 538 break; 539 540 case AML_MUTEX_OP: 541 542 Status = AcpiExCreateMutex (WalkState); 543 break; 544 545 case AML_EVENT_OP: 546 547 Status = AcpiExCreateEvent (WalkState); 548 break; 549 550 551 case AML_ALIAS_OP: 552 553 Status = AcpiExCreateAlias (WalkState); 554 break; 555 556 default: 557 /* Unknown opcode */ 558 559 Status = AE_OK; 560 goto Cleanup; 561 } 562 563 /* Delete operands */ 564 565 for (i = 1; i < WalkState->NumOperands; i++) 566 { 567 AcpiUtRemoveReference (WalkState->Operands[i]); 568 WalkState->Operands[i] = NULL; 569 } 570 571 break; 572#endif /* ACPI_NO_METHOD_EXECUTION */ 573 574 case AML_TYPE_NAMED_COMPLEX: 575 576 switch (Op->Common.AmlOpcode) 577 { 578#ifndef ACPI_NO_METHOD_EXECUTION 579 case AML_REGION_OP: 580 case AML_DATA_REGION_OP: 581 582 if (Op->Common.AmlOpcode == AML_REGION_OP) 583 { 584 RegionSpace = (ACPI_ADR_SPACE_TYPE) 585 ((Op->Common.Value.Arg)->Common.Value.Integer); 586 } 587 else 588 { 589 RegionSpace = ACPI_ADR_SPACE_DATA_TABLE; 590 } 591 592 /* 593 * The OpRegion is not fully parsed at this time. The only valid 594 * argument is the SpaceId. (We must save the address of the 595 * AML of the address and length operands) 596 * 597 * If we have a valid region, initialize it. The namespace is 598 * unlocked at this point. 599 * 600 * Need to unlock interpreter if it is locked (if we are running 601 * a control method), in order to allow _REG methods to be run 602 * during AcpiEvInitializeRegion. 603 */ 604 if (WalkState->MethodNode) 605 { 606 /* 607 * Executing a method: initialize the region and unlock 608 * the interpreter 609 */ 610 Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length, 611 RegionSpace, WalkState); 612 if (ACPI_FAILURE (Status)) 613 { 614 return (Status); 615 } 616 617 AcpiExExitInterpreter (); 618 } 619 620 Status = AcpiEvInitializeRegion (AcpiNsGetAttachedObject (Node), 621 FALSE); 622 if (WalkState->MethodNode) 623 { 624 AcpiExEnterInterpreter (); 625 } 626 627 if (ACPI_FAILURE (Status)) 628 { 629 /* 630 * If AE_NOT_EXIST is returned, it is not fatal 631 * because many regions get created before a handler 632 * is installed for said region. 633 */ 634 if (AE_NOT_EXIST == Status) 635 { 636 Status = AE_OK; 637 } 638 } 639 break; 640 641 642 case AML_NAME_OP: 643 644 Status = AcpiDsCreateNode (WalkState, Node, Op); 645 break; 646 647 648 case AML_METHOD_OP: 649 /* 650 * MethodOp PkgLength NameString MethodFlags TermList 651 * 652 * Note: We must create the method node/object pair as soon as we 653 * see the method declaration. This allows later pass1 parsing 654 * of invocations of the method (need to know the number of 655 * arguments.) 656 */ 657 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 658 "LOADING-Method: State=%p Op=%p NamedObj=%p\n", 659 WalkState, Op, Op->Named.Node)); 660 661 if (!AcpiNsGetAttachedObject (Op->Named.Node)) 662 { 663 WalkState->Operands[0] = ACPI_CAST_PTR (void, Op->Named.Node); 664 WalkState->NumOperands = 1; 665 666 Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg); 667 if (ACPI_SUCCESS (Status)) 668 { 669 Status = AcpiExCreateMethod (Op->Named.Data, 670 Op->Named.Length, WalkState); 671 } 672 WalkState->Operands[0] = NULL; 673 WalkState->NumOperands = 0; 674 675 if (ACPI_FAILURE (Status)) 676 { 677 return_ACPI_STATUS (Status); 678 } 679 } 680 break; 681 682#endif /* ACPI_NO_METHOD_EXECUTION */ 683 684 default: 685 /* All NAMED_COMPLEX opcodes must be handled above */ 686 break; 687 } 688 break; 689 690 691 case AML_CLASS_INTERNAL: 692 693 /* case AML_INT_NAMEPATH_OP: */ 694 break; 695 696 697 case AML_CLASS_METHOD_CALL: 698 699 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 700 "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", 701 WalkState, Op, Node)); 702 703 /* 704 * Lookup the method name and save the Node 705 */ 706 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String, 707 ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS2, 708 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 709 WalkState, &(NewNode)); 710 if (ACPI_SUCCESS (Status)) 711 { 712 /* 713 * Make sure that what we found is indeed a method 714 * We didn't search for a method on purpose, to see if the name 715 * would resolve 716 */ 717 if (NewNode->Type != ACPI_TYPE_METHOD) 718 { 719 Status = AE_AML_OPERAND_TYPE; 720 } 721 722 /* We could put the returned object (Node) on the object stack for 723 * later, but for now, we will put it in the "op" object that the 724 * parser uses, so we can get it again at the end of this scope 725 */ 726 Op->Common.Node = NewNode; 727 } 728 else 729 { 730 ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status); 731 } 732 break; 733 734 735 default: 736 break; 737 } 738 739Cleanup: 740 741 /* Remove the Node pushed at the very beginning */ 742 743 WalkState->Operands[0] = NULL; 744 WalkState->NumOperands = 0; 745 return_ACPI_STATUS (Status); 746} 747
|