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