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_WARNING, 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 422 if (Op->Asl.Child->Asl.AmlOpcode != AML_INT_NAMEPATH_OP) 423 { 424 break; 425 } 426 Arg = Op->Asl.Child; 427 428 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Asl.ExternalName, 429 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 430 WalkState, &Node); 431 if (ACPI_FAILURE (Status)) 432 { 433 break; 434 } 435 436 if (Node->Type == ACPI_TYPE_BUFFER) 437 { 438 Arg->Asl.Node = Node; 439 440 Arg = Node->Op->Asl.Child; /* Get namepath */ 441 Arg = Arg->Asl.Next; /* Get actual buffer */ 442 Arg = Arg->Asl.Child; /* Buffer length */ 443 Arg = Arg->Asl.Next; /* RAW_DATA buffer */ 444 } 445 break; 446 447 default: 448 449 /* All other opcodes go below */ 450 451 break; 452 } 453 454 /* Check if this object has already been installed in the namespace */ 455 456 if (Op->Asl.Node) 457 { 458 return (AE_OK); 459 } 460 461 /* Check for a possible illegal forward reference */ 462 463 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 464 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) 465 { 466 /* 467 * Op->Asl.Namepath will be NULL for these opcodes. 468 * These opcodes are guaranteed to have a parent. 469 * Examine the parent opcode. 470 */ 471 Status = AE_OK; 472 ParentOp = Op->Asl.Parent; 473 OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Asl.AmlOpcode); 474 475 /* 476 * Exclude all operators that actually declare a new name: 477 * Name (ABCD, 1) -> Ignore (AML_CLASS_NAMED_OBJECT) 478 * We only want references to named objects: 479 * Store (2, WXYZ) -> Attempt to resolve the name 480 */ 481 if (OpInfo->Class == AML_CLASS_NAMED_OBJECT) 482 { 483 return (AE_OK); 484 } 485 486 /* 487 * Check if the referenced object exists at this point during 488 * the load: 489 * 1) If it exists, then this cannot be a forward reference. 490 * 2) If it does not exist, it could be a forward reference or 491 * it truly does not exist (and no external declaration). 492 */ 493 Status = AcpiNsLookup (WalkState->ScopeInfo, 494 Op->Asl.Value.Name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 495 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 496 WalkState, &Node); 497 if (Status == AE_NOT_FOUND) 498 { 499 /* 500 * This is either a forward reference or the object truly 501 * does not exist. The two cases can only be differentiated 502 * during the cross-reference stage later. Mark the Op/Name 503 * as not-found for now to indicate the need for further 504 * processing. 505 * 506 * Special case: Allow forward references from elements of 507 * Package objects. This provides compatibility with other 508 * ACPI implementations. To correctly implement this, the 509 * ACPICA table load defers package resolution until the entire 510 * namespace has been loaded. 511 */ 512 if ((ParentOp->Asl.ParseOpcode != PARSEOP_PACKAGE) && 513 (ParentOp->Asl.ParseOpcode != PARSEOP_VAR_PACKAGE)) 514 { 515 Op->Asl.CompileFlags |= OP_NOT_FOUND_DURING_LOAD; 516 } 517 518 return (AE_OK); 519 } 520 521 return (Status); 522 } 523 524 Path = Op->Asl.Namepath; 525 if (!Path) 526 { 527 return (AE_OK); 528 } 529 530 /* Map the raw opcode into an internal object type */ 531 532 switch (Op->Asl.ParseOpcode) 533 { 534 case PARSEOP_NAME: 535 536 Arg = Op->Asl.Child; /* Get the NameSeg/NameString node */ 537 Arg = Arg->Asl.Next; /* First peer is the object to be associated with the name */ 538 539 /* 540 * If this name refers to a ResourceTemplate, we will need to open 541 * a new scope so that the resource subfield names can be entered into 542 * the namespace underneath this name 543 */ 544 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) 545 { 546 ForceNewScope = TRUE; 547 } 548 549 /* Get the data type associated with the named object, not the name itself */ 550 551 /* Log2 loop to convert from Btype (binary) to Etype (encoded) */ 552 553 ObjectType = 1; 554 for (i = 1; i < Arg->Asl.AcpiBtype; i *= 2) 555 { 556 ObjectType++; 557 } 558 break; 559 560 case PARSEOP_EXTERNAL: 561 /* 562 * "External" simply enters a name and type into the namespace. 563 * We must be careful to not open a new scope, however, no matter 564 * what type the external name refers to (e.g., a method) 565 * 566 * first child is name, next child is ObjectType 567 */ 568 ActualObjectType = (UINT8) Op->Asl.Child->Asl.Next->Asl.Value.Integer; 569 ObjectType = ACPI_TYPE_ANY; 570 571 /* 572 * We will mark every new node along the path as "External". This 573 * allows some or all of the nodes to be created later in the ASL 574 * code. Handles cases like this: 575 * 576 * External (\_SB_.PCI0.ABCD, IntObj) 577 * Scope (_SB_) 578 * { 579 * Device (PCI0) 580 * { 581 * } 582 * } 583 * Method (X) 584 * { 585 * Store (\_SB_.PCI0.ABCD, Local0) 586 * } 587 */ 588 Flags |= ACPI_NS_EXTERNAL; 589 break; 590 591 case PARSEOP_DEFAULT_ARG: 592 593 if (Op->Asl.CompileFlags == OP_IS_RESOURCE_DESC) 594 { 595 Status = LdLoadResourceElements (Op, WalkState); 596 return_ACPI_STATUS (Status); 597 } 598 599 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 600 break; 601 602 case PARSEOP_SCOPE: 603 /* 604 * The name referenced by Scope(Name) must already exist at this point. 605 * In other words, forward references for Scope() are not supported. 606 * The only real reason for this is that the MS interpreter cannot 607 * handle this case. Perhaps someday this case can go away. 608 */ 609 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 610 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &Node); 611 if (ACPI_FAILURE (Status)) 612 { 613 if (Status == AE_NOT_FOUND) 614 { 615 /* The name was not found, go ahead and create it */ 616 617 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, 618 ACPI_TYPE_LOCAL_SCOPE, ACPI_IMODE_LOAD_PASS1, 619 Flags, WalkState, &Node); 620 if (ACPI_FAILURE (Status)) 621 { 622 return_ACPI_STATUS (Status); 623 } 624 625 /* However, this is an error -- operand to Scope must exist */ 626 627 if (strlen (Op->Asl.ExternalName) == ACPI_NAMESEG_SIZE) 628 { 629 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 630 Op->Asl.ExternalName); 631 } 632 else 633 { 634 AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op, 635 Op->Asl.ExternalName); 636 } 637 638 goto FinishNode; 639 } 640 641 AslCoreSubsystemError (Op, Status, 642 "Failure from namespace lookup", FALSE); 643 644 return_ACPI_STATUS (Status); 645 } 646 else /* Status AE_OK */ 647 { 648 /* 649 * Do not allow references to external scopes from the DSDT. 650 * This is because the DSDT is always loaded first, and the 651 * external reference cannot be resolved -- causing a runtime 652 * error because Scope() must be resolved immediately. 653 * 10/2015. 654 */ 655 if ((Node->Flags & ANOBJ_IS_EXTERNAL) && 656 (ACPI_COMPARE_NAMESEG (AslGbl_TableSignature, "DSDT"))) 657 { 658 /* However, allowed if the reference is within a method */ 659 660 MethodOp = Op->Asl.Parent; 661 while (MethodOp && 662 (MethodOp->Asl.ParseOpcode != PARSEOP_METHOD)) 663 { 664 MethodOp = MethodOp->Asl.Parent; 665 } 666 667 if (!MethodOp) 668 { 669 /* Not in a control method, error */ 670 671 AslError (ASL_ERROR, ASL_MSG_CROSS_TABLE_SCOPE, Op, NULL); 672 } 673 } 674 } 675 676 /* We found a node with this name, now check the type */ 677 678 switch (Node->Type) 679 { 680 case ACPI_TYPE_LOCAL_SCOPE: 681 case ACPI_TYPE_DEVICE: 682 case ACPI_TYPE_POWER: 683 case ACPI_TYPE_PROCESSOR: 684 case ACPI_TYPE_THERMAL: 685 686 /* These are acceptable types - they all open a new scope */ 687 break; 688 689 case ACPI_TYPE_INTEGER: 690 case ACPI_TYPE_STRING: 691 case ACPI_TYPE_BUFFER: 692 /* 693 * These types we will allow, but we will change the type. 694 * This enables some existing code of the form: 695 * 696 * Name (DEB, 0) 697 * Scope (DEB) { ... } 698 * 699 * Which is used to workaround the fact that the MS interpreter 700 * does not allow Scope() forward references. 701 */ 702 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "%s [%s], changing type to [Scope]", 703 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); 704 AslError (ASL_REMARK, ASL_MSG_SCOPE_TYPE, Op, AslGbl_MsgBuffer); 705 706 /* Switch the type to scope, open the new scope */ 707 708 Node->Type = ACPI_TYPE_LOCAL_SCOPE; 709 Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, 710 WalkState); 711 if (ACPI_FAILURE (Status)) 712 { 713 return_ACPI_STATUS (Status); 714 } 715 break; 716 717 default: 718 719 /* All other types are an error */ 720 721 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "%s [%s]", Op->Asl.ExternalName, 722 AcpiUtGetTypeName (Node->Type)); 723 AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, AslGbl_MsgBuffer); 724 725 /* 726 * However, switch the type to be an actual scope so 727 * that compilation can continue without generating a whole 728 * cascade of additional errors. Open the new scope. 729 */ 730 Node->Type = ACPI_TYPE_LOCAL_SCOPE; 731 Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, 732 WalkState); 733 if (ACPI_FAILURE (Status)) 734 { 735 return_ACPI_STATUS (Status); 736 } 737 break; 738 } 739 740 Status = AE_OK; 741 goto FinishNode; 742 743 default: 744 745 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 746 break; 747 } 748 749 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Loading name: %s, (%s)\n", 750 Op->Asl.ExternalName, AcpiUtGetTypeName (ObjectType))); 751 752 /* The name must not already exist */ 753 754 Flags |= ACPI_NS_ERROR_IF_FOUND; 755 756 /* 757 * For opcodes that enter new names into the namespace, 758 * all prefix NameSegs must exist. 759 */ 760 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 761 if (((WalkState->OpInfo->Flags & AML_NAMED) || 762 (WalkState->OpInfo->Flags & AML_CREATE)) && 763 (Op->Asl.AmlOpcode != AML_EXTERNAL_OP)) 764 { 765 Flags |= ACPI_NS_PREFIX_MUST_EXIST; 766 } 767 768 /* 769 * Enter the named type into the internal namespace. We enter the name 770 * as we go downward in the parse tree. Any necessary subobjects that 771 * involve arguments to the opcode must be created as we go back up the 772 * parse tree later. 773 */ 774 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 775 ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); 776 if (ACPI_FAILURE (Status)) 777 { 778 if (Status == AE_ALREADY_EXISTS) 779 { 780 /* The name already exists in this scope */ 781 782 if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) 783 { 784 /* Allow multiple references to the same scope */ 785 786 Node->Type = (UINT8) ObjectType; 787 Status = AE_OK; 788 } 789 else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && 790 (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL)) 791 { 792 /* 793 * Allow one create on an object or segment that was 794 * previously declared External 795 */ 796 Node->Flags &= ~ANOBJ_IS_EXTERNAL; 797 Node->Type = (UINT8) ObjectType; 798 799 /* Just retyped a node, probably will need to open a scope */ 800 801 if (AcpiNsOpensScope (ObjectType)) 802 { 803 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 804 if (ACPI_FAILURE (Status)) 805 { 806 return_ACPI_STATUS (Status); 807 } 808 } 809 810 Status = AE_OK; 811 } 812 else if (!(Node->Flags & ANOBJ_IS_EXTERNAL) && 813 (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)) 814 { 815 /* 816 * Allow externals in same scope as the definition of the 817 * actual object. Similar to C. Allows multiple definition 818 * blocks that refer to each other in the same file. 819 */ 820 Status = AE_OK; 821 } 822 else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && 823 (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL) && 824 (ObjectType == ACPI_TYPE_ANY)) 825 { 826 /* Allow update of externals of unknown type. */ 827 828 if (AcpiNsOpensScope (ActualObjectType)) 829 { 830 Node->Type = (UINT8) ActualObjectType; 831 Status = AE_OK; 832 } 833 else 834 { 835 sprintf (AslGbl_MsgBuffer, "%s [%s]", Op->Asl.ExternalName, 836 AcpiUtGetTypeName (Node->Type)); 837 AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, AslGbl_MsgBuffer); 838 return_ACPI_STATUS (AE_OK); 839 } 840 } 841 else 842 { 843 /* Valid error, object already exists */ 844 845 AslDualParseOpError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op, 846 Op->Asl.ExternalName, ASL_MSG_FOUND_HERE, Node->Op, 847 Node->Op->Asl.ExternalName); 848 return_ACPI_STATUS (AE_OK); 849 } 850 } 851 else if (AE_NOT_FOUND) 852 { 853 /* 854 * One or more prefix NameSegs of the NamePath do not exist 855 * (all of them must exist). Attempt to continue compilation 856 * by setting the current scope to the root. 857 */ 858 Node = AcpiGbl_RootNode; 859 Status = AE_OK; 860 } 861 else 862 { 863 /* Flag all other errors as coming from the ACPICA core */ 864 865 AslCoreSubsystemError (Op, Status, 866 "Failure from namespace lookup", FALSE); 867 return_ACPI_STATUS (Status); 868 } 869 } 870 871 /* Check special names like _WAK and _PTS */ 872 873 LdCheckSpecialNames (Node, Op); 874 875 if (ForceNewScope) 876 { 877 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 878 if (ACPI_FAILURE (Status)) 879 { 880 return_ACPI_STATUS (Status); 881 } 882 } 883 884 FinishNode: 885 /* 886 * Point the parse node to the new namespace node, and point 887 * the Node back to the original Parse node 888 */ 889 Op->Asl.Node = Node; 890 Node->Op = Op; 891 892 /* Set the actual data type if appropriate (EXTERNAL term only) */ 893 894 if (ActualObjectType != ACPI_TYPE_ANY) 895 { 896 Node->Type = (UINT8) ActualObjectType; 897 Node->Value = ASL_EXTERNAL_METHOD; 898 } 899 900 if (Op->Asl.ParseOpcode == PARSEOP_METHOD) 901 { 902 /* 903 * Get the method argument count from "Extra" and save 904 * it in the namespace node 905 */ 906 Node->Value = (UINT32) Op->Asl.Extra; 907 } 908 909 return_ACPI_STATUS (Status); 910 } 911 912 913 /******************************************************************************* 914 * 915 * FUNCTION: LdCheckSpecialNames 916 * 917 * PARAMETERS: Node - Node that represents the named object 918 * Op - Named object declaring this named object 919 * 920 * RETURN: None 921 * 922 * DESCRIPTION: Check if certain named objects are declared in the incorrect 923 * scope. Special named objects are listed in 924 * AslGbl_SpecialNamedObjects and can only be declared at the root 925 * scope. _UID inside of a processor declaration must not be a 926 * string. 927 * 928 ******************************************************************************/ 929 930 static void 931 LdCheckSpecialNames ( 932 ACPI_NAMESPACE_NODE *Node, 933 ACPI_PARSE_OBJECT *Op) 934 { 935 UINT32 i; 936 937 938 for (i = 0; i < MAX_SPECIAL_NAMES; i++) 939 { 940 if (ACPI_COMPARE_NAMESEG(Node->Name.Ascii, AslGbl_SpecialNamedObjects[i]) && 941 Node->Parent != AcpiGbl_RootNode) 942 { 943 AslError (ASL_ERROR, ASL_MSG_INVALID_SPECIAL_NAME, Op, Op->Asl.ExternalName); 944 return; 945 } 946 } 947 948 if (ACPI_COMPARE_NAMESEG (Node->Name.Ascii, "_UID") && 949 Node->Parent->Type == ACPI_TYPE_PROCESSOR && 950 Node->Type == ACPI_TYPE_STRING) 951 { 952 AslError (ASL_ERROR, ASL_MSG_INVALID_PROCESSOR_UID , Op, "found a string"); 953 } 954 } 955 956 957 /******************************************************************************* 958 * 959 * FUNCTION: LdNamespace2Begin 960 * 961 * PARAMETERS: ASL_WALK_CALLBACK 962 * 963 * RETURN: Status 964 * 965 * DESCRIPTION: Descending callback used during the pass 2 parse tree walk. 966 * Second pass resolves some forward references. 967 * 968 * Notes: 969 * Currently only needs to handle the Alias operator. 970 * Could be used to allow forward references from the Scope() operator, but 971 * the MS interpreter does not allow this, so this compiler does not either. 972 * 973 ******************************************************************************/ 974 975 static ACPI_STATUS 976 LdNamespace2Begin ( 977 ACPI_PARSE_OBJECT *Op, 978 UINT32 Level, 979 void *Context) 980 { 981 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 982 ACPI_STATUS Status; 983 ACPI_NAMESPACE_NODE *Node; 984 ACPI_OBJECT_TYPE ObjectType; 985 BOOLEAN ForceNewScope = FALSE; 986 ACPI_PARSE_OBJECT *Arg; 987 char *Path; 988 ACPI_NAMESPACE_NODE *TargetNode; 989 990 991 ACPI_FUNCTION_NAME (LdNamespace2Begin); 992 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", 993 Op, Op->Asl.ParseOpName)); 994 995 996 /* Ignore Ops with no namespace node */ 997 998 Node = Op->Asl.Node; 999 if (!Node) 1000 { 1001 return (AE_OK); 1002 } 1003 1004 /* Get the type to determine if we should push the scope */ 1005 1006 if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) && 1007 (Op->Asl.CompileFlags == OP_IS_RESOURCE_DESC)) 1008 { 1009 ObjectType = ACPI_TYPE_LOCAL_RESOURCE; 1010 } 1011 else 1012 { 1013 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 1014 } 1015 1016 /* Push scope for Resource Templates */ 1017 1018 if (Op->Asl.ParseOpcode == PARSEOP_NAME) 1019 { 1020 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) 1021 { 1022 ForceNewScope = TRUE; 1023 } 1024 } 1025 1026 /* Push the scope stack */ 1027 1028 if (ForceNewScope || AcpiNsOpensScope (ObjectType)) 1029 { 1030 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); 1031 if (ACPI_FAILURE (Status)) 1032 { 1033 return_ACPI_STATUS (Status); 1034 } 1035 } 1036 1037 if (Op->Asl.ParseOpcode == PARSEOP_ALIAS) 1038 { 1039 /* 1040 * Complete the alias node by getting and saving the target node. 1041 * First child is the alias target 1042 */ 1043 Arg = Op->Asl.Child; 1044 1045 /* Get the target pathname */ 1046 1047 Path = Arg->Asl.Namepath; 1048 if (!Path) 1049 { 1050 Status = UtInternalizeName (Arg->Asl.ExternalName, &Path); 1051 if (ACPI_FAILURE (Status)) 1052 { 1053 return (Status); 1054 } 1055 } 1056 1057 /* Get the NS node associated with the target. It must exist. */ 1058 1059 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 1060 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 1061 WalkState, &TargetNode); 1062 if (ACPI_FAILURE (Status)) 1063 { 1064 if (Status == AE_NOT_FOUND) 1065 { 1066 /* Standalone NameSeg vs. NamePath */ 1067 1068 if (strlen (Arg->Asl.ExternalName) == ACPI_NAMESEG_SIZE) 1069 { 1070 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 1071 Arg->Asl.ExternalName); 1072 } 1073 else 1074 { 1075 AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op, 1076 Arg->Asl.ExternalName); 1077 } 1078 1079 #if 0 1080 /* 1081 * NOTE: Removed 10/2018 to enhance compiler error reporting. No 1082 * regressions seen. 1083 */ 1084 /* 1085 * The name was not found, go ahead and create it. 1086 * This prevents more errors later. 1087 */ 1088 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, 1089 ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1, 1090 ACPI_NS_NO_UPSEARCH, WalkState, &Node); 1091 #endif 1092 return (Status); 1093 /* Removed: return (AE_OK)*/ 1094 } 1095 1096 AslCoreSubsystemError (Op, Status, 1097 "Failure from namespace lookup", FALSE); 1098 return (AE_OK); 1099 } 1100 1101 /* Save the target node within the alias node */ 1102 1103 Node->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode); 1104 } 1105 1106 return (AE_OK); 1107 } 1108 1109 1110 /******************************************************************************* 1111 * 1112 * FUNCTION: LdCommonNamespaceEnd 1113 * 1114 * PARAMETERS: ASL_WALK_CALLBACK 1115 * 1116 * RETURN: Status 1117 * 1118 * DESCRIPTION: Ascending callback used during the loading of the namespace, 1119 * We only need to worry about managing the scope stack here. 1120 * 1121 ******************************************************************************/ 1122 1123 static ACPI_STATUS 1124 LdCommonNamespaceEnd ( 1125 ACPI_PARSE_OBJECT *Op, 1126 UINT32 Level, 1127 void *Context) 1128 { 1129 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 1130 ACPI_OBJECT_TYPE ObjectType; 1131 BOOLEAN ForceNewScope = FALSE; 1132 1133 1134 ACPI_FUNCTION_NAME (LdCommonNamespaceEnd); 1135 1136 1137 /* We are only interested in opcodes that have an associated name */ 1138 1139 if (!Op->Asl.Namepath) 1140 { 1141 return (AE_OK); 1142 } 1143 1144 /* Get the type to determine if we should pop the scope */ 1145 1146 if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) && 1147 (Op->Asl.CompileFlags == OP_IS_RESOURCE_DESC)) 1148 { 1149 /* TBD: Merge into AcpiDsMapNamedOpcodeToDataType */ 1150 1151 ObjectType = ACPI_TYPE_LOCAL_RESOURCE; 1152 } 1153 else 1154 { 1155 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 1156 } 1157 1158 /* Pop scope that was pushed for Resource Templates */ 1159 1160 if (Op->Asl.ParseOpcode == PARSEOP_NAME) 1161 { 1162 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) 1163 { 1164 ForceNewScope = TRUE; 1165 } 1166 } 1167 1168 /* Pop the scope stack */ 1169 1170 if (ForceNewScope || AcpiNsOpensScope (ObjectType)) 1171 { 1172 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 1173 "(%s): Popping scope for Op [%s] %p\n", 1174 AcpiUtGetTypeName (ObjectType), Op->Asl.ParseOpName, Op)); 1175 1176 (void) AcpiDsScopeStackPop (WalkState); 1177 } 1178 1179 return (AE_OK); 1180 } 1181