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