1 /****************************************************************************** 2 * 3 * Module Name: dswload - Dispatcher namespace load callbacks 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, 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 "aslcompiler.h" 45 #include "amlcode.h" 46 #include "acdispat.h" 47 #include "acnamesp.h" 48 #include "acparser.h" 49 #include "aslcompiler.y.h" 50 51 52 #define _COMPONENT ACPI_COMPILER 53 ACPI_MODULE_NAME ("aslload") 54 55 /* Local prototypes */ 56 57 static ACPI_STATUS 58 LdLoadFieldElements ( 59 ACPI_PARSE_OBJECT *Op, 60 ACPI_WALK_STATE *WalkState); 61 62 static ACPI_STATUS 63 LdLoadResourceElements ( 64 ACPI_PARSE_OBJECT *Op, 65 ACPI_WALK_STATE *WalkState); 66 67 static ACPI_STATUS 68 LdNamespace1Begin ( 69 ACPI_PARSE_OBJECT *Op, 70 UINT32 Level, 71 void *Context); 72 73 static ACPI_STATUS 74 LdNamespace2Begin ( 75 ACPI_PARSE_OBJECT *Op, 76 UINT32 Level, 77 void *Context); 78 79 static ACPI_STATUS 80 LdCommonNamespaceEnd ( 81 ACPI_PARSE_OBJECT *Op, 82 UINT32 Level, 83 void *Context); 84 85 86 /******************************************************************************* 87 * 88 * FUNCTION: LdLoadNamespace 89 * 90 * PARAMETERS: RootOp - Root of the parse tree 91 * 92 * RETURN: Status 93 * 94 * DESCRIPTION: Perform a walk of the parse tree that in turn loads all of the 95 * named ASL/AML objects into the namespace. The namespace is 96 * constructed in order to resolve named references and references 97 * to named fields within resource templates/descriptors. 98 * 99 ******************************************************************************/ 100 101 ACPI_STATUS 102 LdLoadNamespace ( 103 ACPI_PARSE_OBJECT *RootOp) 104 { 105 ACPI_WALK_STATE *WalkState; 106 107 108 /* Create a new walk state */ 109 110 WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); 111 if (!WalkState) 112 { 113 return (AE_NO_MEMORY); 114 } 115 116 /* Walk the entire parse tree, first pass */ 117 118 TrWalkParseTree (RootOp, ASL_WALK_VISIT_TWICE, LdNamespace1Begin, 119 LdCommonNamespaceEnd, WalkState); 120 121 /* Second pass to handle forward references */ 122 123 TrWalkParseTree (RootOp, ASL_WALK_VISIT_TWICE, LdNamespace2Begin, 124 LdCommonNamespaceEnd, WalkState); 125 126 /* Dump the namespace if debug is enabled */ 127 128 if (AcpiDbgLevel & ACPI_LV_TABLES) 129 { 130 AcpiNsDumpTables (ACPI_NS_ALL, ACPI_UINT32_MAX); 131 } 132 133 ACPI_FREE (WalkState); 134 return (AE_OK); 135 } 136 137 138 /******************************************************************************* 139 * 140 * FUNCTION: LdLoadFieldElements 141 * 142 * PARAMETERS: Op - Parent node (Field) 143 * WalkState - Current walk state 144 * 145 * RETURN: Status 146 * 147 * DESCRIPTION: Enter the named elements of the field (children of the parent) 148 * into the namespace. 149 * 150 ******************************************************************************/ 151 152 static ACPI_STATUS 153 LdLoadFieldElements ( 154 ACPI_PARSE_OBJECT *Op, 155 ACPI_WALK_STATE *WalkState) 156 { 157 ACPI_PARSE_OBJECT *Child = NULL; 158 ACPI_NAMESPACE_NODE *Node; 159 ACPI_STATUS Status; 160 161 162 /* Get the first named field element */ 163 164 switch (Op->Asl.AmlOpcode) 165 { 166 case AML_BANK_FIELD_OP: 167 168 Child = UtGetArg (Op, 6); 169 break; 170 171 case AML_INDEX_FIELD_OP: 172 173 Child = UtGetArg (Op, 5); 174 break; 175 176 case AML_FIELD_OP: 177 178 Child = UtGetArg (Op, 4); 179 break; 180 181 default: 182 183 /* No other opcodes should arrive here */ 184 185 return (AE_BAD_PARAMETER); 186 } 187 188 /* Enter all elements into the namespace */ 189 190 while (Child) 191 { 192 switch (Child->Asl.AmlOpcode) 193 { 194 case AML_INT_RESERVEDFIELD_OP: 195 case AML_INT_ACCESSFIELD_OP: 196 case AML_INT_CONNECTION_OP: 197 break; 198 199 default: 200 201 Status = AcpiNsLookup (WalkState->ScopeInfo, 202 Child->Asl.Value.String, 203 ACPI_TYPE_LOCAL_REGION_FIELD, 204 ACPI_IMODE_LOAD_PASS1, 205 ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | 206 ACPI_NS_ERROR_IF_FOUND, NULL, &Node); 207 if (ACPI_FAILURE (Status)) 208 { 209 if (Status != AE_ALREADY_EXISTS) 210 { 211 AslError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, Child, 212 Child->Asl.Value.String); 213 return (Status); 214 } 215 else if (Status == AE_ALREADY_EXISTS && 216 (Node->Flags & ANOBJ_IS_EXTERNAL)) 217 { 218 Node->Type = (UINT8) ACPI_TYPE_LOCAL_REGION_FIELD; 219 } 220 else 221 { 222 /* 223 * The name already exists in this scope 224 * But continue processing the elements 225 */ 226 AslDualParseOpError (ASL_WARNING, ASL_MSG_EXTERN_COLLISION, Child, 227 Child->Asl.Value.String, ASL_MSG_EXTERN_FOUND_HERE, Node->Op, 228 Node->Op->Asl.ExternalName); 229 } 230 } 231 else 232 { 233 Child->Asl.Node = Node; 234 Node->Op = Child; 235 } 236 break; 237 } 238 239 Child = Child->Asl.Next; 240 } 241 242 return (AE_OK); 243 } 244 245 246 /******************************************************************************* 247 * 248 * FUNCTION: LdLoadResourceElements 249 * 250 * PARAMETERS: Op - Parent node (Resource Descriptor) 251 * WalkState - Current walk state 252 * 253 * RETURN: Status 254 * 255 * DESCRIPTION: Enter the named elements of the resource descriptor (children 256 * of the parent) into the namespace. 257 * 258 * NOTE: In the real AML namespace, these named elements never exist. But 259 * we simply use the namespace here as a symbol table so we can look 260 * them up as they are referenced. 261 * 262 ******************************************************************************/ 263 264 static ACPI_STATUS 265 LdLoadResourceElements ( 266 ACPI_PARSE_OBJECT *Op, 267 ACPI_WALK_STATE *WalkState) 268 { 269 ACPI_PARSE_OBJECT *InitializerOp = NULL; 270 ACPI_NAMESPACE_NODE *Node; 271 ACPI_STATUS Status; 272 273 274 /* 275 * Enter the resource name into the namespace. Name must not already exist. 276 * This opens a scope, so later field names are guaranteed to be new/unique. 277 */ 278 Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Asl.Namepath, 279 ACPI_TYPE_LOCAL_RESOURCE, ACPI_IMODE_LOAD_PASS1, 280 ACPI_NS_NO_UPSEARCH | ACPI_NS_ERROR_IF_FOUND, 281 WalkState, &Node); 282 if (ACPI_FAILURE (Status)) 283 { 284 if (Status == AE_ALREADY_EXISTS) 285 { 286 /* Actual node causing the error was saved in ParentMethod */ 287 288 AslDualParseOpError (ASL_ERROR, ASL_MSG_NAME_EXISTS, 289 (ACPI_PARSE_OBJECT *) Op->Asl.ParentMethod, 290 Op->Asl.Namepath, ASL_MSG_FOUND_HERE, Node->Op, 291 Node->Op->Asl.ExternalName); 292 return (AE_OK); 293 } 294 return (Status); 295 } 296 297 Node->Value = (UINT32) Op->Asl.Value.Integer; 298 Node->Op = Op; 299 Op->Asl.Node = Node; 300 301 /* 302 * Now enter the predefined fields, for easy lookup when referenced 303 * by the source ASL 304 */ 305 InitializerOp = ASL_GET_CHILD_NODE (Op); 306 while (InitializerOp) 307 { 308 if (InitializerOp->Asl.ExternalName) 309 { 310 Status = AcpiNsLookup (WalkState->ScopeInfo, 311 InitializerOp->Asl.ExternalName, 312 ACPI_TYPE_LOCAL_RESOURCE_FIELD, 313 ACPI_IMODE_LOAD_PASS1, 314 ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, 315 NULL, &Node); 316 if (ACPI_FAILURE (Status)) 317 { 318 return (Status); 319 } 320 321 /* 322 * Store the field offset and length in the namespace node 323 * so it can be used when the field is referenced 324 */ 325 Node->Value = InitializerOp->Asl.Value.Tag.BitOffset; 326 Node->Length = InitializerOp->Asl.Value.Tag.BitLength; 327 InitializerOp->Asl.Node = Node; 328 Node->Op = InitializerOp; 329 } 330 331 InitializerOp = ASL_GET_PEER_NODE (InitializerOp); 332 } 333 334 return (AE_OK); 335 } 336 337 338 /******************************************************************************* 339 * 340 * FUNCTION: LdNamespace1Begin 341 * 342 * PARAMETERS: ASL_WALK_CALLBACK 343 * 344 * RETURN: Status 345 * 346 * DESCRIPTION: Descending callback used during the parse tree walk. If this 347 * is a named AML opcode, enter into the namespace 348 * 349 ******************************************************************************/ 350 351 static ACPI_STATUS 352 LdNamespace1Begin ( 353 ACPI_PARSE_OBJECT *Op, 354 UINT32 Level, 355 void *Context) 356 { 357 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 358 ACPI_NAMESPACE_NODE *Node; 359 ACPI_PARSE_OBJECT *MethodOp; 360 ACPI_STATUS Status; 361 ACPI_OBJECT_TYPE ObjectType; 362 ACPI_OBJECT_TYPE ActualObjectType = ACPI_TYPE_ANY; 363 char *Path; 364 UINT32 Flags = ACPI_NS_NO_UPSEARCH; 365 ACPI_PARSE_OBJECT *Arg; 366 UINT32 i; 367 BOOLEAN ForceNewScope = FALSE; 368 const ACPI_OPCODE_INFO *OpInfo; 369 ACPI_PARSE_OBJECT *ParentOp; 370 371 372 ACPI_FUNCTION_NAME (LdNamespace1Begin); 373 374 375 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", 376 Op, Op->Asl.ParseOpName)); 377 378 /* 379 * We are only interested in opcodes that have an associated name 380 * (or multiple names) 381 */ 382 switch (Op->Asl.AmlOpcode) 383 { 384 case AML_BANK_FIELD_OP: 385 case AML_INDEX_FIELD_OP: 386 case AML_FIELD_OP: 387 388 Status = LdLoadFieldElements (Op, WalkState); 389 return (Status); 390 391 case AML_INT_CONNECTION_OP: 392 393 394 if (Op->Asl.Child->Asl.AmlOpcode != AML_INT_NAMEPATH_OP) 395 { 396 break; 397 } 398 Arg = Op->Asl.Child; 399 400 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Asl.ExternalName, 401 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 402 WalkState, &Node); 403 if (ACPI_FAILURE (Status)) 404 { 405 break; 406 } 407 408 if (Node->Type == ACPI_TYPE_BUFFER) 409 { 410 Arg->Asl.Node = Node; 411 412 Arg = Node->Op->Asl.Child; /* Get namepath */ 413 Arg = Arg->Asl.Next; /* Get actual buffer */ 414 Arg = Arg->Asl.Child; /* Buffer length */ 415 Arg = Arg->Asl.Next; /* RAW_DATA buffer */ 416 } 417 break; 418 419 default: 420 421 /* All other opcodes go below */ 422 423 break; 424 } 425 426 /* Check if this object has already been installed in the namespace */ 427 428 if (Op->Asl.Node) 429 { 430 return (AE_OK); 431 } 432 433 /* Check for a possible illegal forward reference */ 434 435 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 436 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) 437 { 438 /* 439 * Op->Asl.Namepath will be NULL for these opcodes. 440 * These opcodes are guaranteed to have a parent. 441 * Examine the parent opcode. 442 */ 443 Status = AE_OK; 444 ParentOp = Op->Asl.Parent; 445 OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Asl.AmlOpcode); 446 447 /* 448 * Exclude all operators that actually declare a new name: 449 * Name (ABCD, 1) -> Ignore (AML_CLASS_NAMED_OBJECT) 450 * We only want references to named objects: 451 * Store (2, WXYZ) -> Attempt to resolve the name 452 */ 453 if (OpInfo->Class == AML_CLASS_NAMED_OBJECT) 454 { 455 return (AE_OK); 456 } 457 458 /* 459 * Check if the referenced object exists at this point during 460 * the load: 461 * 1) If it exists, then this cannot be a forward reference. 462 * 2) If it does not exist, it could be a forward reference or 463 * it truly does not exist (and no external declaration). 464 */ 465 Status = AcpiNsLookup (WalkState->ScopeInfo, 466 Op->Asl.Value.Name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 467 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 468 WalkState, &Node); 469 if (Status == AE_NOT_FOUND) 470 { 471 /* 472 * This is either a foward reference or the object truly 473 * does not exist. The two cases can only be differentiated 474 * during the cross-reference stage later. Mark the Op/Name 475 * as not-found for now to indicate the need for further 476 * processing. 477 * 478 * Special case: Allow forward references from elements of 479 * Package objects. This provides compatibility with other 480 * ACPI implementations. To correctly implement this, the 481 * ACPICA table load defers package resolution until the entire 482 * namespace has been loaded. 483 */ 484 if ((ParentOp->Asl.ParseOpcode != PARSEOP_PACKAGE) && 485 (ParentOp->Asl.ParseOpcode != PARSEOP_VAR_PACKAGE)) 486 { 487 Op->Asl.CompileFlags |= OP_NOT_FOUND_DURING_LOAD; 488 } 489 490 return (AE_OK); 491 } 492 493 return (Status); 494 } 495 496 Path = Op->Asl.Namepath; 497 if (!Path) 498 { 499 return (AE_OK); 500 } 501 502 /* Map the raw opcode into an internal object type */ 503 504 switch (Op->Asl.ParseOpcode) 505 { 506 case PARSEOP_NAME: 507 508 Arg = Op->Asl.Child; /* Get the NameSeg/NameString node */ 509 Arg = Arg->Asl.Next; /* First peer is the object to be associated with the name */ 510 511 /* 512 * If this name refers to a ResourceTemplate, we will need to open 513 * a new scope so that the resource subfield names can be entered into 514 * the namespace underneath this name 515 */ 516 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) 517 { 518 ForceNewScope = TRUE; 519 } 520 521 /* Get the data type associated with the named object, not the name itself */ 522 523 /* Log2 loop to convert from Btype (binary) to Etype (encoded) */ 524 525 ObjectType = 1; 526 for (i = 1; i < Arg->Asl.AcpiBtype; i *= 2) 527 { 528 ObjectType++; 529 } 530 break; 531 532 case PARSEOP_EXTERNAL: 533 /* 534 * "External" simply enters a name and type into the namespace. 535 * We must be careful to not open a new scope, however, no matter 536 * what type the external name refers to (e.g., a method) 537 * 538 * first child is name, next child is ObjectType 539 */ 540 ActualObjectType = (UINT8) Op->Asl.Child->Asl.Next->Asl.Value.Integer; 541 ObjectType = ACPI_TYPE_ANY; 542 543 /* 544 * We will mark every new node along the path as "External". This 545 * allows some or all of the nodes to be created later in the ASL 546 * code. Handles cases like this: 547 * 548 * External (\_SB_.PCI0.ABCD, IntObj) 549 * Scope (_SB_) 550 * { 551 * Device (PCI0) 552 * { 553 * } 554 * } 555 * Method (X) 556 * { 557 * Store (\_SB_.PCI0.ABCD, Local0) 558 * } 559 */ 560 Flags |= ACPI_NS_EXTERNAL; 561 break; 562 563 case PARSEOP_DEFAULT_ARG: 564 565 if (Op->Asl.CompileFlags == OP_IS_RESOURCE_DESC) 566 { 567 Status = LdLoadResourceElements (Op, WalkState); 568 return_ACPI_STATUS (Status); 569 } 570 571 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 572 break; 573 574 case PARSEOP_SCOPE: 575 /* 576 * The name referenced by Scope(Name) must already exist at this point. 577 * In other words, forward references for Scope() are not supported. 578 * The only real reason for this is that the MS interpreter cannot 579 * handle this case. Perhaps someday this case can go away. 580 */ 581 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 582 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 583 WalkState, &(Node)); 584 if (ACPI_FAILURE (Status)) 585 { 586 if (Status == AE_NOT_FOUND) 587 { 588 /* The name was not found, go ahead and create it */ 589 590 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, 591 ACPI_TYPE_LOCAL_SCOPE, 592 ACPI_IMODE_LOAD_PASS1, Flags, 593 WalkState, &(Node)); 594 if (ACPI_FAILURE (Status)) 595 { 596 return_ACPI_STATUS (Status); 597 } 598 599 /* 600 * However, this is an error -- primarily because the MS 601 * interpreter can't handle a forward reference from the 602 * Scope() operator. 603 */ 604 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 605 Op->Asl.ExternalName); 606 AslError (ASL_ERROR, ASL_MSG_SCOPE_FWD_REF, Op, 607 Op->Asl.ExternalName); 608 goto FinishNode; 609 } 610 611 AslCoreSubsystemError (Op, Status, 612 "Failure from namespace lookup", FALSE); 613 614 return_ACPI_STATUS (Status); 615 } 616 else /* Status AE_OK */ 617 { 618 /* 619 * Do not allow references to external scopes from the DSDT. 620 * This is because the DSDT is always loaded first, and the 621 * external reference cannot be resolved -- causing a runtime 622 * error because Scope() must be resolved immediately. 623 * 10/2015. 624 */ 625 if ((Node->Flags & ANOBJ_IS_EXTERNAL) && 626 (ACPI_COMPARE_NAME (Gbl_TableSignature, "DSDT"))) 627 { 628 /* However, allowed if the reference is within a method */ 629 630 MethodOp = Op->Asl.Parent; 631 while (MethodOp && 632 (MethodOp->Asl.ParseOpcode != PARSEOP_METHOD)) 633 { 634 MethodOp = MethodOp->Asl.Parent; 635 } 636 637 if (!MethodOp) 638 { 639 /* Not in a control method, error */ 640 641 AslError (ASL_ERROR, ASL_MSG_CROSS_TABLE_SCOPE, Op, NULL); 642 } 643 } 644 } 645 646 /* We found a node with this name, now check the type */ 647 648 switch (Node->Type) 649 { 650 case ACPI_TYPE_LOCAL_SCOPE: 651 case ACPI_TYPE_DEVICE: 652 case ACPI_TYPE_POWER: 653 case ACPI_TYPE_PROCESSOR: 654 case ACPI_TYPE_THERMAL: 655 656 /* These are acceptable types - they all open a new scope */ 657 break; 658 659 case ACPI_TYPE_INTEGER: 660 case ACPI_TYPE_STRING: 661 case ACPI_TYPE_BUFFER: 662 /* 663 * These types we will allow, but we will change the type. 664 * This enables some existing code of the form: 665 * 666 * Name (DEB, 0) 667 * Scope (DEB) { ... } 668 * 669 * Which is used to workaround the fact that the MS interpreter 670 * does not allow Scope() forward references. 671 */ 672 snprintf (MsgBuffer, sizeof(MsgBuffer), "%s [%s], changing type to [Scope]", 673 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); 674 AslError (ASL_REMARK, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); 675 676 /* Switch the type to scope, open the new scope */ 677 678 Node->Type = ACPI_TYPE_LOCAL_SCOPE; 679 Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, 680 WalkState); 681 if (ACPI_FAILURE (Status)) 682 { 683 return_ACPI_STATUS (Status); 684 } 685 break; 686 687 default: 688 689 /* All other types are an error */ 690 691 snprintf (MsgBuffer, sizeof(MsgBuffer), "%s [%s]", Op->Asl.ExternalName, 692 AcpiUtGetTypeName (Node->Type)); 693 AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); 694 695 /* 696 * However, switch the type to be an actual scope so 697 * that compilation can continue without generating a whole 698 * cascade of additional errors. Open the new scope. 699 */ 700 Node->Type = ACPI_TYPE_LOCAL_SCOPE; 701 Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, 702 WalkState); 703 if (ACPI_FAILURE (Status)) 704 { 705 return_ACPI_STATUS (Status); 706 } 707 break; 708 } 709 710 Status = AE_OK; 711 goto FinishNode; 712 713 default: 714 715 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 716 break; 717 } 718 719 720 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Loading name: %s, (%s)\n", 721 Op->Asl.ExternalName, AcpiUtGetTypeName (ObjectType))); 722 723 /* The name must not already exist */ 724 725 Flags |= ACPI_NS_ERROR_IF_FOUND; 726 727 /* 728 * Enter the named type into the internal namespace. We enter the name 729 * as we go downward in the parse tree. Any necessary subobjects that 730 * involve arguments to the opcode must be created as we go back up the 731 * parse tree later. 732 */ 733 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 734 ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); 735 if (ACPI_FAILURE (Status)) 736 { 737 if (Status == AE_ALREADY_EXISTS) 738 { 739 /* The name already exists in this scope */ 740 741 if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) 742 { 743 /* Allow multiple references to the same scope */ 744 745 Node->Type = (UINT8) ObjectType; 746 Status = AE_OK; 747 } 748 else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && 749 (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL)) 750 { 751 /* 752 * Allow one create on an object or segment that was 753 * previously declared External 754 */ 755 Node->Flags &= ~ANOBJ_IS_EXTERNAL; 756 Node->Type = (UINT8) ObjectType; 757 758 /* Just retyped a node, probably will need to open a scope */ 759 760 if (AcpiNsOpensScope (ObjectType)) 761 { 762 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 763 if (ACPI_FAILURE (Status)) 764 { 765 return_ACPI_STATUS (Status); 766 } 767 } 768 769 Status = AE_OK; 770 } 771 else if (!(Node->Flags & ANOBJ_IS_EXTERNAL) && 772 (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)) 773 { 774 /* 775 * Allow externals in same scope as the definition of the 776 * actual object. Similar to C. Allows multiple definition 777 * blocks that refer to each other in the same file. 778 */ 779 Status = AE_OK; 780 } 781 else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && 782 (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL) && 783 (ObjectType == ACPI_TYPE_ANY)) 784 { 785 /* Allow update of externals of unknown type. */ 786 787 if (AcpiNsOpensScope (ActualObjectType)) 788 { 789 Node->Type = (UINT8) ActualObjectType; 790 Status = AE_OK; 791 } 792 else 793 { 794 sprintf (MsgBuffer, "%s [%s]", Op->Asl.ExternalName, 795 AcpiUtGetTypeName (Node->Type)); 796 AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); 797 return_ACPI_STATUS (AE_OK); 798 } 799 } 800 else 801 { 802 /* Valid error, object already exists */ 803 804 AslDualParseOpError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op, 805 Op->Asl.ExternalName, ASL_MSG_FOUND_HERE, Node->Op, 806 Node->Op->Asl.ExternalName); 807 return_ACPI_STATUS (AE_OK); 808 } 809 } 810 else 811 { 812 AslCoreSubsystemError (Op, Status, 813 "Failure from namespace lookup", FALSE); 814 return_ACPI_STATUS (Status); 815 } 816 } 817 818 if (ForceNewScope) 819 { 820 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 821 if (ACPI_FAILURE (Status)) 822 { 823 return_ACPI_STATUS (Status); 824 } 825 } 826 827 FinishNode: 828 /* 829 * Point the parse node to the new namespace node, and point 830 * the Node back to the original Parse node 831 */ 832 Op->Asl.Node = Node; 833 Node->Op = Op; 834 835 /* Set the actual data type if appropriate (EXTERNAL term only) */ 836 837 if (ActualObjectType != ACPI_TYPE_ANY) 838 { 839 Node->Type = (UINT8) ActualObjectType; 840 Node->Value = ASL_EXTERNAL_METHOD; 841 } 842 843 if (Op->Asl.ParseOpcode == PARSEOP_METHOD) 844 { 845 /* 846 * Get the method argument count from "Extra" and save 847 * it in the namespace node 848 */ 849 Node->Value = (UINT32) Op->Asl.Extra; 850 } 851 852 return_ACPI_STATUS (Status); 853 } 854 855 856 /******************************************************************************* 857 * 858 * FUNCTION: LdNamespace2Begin 859 * 860 * PARAMETERS: ASL_WALK_CALLBACK 861 * 862 * RETURN: Status 863 * 864 * DESCRIPTION: Descending callback used during the pass 2 parse tree walk. 865 * Second pass resolves some forward references. 866 * 867 * Notes: 868 * Currently only needs to handle the Alias operator. 869 * Could be used to allow forward references from the Scope() operator, but 870 * the MS interpreter does not allow this, so this compiler does not either. 871 * 872 ******************************************************************************/ 873 874 static ACPI_STATUS 875 LdNamespace2Begin ( 876 ACPI_PARSE_OBJECT *Op, 877 UINT32 Level, 878 void *Context) 879 { 880 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 881 ACPI_STATUS Status; 882 ACPI_NAMESPACE_NODE *Node; 883 ACPI_OBJECT_TYPE ObjectType; 884 BOOLEAN ForceNewScope = FALSE; 885 ACPI_PARSE_OBJECT *Arg; 886 char *Path; 887 ACPI_NAMESPACE_NODE *TargetNode; 888 889 890 ACPI_FUNCTION_NAME (LdNamespace2Begin); 891 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", 892 Op, Op->Asl.ParseOpName)); 893 894 895 /* Ignore Ops with no namespace node */ 896 897 Node = Op->Asl.Node; 898 if (!Node) 899 { 900 return (AE_OK); 901 } 902 903 /* Get the type to determine if we should push the scope */ 904 905 if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) && 906 (Op->Asl.CompileFlags == OP_IS_RESOURCE_DESC)) 907 { 908 ObjectType = ACPI_TYPE_LOCAL_RESOURCE; 909 } 910 else 911 { 912 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 913 } 914 915 /* Push scope for Resource Templates */ 916 917 if (Op->Asl.ParseOpcode == PARSEOP_NAME) 918 { 919 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) 920 { 921 ForceNewScope = TRUE; 922 } 923 } 924 925 /* Push the scope stack */ 926 927 if (ForceNewScope || AcpiNsOpensScope (ObjectType)) 928 { 929 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 930 if (ACPI_FAILURE (Status)) 931 { 932 return_ACPI_STATUS (Status); 933 } 934 } 935 936 if (Op->Asl.ParseOpcode == PARSEOP_ALIAS) 937 { 938 /* Complete the alias node by getting and saving the target node */ 939 940 /* First child is the alias target */ 941 942 Arg = Op->Asl.Child; 943 944 /* Get the target pathname */ 945 946 Path = Arg->Asl.Namepath; 947 if (!Path) 948 { 949 Status = UtInternalizeName (Arg->Asl.ExternalName, &Path); 950 if (ACPI_FAILURE (Status)) 951 { 952 return (Status); 953 } 954 } 955 956 /* Get the NS node associated with the target. It must exist. */ 957 958 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 959 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 960 WalkState, &TargetNode); 961 if (ACPI_FAILURE (Status)) 962 { 963 if (Status == AE_NOT_FOUND) 964 { 965 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 966 Op->Asl.ExternalName); 967 968 /* 969 * The name was not found, go ahead and create it. 970 * This prevents more errors later. 971 */ 972 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, 973 ACPI_TYPE_ANY, 974 ACPI_IMODE_LOAD_PASS1, ACPI_NS_NO_UPSEARCH, 975 WalkState, &(Node)); 976 return (AE_OK); 977 } 978 979 AslCoreSubsystemError (Op, Status, 980 "Failure from namespace lookup", FALSE); 981 return (AE_OK); 982 } 983 984 /* Save the target node within the alias node */ 985 986 Node->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode); 987 } 988 989 return (AE_OK); 990 } 991 992 993 /******************************************************************************* 994 * 995 * FUNCTION: LdCommonNamespaceEnd 996 * 997 * PARAMETERS: ASL_WALK_CALLBACK 998 * 999 * RETURN: Status 1000 * 1001 * DESCRIPTION: Ascending callback used during the loading of the namespace, 1002 * We only need to worry about managing the scope stack here. 1003 * 1004 ******************************************************************************/ 1005 1006 static ACPI_STATUS 1007 LdCommonNamespaceEnd ( 1008 ACPI_PARSE_OBJECT *Op, 1009 UINT32 Level, 1010 void *Context) 1011 { 1012 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 1013 ACPI_OBJECT_TYPE ObjectType; 1014 BOOLEAN ForceNewScope = FALSE; 1015 1016 1017 ACPI_FUNCTION_NAME (LdCommonNamespaceEnd); 1018 1019 1020 /* We are only interested in opcodes that have an associated name */ 1021 1022 if (!Op->Asl.Namepath) 1023 { 1024 return (AE_OK); 1025 } 1026 1027 /* Get the type to determine if we should pop the scope */ 1028 1029 if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) && 1030 (Op->Asl.CompileFlags == OP_IS_RESOURCE_DESC)) 1031 { 1032 /* TBD: Merge into AcpiDsMapNamedOpcodeToDataType */ 1033 1034 ObjectType = ACPI_TYPE_LOCAL_RESOURCE; 1035 } 1036 else 1037 { 1038 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 1039 } 1040 1041 /* Pop scope that was pushed for Resource Templates */ 1042 1043 if (Op->Asl.ParseOpcode == PARSEOP_NAME) 1044 { 1045 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) 1046 { 1047 ForceNewScope = TRUE; 1048 } 1049 } 1050 1051 /* Pop the scope stack */ 1052 1053 if (ForceNewScope || AcpiNsOpensScope (ObjectType)) 1054 { 1055 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 1056 "(%s): Popping scope for Op [%s] %p\n", 1057 AcpiUtGetTypeName (ObjectType), Op->Asl.ParseOpName, Op)); 1058 1059 (void) AcpiDsScopeStackPop (WalkState); 1060 } 1061 1062 return (AE_OK); 1063 } 1064