Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/acpica/nsutils.c need to be fixed.

0001 /******************************************************************************
0002  *
0003  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
0004  *                        parents and siblings and Scope manipulation
0005  *
0006  *****************************************************************************/
0007 
0008 /******************************************************************************
0009  *
0010  * 1. Copyright Notice
0011  *
0012  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
0013  * All rights reserved.
0014  *
0015  * 2. License
0016  *
0017  * 2.1. This is your license from Intel Corp. under its intellectual property
0018  * rights.  You may have additional license terms from the party that provided
0019  * you this software, covering your right to use that party's intellectual
0020  * property rights.
0021  *
0022  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0023  * copy of the source code appearing in this file ("Covered Code") an
0024  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0025  * base code distributed originally by Intel ("Original Intel Code") to copy,
0026  * make derivatives, distribute, use and display any portion of the Covered
0027  * Code in any form, with the right to sublicense such rights; and
0028  *
0029  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0030  * license (with the right to sublicense), under only those claims of Intel
0031  * patents that are infringed by the Original Intel Code, to make, use, sell,
0032  * offer to sell, and import the Covered Code and derivative works thereof
0033  * solely to the minimum extent necessary to exercise the above copyright
0034  * license, and in no event shall the patent license extend to any additions
0035  * to or modifications of the Original Intel Code.  No other license or right
0036  * is granted directly or by implication, estoppel or otherwise;
0037  *
0038  * The above copyright and patent license is granted only if the following
0039  * conditions are met:
0040  *
0041  * 3. Conditions
0042  *
0043  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0044  * Redistribution of source code of any substantial portion of the Covered
0045  * Code or modification with rights to further distribute source must include
0046  * the above Copyright Notice, the above License, this list of Conditions,
0047  * and the following Disclaimer and Export Compliance provision.  In addition,
0048  * Licensee must cause all Covered Code to which Licensee contributes to
0049  * contain a file documenting the changes Licensee made to create that Covered
0050  * Code and the date of any change.  Licensee must include in that file the
0051  * documentation of any changes made by any predecessor Licensee.  Licensee
0052  * must include a prominent statement that the modification is derived,
0053  * directly or indirectly, from Original Intel Code.
0054  *
0055  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0056  * Redistribution of source code of any substantial portion of the Covered
0057  * Code or modification without rights to further distribute source must
0058  * include the following Disclaimer and Export Compliance provision in the
0059  * documentation and/or other materials provided with distribution.  In
0060  * addition, Licensee may not authorize further sublicense of source of any
0061  * portion of the Covered Code, and must include terms to the effect that the
0062  * license from Licensee to its licensee is limited to the intellectual
0063  * property embodied in the software Licensee provides to its licensee, and
0064  * not to intellectual property embodied in modifications its licensee may
0065  * make.
0066  *
0067  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0068  * substantial portion of the Covered Code or modification must reproduce the
0069  * above Copyright Notice, and the following Disclaimer and Export Compliance
0070  * provision in the documentation and/or other materials provided with the
0071  * distribution.
0072  *
0073  * 3.4. Intel retains all right, title, and interest in and to the Original
0074  * Intel Code.
0075  *
0076  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0077  * Intel shall be used in advertising or otherwise to promote the sale, use or
0078  * other dealings in products derived from or relating to the Covered Code
0079  * without prior written authorization from Intel.
0080  *
0081  * 4. Disclaimer and Export Compliance
0082  *
0083  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0084  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0085  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
0086  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
0087  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
0088  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0089  * PARTICULAR PURPOSE.
0090  *
0091  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0092  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0093  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0094  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0095  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0096  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
0097  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0098  * LIMITED REMEDY.
0099  *
0100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0101  * software or system incorporating such software without first obtaining any
0102  * required license or other approval from the U. S. Department of Commerce or
0103  * any other agency or department of the United States Government.  In the
0104  * event Licensee exports any such software from the United States or
0105  * re-exports any such software from a foreign destination, Licensee shall
0106  * ensure that the distribution and export/re-export of the software is in
0107  * compliance with all laws, regulations, orders, or other restrictions of the
0108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0109  * any of its subsidiaries will export/re-export any technical data, process,
0110  * software, or service, directly or indirectly, to any country for which the
0111  * United States government or any agency thereof requires an export license,
0112  * other governmental approval, or letter of assurance, without first obtaining
0113  * such license, approval or letter.
0114  *
0115  *****************************************************************************/
0116 
0117 #define __NSUTILS_C__
0118 
0119 #include "acpi.h"
0120 #include "accommon.h"
0121 #include "acnamesp.h"
0122 #include "amlcode.h"
0123 
0124 #define _COMPONENT          ACPI_NAMESPACE
0125         ACPI_MODULE_NAME    ("nsutils")
0126 
0127 /* Local prototypes */
0128 
0129 static BOOLEAN
0130 AcpiNsValidPathSeparator (
0131     char                    Sep);
0132 
0133 #ifdef ACPI_OBSOLETE_FUNCTIONS
0134 ACPI_NAME
0135 AcpiNsFindParentName (
0136     ACPI_NAMESPACE_NODE     *NodeToSearch);
0137 #endif
0138 
0139 
0140 /*******************************************************************************
0141  *
0142  * FUNCTION:    AcpiNsReportError
0143  *
0144  * PARAMETERS:  ModuleName          - Caller's module name (for error output)
0145  *              LineNumber          - Caller's line number (for error output)
0146  *              InternalName        - Name or path of the namespace node
0147  *              LookupStatus        - Exception code from NS lookup
0148  *
0149  * RETURN:      None
0150  *
0151  * DESCRIPTION: Print warning message with full pathname
0152  *
0153  ******************************************************************************/
0154 
0155 void
0156 AcpiNsReportError (
0157     const char              *ModuleName,
0158     UINT32                  LineNumber,
0159     const char              *InternalName,
0160     ACPI_STATUS             LookupStatus)
0161 {
0162     ACPI_STATUS             Status;
0163     UINT32                  BadName;
0164     char                    *Name = NULL;
0165 
0166 
0167     AcpiOsPrintf ("ACPI Error (%s-%04d): ", ModuleName, LineNumber);
0168 
0169     if (LookupStatus == AE_BAD_CHARACTER)
0170     {
0171         /* There is a non-ascii character in the name */
0172 
0173         ACPI_MOVE_32_TO_32 (&BadName, ACPI_CAST_PTR (UINT32, InternalName));
0174         AcpiOsPrintf ("[0x%4.4X] (NON-ASCII)", BadName);
0175     }
0176     else
0177     {
0178         /* Convert path to external format */
0179 
0180         Status = AcpiNsExternalizeName (ACPI_UINT32_MAX,
0181                     InternalName, NULL, &Name);
0182 
0183         /* Print target name */
0184 
0185         if (ACPI_SUCCESS (Status))
0186         {
0187             AcpiOsPrintf ("[%s]", Name);
0188         }
0189         else
0190         {
0191             AcpiOsPrintf ("[COULD NOT EXTERNALIZE NAME]");
0192         }
0193 
0194         if (Name)
0195         {
0196             ACPI_FREE (Name);
0197         }
0198     }
0199 
0200     AcpiOsPrintf (" Namespace lookup failure, %s\n",
0201         AcpiFormatException (LookupStatus));
0202 }
0203 
0204 
0205 /*******************************************************************************
0206  *
0207  * FUNCTION:    AcpiNsReportMethodError
0208  *
0209  * PARAMETERS:  ModuleName          - Caller's module name (for error output)
0210  *              LineNumber          - Caller's line number (for error output)
0211  *              Message             - Error message to use on failure
0212  *              PrefixNode          - Prefix relative to the path
0213  *              Path                - Path to the node (optional)
0214  *              MethodStatus        - Execution status
0215  *
0216  * RETURN:      None
0217  *
0218  * DESCRIPTION: Print warning message with full pathname
0219  *
0220  ******************************************************************************/
0221 
0222 void
0223 AcpiNsReportMethodError (
0224     const char              *ModuleName,
0225     UINT32                  LineNumber,
0226     const char              *Message,
0227     ACPI_NAMESPACE_NODE     *PrefixNode,
0228     const char              *Path,
0229     ACPI_STATUS             MethodStatus)
0230 {
0231     ACPI_STATUS             Status;
0232     ACPI_NAMESPACE_NODE     *Node = PrefixNode;
0233 
0234 
0235     AcpiOsPrintf ("ACPI Error (%s-%04d): ", ModuleName, LineNumber);
0236 
0237     if (Path)
0238     {
0239         Status = AcpiNsGetNode (PrefixNode, Path, ACPI_NS_NO_UPSEARCH,
0240                     &Node);
0241         if (ACPI_FAILURE (Status))
0242         {
0243             AcpiOsPrintf ("[Could not get node by pathname]");
0244         }
0245     }
0246 
0247     AcpiNsPrintNodePathname (Node, Message);
0248     AcpiOsPrintf (", %s\n", AcpiFormatException (MethodStatus));
0249 }
0250 
0251 
0252 /*******************************************************************************
0253  *
0254  * FUNCTION:    AcpiNsPrintNodePathname
0255  *
0256  * PARAMETERS:  Node            - Object
0257  *              Message         - Prefix message
0258  *
0259  * DESCRIPTION: Print an object's full namespace pathname
0260  *              Manages allocation/freeing of a pathname buffer
0261  *
0262  ******************************************************************************/
0263 
0264 void
0265 AcpiNsPrintNodePathname (
0266     ACPI_NAMESPACE_NODE     *Node,
0267     const char              *Message)
0268 {
0269     ACPI_BUFFER             Buffer;
0270     ACPI_STATUS             Status;
0271 
0272 
0273     if (!Node)
0274     {
0275         AcpiOsPrintf ("[NULL NAME]");
0276         return;
0277     }
0278 
0279     /* Convert handle to full pathname and print it (with supplied message) */
0280 
0281     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
0282 
0283     Status = AcpiNsHandleToPathname (Node, &Buffer);
0284     if (ACPI_SUCCESS (Status))
0285     {
0286         if (Message)
0287         {
0288             AcpiOsPrintf ("%s ", Message);
0289         }
0290 
0291         AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node);
0292         ACPI_FREE (Buffer.Pointer);
0293     }
0294 }
0295 
0296 
0297 /*******************************************************************************
0298  *
0299  * FUNCTION:    AcpiNsValidRootPrefix
0300  *
0301  * PARAMETERS:  Prefix          - Character to be checked
0302  *
0303  * RETURN:      TRUE if a valid prefix
0304  *
0305  * DESCRIPTION: Check if a character is a valid ACPI Root prefix
0306  *
0307  ******************************************************************************/
0308 
0309 BOOLEAN
0310 AcpiNsValidRootPrefix (
0311     char                    Prefix)
0312 {
0313 
0314     return ((BOOLEAN) (Prefix == '\\'));
0315 }
0316 
0317 
0318 /*******************************************************************************
0319  *
0320  * FUNCTION:    AcpiNsValidPathSeparator
0321  *
0322  * PARAMETERS:  Sep         - Character to be checked
0323  *
0324  * RETURN:      TRUE if a valid path separator
0325  *
0326  * DESCRIPTION: Check if a character is a valid ACPI path separator
0327  *
0328  ******************************************************************************/
0329 
0330 static BOOLEAN
0331 AcpiNsValidPathSeparator (
0332     char                    Sep)
0333 {
0334 
0335     return ((BOOLEAN) (Sep == '.'));
0336 }
0337 
0338 
0339 /*******************************************************************************
0340  *
0341  * FUNCTION:    AcpiNsGetType
0342  *
0343  * PARAMETERS:  Node        - Parent Node to be examined
0344  *
0345  * RETURN:      Type field from Node whose handle is passed
0346  *
0347  * DESCRIPTION: Return the type of a Namespace node
0348  *
0349  ******************************************************************************/
0350 
0351 ACPI_OBJECT_TYPE
0352 AcpiNsGetType (
0353     ACPI_NAMESPACE_NODE     *Node)
0354 {
0355     ACPI_FUNCTION_TRACE (NsGetType);
0356 
0357 
0358     if (!Node)
0359     {
0360         ACPI_WARNING ((AE_INFO, "Null Node parameter"));
0361         return_UINT32 (ACPI_TYPE_ANY);
0362     }
0363 
0364     return_UINT32 ((ACPI_OBJECT_TYPE) Node->Type);
0365 }
0366 
0367 
0368 /*******************************************************************************
0369  *
0370  * FUNCTION:    AcpiNsLocal
0371  *
0372  * PARAMETERS:  Type        - A namespace object type
0373  *
0374  * RETURN:      LOCAL if names must be found locally in objects of the
0375  *              passed type, 0 if enclosing scopes should be searched
0376  *
0377  * DESCRIPTION: Returns scope rule for the given object type.
0378  *
0379  ******************************************************************************/
0380 
0381 UINT32
0382 AcpiNsLocal (
0383     ACPI_OBJECT_TYPE        Type)
0384 {
0385     ACPI_FUNCTION_TRACE (NsLocal);
0386 
0387 
0388     if (!AcpiUtValidObjectType (Type))
0389     {
0390         /* Type code out of range  */
0391 
0392         ACPI_WARNING ((AE_INFO, "Invalid Object Type %X", Type));
0393         return_UINT32 (ACPI_NS_NORMAL);
0394     }
0395 
0396     return_UINT32 ((UINT32) AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
0397 }
0398 
0399 
0400 /*******************************************************************************
0401  *
0402  * FUNCTION:    AcpiNsGetInternalNameLength
0403  *
0404  * PARAMETERS:  Info            - Info struct initialized with the
0405  *                                external name pointer.
0406  *
0407  * RETURN:      None
0408  *
0409  * DESCRIPTION: Calculate the length of the internal (AML) namestring
0410  *              corresponding to the external (ASL) namestring.
0411  *
0412  ******************************************************************************/
0413 
0414 void
0415 AcpiNsGetInternalNameLength (
0416     ACPI_NAMESTRING_INFO    *Info)
0417 {
0418     const char              *NextExternalChar;
0419     UINT32                  i;
0420 
0421 
0422     ACPI_FUNCTION_ENTRY ();
0423 
0424 
0425     NextExternalChar = Info->ExternalName;
0426     Info->NumCarats = 0;
0427     Info->NumSegments = 0;
0428     Info->FullyQualified = FALSE;
0429 
0430     /*
0431      * For the internal name, the required length is 4 bytes per segment, plus
0432      * 1 each for RootPrefix, MultiNamePrefixOp, segment count, trailing null
0433      * (which is not really needed, but no there's harm in putting it there)
0434      *
0435      * strlen() + 1 covers the first NameSeg, which has no path separator
0436      */
0437     if (AcpiNsValidRootPrefix (*NextExternalChar))
0438     {
0439         Info->FullyQualified = TRUE;
0440         NextExternalChar++;
0441 
0442         /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */
0443 
0444         while (AcpiNsValidRootPrefix (*NextExternalChar))
0445         {
0446             NextExternalChar++;
0447         }
0448     }
0449     else
0450     {
0451         /* Handle Carat prefixes */
0452 
0453         while (*NextExternalChar == '^')
0454         {
0455             Info->NumCarats++;
0456             NextExternalChar++;
0457         }
0458     }
0459 
0460     /*
0461      * Determine the number of ACPI name "segments" by counting the number of
0462      * path separators within the string. Start with one segment since the
0463      * segment count is [(# separators) + 1], and zero separators is ok.
0464      */
0465     if (*NextExternalChar)
0466     {
0467         Info->NumSegments = 1;
0468         for (i = 0; NextExternalChar[i]; i++)
0469         {
0470             if (AcpiNsValidPathSeparator (NextExternalChar[i]))
0471             {
0472                 Info->NumSegments++;
0473             }
0474         }
0475     }
0476 
0477     Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) +
0478                     4 + Info->NumCarats;
0479 
0480     Info->NextExternalChar = NextExternalChar;
0481 }
0482 
0483 
0484 /*******************************************************************************
0485  *
0486  * FUNCTION:    AcpiNsBuildInternalName
0487  *
0488  * PARAMETERS:  Info            - Info struct fully initialized
0489  *
0490  * RETURN:      Status
0491  *
0492  * DESCRIPTION: Construct the internal (AML) namestring
0493  *              corresponding to the external (ASL) namestring.
0494  *
0495  ******************************************************************************/
0496 
0497 ACPI_STATUS
0498 AcpiNsBuildInternalName (
0499     ACPI_NAMESTRING_INFO    *Info)
0500 {
0501     UINT32                  NumSegments = Info->NumSegments;
0502     char                    *InternalName = Info->InternalName;
0503     const char              *ExternalName = Info->NextExternalChar;
0504     char                    *Result = NULL;
0505     UINT32                  i;
0506 
0507 
0508     ACPI_FUNCTION_TRACE (NsBuildInternalName);
0509 
0510 
0511     /* Setup the correct prefixes, counts, and pointers */
0512 
0513     if (Info->FullyQualified)
0514     {
0515         InternalName[0] = '\\';
0516 
0517         if (NumSegments <= 1)
0518         {
0519             Result = &InternalName[1];
0520         }
0521         else if (NumSegments == 2)
0522         {
0523             InternalName[1] = AML_DUAL_NAME_PREFIX;
0524             Result = &InternalName[2];
0525         }
0526         else
0527         {
0528             InternalName[1] = AML_MULTI_NAME_PREFIX_OP;
0529             InternalName[2] = (char) NumSegments;
0530             Result = &InternalName[3];
0531         }
0532     }
0533     else
0534     {
0535         /*
0536          * Not fully qualified.
0537          * Handle Carats first, then append the name segments
0538          */
0539         i = 0;
0540         if (Info->NumCarats)
0541         {
0542             for (i = 0; i < Info->NumCarats; i++)
0543             {
0544                 InternalName[i] = '^';
0545             }
0546         }
0547 
0548         if (NumSegments <= 1)
0549         {
0550             Result = &InternalName[i];
0551         }
0552         else if (NumSegments == 2)
0553         {
0554             InternalName[i] = AML_DUAL_NAME_PREFIX;
0555             Result = &InternalName[(ACPI_SIZE) i+1];
0556         }
0557         else
0558         {
0559             InternalName[i] = AML_MULTI_NAME_PREFIX_OP;
0560             InternalName[(ACPI_SIZE) i+1] = (char) NumSegments;
0561             Result = &InternalName[(ACPI_SIZE) i+2];
0562         }
0563     }
0564 
0565     /* Build the name (minus path separators) */
0566 
0567     for (; NumSegments; NumSegments--)
0568     {
0569         for (i = 0; i < ACPI_NAME_SIZE; i++)
0570         {
0571             if (AcpiNsValidPathSeparator (*ExternalName) ||
0572                (*ExternalName == 0))
0573             {
0574                 /* Pad the segment with underscore(s) if segment is short */
0575 
0576                 Result[i] = '_';
0577             }
0578             else
0579             {
0580                 /* Convert the character to uppercase and save it */
0581 
0582                 Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName);
0583                 ExternalName++;
0584             }
0585         }
0586 
0587         /* Now we must have a path separator, or the pathname is bad */
0588 
0589         if (!AcpiNsValidPathSeparator (*ExternalName) &&
0590             (*ExternalName != 0))
0591         {
0592             return_ACPI_STATUS (AE_BAD_PARAMETER);
0593         }
0594 
0595         /* Move on the next segment */
0596 
0597         ExternalName++;
0598         Result += ACPI_NAME_SIZE;
0599     }
0600 
0601     /* Terminate the string */
0602 
0603     *Result = 0;
0604 
0605     if (Info->FullyQualified)
0606     {
0607         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
0608             InternalName, InternalName));
0609     }
0610     else
0611     {
0612         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
0613             InternalName, InternalName));
0614     }
0615 
0616     return_ACPI_STATUS (AE_OK);
0617 }
0618 
0619 
0620 /*******************************************************************************
0621  *
0622  * FUNCTION:    AcpiNsInternalizeName
0623  *
0624  * PARAMETERS:  *ExternalName           - External representation of name
0625  *              **Converted Name        - Where to return the resulting
0626  *                                        internal represention of the name
0627  *
0628  * RETURN:      Status
0629  *
0630  * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
0631  *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
0632  *
0633  *******************************************************************************/
0634 
0635 ACPI_STATUS
0636 AcpiNsInternalizeName (
0637     const char              *ExternalName,
0638     char                    **ConvertedName)
0639 {
0640     char                    *InternalName;
0641     ACPI_NAMESTRING_INFO    Info;
0642     ACPI_STATUS             Status;
0643 
0644 
0645     ACPI_FUNCTION_TRACE (NsInternalizeName);
0646 
0647 
0648     if ((!ExternalName)      ||
0649         (*ExternalName == 0) ||
0650         (!ConvertedName))
0651     {
0652         return_ACPI_STATUS (AE_BAD_PARAMETER);
0653     }
0654 
0655     /* Get the length of the new internal name */
0656 
0657     Info.ExternalName = ExternalName;
0658     AcpiNsGetInternalNameLength (&Info);
0659 
0660     /* We need a segment to store the internal  name */
0661 
0662     InternalName = ACPI_ALLOCATE_ZEROED (Info.Length);
0663     if (!InternalName)
0664     {
0665         return_ACPI_STATUS (AE_NO_MEMORY);
0666     }
0667 
0668     /* Build the name */
0669 
0670     Info.InternalName = InternalName;
0671     Status = AcpiNsBuildInternalName (&Info);
0672     if (ACPI_FAILURE (Status))
0673     {
0674         ACPI_FREE (InternalName);
0675         return_ACPI_STATUS (Status);
0676     }
0677 
0678     *ConvertedName = InternalName;
0679     return_ACPI_STATUS (AE_OK);
0680 }
0681 
0682 
0683 /*******************************************************************************
0684  *
0685  * FUNCTION:    AcpiNsExternalizeName
0686  *
0687  * PARAMETERS:  InternalNameLength  - Lenth of the internal name below
0688  *              InternalName        - Internal representation of name
0689  *              ConvertedNameLength - Where the length is returned
0690  *              ConvertedName       - Where the resulting external name
0691  *                                    is returned
0692  *
0693  * RETURN:      Status
0694  *
0695  * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
0696  *              to its external (printable) form (e.g. "\_PR_.CPU0")
0697  *
0698  ******************************************************************************/
0699 
0700 ACPI_STATUS
0701 AcpiNsExternalizeName (
0702     UINT32                  InternalNameLength,
0703     const char              *InternalName,
0704     UINT32                  *ConvertedNameLength,
0705     char                    **ConvertedName)
0706 {
0707     UINT32                  NamesIndex = 0;
0708     UINT32                  NumSegments = 0;
0709     UINT32                  RequiredLength;
0710     UINT32                  PrefixLength = 0;
0711     UINT32                  i = 0;
0712     UINT32                  j = 0;
0713 
0714 
0715     ACPI_FUNCTION_TRACE (NsExternalizeName);
0716 
0717 
0718     if (!InternalNameLength     ||
0719         !InternalName           ||
0720         !ConvertedName)
0721     {
0722         return_ACPI_STATUS (AE_BAD_PARAMETER);
0723     }
0724 
0725     /* Check for a prefix (one '\' | one or more '^') */
0726 
0727     switch (InternalName[0])
0728     {
0729     case '\\':
0730         PrefixLength = 1;
0731         break;
0732 
0733     case '^':
0734         for (i = 0; i < InternalNameLength; i++)
0735         {
0736             if (InternalName[i] == '^')
0737             {
0738                 PrefixLength = i + 1;
0739             }
0740             else
0741             {
0742                 break;
0743             }
0744         }
0745 
0746         if (i == InternalNameLength)
0747         {
0748             PrefixLength = i;
0749         }
0750 
0751         break;
0752 
0753     default:
0754         break;
0755     }
0756 
0757     /*
0758      * Check for object names. Note that there could be 0-255 of these
0759      * 4-byte elements.
0760      */
0761     if (PrefixLength < InternalNameLength)
0762     {
0763         switch (InternalName[PrefixLength])
0764         {
0765         case AML_MULTI_NAME_PREFIX_OP:
0766 
0767             /* <count> 4-byte names */
0768 
0769             NamesIndex = PrefixLength + 2;
0770             NumSegments = (UINT8)
0771                 InternalName[(ACPI_SIZE) PrefixLength + 1];
0772             break;
0773 
0774         case AML_DUAL_NAME_PREFIX:
0775 
0776             /* Two 4-byte names */
0777 
0778             NamesIndex = PrefixLength + 1;
0779             NumSegments = 2;
0780             break;
0781 
0782         case 0:
0783 
0784             /* NullName */
0785 
0786             NamesIndex = 0;
0787             NumSegments = 0;
0788             break;
0789 
0790         default:
0791 
0792             /* one 4-byte name */
0793 
0794             NamesIndex = PrefixLength;
0795             NumSegments = 1;
0796             break;
0797         }
0798     }
0799 
0800     /*
0801      * Calculate the length of ConvertedName, which equals the length
0802      * of the prefix, length of all object names, length of any required
0803      * punctuation ('.') between object names, plus the NULL terminator.
0804      */
0805     RequiredLength = PrefixLength + (4 * NumSegments) +
0806                         ((NumSegments > 0) ? (NumSegments - 1) : 0) + 1;
0807 
0808     /*
0809      * Check to see if we're still in bounds.  If not, there's a problem
0810      * with InternalName (invalid format).
0811      */
0812     if (RequiredLength > InternalNameLength)
0813     {
0814         ACPI_ERROR ((AE_INFO, "Invalid internal name"));
0815         return_ACPI_STATUS (AE_BAD_PATHNAME);
0816     }
0817 
0818     /* Build the ConvertedName */
0819 
0820     *ConvertedName = ACPI_ALLOCATE_ZEROED (RequiredLength);
0821     if (!(*ConvertedName))
0822     {
0823         return_ACPI_STATUS (AE_NO_MEMORY);
0824     }
0825 
0826     j = 0;
0827 
0828     for (i = 0; i < PrefixLength; i++)
0829     {
0830         (*ConvertedName)[j++] = InternalName[i];
0831     }
0832 
0833     if (NumSegments > 0)
0834     {
0835         for (i = 0; i < NumSegments; i++)
0836         {
0837             if (i > 0)
0838             {
0839                 (*ConvertedName)[j++] = '.';
0840             }
0841 
0842             (*ConvertedName)[j++] = InternalName[NamesIndex++];
0843             (*ConvertedName)[j++] = InternalName[NamesIndex++];
0844             (*ConvertedName)[j++] = InternalName[NamesIndex++];
0845             (*ConvertedName)[j++] = InternalName[NamesIndex++];
0846         }
0847     }
0848 
0849     if (ConvertedNameLength)
0850     {
0851         *ConvertedNameLength = (UINT32) RequiredLength;
0852     }
0853 
0854     return_ACPI_STATUS (AE_OK);
0855 }
0856 
0857 
0858 /*******************************************************************************
0859  *
0860  * FUNCTION:    AcpiNsMapHandleToNode
0861  *
0862  * PARAMETERS:  Handle          - Handle to be converted to an Node
0863  *
0864  * RETURN:      A Name table entry pointer
0865  *
0866  * DESCRIPTION: Convert a namespace handle to a real Node
0867  *
0868  * Note: Real integer handles would allow for more verification
0869  *       and keep all pointers within this subsystem - however this introduces
0870  *       more (and perhaps unnecessary) overhead.
0871  *
0872  * The current implemenation is basically a placeholder until such time comes
0873  * that it is needed.
0874  *
0875  ******************************************************************************/
0876 
0877 ACPI_NAMESPACE_NODE *
0878 AcpiNsMapHandleToNode (
0879     ACPI_HANDLE             Handle)
0880 {
0881 
0882     ACPI_FUNCTION_ENTRY ();
0883 
0884 
0885     /* Parameter validation */
0886 
0887     if ((!Handle) || (Handle == ACPI_ROOT_OBJECT))
0888     {
0889         return (AcpiGbl_RootNode);
0890     }
0891 
0892     /* We can at least attempt to verify the handle */
0893 
0894     if (ACPI_GET_DESCRIPTOR_TYPE (Handle) != ACPI_DESC_TYPE_NAMED)
0895     {
0896         return (NULL);
0897     }
0898 
0899     return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle));
0900 }
0901 
0902 
0903 /*******************************************************************************
0904  *
0905  * FUNCTION:    AcpiNsConvertEntryToHandle
0906  *
0907  * PARAMETERS:  Node          - Node to be converted to a Handle
0908  *
0909  * RETURN:      A user handle
0910  *
0911  * DESCRIPTION: Convert a real Node to a namespace handle
0912  *
0913  ******************************************************************************/
0914 
0915 ACPI_HANDLE
0916 AcpiNsConvertEntryToHandle (
0917     ACPI_NAMESPACE_NODE         *Node)
0918 {
0919 
0920 
0921     /*
0922      * Simple implementation for now;
0923      */
0924     return ((ACPI_HANDLE) Node);
0925 
0926 
0927 /* Example future implementation ---------------------
0928 
0929     if (!Node)
0930     {
0931         return (NULL);
0932     }
0933 
0934     if (Node == AcpiGbl_RootNode)
0935     {
0936         return (ACPI_ROOT_OBJECT);
0937     }
0938 
0939 
0940     return ((ACPI_HANDLE) Node);
0941 ------------------------------------------------------*/
0942 }
0943 
0944 
0945 /*******************************************************************************
0946  *
0947  * FUNCTION:    AcpiNsTerminate
0948  *
0949  * PARAMETERS:  none
0950  *
0951  * RETURN:      none
0952  *
0953  * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
0954  *
0955  ******************************************************************************/
0956 
0957 void
0958 AcpiNsTerminate (
0959     void)
0960 {
0961     ACPI_OPERAND_OBJECT     *ObjDesc;
0962 
0963 
0964     ACPI_FUNCTION_TRACE (NsTerminate);
0965 
0966 
0967     /*
0968      * 1) Free the entire namespace -- all nodes and objects
0969      *
0970      * Delete all object descriptors attached to namepsace nodes
0971      */
0972     AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
0973 
0974     /* Detach any objects attached to the root */
0975 
0976     ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode);
0977     if (ObjDesc)
0978     {
0979         AcpiNsDetachObject (AcpiGbl_RootNode);
0980     }
0981 
0982     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
0983     return_VOID;
0984 }
0985 
0986 
0987 /*******************************************************************************
0988  *
0989  * FUNCTION:    AcpiNsOpensScope
0990  *
0991  * PARAMETERS:  Type        - A valid namespace type
0992  *
0993  * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
0994  *              to the ACPI specification, else 0
0995  *
0996  ******************************************************************************/
0997 
0998 UINT32
0999 AcpiNsOpensScope (
1000     ACPI_OBJECT_TYPE        Type)
1001 {
1002     ACPI_FUNCTION_TRACE_STR (NsOpensScope, AcpiUtGetTypeName (Type));
1003 
1004 
1005     if (!AcpiUtValidObjectType (Type))
1006     {
1007         /* type code out of range  */
1008 
1009         ACPI_WARNING ((AE_INFO, "Invalid Object Type %X", Type));
1010         return_UINT32 (ACPI_NS_NORMAL);
1011     }
1012 
1013     return_UINT32 (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE);
1014 }
1015 
1016 
1017 /*******************************************************************************
1018  *
1019  * FUNCTION:    AcpiNsGetNode
1020  *
1021  * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
1022  *                            \ (backslash) and ^ (carat) prefixes, and the
1023  *                            . (period) to separate segments are supported.
1024  *              PrefixNode   - Root of subtree to be searched, or NS_ALL for the
1025  *                            root of the name space.  If Name is fully
1026  *                            qualified (first INT8 is '\'), the passed value
1027  *                            of Scope will not be accessed.
1028  *              Flags       - Used to indicate whether to perform upsearch or
1029  *                            not.
1030  *              ReturnNode  - Where the Node is returned
1031  *
1032  * DESCRIPTION: Look up a name relative to a given scope and return the
1033  *              corresponding Node.  NOTE: Scope can be null.
1034  *
1035  * MUTEX:       Locks namespace
1036  *
1037  ******************************************************************************/
1038 
1039 ACPI_STATUS
1040 AcpiNsGetNode (
1041     ACPI_NAMESPACE_NODE     *PrefixNode,
1042     const char              *Pathname,
1043     UINT32                  Flags,
1044     ACPI_NAMESPACE_NODE     **ReturnNode)
1045 {
1046     ACPI_GENERIC_STATE      ScopeInfo;
1047     ACPI_STATUS             Status;
1048     char                    *InternalPath;
1049 
1050 
1051     ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));
1052 
1053 
1054     if (!Pathname)
1055     {
1056         *ReturnNode = PrefixNode;
1057         if (!PrefixNode)
1058         {
1059             *ReturnNode = AcpiGbl_RootNode;
1060         }
1061         return_ACPI_STATUS (AE_OK);
1062     }
1063 
1064     /* Convert path to internal representation */
1065 
1066     Status = AcpiNsInternalizeName (Pathname, &InternalPath);
1067     if (ACPI_FAILURE (Status))
1068     {
1069         return_ACPI_STATUS (Status);
1070     }
1071 
1072     /* Must lock namespace during lookup */
1073 
1074     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1075     if (ACPI_FAILURE (Status))
1076     {
1077         goto Cleanup;
1078     }
1079 
1080     /* Setup lookup scope (search starting point) */
1081 
1082     ScopeInfo.Scope.Node = PrefixNode;
1083 
1084     /* Lookup the name in the namespace */
1085 
1086     Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY,
1087                 ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE),
1088                 NULL, ReturnNode);
1089     if (ACPI_FAILURE (Status))
1090     {
1091         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n",
1092                 Pathname, AcpiFormatException (Status)));
1093     }
1094 
1095     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1096 
1097 Cleanup:
1098     ACPI_FREE (InternalPath);
1099     return_ACPI_STATUS (Status);
1100 }
1101 
1102 
1103 /*******************************************************************************
1104  *
1105  * FUNCTION:    AcpiNsGetParentNode
1106  *
1107  * PARAMETERS:  Node       - Current table entry
1108  *
1109  * RETURN:      Parent entry of the given entry
1110  *
1111  * DESCRIPTION: Obtain the parent entry for a given entry in the namespace.
1112  *
1113  ******************************************************************************/
1114 
1115 ACPI_NAMESPACE_NODE *
1116 AcpiNsGetParentNode (
1117     ACPI_NAMESPACE_NODE     *Node)
1118 {
1119     ACPI_FUNCTION_ENTRY ();
1120 
1121 
1122     if (!Node)
1123     {
1124         return (NULL);
1125     }
1126 
1127     /*
1128      * Walk to the end of this peer list. The last entry is marked with a flag
1129      * and the peer pointer is really a pointer back to the parent. This saves
1130      * putting a parent back pointer in each and every named object!
1131      */
1132     while (!(Node->Flags & ANOBJ_END_OF_PEER_LIST))
1133     {
1134         Node = Node->Peer;
1135     }
1136 
1137     return (Node->Peer);
1138 }
1139 
1140 
1141 /*******************************************************************************
1142  *
1143  * FUNCTION:    AcpiNsGetNextValidNode
1144  *
1145  * PARAMETERS:  Node       - Current table entry
1146  *
1147  * RETURN:      Next valid Node in the linked node list. NULL if no more valid
1148  *              nodes.
1149  *
1150  * DESCRIPTION: Find the next valid node within a name table.
1151  *              Useful for implementing NULL-end-of-list loops.
1152  *
1153  ******************************************************************************/
1154 
1155 ACPI_NAMESPACE_NODE *
1156 AcpiNsGetNextValidNode (
1157     ACPI_NAMESPACE_NODE     *Node)
1158 {
1159 
1160     /* If we are at the end of this peer list, return NULL */
1161 
1162     if (Node->Flags & ANOBJ_END_OF_PEER_LIST)
1163     {
1164         return NULL;
1165     }
1166 
1167     /* Otherwise just return the next peer */
1168 
1169     return (Node->Peer);
1170 }
1171 
1172 
1173 #ifdef ACPI_OBSOLETE_FUNCTIONS
1174 /*******************************************************************************
1175  *
1176  * FUNCTION:    AcpiNsFindParentName
1177  *
1178  * PARAMETERS:  *ChildNode             - Named Obj whose name is to be found
1179  *
1180  * RETURN:      The ACPI name
1181  *
1182  * DESCRIPTION: Search for the given obj in its parent scope and return the
1183  *              name segment, or "????" if the parent name can't be found
1184  *              (which "should not happen").
1185  *
1186  ******************************************************************************/
1187 
1188 ACPI_NAME
1189 AcpiNsFindParentName (
1190     ACPI_NAMESPACE_NODE     *ChildNode)
1191 {
1192     ACPI_NAMESPACE_NODE     *ParentNode;
1193 
1194 
1195     ACPI_FUNCTION_TRACE (NsFindParentName);
1196 
1197 
1198     if (ChildNode)
1199     {
1200         /* Valid entry.  Get the parent Node */
1201 
1202         ParentNode = AcpiNsGetParentNode (ChildNode);
1203         if (ParentNode)
1204         {
1205             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
1206                 "Parent of %p [%4.4s] is %p [%4.4s]\n",
1207                 ChildNode,  AcpiUtGetNodeName (ChildNode),
1208                 ParentNode, AcpiUtGetNodeName (ParentNode)));
1209 
1210             if (ParentNode->Name.Integer)
1211             {
1212                 return_VALUE ((ACPI_NAME) ParentNode->Name.Integer);
1213             }
1214         }
1215 
1216         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
1217             "Unable to find parent of %p (%4.4s)\n",
1218             ChildNode, AcpiUtGetNodeName (ChildNode)));
1219     }
1220 
1221     return_VALUE (ACPI_UNKNOWN_NAME);
1222 }
1223 #endif
1224 
1225