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