Home | History | Annotate | Line # | Download | only in namespace
nsutils.c revision 1.1
      1 /******************************************************************************
      2  *
      3  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
      4  *                        parents and siblings and Scope manipulation
      5  *
      6  *****************************************************************************/
      7 
      8 /******************************************************************************
      9  *
     10  * 1. Copyright Notice
     11  *
     12  * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
     13  * All rights reserved.
     14  *
     15  * 2. License
     16  *
     17  * 2.1. This is your license from Intel Corp. under its intellectual property
     18  * rights.  You may have additional license terms from the party that provided
     19  * you this software, covering your right to use that party's intellectual
     20  * property rights.
     21  *
     22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     23  * copy of the source code appearing in this file ("Covered Code") an
     24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     25  * base code distributed originally by Intel ("Original Intel Code") to copy,
     26  * make derivatives, distribute, use and display any portion of the Covered
     27  * Code in any form, with the right to sublicense such rights; and
     28  *
     29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     30  * license (with the right to sublicense), under only those claims of Intel
     31  * patents that are infringed by the Original Intel Code, to make, use, sell,
     32  * offer to sell, and import the Covered Code and derivative works thereof
     33  * solely to the minimum extent necessary to exercise the above copyright
     34  * license, and in no event shall the patent license extend to any additions
     35  * to or modifications of the Original Intel Code.  No other license or right
     36  * is granted directly or by implication, estoppel or otherwise;
     37  *
     38  * The above copyright and patent license is granted only if the following
     39  * conditions are met:
     40  *
     41  * 3. Conditions
     42  *
     43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     44  * Redistribution of source code of any substantial portion of the Covered
     45  * Code or modification with rights to further distribute source must include
     46  * the above Copyright Notice, the above License, this list of Conditions,
     47  * and the following Disclaimer and Export Compliance provision.  In addition,
     48  * Licensee must cause all Covered Code to which Licensee contributes to
     49  * contain a file documenting the changes Licensee made to create that Covered
     50  * Code and the date of any change.  Licensee must include in that file the
     51  * documentation of any changes made by any predecessor Licensee.  Licensee
     52  * must include a prominent statement that the modification is derived,
     53  * directly or indirectly, from Original Intel Code.
     54  *
     55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     56  * Redistribution of source code of any substantial portion of the Covered
     57  * Code or modification without rights to further distribute source must
     58  * include the following Disclaimer and Export Compliance provision in the
     59  * documentation and/or other materials provided with distribution.  In
     60  * addition, Licensee may not authorize further sublicense of source of any
     61  * portion of the Covered Code, and must include terms to the effect that the
     62  * license from Licensee to its licensee is limited to the intellectual
     63  * property embodied in the software Licensee provides to its licensee, and
     64  * not to intellectual property embodied in modifications its licensee may
     65  * make.
     66  *
     67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     68  * substantial portion of the Covered Code or modification must reproduce the
     69  * above Copyright Notice, and the following Disclaimer and Export Compliance
     70  * provision in the documentation and/or other materials provided with the
     71  * distribution.
     72  *
     73  * 3.4. Intel retains all right, title, and interest in and to the Original
     74  * Intel Code.
     75  *
     76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     77  * Intel shall be used in advertising or otherwise to promote the sale, use or
     78  * other dealings in products derived from or relating to the Covered Code
     79  * without prior written authorization from Intel.
     80  *
     81  * 4. Disclaimer and Export Compliance
     82  *
     83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
     86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
     87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
     88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     89  * PARTICULAR PURPOSE.
     90  *
     91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
     97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     98  * LIMITED REMEDY.
     99  *
    100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    101  * software or system incorporating such software without first obtaining any
    102  * required license or other approval from the U. S. Department of Commerce or
    103  * any other agency or department of the United States Government.  In the
    104  * event Licensee exports any such software from the United States or
    105  * re-exports any such software from a foreign destination, Licensee shall
    106  * ensure that the distribution and export/re-export of the software is in
    107  * compliance with all laws, regulations, orders, or other restrictions of the
    108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    109  * any of its subsidiaries will export/re-export any technical data, process,
    110  * software, or service, directly or indirectly, to any country for which the
    111  * United States government or any agency thereof requires an export license,
    112  * other governmental approval, or letter of assurance, without first obtaining
    113  * such license, approval or letter.
    114  *
    115  *****************************************************************************/
    116 
    117 #define __NSUTILS_C__
    118 
    119 #include "acpi.h"
    120 #include "accommon.h"
    121 #include "acnamesp.h"
    122 #include "amlcode.h"
    123 
    124 #define _COMPONENT          ACPI_NAMESPACE
    125         ACPI_MODULE_NAME    ("nsutils")
    126 
    127 /* Local prototypes */
    128 
    129 static BOOLEAN
    130 AcpiNsValidPathSeparator (
    131     char                    Sep);
    132 
    133 #ifdef ACPI_OBSOLETE_FUNCTIONS
    134 ACPI_NAME
    135 AcpiNsFindParentName (
    136     ACPI_NAMESPACE_NODE     *NodeToSearch);
    137 #endif
    138 
    139 
    140 /*******************************************************************************
    141  *
    142  * FUNCTION:    AcpiNsReportError
    143  *
    144  * PARAMETERS:  ModuleName          - Caller's module name (for error output)
    145  *              LineNumber          - Caller's line number (for error output)
    146  *              InternalName        - Name or path of the namespace node
    147  *              LookupStatus        - Exception code from NS lookup
    148  *
    149  * RETURN:      None
    150  *
    151  * DESCRIPTION: Print warning message with full pathname
    152  *
    153  ******************************************************************************/
    154 
    155 void
    156 AcpiNsReportError (
    157     const char              *ModuleName,
    158     UINT32                  LineNumber,
    159     const char              *InternalName,
    160     ACPI_STATUS             LookupStatus)
    161 {
    162     ACPI_STATUS             Status;
    163     UINT32                  BadName;
    164     char                    *Name = NULL;
    165 
    166 
    167     AcpiOsPrintf ("ACPI Error (%s-%04d): ", ModuleName, LineNumber);
    168 
    169     if (LookupStatus == AE_BAD_CHARACTER)
    170     {
    171         /* There is a non-ascii character in the name */
    172 
    173         ACPI_MOVE_32_TO_32 (&BadName, ACPI_CAST_PTR (UINT32, InternalName));
    174         AcpiOsPrintf ("[0x%4.4X] (NON-ASCII)", BadName);
    175     }
    176     else
    177     {
    178         /* Convert path to external format */
    179 
    180         Status = AcpiNsExternalizeName (ACPI_UINT32_MAX,
    181                     InternalName, NULL, &Name);
    182 
    183         /* Print target name */
    184 
    185         if (ACPI_SUCCESS (Status))
    186         {
    187             AcpiOsPrintf ("[%s]", Name);
    188         }
    189         else
    190         {
    191             AcpiOsPrintf ("[COULD NOT EXTERNALIZE NAME]");
    192         }
    193 
    194         if (Name)
    195         {
    196             ACPI_FREE (Name);
    197         }
    198     }
    199 
    200     AcpiOsPrintf (" Namespace lookup failure, %s\n",
    201         AcpiFormatException (LookupStatus));
    202 }
    203 
    204 
    205 /*******************************************************************************
    206  *
    207  * FUNCTION:    AcpiNsReportMethodError
    208  *
    209  * PARAMETERS:  ModuleName          - Caller's module name (for error output)
    210  *              LineNumber          - Caller's line number (for error output)
    211  *              Message             - Error message to use on failure
    212  *              PrefixNode          - Prefix relative to the path
    213  *              Path                - Path to the node (optional)
    214  *              MethodStatus        - Execution status
    215  *
    216  * RETURN:      None
    217  *
    218  * DESCRIPTION: Print warning message with full pathname
    219  *
    220  ******************************************************************************/
    221 
    222 void
    223 AcpiNsReportMethodError (
    224     const char              *ModuleName,
    225     UINT32                  LineNumber,
    226     const char              *Message,
    227     ACPI_NAMESPACE_NODE     *PrefixNode,
    228     const char              *Path,
    229     ACPI_STATUS             MethodStatus)
    230 {
    231     ACPI_STATUS             Status;
    232     ACPI_NAMESPACE_NODE     *Node = PrefixNode;
    233 
    234 
    235     AcpiOsPrintf ("ACPI Error (%s-%04d): ", ModuleName, LineNumber);
    236 
    237     if (Path)
    238     {
    239         Status = AcpiNsGetNode (PrefixNode, Path, ACPI_NS_NO_UPSEARCH,
    240                     &Node);
    241         if (ACPI_FAILURE (Status))
    242         {
    243             AcpiOsPrintf ("[Could not get node by pathname]");
    244         }
    245     }
    246 
    247     AcpiNsPrintNodePathname (Node, Message);
    248     AcpiOsPrintf (", %s\n", AcpiFormatException (MethodStatus));
    249 }
    250 
    251 
    252 /*******************************************************************************
    253  *
    254  * FUNCTION:    AcpiNsPrintNodePathname
    255  *
    256  * PARAMETERS:  Node            - Object
    257  *              Message         - Prefix message
    258  *
    259  * DESCRIPTION: Print an object's full namespace pathname
    260  *              Manages allocation/freeing of a pathname buffer
    261  *
    262  ******************************************************************************/
    263 
    264 void
    265 AcpiNsPrintNodePathname (
    266     ACPI_NAMESPACE_NODE     *Node,
    267     const char              *Message)
    268 {
    269     ACPI_BUFFER             Buffer;
    270     ACPI_STATUS             Status;
    271 
    272 
    273     if (!Node)
    274     {
    275         AcpiOsPrintf ("[NULL NAME]");
    276         return;
    277     }
    278 
    279     /* Convert handle to full pathname and print it (with supplied message) */
    280 
    281     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    282 
    283     Status = AcpiNsHandleToPathname (Node, &Buffer);
    284     if (ACPI_SUCCESS (Status))
    285     {
    286         if (Message)
    287         {
    288             AcpiOsPrintf ("%s ", Message);
    289         }
    290 
    291         AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node);
    292         ACPI_FREE (Buffer.Pointer);
    293     }
    294 }
    295 
    296 
    297 /*******************************************************************************
    298  *
    299  * FUNCTION:    AcpiNsValidRootPrefix
    300  *
    301  * PARAMETERS:  Prefix          - Character to be checked
    302  *
    303  * RETURN:      TRUE if a valid prefix
    304  *
    305  * DESCRIPTION: Check if a character is a valid ACPI Root prefix
    306  *
    307  ******************************************************************************/
    308 
    309 BOOLEAN
    310 AcpiNsValidRootPrefix (
    311     char                    Prefix)
    312 {
    313 
    314     return ((BOOLEAN) (Prefix == '\\'));
    315 }
    316 
    317 
    318 /*******************************************************************************
    319  *
    320  * FUNCTION:    AcpiNsValidPathSeparator
    321  *
    322  * PARAMETERS:  Sep         - Character to be checked
    323  *
    324  * RETURN:      TRUE if a valid path separator
    325  *
    326  * DESCRIPTION: Check if a character is a valid ACPI path separator
    327  *
    328  ******************************************************************************/
    329 
    330 static BOOLEAN
    331 AcpiNsValidPathSeparator (
    332     char                    Sep)
    333 {
    334 
    335     return ((BOOLEAN) (Sep == '.'));
    336 }
    337 
    338 
    339 /*******************************************************************************
    340  *
    341  * FUNCTION:    AcpiNsGetType
    342  *
    343  * PARAMETERS:  Node        - Parent Node to be examined
    344  *
    345  * RETURN:      Type field from Node whose handle is passed
    346  *
    347  * DESCRIPTION: Return the type of a Namespace node
    348  *
    349  ******************************************************************************/
    350 
    351 ACPI_OBJECT_TYPE
    352 AcpiNsGetType (
    353     ACPI_NAMESPACE_NODE     *Node)
    354 {
    355     ACPI_FUNCTION_TRACE (NsGetType);
    356 
    357 
    358     if (!Node)
    359     {
    360         ACPI_WARNING ((AE_INFO, "Null Node parameter"));
    361         return_UINT32 (ACPI_TYPE_ANY);
    362     }
    363 
    364     return_UINT32 ((ACPI_OBJECT_TYPE) Node->Type);
    365 }
    366 
    367 
    368 /*******************************************************************************
    369  *
    370  * FUNCTION:    AcpiNsLocal
    371  *
    372  * PARAMETERS:  Type        - A namespace object type
    373  *
    374  * RETURN:      LOCAL if names must be found locally in objects of the
    375  *              passed type, 0 if enclosing scopes should be searched
    376  *
    377  * DESCRIPTION: Returns scope rule for the given object type.
    378  *
    379  ******************************************************************************/
    380 
    381 UINT32
    382 AcpiNsLocal (
    383     ACPI_OBJECT_TYPE        Type)
    384 {
    385     ACPI_FUNCTION_TRACE (NsLocal);
    386 
    387 
    388     if (!AcpiUtValidObjectType (Type))
    389     {
    390         /* Type code out of range  */
    391 
    392         ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
    393         return_UINT32 (ACPI_NS_NORMAL);
    394     }
    395 
    396     return_UINT32 ((UINT32) AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
    397 }
    398 
    399 
    400 /*******************************************************************************
    401  *
    402  * FUNCTION:    AcpiNsGetInternalNameLength
    403  *
    404  * PARAMETERS:  Info            - Info struct initialized with the
    405  *                                external name pointer.
    406  *
    407  * RETURN:      None
    408  *
    409  * DESCRIPTION: Calculate the length of the internal (AML) namestring
    410  *              corresponding to the external (ASL) namestring.
    411  *
    412  ******************************************************************************/
    413 
    414 void
    415 AcpiNsGetInternalNameLength (
    416     ACPI_NAMESTRING_INFO    *Info)
    417 {
    418     const char              *NextExternalChar;
    419     UINT32                  i;
    420 
    421 
    422     ACPI_FUNCTION_ENTRY ();
    423 
    424 
    425     NextExternalChar = Info->ExternalName;
    426     Info->NumCarats = 0;
    427     Info->NumSegments = 0;
    428     Info->FullyQualified = FALSE;
    429 
    430     /*
    431      * For the internal name, the required length is 4 bytes per segment, plus
    432      * 1 each for RootPrefix, MultiNamePrefixOp, segment count, trailing null
    433      * (which is not really needed, but no there's harm in putting it there)
    434      *
    435      * strlen() + 1 covers the first NameSeg, which has no path separator
    436      */
    437     if (AcpiNsValidRootPrefix (*NextExternalChar))
    438     {
    439         Info->FullyQualified = TRUE;
    440         NextExternalChar++;
    441 
    442         /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */
    443 
    444         while (AcpiNsValidRootPrefix (*NextExternalChar))
    445         {
    446             NextExternalChar++;
    447         }
    448     }
    449     else
    450     {
    451         /* Handle Carat prefixes */
    452 
    453         while (*NextExternalChar == '^')
    454         {
    455             Info->NumCarats++;
    456             NextExternalChar++;
    457         }
    458     }
    459 
    460     /*
    461      * Determine the number of ACPI name "segments" by counting the number of
    462      * path separators within the string. Start with one segment since the
    463      * segment count is [(# separators) + 1], and zero separators is ok.
    464      */
    465     if (*NextExternalChar)
    466     {
    467         Info->NumSegments = 1;
    468         for (i = 0; NextExternalChar[i]; i++)
    469         {
    470             if (AcpiNsValidPathSeparator (NextExternalChar[i]))
    471             {
    472                 Info->NumSegments++;
    473             }
    474         }
    475     }
    476 
    477     Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) +
    478                     4 + Info->NumCarats;
    479 
    480     Info->NextExternalChar = NextExternalChar;
    481 }
    482 
    483 
    484 /*******************************************************************************
    485  *
    486  * FUNCTION:    AcpiNsBuildInternalName
    487  *
    488  * PARAMETERS:  Info            - Info struct fully initialized
    489  *
    490  * RETURN:      Status
    491  *
    492  * DESCRIPTION: Construct the internal (AML) namestring
    493  *              corresponding to the external (ASL) namestring.
    494  *
    495  ******************************************************************************/
    496 
    497 ACPI_STATUS
    498 AcpiNsBuildInternalName (
    499     ACPI_NAMESTRING_INFO    *Info)
    500 {
    501     UINT32                  NumSegments = Info->NumSegments;
    502     char                    *InternalName = Info->InternalName;
    503     const char              *ExternalName = Info->NextExternalChar;
    504     char                    *Result = NULL;
    505     UINT32                  i;
    506 
    507 
    508     ACPI_FUNCTION_TRACE (NsBuildInternalName);
    509 
    510 
    511     /* Setup the correct prefixes, counts, and pointers */
    512 
    513     if (Info->FullyQualified)
    514     {
    515         InternalName[0] = '\\';
    516 
    517         if (NumSegments <= 1)
    518         {
    519             Result = &InternalName[1];
    520         }
    521         else if (NumSegments == 2)
    522         {
    523             InternalName[1] = AML_DUAL_NAME_PREFIX;
    524             Result = &InternalName[2];
    525         }
    526         else
    527         {
    528             InternalName[1] = AML_MULTI_NAME_PREFIX_OP;
    529             InternalName[2] = (char) NumSegments;
    530             Result = &InternalName[3];
    531         }
    532     }
    533     else
    534     {
    535         /*
    536          * Not fully qualified.
    537          * Handle Carats first, then append the name segments
    538          */
    539         i = 0;
    540         if (Info->NumCarats)
    541         {
    542             for (i = 0; i < Info->NumCarats; i++)
    543             {
    544                 InternalName[i] = '^';
    545             }
    546         }
    547 
    548         if (NumSegments <= 1)
    549         {
    550             Result = &InternalName[i];
    551         }
    552         else if (NumSegments == 2)
    553         {
    554             InternalName[i] = AML_DUAL_NAME_PREFIX;
    555             Result = &InternalName[(ACPI_SIZE) i+1];
    556         }
    557         else
    558         {
    559             InternalName[i] = AML_MULTI_NAME_PREFIX_OP;
    560             InternalName[(ACPI_SIZE) i+1] = (char) NumSegments;
    561             Result = &InternalName[(ACPI_SIZE) i+2];
    562         }
    563     }
    564 
    565     /* Build the name (minus path separators) */
    566 
    567     for (; NumSegments; NumSegments--)
    568     {
    569         for (i = 0; i < ACPI_NAME_SIZE; i++)
    570         {
    571             if (AcpiNsValidPathSeparator (*ExternalName) ||
    572                (*ExternalName == 0))
    573             {
    574                 /* Pad the segment with underscore(s) if segment is short */
    575 
    576                 Result[i] = '_';
    577             }
    578             else
    579             {
    580                 /* Convert the character to uppercase and save it */
    581 
    582                 Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName);
    583                 ExternalName++;
    584             }
    585         }
    586 
    587         /* Now we must have a path separator, or the pathname is bad */
    588 
    589         if (!AcpiNsValidPathSeparator (*ExternalName) &&
    590             (*ExternalName != 0))
    591         {
    592             return_ACPI_STATUS (AE_BAD_PARAMETER);
    593         }
    594 
    595         /* Move on the next segment */
    596 
    597         ExternalName++;
    598         Result += ACPI_NAME_SIZE;
    599     }
    600 
    601     /* Terminate the string */
    602 
    603     *Result = 0;
    604 
    605     if (Info->FullyQualified)
    606     {
    607         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
    608             InternalName, InternalName));
    609     }
    610     else
    611     {
    612         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
    613             InternalName, InternalName));
    614     }
    615 
    616     return_ACPI_STATUS (AE_OK);
    617 }
    618 
    619 
    620 /*******************************************************************************
    621  *
    622  * FUNCTION:    AcpiNsInternalizeName
    623  *
    624  * PARAMETERS:  *ExternalName           - External representation of name
    625  *              **Converted Name        - Where to return the resulting
    626  *                                        internal represention of the name
    627  *
    628  * RETURN:      Status
    629  *
    630  * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
    631  *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
    632  *
    633  *******************************************************************************/
    634 
    635 ACPI_STATUS
    636 AcpiNsInternalizeName (
    637     const char              *ExternalName,
    638     char                    **ConvertedName)
    639 {
    640     char                    *InternalName;
    641     ACPI_NAMESTRING_INFO    Info;
    642     ACPI_STATUS             Status;
    643 
    644 
    645     ACPI_FUNCTION_TRACE (NsInternalizeName);
    646 
    647 
    648     if ((!ExternalName)      ||
    649         (*ExternalName == 0) ||
    650         (!ConvertedName))
    651     {
    652         return_ACPI_STATUS (AE_BAD_PARAMETER);
    653     }
    654 
    655     /* Get the length of the new internal name */
    656 
    657     Info.ExternalName = ExternalName;
    658     AcpiNsGetInternalNameLength (&Info);
    659 
    660     /* We need a segment to store the internal  name */
    661 
    662     InternalName = ACPI_ALLOCATE_ZEROED (Info.Length);
    663     if (!InternalName)
    664     {
    665         return_ACPI_STATUS (AE_NO_MEMORY);
    666     }
    667 
    668     /* Build the name */
    669 
    670     Info.InternalName = InternalName;
    671     Status = AcpiNsBuildInternalName (&Info);
    672     if (ACPI_FAILURE (Status))
    673     {
    674         ACPI_FREE (InternalName);
    675         return_ACPI_STATUS (Status);
    676     }
    677 
    678     *ConvertedName = InternalName;
    679     return_ACPI_STATUS (AE_OK);
    680 }
    681 
    682 
    683 /*******************************************************************************
    684  *
    685  * FUNCTION:    AcpiNsExternalizeName
    686  *
    687  * PARAMETERS:  InternalNameLength  - Lenth of the internal name below
    688  *              InternalName        - Internal representation of name
    689  *              ConvertedNameLength - Where the length is returned
    690  *              ConvertedName       - Where the resulting external name
    691  *                                    is returned
    692  *
    693  * RETURN:      Status
    694  *
    695  * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
    696  *              to its external (printable) form (e.g. "\_PR_.CPU0")
    697  *
    698  ******************************************************************************/
    699 
    700 ACPI_STATUS
    701 AcpiNsExternalizeName (
    702     UINT32                  InternalNameLength,
    703     const char              *InternalName,
    704     UINT32                  *ConvertedNameLength,
    705     char                    **ConvertedName)
    706 {
    707     UINT32                  NamesIndex = 0;
    708     UINT32                  NumSegments = 0;
    709     UINT32                  RequiredLength;
    710     UINT32                  PrefixLength = 0;
    711     UINT32                  i = 0;
    712     UINT32                  j = 0;
    713 
    714 
    715     ACPI_FUNCTION_TRACE (NsExternalizeName);
    716 
    717 
    718     if (!InternalNameLength     ||
    719         !InternalName           ||
    720         !ConvertedName)
    721     {
    722         return_ACPI_STATUS (AE_BAD_PARAMETER);
    723     }
    724 
    725     /* Check for a prefix (one '\' | one or more '^') */
    726 
    727     switch (InternalName[0])
    728     {
    729     case '\\':
    730         PrefixLength = 1;
    731         break;
    732 
    733     case '^':
    734         for (i = 0; i < InternalNameLength; i++)
    735         {
    736             if (InternalName[i] == '^')
    737             {
    738                 PrefixLength = i + 1;
    739             }
    740             else
    741             {
    742                 break;
    743             }
    744         }
    745 
    746         if (i == InternalNameLength)
    747         {
    748             PrefixLength = i;
    749         }
    750 
    751         break;
    752 
    753     default:
    754         break;
    755     }
    756 
    757     /*
    758      * Check for object names. Note that there could be 0-255 of these
    759      * 4-byte elements.
    760      */
    761     if (PrefixLength < InternalNameLength)
    762     {
    763         switch (InternalName[PrefixLength])
    764         {
    765         case AML_MULTI_NAME_PREFIX_OP:
    766 
    767             /* <count> 4-byte names */
    768 
    769             NamesIndex = PrefixLength + 2;
    770             NumSegments = (UINT8)
    771                 InternalName[(ACPI_SIZE) PrefixLength + 1];
    772             break;
    773 
    774         case AML_DUAL_NAME_PREFIX:
    775 
    776             /* Two 4-byte names */
    777 
    778             NamesIndex = PrefixLength + 1;
    779             NumSegments = 2;
    780             break;
    781 
    782         case 0:
    783 
    784             /* NullName */
    785 
    786             NamesIndex = 0;
    787             NumSegments = 0;
    788             break;
    789 
    790         default:
    791 
    792             /* one 4-byte name */
    793 
    794             NamesIndex = PrefixLength;
    795             NumSegments = 1;
    796             break;
    797         }
    798     }
    799 
    800     /*
    801      * Calculate the length of ConvertedName, which equals the length
    802      * of the prefix, length of all object names, length of any required
    803      * punctuation ('.') between object names, plus the NULL terminator.
    804      */
    805     RequiredLength = PrefixLength + (4 * NumSegments) +
    806                         ((NumSegments > 0) ? (NumSegments - 1) : 0) + 1;
    807 
    808     /*
    809      * Check to see if we're still in bounds.  If not, there's a problem
    810      * with InternalName (invalid format).
    811      */
    812     if (RequiredLength > InternalNameLength)
    813     {
    814         ACPI_ERROR ((AE_INFO, "Invalid internal name"));
    815         return_ACPI_STATUS (AE_BAD_PATHNAME);
    816     }
    817 
    818     /* Build the ConvertedName */
    819 
    820     *ConvertedName = ACPI_ALLOCATE_ZEROED (RequiredLength);
    821     if (!(*ConvertedName))
    822     {
    823         return_ACPI_STATUS (AE_NO_MEMORY);
    824     }
    825 
    826     j = 0;
    827 
    828     for (i = 0; i < PrefixLength; i++)
    829     {
    830         (*ConvertedName)[j++] = InternalName[i];
    831     }
    832 
    833     if (NumSegments > 0)
    834     {
    835         for (i = 0; i < NumSegments; i++)
    836         {
    837             if (i > 0)
    838             {
    839                 (*ConvertedName)[j++] = '.';
    840             }
    841 
    842             (*ConvertedName)[j++] = InternalName[NamesIndex++];
    843             (*ConvertedName)[j++] = InternalName[NamesIndex++];
    844             (*ConvertedName)[j++] = InternalName[NamesIndex++];
    845             (*ConvertedName)[j++] = InternalName[NamesIndex++];
    846         }
    847     }
    848 
    849     if (ConvertedNameLength)
    850     {
    851         *ConvertedNameLength = (UINT32) RequiredLength;
    852     }
    853 
    854     return_ACPI_STATUS (AE_OK);
    855 }
    856 
    857 
    858 /*******************************************************************************
    859  *
    860  * FUNCTION:    AcpiNsValidateHandle
    861  *
    862  * PARAMETERS:  Handle          - Handle to be validated and typecast to a
    863  *                                namespace node.
    864  *
    865  * RETURN:      A pointer to a namespace node
    866  *
    867  * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
    868  *              cases for the root node.
    869  *
    870  * NOTE: Real integer handles would allow for more verification
    871  *       and keep all pointers within this subsystem - however this introduces
    872  *       more overhead and has not been necessary to this point. Drivers
    873  *       holding handles are typically notified before a node becomes invalid
    874  *       due to a table unload.
    875  *
    876  ******************************************************************************/
    877 
    878 ACPI_NAMESPACE_NODE *
    879 AcpiNsValidateHandle (
    880     ACPI_HANDLE             Handle)
    881 {
    882 
    883     ACPI_FUNCTION_ENTRY ();
    884 
    885 
    886     /* Parameter validation */
    887 
    888     if ((!Handle) || (Handle == ACPI_ROOT_OBJECT))
    889     {
    890         return (AcpiGbl_RootNode);
    891     }
    892 
    893     /* We can at least attempt to verify the handle */
    894 
    895     if (ACPI_GET_DESCRIPTOR_TYPE (Handle) != ACPI_DESC_TYPE_NAMED)
    896     {
    897         return (NULL);
    898     }
    899 
    900     return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle));
    901 }
    902 
    903 
    904 /*******************************************************************************
    905  *
    906  * FUNCTION:    AcpiNsTerminate
    907  *
    908  * PARAMETERS:  none
    909  *
    910  * RETURN:      none
    911  *
    912  * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
    913  *
    914  ******************************************************************************/
    915 
    916 void
    917 AcpiNsTerminate (
    918     void)
    919 {
    920     ACPI_OPERAND_OBJECT     *ObjDesc;
    921 
    922 
    923     ACPI_FUNCTION_TRACE (NsTerminate);
    924 
    925 
    926     /*
    927      * 1) Free the entire namespace -- all nodes and objects
    928      *
    929      * Delete all object descriptors attached to namepsace nodes
    930      */
    931     AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
    932 
    933     /* Detach any objects attached to the root */
    934 
    935     ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode);
    936     if (ObjDesc)
    937     {
    938         AcpiNsDetachObject (AcpiGbl_RootNode);
    939     }
    940 
    941     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
    942     return_VOID;
    943 }
    944 
    945 
    946 /*******************************************************************************
    947  *
    948  * FUNCTION:    AcpiNsOpensScope
    949  *
    950  * PARAMETERS:  Type        - A valid namespace type
    951  *
    952  * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
    953  *              to the ACPI specification, else 0
    954  *
    955  ******************************************************************************/
    956 
    957 UINT32
    958 AcpiNsOpensScope (
    959     ACPI_OBJECT_TYPE        Type)
    960 {
    961     ACPI_FUNCTION_TRACE_STR (NsOpensScope, AcpiUtGetTypeName (Type));
    962 
    963 
    964     if (!AcpiUtValidObjectType (Type))
    965     {
    966         /* type code out of range  */
    967 
    968         ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
    969         return_UINT32 (ACPI_NS_NORMAL);
    970     }
    971 
    972     return_UINT32 (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE);
    973 }
    974 
    975 
    976 /*******************************************************************************
    977  *
    978  * FUNCTION:    AcpiNsGetNode
    979  *
    980  * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
    981  *                            \ (backslash) and ^ (carat) prefixes, and the
    982  *                            . (period) to separate segments are supported.
    983  *              PrefixNode   - Root of subtree to be searched, or NS_ALL for the
    984  *                            root of the name space.  If Name is fully
    985  *                            qualified (first INT8 is '\'), the passed value
    986  *                            of Scope will not be accessed.
    987  *              Flags       - Used to indicate whether to perform upsearch or
    988  *                            not.
    989  *              ReturnNode  - Where the Node is returned
    990  *
    991  * DESCRIPTION: Look up a name relative to a given scope and return the
    992  *              corresponding Node.  NOTE: Scope can be null.
    993  *
    994  * MUTEX:       Locks namespace
    995  *
    996  ******************************************************************************/
    997 
    998 ACPI_STATUS
    999 AcpiNsGetNode (
   1000     ACPI_NAMESPACE_NODE     *PrefixNode,
   1001     const char              *Pathname,
   1002     UINT32                  Flags,
   1003     ACPI_NAMESPACE_NODE     **ReturnNode)
   1004 {
   1005     ACPI_GENERIC_STATE      ScopeInfo;
   1006     ACPI_STATUS             Status;
   1007     char                    *InternalPath;
   1008 
   1009 
   1010     ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));
   1011 
   1012 
   1013     if (!Pathname)
   1014     {
   1015         *ReturnNode = PrefixNode;
   1016         if (!PrefixNode)
   1017         {
   1018             *ReturnNode = AcpiGbl_RootNode;
   1019         }
   1020         return_ACPI_STATUS (AE_OK);
   1021     }
   1022 
   1023     /* Convert path to internal representation */
   1024 
   1025     Status = AcpiNsInternalizeName (Pathname, &InternalPath);
   1026     if (ACPI_FAILURE (Status))
   1027     {
   1028         return_ACPI_STATUS (Status);
   1029     }
   1030 
   1031     /* Must lock namespace during lookup */
   1032 
   1033     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
   1034     if (ACPI_FAILURE (Status))
   1035     {
   1036         goto Cleanup;
   1037     }
   1038 
   1039     /* Setup lookup scope (search starting point) */
   1040 
   1041     ScopeInfo.Scope.Node = PrefixNode;
   1042 
   1043     /* Lookup the name in the namespace */
   1044 
   1045     Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY,
   1046                 ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE),
   1047                 NULL, ReturnNode);
   1048     if (ACPI_FAILURE (Status))
   1049     {
   1050         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n",
   1051                 Pathname, AcpiFormatException (Status)));
   1052     }
   1053 
   1054     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
   1055 
   1056 Cleanup:
   1057     ACPI_FREE (InternalPath);
   1058     return_ACPI_STATUS (Status);
   1059 }
   1060