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