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