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