1 /******************************************************************************* 2 * 3 * Module Name: nsaccess - Top-level functions for accessing ACPI namespace 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2021, 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 "acpi.h" 45 #include "accommon.h" 46 #include "amlcode.h" 47 #include "acnamesp.h" 48 #include "acdispat.h" 49 50 #ifdef ACPI_ASL_COMPILER 51 #include "acdisasm.h" 52 #endif 53 54 #define _COMPONENT ACPI_NAMESPACE 55 ACPI_MODULE_NAME ("nsaccess") 56 57 58 /******************************************************************************* 59 * 60 * FUNCTION: AcpiNsRootInitialize 61 * 62 * PARAMETERS: None 63 * 64 * RETURN: Status 65 * 66 * DESCRIPTION: Allocate and initialize the default root named objects 67 * 68 * MUTEX: Locks namespace for entire execution 69 * 70 ******************************************************************************/ 71 72 ACPI_STATUS 73 AcpiNsRootInitialize ( 74 void) 75 { 76 ACPI_STATUS Status; 77 const ACPI_PREDEFINED_NAMES *InitVal = NULL; 78 ACPI_NAMESPACE_NODE *NewNode; 79 ACPI_NAMESPACE_NODE *PrevNode = NULL; 80 ACPI_OPERAND_OBJECT *ObjDesc; 81 ACPI_STRING Val = NULL; 82 UINT32 Name; 83 84 85 ACPI_FUNCTION_TRACE (NsRootInitialize); 86 87 88 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 89 if (ACPI_FAILURE (Status)) 90 { 91 return_ACPI_STATUS (Status); 92 } 93 94 /* 95 * The global root ptr is initially NULL, so a non-NULL value indicates 96 * that AcpiNsRootInitialize() has already been called; just return. 97 */ 98 if (AcpiGbl_RootNode) 99 { 100 Status = AE_OK; 101 goto UnlockAndExit; 102 } 103 104 /* 105 * Tell the rest of the subsystem that the root is initialized 106 * (This is OK because the namespace is locked) 107 */ 108 AcpiGbl_RootNode = &AcpiGbl_RootNodeStruct; 109 110 /* Enter the predefined names in the name table */ 111 112 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 113 "Entering predefined entries into namespace\n")); 114 115 /* 116 * Create the initial (default) namespace. 117 * This namespace looks like something similar to this: 118 * 119 * ACPI Namespace (from Namespace Root): 120 * 0 _GPE Scope 00203160 00 121 * 0 _PR_ Scope 002031D0 00 122 * 0 _SB_ Device 00203240 00 Notify Object: 0020ADD8 123 * 0 _SI_ Scope 002032B0 00 124 * 0 _TZ_ Device 00203320 00 125 * 0 _REV Integer 00203390 00 = 0000000000000002 126 * 0 _OS_ String 00203488 00 Len 14 "Microsoft Windows NT" 127 * 0 _GL_ Mutex 00203580 00 Object 002035F0 128 * 0 _OSI Method 00203678 00 Args 1 Len 0000 Aml 00000000 129 */ 130 for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++) 131 { 132 Status = AE_OK; 133 134 /* _OSI is optional for now, will be permanent later */ 135 136 if (!strcmp (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod) 137 { 138 continue; 139 } 140 141 /* 142 * Create, init, and link the new predefined name 143 * Note: No need to use AcpiNsLookup here because all the 144 * predefined names are at the root level. It is much easier to 145 * just create and link the new node(s) here. 146 */ 147 memcpy(&Name, InitVal->Name, sizeof(Name)); 148 NewNode = AcpiNsCreateNode (Name); 149 if (!NewNode) 150 { 151 Status = AE_NO_MEMORY; 152 goto UnlockAndExit; 153 } 154 155 NewNode->DescriptorType = ACPI_DESC_TYPE_NAMED; 156 NewNode->Type = InitVal->Type; 157 158 if (!PrevNode) 159 { 160 AcpiGbl_RootNodeStruct.Child = NewNode; 161 } 162 else 163 { 164 PrevNode->Peer = NewNode; 165 } 166 167 NewNode->Parent = &AcpiGbl_RootNodeStruct; 168 PrevNode = NewNode; 169 170 /* 171 * Name entered successfully. If entry in PreDefinedNames[] specifies 172 * an initial value, create the initial value. 173 */ 174 if (InitVal->Val) 175 { 176 Status = AcpiOsPredefinedOverride (InitVal, &Val); 177 if (ACPI_FAILURE (Status)) 178 { 179 ACPI_ERROR ((AE_INFO, 180 "Could not override predefined %s", 181 InitVal->Name)); 182 } 183 184 if (!Val) 185 { 186 Val = __UNCONST(InitVal->Val); 187 } 188 189 /* 190 * Entry requests an initial value, allocate a 191 * descriptor for it. 192 */ 193 ObjDesc = AcpiUtCreateInternalObject (InitVal->Type); 194 if (!ObjDesc) 195 { 196 Status = AE_NO_MEMORY; 197 goto UnlockAndExit; 198 } 199 200 /* 201 * Convert value string from table entry to 202 * internal representation. Only types actually 203 * used for initial values are implemented here. 204 */ 205 switch (InitVal->Type) 206 { 207 case ACPI_TYPE_METHOD: 208 209 ObjDesc->Method.ParamCount = (UINT8) ACPI_TO_INTEGER (Val); 210 ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; 211 212 #if defined (ACPI_ASL_COMPILER) 213 214 /* Save the parameter count for the iASL compiler */ 215 216 NewNode->Value = ObjDesc->Method.ParamCount; 217 #else 218 /* Mark this as a very SPECIAL method (_OSI) */ 219 220 ObjDesc->Method.InfoFlags = ACPI_METHOD_INTERNAL_ONLY; 221 ObjDesc->Method.Dispatch.Implementation = AcpiUtOsiImplementation; 222 #endif 223 break; 224 225 case ACPI_TYPE_INTEGER: 226 227 ObjDesc->Integer.Value = ACPI_TO_INTEGER (Val); 228 break; 229 230 case ACPI_TYPE_STRING: 231 232 /* Build an object around the static string */ 233 234 ObjDesc->String.Length = (UINT32) strlen (Val); 235 ObjDesc->String.Pointer = Val; 236 ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER; 237 break; 238 239 case ACPI_TYPE_MUTEX: 240 241 ObjDesc->Mutex.Node = NewNode; 242 ObjDesc->Mutex.SyncLevel = (UINT8) (ACPI_TO_INTEGER (Val) - 1); 243 244 /* Create a mutex */ 245 246 Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex); 247 if (ACPI_FAILURE (Status)) 248 { 249 AcpiUtRemoveReference (ObjDesc); 250 goto UnlockAndExit; 251 } 252 253 /* Special case for ACPI Global Lock */ 254 255 if (strcmp (InitVal->Name, "_GL_") == 0) 256 { 257 AcpiGbl_GlobalLockMutex = ObjDesc; 258 259 /* Create additional counting semaphore for global lock */ 260 261 Status = AcpiOsCreateSemaphore ( 262 1, 0, &AcpiGbl_GlobalLockSemaphore); 263 if (ACPI_FAILURE (Status)) 264 { 265 AcpiUtRemoveReference (ObjDesc); 266 goto UnlockAndExit; 267 } 268 } 269 break; 270 271 default: 272 273 ACPI_ERROR ((AE_INFO, "Unsupported initial type value 0x%X", 274 InitVal->Type)); 275 AcpiUtRemoveReference (ObjDesc); 276 ObjDesc = NULL; 277 continue; 278 } 279 280 /* Store pointer to value descriptor in the Node */ 281 282 Status = AcpiNsAttachObject (NewNode, ObjDesc, 283 ObjDesc->Common.Type); 284 285 /* Remove local reference to the object */ 286 287 AcpiUtRemoveReference (ObjDesc); 288 } 289 } 290 291 UnlockAndExit: 292 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 293 294 /* Save a handle to "_GPE", it is always present */ 295 296 if (ACPI_SUCCESS (Status)) 297 { 298 Status = AcpiNsGetNode (NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, 299 &AcpiGbl_FadtGpeDevice); 300 } 301 302 return_ACPI_STATUS (Status); 303 } 304 305 306 /******************************************************************************* 307 * 308 * FUNCTION: AcpiNsLookup 309 * 310 * PARAMETERS: ScopeInfo - Current scope info block 311 * Pathname - Search pathname, in internal format 312 * (as represented in the AML stream) 313 * Type - Type associated with name 314 * InterpreterMode - IMODE_LOAD_PASS2 => add name if not found 315 * Flags - Flags describing the search restrictions 316 * WalkState - Current state of the walk 317 * ReturnNode - Where the Node is placed (if found 318 * or created successfully) 319 * 320 * RETURN: Status 321 * 322 * DESCRIPTION: Find or enter the passed name in the name space. 323 * Log an error if name not found in Exec mode. 324 * 325 * MUTEX: Assumes namespace is locked. 326 * 327 ******************************************************************************/ 328 329 ACPI_STATUS 330 AcpiNsLookup ( 331 ACPI_GENERIC_STATE *ScopeInfo, 332 char *Pathname, 333 ACPI_OBJECT_TYPE Type, 334 ACPI_INTERPRETER_MODE InterpreterMode, 335 UINT32 Flags, 336 ACPI_WALK_STATE *WalkState, 337 ACPI_NAMESPACE_NODE **ReturnNode) 338 { 339 ACPI_STATUS Status; 340 char *Path = Pathname; 341 char *ExternalPath; 342 ACPI_NAMESPACE_NODE *PrefixNode; 343 ACPI_NAMESPACE_NODE *CurrentNode = NULL; 344 ACPI_NAMESPACE_NODE *ThisNode = NULL; 345 UINT32 NumSegments; 346 UINT32 NumCarats; 347 ACPI_NAME SimpleName; 348 ACPI_OBJECT_TYPE TypeToCheckFor; 349 ACPI_OBJECT_TYPE ThisSearchType; 350 UINT32 SearchParentFlag = ACPI_NS_SEARCH_PARENT; 351 UINT32 LocalFlags; 352 ACPI_INTERPRETER_MODE LocalInterpreterMode; 353 354 355 ACPI_FUNCTION_TRACE (NsLookup); 356 357 358 if (!ReturnNode) 359 { 360 return_ACPI_STATUS (AE_BAD_PARAMETER); 361 } 362 363 LocalFlags = Flags & 364 ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_OVERRIDE_IF_FOUND | 365 ACPI_NS_SEARCH_PARENT); 366 *ReturnNode = ACPI_ENTRY_NOT_FOUND; 367 AcpiGbl_NsLookupCount++; 368 369 if (!AcpiGbl_RootNode) 370 { 371 return_ACPI_STATUS (AE_NO_NAMESPACE); 372 } 373 374 /* Get the prefix scope. A null scope means use the root scope */ 375 376 if ((!ScopeInfo) || 377 (!ScopeInfo->Scope.Node)) 378 { 379 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 380 "Null scope prefix, using root node (%p)\n", 381 AcpiGbl_RootNode)); 382 383 PrefixNode = AcpiGbl_RootNode; 384 } 385 else 386 { 387 PrefixNode = ScopeInfo->Scope.Node; 388 if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED) 389 { 390 ACPI_ERROR ((AE_INFO, "%p is not a namespace node [%s]", 391 PrefixNode, AcpiUtGetDescriptorName (PrefixNode))); 392 return_ACPI_STATUS (AE_AML_INTERNAL); 393 } 394 395 if (!(Flags & ACPI_NS_PREFIX_IS_SCOPE)) 396 { 397 /* 398 * This node might not be a actual "scope" node (such as a 399 * Device/Method, etc.) It could be a Package or other object 400 * node. Backup up the tree to find the containing scope node. 401 */ 402 while (!AcpiNsOpensScope (PrefixNode->Type) && 403 PrefixNode->Type != ACPI_TYPE_ANY) 404 { 405 PrefixNode = PrefixNode->Parent; 406 } 407 } 408 } 409 410 /* Save type. TBD: may be no longer necessary */ 411 412 TypeToCheckFor = Type; 413 414 /* 415 * Begin examination of the actual pathname 416 */ 417 if (!Pathname) 418 { 419 /* A Null NamePath is allowed and refers to the root */ 420 421 NumSegments = 0; 422 ThisNode = AcpiGbl_RootNode; 423 Path = __UNCONST(""); 424 425 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 426 "Null Pathname (Zero segments), Flags=%X\n", Flags)); 427 } 428 else 429 { 430 /* 431 * Name pointer is valid (and must be in internal name format) 432 * 433 * Check for scope prefixes: 434 * 435 * As represented in the AML stream, a namepath consists of an 436 * optional scope prefix followed by a name segment part. 437 * 438 * If present, the scope prefix is either a Root Prefix (in 439 * which case the name is fully qualified), or one or more 440 * Parent Prefixes (in which case the name's scope is relative 441 * to the current scope). 442 */ 443 if (*Path == (UINT8) AML_ROOT_PREFIX) 444 { 445 /* Pathname is fully qualified, start from the root */ 446 447 ThisNode = AcpiGbl_RootNode; 448 SearchParentFlag = ACPI_NS_NO_UPSEARCH; 449 450 /* Point to name segment part */ 451 452 Path++; 453 454 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 455 "Path is absolute from root [%p]\n", ThisNode)); 456 } 457 else 458 { 459 /* Pathname is relative to current scope, start there */ 460 461 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 462 "Searching relative to prefix scope [%4.4s] (%p)\n", 463 AcpiUtGetNodeName (PrefixNode), PrefixNode)); 464 465 /* 466 * Handle multiple Parent Prefixes (carat) by just getting 467 * the parent node for each prefix instance. 468 */ 469 ThisNode = PrefixNode; 470 NumCarats = 0; 471 while (*Path == (UINT8) AML_PARENT_PREFIX) 472 { 473 /* Name is fully qualified, no search rules apply */ 474 475 SearchParentFlag = ACPI_NS_NO_UPSEARCH; 476 477 /* 478 * Point past this prefix to the name segment 479 * part or the next Parent Prefix 480 */ 481 Path++; 482 483 /* Backup to the parent node */ 484 485 NumCarats++; 486 ThisNode = ThisNode->Parent; 487 if (!ThisNode) 488 { 489 /* 490 * Current scope has no parent scope. Externalize 491 * the internal path for error message. 492 */ 493 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Pathname, 494 NULL, &ExternalPath); 495 if (ACPI_SUCCESS (Status)) 496 { 497 ACPI_ERROR ((AE_INFO, 498 "%s: Path has too many parent prefixes (^)", 499 ExternalPath)); 500 501 ACPI_FREE (ExternalPath); 502 } 503 504 return_ACPI_STATUS (AE_NOT_FOUND); 505 } 506 } 507 508 if (SearchParentFlag == ACPI_NS_NO_UPSEARCH) 509 { 510 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 511 "Search scope is [%4.4s], path has %u carat(s)\n", 512 AcpiUtGetNodeName (ThisNode), NumCarats)); 513 } 514 } 515 516 /* 517 * Determine the number of ACPI name segments in this pathname. 518 * 519 * The segment part consists of either: 520 * - A Null name segment (0) 521 * - A DualNamePrefix followed by two 4-byte name segments 522 * - A MultiNamePrefix followed by a byte indicating the 523 * number of segments and the segments themselves. 524 * - A single 4-byte name segment 525 * 526 * Examine the name prefix opcode, if any, to determine the number of 527 * segments. 528 */ 529 switch (*Path) 530 { 531 case 0: 532 /* 533 * Null name after a root or parent prefixes. We already 534 * have the correct target node and there are no name segments. 535 */ 536 NumSegments = 0; 537 Type = ThisNode->Type; 538 539 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 540 "Prefix-only Pathname (Zero name segments), Flags=%X\n", 541 Flags)); 542 break; 543 544 case AML_DUAL_NAME_PREFIX: 545 546 /* More than one NameSeg, search rules do not apply */ 547 548 SearchParentFlag = ACPI_NS_NO_UPSEARCH; 549 550 /* Two segments, point to first name segment */ 551 552 NumSegments = 2; 553 Path++; 554 555 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 556 "Dual Pathname (2 segments, Flags=%X)\n", Flags)); 557 break; 558 559 case AML_MULTI_NAME_PREFIX: 560 561 /* More than one NameSeg, search rules do not apply */ 562 563 SearchParentFlag = ACPI_NS_NO_UPSEARCH; 564 565 /* Extract segment count, point to first name segment */ 566 567 Path++; 568 NumSegments = (UINT32) (UINT8) *Path; 569 Path++; 570 571 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 572 "Multi Pathname (%u Segments, Flags=%X)\n", 573 NumSegments, Flags)); 574 break; 575 576 default: 577 /* 578 * Not a Null name, no Dual or Multi prefix, hence there is 579 * only one name segment and Pathname is already pointing to it. 580 */ 581 NumSegments = 1; 582 583 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 584 "Simple Pathname (1 segment, Flags=%X)\n", Flags)); 585 break; 586 } 587 588 ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path)); 589 } 590 591 592 /* 593 * Search namespace for each segment of the name. Loop through and 594 * verify (or add to the namespace) each name segment. 595 * 596 * The object type is significant only at the last name 597 * segment. (We don't care about the types along the path, only 598 * the type of the final target object.) 599 */ 600 ThisSearchType = ACPI_TYPE_ANY; 601 CurrentNode = ThisNode; 602 603 while (NumSegments && CurrentNode) 604 { 605 NumSegments--; 606 if (!NumSegments) 607 { 608 /* This is the last segment, enable typechecking */ 609 610 ThisSearchType = Type; 611 612 /* 613 * Only allow automatic parent search (search rules) if the caller 614 * requested it AND we have a single, non-fully-qualified NameSeg 615 */ 616 if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) && 617 (Flags & ACPI_NS_SEARCH_PARENT)) 618 { 619 LocalFlags |= ACPI_NS_SEARCH_PARENT; 620 } 621 622 /* Set error flag according to caller */ 623 624 if (Flags & ACPI_NS_ERROR_IF_FOUND) 625 { 626 LocalFlags |= ACPI_NS_ERROR_IF_FOUND; 627 } 628 629 /* Set override flag according to caller */ 630 631 if (Flags & ACPI_NS_OVERRIDE_IF_FOUND) 632 { 633 LocalFlags |= ACPI_NS_OVERRIDE_IF_FOUND; 634 } 635 } 636 637 /* Handle opcodes that create a new NameSeg via a full NamePath */ 638 639 LocalInterpreterMode = InterpreterMode; 640 if ((Flags & ACPI_NS_PREFIX_MUST_EXIST) && (NumSegments > 0)) 641 { 642 /* Every element of the path must exist (except for the final NameSeg) */ 643 644 LocalInterpreterMode = ACPI_IMODE_EXECUTE; 645 } 646 647 /* Extract one ACPI name from the front of the pathname */ 648 649 ACPI_MOVE_32_TO_32 (&SimpleName, Path); 650 651 /* Try to find the single (4 character) ACPI name */ 652 653 Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode, 654 LocalInterpreterMode, ThisSearchType, LocalFlags, &ThisNode); 655 if (ACPI_FAILURE (Status)) 656 { 657 if (Status == AE_NOT_FOUND) 658 { 659 #if !defined ACPI_ASL_COMPILER /* Note: iASL reports this error by itself, not needed here */ 660 if (Flags & ACPI_NS_PREFIX_MUST_EXIST) 661 { 662 AcpiOsPrintf (ACPI_MSG_BIOS_ERROR 663 "Object does not exist: %4.4s\n", (char *) &SimpleName); 664 } 665 #endif 666 /* Name not found in ACPI namespace */ 667 668 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 669 "Name [%4.4s] not found in scope [%4.4s] %p\n", 670 (char *) &SimpleName, (char *) &CurrentNode->Name, 671 CurrentNode)); 672 } 673 674 #ifdef ACPI_EXEC_APP 675 if ((Status == AE_ALREADY_EXISTS) && 676 (ThisNode->Flags & ANOBJ_NODE_EARLY_INIT)) 677 { 678 ThisNode->Flags &= ~ANOBJ_NODE_EARLY_INIT; 679 Status = AE_OK; 680 } 681 #endif 682 683 #ifdef ACPI_ASL_COMPILER 684 /* 685 * If this ACPI name already exists within the namespace as an 686 * external declaration, then mark the external as a conflicting 687 * declaration and proceed to process the current node as if it did 688 * not exist in the namespace. If this node is not processed as 689 * normal, then it could cause improper namespace resolution 690 * by failing to open a new scope. 691 */ 692 if (AcpiGbl_DisasmFlag && 693 (Status == AE_ALREADY_EXISTS) && 694 ((ThisNode->Flags & ANOBJ_IS_EXTERNAL) || 695 (WalkState && WalkState->Opcode == AML_EXTERNAL_OP))) 696 { 697 ThisNode->Flags &= ~ANOBJ_IS_EXTERNAL; 698 ThisNode->Type = (UINT8)ThisSearchType; 699 if (WalkState->Opcode != AML_EXTERNAL_OP) 700 { 701 AcpiDmMarkExternalConflict (ThisNode); 702 } 703 break; 704 } 705 #endif 706 707 *ReturnNode = ThisNode; 708 return_ACPI_STATUS (Status); 709 } 710 711 /* More segments to follow? */ 712 713 if (NumSegments > 0) 714 { 715 /* 716 * If we have an alias to an object that opens a scope (such as a 717 * device or processor), we need to dereference the alias here so 718 * that we can access any children of the original node (via the 719 * remaining segments). 720 */ 721 if (ThisNode->Type == ACPI_TYPE_LOCAL_ALIAS) 722 { 723 if (!ThisNode->Object) 724 { 725 return_ACPI_STATUS (AE_NOT_EXIST); 726 } 727 728 if (AcpiNsOpensScope (((ACPI_NAMESPACE_NODE *) 729 ThisNode->Object)->Type)) 730 { 731 ThisNode = (ACPI_NAMESPACE_NODE *) ThisNode->Object; 732 } 733 } 734 } 735 736 /* Special handling for the last segment (NumSegments == 0) */ 737 738 else 739 { 740 /* 741 * Sanity typecheck of the target object: 742 * 743 * If 1) This is the last segment (NumSegments == 0) 744 * 2) And we are looking for a specific type 745 * (Not checking for TYPE_ANY) 746 * 3) Which is not an alias 747 * 4) Which is not a local type (TYPE_SCOPE) 748 * 5) And the type of target object is known (not TYPE_ANY) 749 * 6) And target object does not match what we are looking for 750 * 751 * Then we have a type mismatch. Just warn and ignore it. 752 */ 753 if ((TypeToCheckFor != ACPI_TYPE_ANY) && 754 (TypeToCheckFor != ACPI_TYPE_LOCAL_ALIAS) && 755 (TypeToCheckFor != ACPI_TYPE_LOCAL_METHOD_ALIAS) && 756 (TypeToCheckFor != ACPI_TYPE_LOCAL_SCOPE) && 757 (ThisNode->Type != ACPI_TYPE_ANY) && 758 (ThisNode->Type != TypeToCheckFor)) 759 { 760 /* Complain about a type mismatch */ 761 762 ACPI_WARNING ((AE_INFO, 763 "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", 764 ACPI_CAST_PTR (char, &SimpleName), 765 AcpiUtGetTypeName (ThisNode->Type), 766 AcpiUtGetTypeName (TypeToCheckFor))); 767 } 768 769 /* 770 * If this is the last name segment and we are not looking for a 771 * specific type, but the type of found object is known, use that 772 * type to (later) see if it opens a scope. 773 */ 774 if (Type == ACPI_TYPE_ANY) 775 { 776 Type = ThisNode->Type; 777 } 778 } 779 780 /* Point to next name segment and make this node current */ 781 782 Path += ACPI_NAMESEG_SIZE; 783 CurrentNode = ThisNode; 784 } 785 786 /* Always check if we need to open a new scope */ 787 788 if (!(Flags & ACPI_NS_DONT_OPEN_SCOPE) && (WalkState)) 789 { 790 /* 791 * If entry is a type which opens a scope, push the new scope on the 792 * scope stack. 793 */ 794 if (AcpiNsOpensScope (Type)) 795 { 796 Status = AcpiDsScopeStackPush (ThisNode, Type, WalkState); 797 if (ACPI_FAILURE (Status)) 798 { 799 return_ACPI_STATUS (Status); 800 } 801 } 802 } 803 804 #ifdef ACPI_EXEC_APP 805 if (Flags & ACPI_NS_EARLY_INIT) 806 { 807 ThisNode->Flags |= ANOBJ_NODE_EARLY_INIT; 808 } 809 #endif 810 811 *ReturnNode = ThisNode; 812 return_ACPI_STATUS (AE_OK); 813 } 814