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