1 /****************************************************************************** 2 * 3 * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing 4 * parents and siblings and Scope manipulation 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2011, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #define __NSUTILS_C__ 46 47 #include "acpi.h" 48 #include "accommon.h" 49 #include "acnamesp.h" 50 #include "amlcode.h" 51 52 #define _COMPONENT ACPI_NAMESPACE 53 ACPI_MODULE_NAME ("nsutils") 54 55 /* Local prototypes */ 56 57 static BOOLEAN 58 AcpiNsValidPathSeparator ( 59 char Sep); 60 61 #ifdef ACPI_OBSOLETE_FUNCTIONS 62 ACPI_NAME 63 AcpiNsFindParentName ( 64 ACPI_NAMESPACE_NODE *NodeToSearch); 65 #endif 66 67 68 /******************************************************************************* 69 * 70 * FUNCTION: AcpiNsPrintNodePathname 71 * 72 * PARAMETERS: Node - Object 73 * Message - Prefix message 74 * 75 * DESCRIPTION: Print an object's full namespace pathname 76 * Manages allocation/freeing of a pathname buffer 77 * 78 ******************************************************************************/ 79 80 void 81 AcpiNsPrintNodePathname ( 82 ACPI_NAMESPACE_NODE *Node, 83 const char *Message) 84 { 85 ACPI_BUFFER Buffer; 86 ACPI_STATUS Status; 87 88 89 if (!Node) 90 { 91 AcpiOsPrintf ("[NULL NAME]"); 92 return; 93 } 94 95 /* Convert handle to full pathname and print it (with supplied message) */ 96 97 Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 98 99 Status = AcpiNsHandleToPathname (Node, &Buffer); 100 if (ACPI_SUCCESS (Status)) 101 { 102 if (Message) 103 { 104 AcpiOsPrintf ("%s ", Message); 105 } 106 107 AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node); 108 ACPI_FREE (Buffer.Pointer); 109 } 110 } 111 112 113 /******************************************************************************* 114 * 115 * FUNCTION: AcpiNsValidRootPrefix 116 * 117 * PARAMETERS: Prefix - Character to be checked 118 * 119 * RETURN: TRUE if a valid prefix 120 * 121 * DESCRIPTION: Check if a character is a valid ACPI Root prefix 122 * 123 ******************************************************************************/ 124 125 BOOLEAN 126 AcpiNsValidRootPrefix ( 127 char Prefix) 128 { 129 130 return ((BOOLEAN) (Prefix == '\\')); 131 } 132 133 134 /******************************************************************************* 135 * 136 * FUNCTION: AcpiNsValidPathSeparator 137 * 138 * PARAMETERS: Sep - Character to be checked 139 * 140 * RETURN: TRUE if a valid path separator 141 * 142 * DESCRIPTION: Check if a character is a valid ACPI path separator 143 * 144 ******************************************************************************/ 145 146 static BOOLEAN 147 AcpiNsValidPathSeparator ( 148 char Sep) 149 { 150 151 return ((BOOLEAN) (Sep == '.')); 152 } 153 154 155 /******************************************************************************* 156 * 157 * FUNCTION: AcpiNsGetType 158 * 159 * PARAMETERS: Node - Parent Node to be examined 160 * 161 * RETURN: Type field from Node whose handle is passed 162 * 163 * DESCRIPTION: Return the type of a Namespace node 164 * 165 ******************************************************************************/ 166 167 ACPI_OBJECT_TYPE 168 AcpiNsGetType ( 169 ACPI_NAMESPACE_NODE *Node) 170 { 171 ACPI_FUNCTION_TRACE (NsGetType); 172 173 174 if (!Node) 175 { 176 ACPI_WARNING ((AE_INFO, "Null Node parameter")); 177 return_UINT32 (ACPI_TYPE_ANY); 178 } 179 180 return_UINT32 ((ACPI_OBJECT_TYPE) Node->Type); 181 } 182 183 184 /******************************************************************************* 185 * 186 * FUNCTION: AcpiNsLocal 187 * 188 * PARAMETERS: Type - A namespace object type 189 * 190 * RETURN: LOCAL if names must be found locally in objects of the 191 * passed type, 0 if enclosing scopes should be searched 192 * 193 * DESCRIPTION: Returns scope rule for the given object type. 194 * 195 ******************************************************************************/ 196 197 UINT32 198 AcpiNsLocal ( 199 ACPI_OBJECT_TYPE Type) 200 { 201 ACPI_FUNCTION_TRACE (NsLocal); 202 203 204 if (!AcpiUtValidObjectType (Type)) 205 { 206 /* Type code out of range */ 207 208 ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type)); 209 return_UINT32 (ACPI_NS_NORMAL); 210 } 211 212 return_UINT32 ((UINT32) AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL); 213 } 214 215 216 /******************************************************************************* 217 * 218 * FUNCTION: AcpiNsGetInternalNameLength 219 * 220 * PARAMETERS: Info - Info struct initialized with the 221 * external name pointer. 222 * 223 * RETURN: None 224 * 225 * DESCRIPTION: Calculate the length of the internal (AML) namestring 226 * corresponding to the external (ASL) namestring. 227 * 228 ******************************************************************************/ 229 230 void 231 AcpiNsGetInternalNameLength ( 232 ACPI_NAMESTRING_INFO *Info) 233 { 234 const char *NextExternalChar; 235 UINT32 i; 236 237 238 ACPI_FUNCTION_ENTRY (); 239 240 241 NextExternalChar = Info->ExternalName; 242 Info->NumCarats = 0; 243 Info->NumSegments = 0; 244 Info->FullyQualified = FALSE; 245 246 /* 247 * For the internal name, the required length is 4 bytes per segment, plus 248 * 1 each for RootPrefix, MultiNamePrefixOp, segment count, trailing null 249 * (which is not really needed, but no there's harm in putting it there) 250 * 251 * strlen() + 1 covers the first NameSeg, which has no path separator 252 */ 253 if (AcpiNsValidRootPrefix (*NextExternalChar)) 254 { 255 Info->FullyQualified = TRUE; 256 NextExternalChar++; 257 258 /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */ 259 260 while (AcpiNsValidRootPrefix (*NextExternalChar)) 261 { 262 NextExternalChar++; 263 } 264 } 265 else 266 { 267 /* Handle Carat prefixes */ 268 269 while (*NextExternalChar == '^') 270 { 271 Info->NumCarats++; 272 NextExternalChar++; 273 } 274 } 275 276 /* 277 * Determine the number of ACPI name "segments" by counting the number of 278 * path separators within the string. Start with one segment since the 279 * segment count is [(# separators) + 1], and zero separators is ok. 280 */ 281 if (*NextExternalChar) 282 { 283 Info->NumSegments = 1; 284 for (i = 0; NextExternalChar[i]; i++) 285 { 286 if (AcpiNsValidPathSeparator (NextExternalChar[i])) 287 { 288 Info->NumSegments++; 289 } 290 } 291 } 292 293 Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) + 294 4 + Info->NumCarats; 295 296 Info->NextExternalChar = NextExternalChar; 297 } 298 299 300 /******************************************************************************* 301 * 302 * FUNCTION: AcpiNsBuildInternalName 303 * 304 * PARAMETERS: Info - Info struct fully initialized 305 * 306 * RETURN: Status 307 * 308 * DESCRIPTION: Construct the internal (AML) namestring 309 * corresponding to the external (ASL) namestring. 310 * 311 ******************************************************************************/ 312 313 ACPI_STATUS 314 AcpiNsBuildInternalName ( 315 ACPI_NAMESTRING_INFO *Info) 316 { 317 UINT32 NumSegments = Info->NumSegments; 318 char *InternalName = Info->InternalName; 319 const char *ExternalName = Info->NextExternalChar; 320 char *Result = NULL; 321 UINT32 i; 322 323 324 ACPI_FUNCTION_TRACE (NsBuildInternalName); 325 326 327 /* Setup the correct prefixes, counts, and pointers */ 328 329 if (Info->FullyQualified) 330 { 331 InternalName[0] = '\\'; 332 333 if (NumSegments <= 1) 334 { 335 Result = &InternalName[1]; 336 } 337 else if (NumSegments == 2) 338 { 339 InternalName[1] = AML_DUAL_NAME_PREFIX; 340 Result = &InternalName[2]; 341 } 342 else 343 { 344 InternalName[1] = AML_MULTI_NAME_PREFIX_OP; 345 InternalName[2] = (char) NumSegments; 346 Result = &InternalName[3]; 347 } 348 } 349 else 350 { 351 /* 352 * Not fully qualified. 353 * Handle Carats first, then append the name segments 354 */ 355 i = 0; 356 if (Info->NumCarats) 357 { 358 for (i = 0; i < Info->NumCarats; i++) 359 { 360 InternalName[i] = '^'; 361 } 362 } 363 364 if (NumSegments <= 1) 365 { 366 Result = &InternalName[i]; 367 } 368 else if (NumSegments == 2) 369 { 370 InternalName[i] = AML_DUAL_NAME_PREFIX; 371 Result = &InternalName[(ACPI_SIZE) i+1]; 372 } 373 else 374 { 375 InternalName[i] = AML_MULTI_NAME_PREFIX_OP; 376 InternalName[(ACPI_SIZE) i+1] = (char) NumSegments; 377 Result = &InternalName[(ACPI_SIZE) i+2]; 378 } 379 } 380 381 /* Build the name (minus path separators) */ 382 383 for (; NumSegments; NumSegments--) 384 { 385 for (i = 0; i < ACPI_NAME_SIZE; i++) 386 { 387 if (AcpiNsValidPathSeparator (*ExternalName) || 388 (*ExternalName == 0)) 389 { 390 /* Pad the segment with underscore(s) if segment is short */ 391 392 Result[i] = '_'; 393 } 394 else 395 { 396 /* Convert the character to uppercase and save it */ 397 398 Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName); 399 ExternalName++; 400 } 401 } 402 403 /* Now we must have a path separator, or the pathname is bad */ 404 405 if (!AcpiNsValidPathSeparator (*ExternalName) && 406 (*ExternalName != 0)) 407 { 408 return_ACPI_STATUS (AE_BAD_PARAMETER); 409 } 410 411 /* Move on the next segment */ 412 413 ExternalName++; 414 Result += ACPI_NAME_SIZE; 415 } 416 417 /* Terminate the string */ 418 419 *Result = 0; 420 421 if (Info->FullyQualified) 422 { 423 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n", 424 InternalName, InternalName)); 425 } 426 else 427 { 428 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n", 429 InternalName, InternalName)); 430 } 431 432 return_ACPI_STATUS (AE_OK); 433 } 434 435 436 /******************************************************************************* 437 * 438 * FUNCTION: AcpiNsInternalizeName 439 * 440 * PARAMETERS: *ExternalName - External representation of name 441 * **Converted Name - Where to return the resulting 442 * internal represention of the name 443 * 444 * RETURN: Status 445 * 446 * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") 447 * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 448 * 449 *******************************************************************************/ 450 451 ACPI_STATUS 452 AcpiNsInternalizeName ( 453 const char *ExternalName, 454 char **ConvertedName) 455 { 456 char *InternalName; 457 ACPI_NAMESTRING_INFO Info; 458 ACPI_STATUS Status; 459 460 461 ACPI_FUNCTION_TRACE (NsInternalizeName); 462 463 464 if ((!ExternalName) || 465 (*ExternalName == 0) || 466 (!ConvertedName)) 467 { 468 return_ACPI_STATUS (AE_BAD_PARAMETER); 469 } 470 471 /* Get the length of the new internal name */ 472 473 Info.ExternalName = ExternalName; 474 AcpiNsGetInternalNameLength (&Info); 475 476 /* We need a segment to store the internal name */ 477 478 InternalName = ACPI_ALLOCATE_ZEROED (Info.Length); 479 if (!InternalName) 480 { 481 return_ACPI_STATUS (AE_NO_MEMORY); 482 } 483 484 /* Build the name */ 485 486 Info.InternalName = InternalName; 487 Status = AcpiNsBuildInternalName (&Info); 488 if (ACPI_FAILURE (Status)) 489 { 490 ACPI_FREE (InternalName); 491 return_ACPI_STATUS (Status); 492 } 493 494 *ConvertedName = InternalName; 495 return_ACPI_STATUS (AE_OK); 496 } 497 498 499 /******************************************************************************* 500 * 501 * FUNCTION: AcpiNsExternalizeName 502 * 503 * PARAMETERS: InternalNameLength - Lenth of the internal name below 504 * InternalName - Internal representation of name 505 * ConvertedNameLength - Where the length is returned 506 * ConvertedName - Where the resulting external name 507 * is returned 508 * 509 * RETURN: Status 510 * 511 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 512 * to its external (printable) form (e.g. "\_PR_.CPU0") 513 * 514 ******************************************************************************/ 515 516 ACPI_STATUS 517 AcpiNsExternalizeName ( 518 UINT32 InternalNameLength, 519 const char *InternalName, 520 UINT32 *ConvertedNameLength, 521 char **ConvertedName) 522 { 523 UINT32 NamesIndex = 0; 524 UINT32 NumSegments = 0; 525 UINT32 RequiredLength; 526 UINT32 PrefixLength = 0; 527 UINT32 i = 0; 528 UINT32 j = 0; 529 530 531 ACPI_FUNCTION_TRACE (NsExternalizeName); 532 533 534 if (!InternalNameLength || 535 !InternalName || 536 !ConvertedName) 537 { 538 return_ACPI_STATUS (AE_BAD_PARAMETER); 539 } 540 541 /* Check for a prefix (one '\' | one or more '^') */ 542 543 switch (InternalName[0]) 544 { 545 case '\\': 546 PrefixLength = 1; 547 break; 548 549 case '^': 550 for (i = 0; i < InternalNameLength; i++) 551 { 552 if (InternalName[i] == '^') 553 { 554 PrefixLength = i + 1; 555 } 556 else 557 { 558 break; 559 } 560 } 561 562 if (i == InternalNameLength) 563 { 564 PrefixLength = i; 565 } 566 567 break; 568 569 default: 570 break; 571 } 572 573 /* 574 * Check for object names. Note that there could be 0-255 of these 575 * 4-byte elements. 576 */ 577 if (PrefixLength < InternalNameLength) 578 { 579 switch (InternalName[PrefixLength]) 580 { 581 case AML_MULTI_NAME_PREFIX_OP: 582 583 /* <count> 4-byte names */ 584 585 NamesIndex = PrefixLength + 2; 586 NumSegments = (UINT8) 587 InternalName[(ACPI_SIZE) PrefixLength + 1]; 588 break; 589 590 case AML_DUAL_NAME_PREFIX: 591 592 /* Two 4-byte names */ 593 594 NamesIndex = PrefixLength + 1; 595 NumSegments = 2; 596 break; 597 598 case 0: 599 600 /* NullName */ 601 602 NamesIndex = 0; 603 NumSegments = 0; 604 break; 605 606 default: 607 608 /* one 4-byte name */ 609 610 NamesIndex = PrefixLength; 611 NumSegments = 1; 612 break; 613 } 614 } 615 616 /* 617 * Calculate the length of ConvertedName, which equals the length 618 * of the prefix, length of all object names, length of any required 619 * punctuation ('.') between object names, plus the NULL terminator. 620 */ 621 RequiredLength = PrefixLength + (4 * NumSegments) + 622 ((NumSegments > 0) ? (NumSegments - 1) : 0) + 1; 623 624 /* 625 * Check to see if we're still in bounds. If not, there's a problem 626 * with InternalName (invalid format). 627 */ 628 if (RequiredLength > InternalNameLength) 629 { 630 ACPI_ERROR ((AE_INFO, "Invalid internal name")); 631 return_ACPI_STATUS (AE_BAD_PATHNAME); 632 } 633 634 /* Build the ConvertedName */ 635 636 *ConvertedName = ACPI_ALLOCATE_ZEROED (RequiredLength); 637 if (!(*ConvertedName)) 638 { 639 return_ACPI_STATUS (AE_NO_MEMORY); 640 } 641 642 j = 0; 643 644 for (i = 0; i < PrefixLength; i++) 645 { 646 (*ConvertedName)[j++] = InternalName[i]; 647 } 648 649 if (NumSegments > 0) 650 { 651 for (i = 0; i < NumSegments; i++) 652 { 653 if (i > 0) 654 { 655 (*ConvertedName)[j++] = '.'; 656 } 657 658 (*ConvertedName)[j++] = InternalName[NamesIndex++]; 659 (*ConvertedName)[j++] = InternalName[NamesIndex++]; 660 (*ConvertedName)[j++] = InternalName[NamesIndex++]; 661 (*ConvertedName)[j++] = InternalName[NamesIndex++]; 662 } 663 } 664 665 if (ConvertedNameLength) 666 { 667 *ConvertedNameLength = (UINT32) RequiredLength; 668 } 669 670 return_ACPI_STATUS (AE_OK); 671 } 672 673 674 /******************************************************************************* 675 * 676 * FUNCTION: AcpiNsValidateHandle 677 * 678 * PARAMETERS: Handle - Handle to be validated and typecast to a 679 * namespace node. 680 * 681 * RETURN: A pointer to a namespace node 682 * 683 * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special 684 * cases for the root node. 685 * 686 * NOTE: Real integer handles would allow for more verification 687 * and keep all pointers within this subsystem - however this introduces 688 * more overhead and has not been necessary to this point. Drivers 689 * holding handles are typically notified before a node becomes invalid 690 * due to a table unload. 691 * 692 ******************************************************************************/ 693 694 ACPI_NAMESPACE_NODE * 695 AcpiNsValidateHandle ( 696 ACPI_HANDLE Handle) 697 { 698 699 ACPI_FUNCTION_ENTRY (); 700 701 702 /* Parameter validation */ 703 704 if ((!Handle) || (Handle == ACPI_ROOT_OBJECT)) 705 { 706 return (AcpiGbl_RootNode); 707 } 708 709 /* We can at least attempt to verify the handle */ 710 711 if (ACPI_GET_DESCRIPTOR_TYPE (Handle) != ACPI_DESC_TYPE_NAMED) 712 { 713 return (NULL); 714 } 715 716 return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle)); 717 } 718 719 720 /******************************************************************************* 721 * 722 * FUNCTION: AcpiNsTerminate 723 * 724 * PARAMETERS: none 725 * 726 * RETURN: none 727 * 728 * DESCRIPTION: free memory allocated for namespace and ACPI table storage. 729 * 730 ******************************************************************************/ 731 732 void 733 AcpiNsTerminate ( 734 void) 735 { 736 ACPI_OPERAND_OBJECT *ObjDesc; 737 738 739 ACPI_FUNCTION_TRACE (NsTerminate); 740 741 742 /* 743 * 1) Free the entire namespace -- all nodes and objects 744 * 745 * Delete all object descriptors attached to namepsace nodes 746 */ 747 AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); 748 749 /* Detach any objects attached to the root */ 750 751 ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode); 752 if (ObjDesc) 753 { 754 AcpiNsDetachObject (AcpiGbl_RootNode); 755 } 756 757 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n")); 758 return_VOID; 759 } 760 761 762 /******************************************************************************* 763 * 764 * FUNCTION: AcpiNsOpensScope 765 * 766 * PARAMETERS: Type - A valid namespace type 767 * 768 * RETURN: NEWSCOPE if the passed type "opens a name scope" according 769 * to the ACPI specification, else 0 770 * 771 ******************************************************************************/ 772 773 UINT32 774 AcpiNsOpensScope ( 775 ACPI_OBJECT_TYPE Type) 776 { 777 ACPI_FUNCTION_TRACE_STR (NsOpensScope, AcpiUtGetTypeName (Type)); 778 779 780 if (!AcpiUtValidObjectType (Type)) 781 { 782 /* type code out of range */ 783 784 ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type)); 785 return_UINT32 (ACPI_NS_NORMAL); 786 } 787 788 return_UINT32 (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE); 789 } 790 791 792 /******************************************************************************* 793 * 794 * FUNCTION: AcpiNsGetNode 795 * 796 * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The 797 * \ (backslash) and ^ (carat) prefixes, and the 798 * . (period) to separate segments are supported. 799 * PrefixNode - Root of subtree to be searched, or NS_ALL for the 800 * root of the name space. If Name is fully 801 * qualified (first INT8 is '\'), the passed value 802 * of Scope will not be accessed. 803 * Flags - Used to indicate whether to perform upsearch or 804 * not. 805 * ReturnNode - Where the Node is returned 806 * 807 * DESCRIPTION: Look up a name relative to a given scope and return the 808 * corresponding Node. NOTE: Scope can be null. 809 * 810 * MUTEX: Locks namespace 811 * 812 ******************************************************************************/ 813 814 ACPI_STATUS 815 AcpiNsGetNode ( 816 ACPI_NAMESPACE_NODE *PrefixNode, 817 const char *Pathname, 818 UINT32 Flags, 819 ACPI_NAMESPACE_NODE **ReturnNode) 820 { 821 ACPI_GENERIC_STATE ScopeInfo; 822 ACPI_STATUS Status; 823 char *InternalPath; 824 825 826 ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname)); 827 828 829 if (!Pathname) 830 { 831 *ReturnNode = PrefixNode; 832 if (!PrefixNode) 833 { 834 *ReturnNode = AcpiGbl_RootNode; 835 } 836 return_ACPI_STATUS (AE_OK); 837 } 838 839 /* Convert path to internal representation */ 840 841 Status = AcpiNsInternalizeName (Pathname, &InternalPath); 842 if (ACPI_FAILURE (Status)) 843 { 844 return_ACPI_STATUS (Status); 845 } 846 847 /* Must lock namespace during lookup */ 848 849 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 850 if (ACPI_FAILURE (Status)) 851 { 852 goto Cleanup; 853 } 854 855 /* Setup lookup scope (search starting point) */ 856 857 ScopeInfo.Scope.Node = PrefixNode; 858 859 /* Lookup the name in the namespace */ 860 861 Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY, 862 ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE), 863 NULL, ReturnNode); 864 if (ACPI_FAILURE (Status)) 865 { 866 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n", 867 Pathname, AcpiFormatException (Status))); 868 } 869 870 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 871 872 Cleanup: 873 ACPI_FREE (InternalPath); 874 return_ACPI_STATUS (Status); 875 } 876