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