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