1 /****************************************************************************** 2 * 3 * Module Name: dswload - Dispatcher namespace load callbacks 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2019, 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 Node->Flags &= ~ANOBJ_IS_EXTERNAL; 220 } 221 else 222 { 223 /* 224 * The name already exists in this scope 225 * But continue processing the elements 226 */ 227 AslDualParseOpError (ASL_WARNING, ASL_MSG_NAME_EXISTS, Child, 228 Child->Asl.Value.String, ASL_MSG_FOUND_HERE, Node->Op, 229 Node->Op->Asl.ExternalName); 230 } 231 } 232 else 233 { 234 Child->Asl.Node = Node; 235 Node->Op = Child; 236 } 237 break; 238 } 239 240 Child = Child->Asl.Next; 241 } 242 243 return (AE_OK); 244 } 245 246 247 /******************************************************************************* 248 * 249 * FUNCTION: LdLoadResourceElements 250 * 251 * PARAMETERS: Op - Parent node (Resource Descriptor) 252 * WalkState - Current walk state 253 * 254 * RETURN: Status 255 * 256 * DESCRIPTION: Enter the named elements of the resource descriptor (children 257 * of the parent) into the namespace. 258 * 259 * NOTE: In the real AML namespace, these named elements never exist. But 260 * we simply use the namespace here as a symbol table so we can look 261 * them up as they are referenced. 262 * 263 ******************************************************************************/ 264 265 static ACPI_STATUS 266 LdLoadResourceElements ( 267 ACPI_PARSE_OBJECT *Op, 268 ACPI_WALK_STATE *WalkState) 269 { 270 ACPI_PARSE_OBJECT *InitializerOp = NULL; 271 ACPI_NAMESPACE_NODE *Node; 272 ACPI_STATUS Status; 273 274 275 /* 276 * Enter the resource name into the namespace. Name must not already exist. 277 * This opens a scope, so later field names are guaranteed to be new/unique. 278 */ 279 Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Asl.Namepath, 280 ACPI_TYPE_LOCAL_RESOURCE, ACPI_IMODE_LOAD_PASS1, 281 ACPI_NS_NO_UPSEARCH | ACPI_NS_ERROR_IF_FOUND, 282 WalkState, &Node); 283 if (ACPI_FAILURE (Status)) 284 { 285 if (Status == AE_ALREADY_EXISTS) 286 { 287 /* Actual node causing the error was saved in ParentMethod */ 288 289 AslDualParseOpError (ASL_ERROR, ASL_MSG_NAME_EXISTS, 290 (ACPI_PARSE_OBJECT *) Op->Asl.ParentMethod, 291 Op->Asl.Namepath, ASL_MSG_FOUND_HERE, Node->Op, 292 Node->Op->Asl.ExternalName); 293 return (AE_OK); 294 } 295 return (Status); 296 } 297 298 Node->Value = (UINT32) Op->Asl.Value.Integer; 299 Node->Op = Op; 300 Op->Asl.Node = Node; 301 302 /* 303 * Now enter the predefined fields, for easy lookup when referenced 304 * by the source ASL 305 */ 306 InitializerOp = ASL_GET_CHILD_NODE (Op); 307 while (InitializerOp) 308 { 309 if (InitializerOp->Asl.ExternalName) 310 { 311 Status = AcpiNsLookup (WalkState->ScopeInfo, 312 InitializerOp->Asl.ExternalName, 313 ACPI_TYPE_LOCAL_RESOURCE_FIELD, ACPI_IMODE_LOAD_PASS1, 314 ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node); 315 if (ACPI_FAILURE (Status)) 316 { 317 return (Status); 318 } 319 320 /* 321 * Store the field offset and length in the namespace node 322 * so it can be used when the field is referenced 323 */ 324 Node->Value = InitializerOp->Asl.Value.Tag.BitOffset; 325 Node->Length = InitializerOp->Asl.Value.Tag.BitLength; 326 InitializerOp->Asl.Node = Node; 327 Node->Op = InitializerOp; 328 } 329 330 InitializerOp = ASL_GET_PEER_NODE (InitializerOp); 331 } 332 333 return (AE_OK); 334 } 335 336 337 /******************************************************************************* 338 * 339 * FUNCTION: LdNamespace1Begin 340 * 341 * PARAMETERS: ASL_WALK_CALLBACK 342 * 343 * RETURN: Status 344 * 345 * DESCRIPTION: Descending callback used during the parse tree walk. If this 346 * is a named AML opcode, enter into the namespace 347 * 348 ******************************************************************************/ 349 350 static ACPI_STATUS 351 LdNamespace1Begin ( 352 ACPI_PARSE_OBJECT *Op, 353 UINT32 Level, 354 void *Context) 355 { 356 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 357 ACPI_NAMESPACE_NODE *Node; 358 ACPI_PARSE_OBJECT *MethodOp; 359 ACPI_STATUS Status; 360 ACPI_OBJECT_TYPE ObjectType; 361 ACPI_OBJECT_TYPE ActualObjectType = ACPI_TYPE_ANY; 362 char *Path; 363 UINT32 Flags = ACPI_NS_NO_UPSEARCH; 364 ACPI_PARSE_OBJECT *Arg; 365 UINT32 i; 366 BOOLEAN ForceNewScope = FALSE; 367 const ACPI_OPCODE_INFO *OpInfo; 368 ACPI_PARSE_OBJECT *ParentOp; 369 370 371 ACPI_FUNCTION_NAME (LdNamespace1Begin); 372 373 374 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", 375 Op, Op->Asl.ParseOpName)); 376 377 /* 378 * We are only interested in opcodes that have an associated name 379 * (or multiple names) 380 */ 381 switch (Op->Asl.AmlOpcode) 382 { 383 case AML_BANK_FIELD_OP: 384 case AML_INDEX_FIELD_OP: 385 case AML_FIELD_OP: 386 387 Status = LdLoadFieldElements (Op, WalkState); 388 break; 389 390 case AML_INT_CONNECTION_OP: 391 392 393 if (Op->Asl.Child->Asl.AmlOpcode != AML_INT_NAMEPATH_OP) 394 { 395 break; 396 } 397 Arg = Op->Asl.Child; 398 399 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Asl.ExternalName, 400 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 401 WalkState, &Node); 402 if (ACPI_FAILURE (Status)) 403 { 404 break; 405 } 406 407 if (Node->Type == ACPI_TYPE_BUFFER) 408 { 409 Arg->Asl.Node = Node; 410 411 Arg = Node->Op->Asl.Child; /* Get namepath */ 412 Arg = Arg->Asl.Next; /* Get actual buffer */ 413 Arg = Arg->Asl.Child; /* Buffer length */ 414 Arg = Arg->Asl.Next; /* RAW_DATA buffer */ 415 } 416 break; 417 418 default: 419 420 /* All other opcodes go below */ 421 422 break; 423 } 424 425 /* Check if this object has already been installed in the namespace */ 426 427 if (Op->Asl.Node) 428 { 429 return (AE_OK); 430 } 431 432 /* Check for a possible illegal forward reference */ 433 434 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 435 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) 436 { 437 /* 438 * Op->Asl.Namepath will be NULL for these opcodes. 439 * These opcodes are guaranteed to have a parent. 440 * Examine the parent opcode. 441 */ 442 Status = AE_OK; 443 ParentOp = Op->Asl.Parent; 444 OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Asl.AmlOpcode); 445 446 /* 447 * Exclude all operators that actually declare a new name: 448 * Name (ABCD, 1) -> Ignore (AML_CLASS_NAMED_OBJECT) 449 * We only want references to named objects: 450 * Store (2, WXYZ) -> Attempt to resolve the name 451 */ 452 if ((OpInfo->Class == AML_CLASS_NAMED_OBJECT) && 453 (OpInfo->Type != AML_TYPE_NAMED_FIELD)) 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 forward 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, WalkState, &Node); 583 if (ACPI_FAILURE (Status)) 584 { 585 if (Status == AE_NOT_FOUND) 586 { 587 /* The name was not found, go ahead and create it */ 588 589 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, 590 ACPI_TYPE_LOCAL_SCOPE, ACPI_IMODE_LOAD_PASS1, 591 Flags, WalkState, &Node); 592 if (ACPI_FAILURE (Status)) 593 { 594 return_ACPI_STATUS (Status); 595 } 596 597 /* However, this is an error -- operand to Scope must exist */ 598 599 if (strlen (Op->Asl.ExternalName) == ACPI_NAMESEG_SIZE) 600 { 601 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 602 Op->Asl.ExternalName); 603 } 604 else 605 { 606 AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op, 607 Op->Asl.ExternalName); 608 } 609 610 goto FinishNode; 611 } 612 613 AslCoreSubsystemError (Op, Status, 614 "Failure from namespace lookup", FALSE); 615 616 return_ACPI_STATUS (Status); 617 } 618 else /* Status AE_OK */ 619 { 620 /* 621 * Do not allow references to external scopes from the DSDT. 622 * This is because the DSDT is always loaded first, and the 623 * external reference cannot be resolved -- causing a runtime 624 * error because Scope() must be resolved immediately. 625 * 10/2015. 626 */ 627 if ((Node->Flags & ANOBJ_IS_EXTERNAL) && 628 (ACPI_COMPARE_NAMESEG (AslGbl_TableSignature, "DSDT"))) 629 { 630 /* However, allowed if the reference is within a method */ 631 632 MethodOp = Op->Asl.Parent; 633 while (MethodOp && 634 (MethodOp->Asl.ParseOpcode != PARSEOP_METHOD)) 635 { 636 MethodOp = MethodOp->Asl.Parent; 637 } 638 639 if (!MethodOp) 640 { 641 /* Not in a control method, error */ 642 643 AslError (ASL_ERROR, ASL_MSG_CROSS_TABLE_SCOPE, Op, NULL); 644 } 645 } 646 } 647 648 /* We found a node with this name, now check the type */ 649 650 switch (Node->Type) 651 { 652 case ACPI_TYPE_LOCAL_SCOPE: 653 case ACPI_TYPE_DEVICE: 654 case ACPI_TYPE_POWER: 655 case ACPI_TYPE_PROCESSOR: 656 case ACPI_TYPE_THERMAL: 657 658 /* These are acceptable types - they all open a new scope */ 659 break; 660 661 case ACPI_TYPE_INTEGER: 662 case ACPI_TYPE_STRING: 663 case ACPI_TYPE_BUFFER: 664 /* 665 * These types we will allow, but we will change the type. 666 * This enables some existing code of the form: 667 * 668 * Name (DEB, 0) 669 * Scope (DEB) { ... } 670 * 671 * Which is used to workaround the fact that the MS interpreter 672 * does not allow Scope() forward references. 673 */ 674 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "%s [%s], changing type to [Scope]", 675 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); 676 AslError (ASL_REMARK, ASL_MSG_SCOPE_TYPE, Op, AslGbl_MsgBuffer); 677 678 /* Switch the type to scope, open the new scope */ 679 680 Node->Type = ACPI_TYPE_LOCAL_SCOPE; 681 Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, 682 WalkState); 683 if (ACPI_FAILURE (Status)) 684 { 685 return_ACPI_STATUS (Status); 686 } 687 break; 688 689 default: 690 691 /* All other types are an error */ 692 693 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "%s [%s]", Op->Asl.ExternalName, 694 AcpiUtGetTypeName (Node->Type)); 695 AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, AslGbl_MsgBuffer); 696 697 /* 698 * However, switch the type to be an actual scope so 699 * that compilation can continue without generating a whole 700 * cascade of additional errors. Open the new scope. 701 */ 702 Node->Type = ACPI_TYPE_LOCAL_SCOPE; 703 Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, 704 WalkState); 705 if (ACPI_FAILURE (Status)) 706 { 707 return_ACPI_STATUS (Status); 708 } 709 break; 710 } 711 712 Status = AE_OK; 713 goto FinishNode; 714 715 default: 716 717 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 718 break; 719 } 720 721 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Loading name: %s, (%s)\n", 722 Op->Asl.ExternalName, AcpiUtGetTypeName (ObjectType))); 723 724 /* The name must not already exist */ 725 726 Flags |= ACPI_NS_ERROR_IF_FOUND; 727 728 /* 729 * For opcodes that enter new names into the namespace, 730 * all prefix NameSegs must exist. 731 */ 732 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 733 if (((WalkState->OpInfo->Flags & AML_NAMED) || 734 (WalkState->OpInfo->Flags & AML_CREATE)) && 735 (Op->Asl.AmlOpcode != AML_EXTERNAL_OP)) 736 { 737 Flags |= ACPI_NS_PREFIX_MUST_EXIST; 738 } 739 740 /* 741 * Enter the named type into the internal namespace. We enter the name 742 * as we go downward in the parse tree. Any necessary subobjects that 743 * involve arguments to the opcode must be created as we go back up the 744 * parse tree later. 745 */ 746 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 747 ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); 748 if (ACPI_FAILURE (Status)) 749 { 750 if (Status == AE_ALREADY_EXISTS) 751 { 752 /* The name already exists in this scope */ 753 754 if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) 755 { 756 /* Allow multiple references to the same scope */ 757 758 Node->Type = (UINT8) ObjectType; 759 Status = AE_OK; 760 } 761 else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && 762 (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL)) 763 { 764 /* 765 * Allow one create on an object or segment that was 766 * previously declared External 767 */ 768 Node->Flags &= ~ANOBJ_IS_EXTERNAL; 769 Node->Type = (UINT8) ObjectType; 770 771 /* Just retyped a node, probably will need to open a scope */ 772 773 if (AcpiNsOpensScope (ObjectType)) 774 { 775 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 776 if (ACPI_FAILURE (Status)) 777 { 778 return_ACPI_STATUS (Status); 779 } 780 } 781 782 Status = AE_OK; 783 } 784 else if (!(Node->Flags & ANOBJ_IS_EXTERNAL) && 785 (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)) 786 { 787 /* 788 * Allow externals in same scope as the definition of the 789 * actual object. Similar to C. Allows multiple definition 790 * blocks that refer to each other in the same file. 791 */ 792 Status = AE_OK; 793 } 794 else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && 795 (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL) && 796 (ObjectType == ACPI_TYPE_ANY)) 797 { 798 /* Allow update of externals of unknown type. */ 799 800 if (AcpiNsOpensScope (ActualObjectType)) 801 { 802 Node->Type = (UINT8) ActualObjectType; 803 Status = AE_OK; 804 } 805 else 806 { 807 sprintf (AslGbl_MsgBuffer, "%s [%s]", Op->Asl.ExternalName, 808 AcpiUtGetTypeName (Node->Type)); 809 AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, AslGbl_MsgBuffer); 810 return_ACPI_STATUS (AE_OK); 811 } 812 } 813 else 814 { 815 /* Valid error, object already exists */ 816 817 AslDualParseOpError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op, 818 Op->Asl.ExternalName, ASL_MSG_FOUND_HERE, Node->Op, 819 Node->Op->Asl.ExternalName); 820 return_ACPI_STATUS (AE_OK); 821 } 822 } 823 else if (AE_NOT_FOUND) 824 { 825 /* 826 * One or more prefix NameSegs of the NamePath do not exist 827 * (all of them must exist). Attempt to continue compilation 828 * by setting the current scope to the root. 829 */ 830 Node = AcpiGbl_RootNode; 831 Status = AE_OK; 832 } 833 else 834 { 835 /* Flag all other errors as coming from the ACPICA core */ 836 837 AslCoreSubsystemError (Op, Status, 838 "Failure from namespace lookup", FALSE); 839 return_ACPI_STATUS (Status); 840 } 841 } 842 843 if (ForceNewScope) 844 { 845 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 846 if (ACPI_FAILURE (Status)) 847 { 848 return_ACPI_STATUS (Status); 849 } 850 } 851 852 FinishNode: 853 /* 854 * Point the parse node to the new namespace node, and point 855 * the Node back to the original Parse node 856 */ 857 Op->Asl.Node = Node; 858 Node->Op = Op; 859 860 /* Set the actual data type if appropriate (EXTERNAL term only) */ 861 862 if (ActualObjectType != ACPI_TYPE_ANY) 863 { 864 Node->Type = (UINT8) ActualObjectType; 865 Node->Value = ASL_EXTERNAL_METHOD; 866 } 867 868 if (Op->Asl.ParseOpcode == PARSEOP_METHOD) 869 { 870 /* 871 * Get the method argument count from "Extra" and save 872 * it in the namespace node 873 */ 874 Node->Value = (UINT32) Op->Asl.Extra; 875 } 876 877 return_ACPI_STATUS (Status); 878 } 879 880 881 /******************************************************************************* 882 * 883 * FUNCTION: LdNamespace2Begin 884 * 885 * PARAMETERS: ASL_WALK_CALLBACK 886 * 887 * RETURN: Status 888 * 889 * DESCRIPTION: Descending callback used during the pass 2 parse tree walk. 890 * Second pass resolves some forward references. 891 * 892 * Notes: 893 * Currently only needs to handle the Alias operator. 894 * Could be used to allow forward references from the Scope() operator, but 895 * the MS interpreter does not allow this, so this compiler does not either. 896 * 897 ******************************************************************************/ 898 899 static ACPI_STATUS 900 LdNamespace2Begin ( 901 ACPI_PARSE_OBJECT *Op, 902 UINT32 Level, 903 void *Context) 904 { 905 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 906 ACPI_STATUS Status; 907 ACPI_NAMESPACE_NODE *Node; 908 ACPI_OBJECT_TYPE ObjectType; 909 BOOLEAN ForceNewScope = FALSE; 910 ACPI_PARSE_OBJECT *Arg; 911 char *Path; 912 ACPI_NAMESPACE_NODE *TargetNode; 913 914 915 ACPI_FUNCTION_NAME (LdNamespace2Begin); 916 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", 917 Op, Op->Asl.ParseOpName)); 918 919 920 /* Ignore Ops with no namespace node */ 921 922 Node = Op->Asl.Node; 923 if (!Node) 924 { 925 return (AE_OK); 926 } 927 928 /* Get the type to determine if we should push the scope */ 929 930 if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) && 931 (Op->Asl.CompileFlags == OP_IS_RESOURCE_DESC)) 932 { 933 ObjectType = ACPI_TYPE_LOCAL_RESOURCE; 934 } 935 else 936 { 937 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 938 } 939 940 /* Push scope for Resource Templates */ 941 942 if (Op->Asl.ParseOpcode == PARSEOP_NAME) 943 { 944 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) 945 { 946 ForceNewScope = TRUE; 947 } 948 } 949 950 /* Push the scope stack */ 951 952 if (ForceNewScope || AcpiNsOpensScope (ObjectType)) 953 { 954 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 955 if (ACPI_FAILURE (Status)) 956 { 957 return_ACPI_STATUS (Status); 958 } 959 } 960 961 if (Op->Asl.ParseOpcode == PARSEOP_ALIAS) 962 { 963 /* 964 * Complete the alias node by getting and saving the target node. 965 * First child is the alias target 966 */ 967 Arg = Op->Asl.Child; 968 969 /* Get the target pathname */ 970 971 Path = Arg->Asl.Namepath; 972 if (!Path) 973 { 974 Status = UtInternalizeName (Arg->Asl.ExternalName, &Path); 975 if (ACPI_FAILURE (Status)) 976 { 977 return (Status); 978 } 979 } 980 981 /* Get the NS node associated with the target. It must exist. */ 982 983 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 984 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 985 WalkState, &TargetNode); 986 if (ACPI_FAILURE (Status)) 987 { 988 if (Status == AE_NOT_FOUND) 989 { 990 /* Standalone NameSeg vs. NamePath */ 991 992 if (strlen (Arg->Asl.ExternalName) == ACPI_NAMESEG_SIZE) 993 { 994 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 995 Arg->Asl.ExternalName); 996 } 997 else 998 { 999 AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op, 1000 Arg->Asl.ExternalName); 1001 } 1002 1003 #if 0 1004 /* 1005 * NOTE: Removed 10/2018 to enhance compiler error reporting. No 1006 * regressions seen. 1007 */ 1008 /* 1009 * The name was not found, go ahead and create it. 1010 * This prevents more errors later. 1011 */ 1012 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, 1013 ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1, 1014 ACPI_NS_NO_UPSEARCH, WalkState, &Node); 1015 #endif 1016 return (Status); 1017 /* Removed: return (AE_OK)*/ 1018 } 1019 1020 AslCoreSubsystemError (Op, Status, 1021 "Failure from namespace lookup", FALSE); 1022 return (AE_OK); 1023 } 1024 1025 /* Save the target node within the alias node */ 1026 1027 Node->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode); 1028 } 1029 1030 return (AE_OK); 1031 } 1032 1033 1034 /******************************************************************************* 1035 * 1036 * FUNCTION: LdCommonNamespaceEnd 1037 * 1038 * PARAMETERS: ASL_WALK_CALLBACK 1039 * 1040 * RETURN: Status 1041 * 1042 * DESCRIPTION: Ascending callback used during the loading of the namespace, 1043 * We only need to worry about managing the scope stack here. 1044 * 1045 ******************************************************************************/ 1046 1047 static ACPI_STATUS 1048 LdCommonNamespaceEnd ( 1049 ACPI_PARSE_OBJECT *Op, 1050 UINT32 Level, 1051 void *Context) 1052 { 1053 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 1054 ACPI_OBJECT_TYPE ObjectType; 1055 BOOLEAN ForceNewScope = FALSE; 1056 1057 1058 ACPI_FUNCTION_NAME (LdCommonNamespaceEnd); 1059 1060 1061 /* We are only interested in opcodes that have an associated name */ 1062 1063 if (!Op->Asl.Namepath) 1064 { 1065 return (AE_OK); 1066 } 1067 1068 /* Get the type to determine if we should pop the scope */ 1069 1070 if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) && 1071 (Op->Asl.CompileFlags == OP_IS_RESOURCE_DESC)) 1072 { 1073 /* TBD: Merge into AcpiDsMapNamedOpcodeToDataType */ 1074 1075 ObjectType = ACPI_TYPE_LOCAL_RESOURCE; 1076 } 1077 else 1078 { 1079 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 1080 } 1081 1082 /* Pop scope that was pushed for Resource Templates */ 1083 1084 if (Op->Asl.ParseOpcode == PARSEOP_NAME) 1085 { 1086 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) 1087 { 1088 ForceNewScope = TRUE; 1089 } 1090 } 1091 1092 /* Pop the scope stack */ 1093 1094 if (ForceNewScope || AcpiNsOpensScope (ObjectType)) 1095 { 1096 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 1097 "(%s): Popping scope for Op [%s] %p\n", 1098 AcpiUtGetTypeName (ObjectType), Op->Asl.ParseOpName, Op)); 1099 1100 (void) AcpiDsScopeStackPop (WalkState); 1101 } 1102 1103 return (AE_OK); 1104 } 1105