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 }