1 /*******************************************************************************
   2  *
   3  * Module Name: nsnames - Name manipulation and search
   4  *
   5  ******************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2013, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 #define __NSNAMES_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "amlcode.h"
  49 #include "acnamesp.h"
  50 
  51 
  52 #define _COMPONENT          ACPI_NAMESPACE
  53         ACPI_MODULE_NAME    ("nsnames")
  54 
  55 
  56 /*******************************************************************************
  57  *
  58  * FUNCTION:    AcpiNsBuildExternalPath
  59  *
  60  * PARAMETERS:  Node            - NS node whose pathname is needed
  61  *              Size            - Size of the pathname
  62  *              *NameBuffer     - Where to return the pathname
  63  *
  64  * RETURN:      Status
  65  *              Places the pathname into the NameBuffer, in external format
  66  *              (name segments separated by path separators)
  67  *
  68  * DESCRIPTION: Generate a full pathaname
  69  *
  70  ******************************************************************************/
  71 
  72 ACPI_STATUS
  73 AcpiNsBuildExternalPath (
  74     ACPI_NAMESPACE_NODE     *Node,
  75     ACPI_SIZE               Size,
  76     char                    *NameBuffer)
  77 {
  78     ACPI_SIZE               Index;
  79     ACPI_NAMESPACE_NODE     *ParentNode;
  80 
  81 
  82     ACPI_FUNCTION_ENTRY ();
  83 
  84 
  85     /* Special case for root */
  86 
  87     Index = Size - 1;
  88     if (Index < ACPI_NAME_SIZE)
  89     {
  90         NameBuffer[0] = AML_ROOT_PREFIX;
  91         NameBuffer[1] = 0;
  92         return (AE_OK);
  93     }
  94 
  95     /* Store terminator byte, then build name backwards */
  96 
  97     ParentNode = Node;
  98     NameBuffer[Index] = 0;
  99 
 100     while ((Index > ACPI_NAME_SIZE) && (ParentNode != AcpiGbl_RootNode))
 101     {
 102         Index -= ACPI_NAME_SIZE;
 103 
 104         /* Put the name into the buffer */
 105 
 106         ACPI_MOVE_32_TO_32 ((NameBuffer + Index), &ParentNode->Name);
 107         ParentNode = ParentNode->Parent;
 108 
 109         /* Prefix name with the path separator */
 110 
 111         Index--;
 112         NameBuffer[Index] = ACPI_PATH_SEPARATOR;
 113     }
 114 
 115     /* Overwrite final separator with the root prefix character */
 116 
 117     NameBuffer[Index] = AML_ROOT_PREFIX;
 118 
 119     if (Index != 0)
 120     {
 121         ACPI_ERROR ((AE_INFO,
 122             "Could not construct external pathname; index=%u, size=%u, Path=%s",
 123             (UINT32) Index, (UINT32) Size, &NameBuffer[Size]));
 124 
 125         return (AE_BAD_PARAMETER);
 126     }
 127 
 128     return (AE_OK);
 129 }
 130 
 131 
 132 /*******************************************************************************
 133  *
 134  * FUNCTION:    AcpiNsGetExternalPathname
 135  *
 136  * PARAMETERS:  Node            - Namespace node whose pathname is needed
 137  *
 138  * RETURN:      Pointer to storage containing the fully qualified name of
 139  *              the node, In external format (name segments separated by path
 140  *              separators.)
 141  *
 142  * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
 143  *              for error and debug statements.
 144  *
 145  ******************************************************************************/
 146 
 147 char *
 148 AcpiNsGetExternalPathname (
 149     ACPI_NAMESPACE_NODE     *Node)
 150 {
 151     ACPI_STATUS             Status;
 152     char                    *NameBuffer;
 153     ACPI_SIZE               Size;
 154 
 155 
 156     ACPI_FUNCTION_TRACE_PTR (NsGetExternalPathname, Node);
 157 
 158 
 159     /* Calculate required buffer size based on depth below root */
 160 
 161     Size = AcpiNsGetPathnameLength (Node);
 162     if (!Size)
 163     {
 164         return_PTR (NULL);
 165     }
 166 
 167     /* Allocate a buffer to be returned to caller */
 168 
 169     NameBuffer = ACPI_ALLOCATE_ZEROED (Size);
 170     if (!NameBuffer)
 171     {
 172         ACPI_ERROR ((AE_INFO, "Could not allocate %u bytes", (UINT32) Size));
 173         return_PTR (NULL);
 174     }
 175 
 176     /* Build the path in the allocated buffer */
 177 
 178     Status = AcpiNsBuildExternalPath (Node, Size, NameBuffer);
 179     if (ACPI_FAILURE (Status))
 180     {
 181         ACPI_FREE (NameBuffer);
 182         return_PTR (NULL);
 183     }
 184 
 185     return_PTR (NameBuffer);
 186 }
 187 
 188 
 189 /*******************************************************************************
 190  *
 191  * FUNCTION:    AcpiNsGetPathnameLength
 192  *
 193  * PARAMETERS:  Node        - Namespace node
 194  *
 195  * RETURN:      Length of path, including prefix
 196  *
 197  * DESCRIPTION: Get the length of the pathname string for this node
 198  *
 199  ******************************************************************************/
 200 
 201 ACPI_SIZE
 202 AcpiNsGetPathnameLength (
 203     ACPI_NAMESPACE_NODE     *Node)
 204 {
 205     ACPI_SIZE               Size;
 206     ACPI_NAMESPACE_NODE     *NextNode;
 207 
 208 
 209     ACPI_FUNCTION_ENTRY ();
 210 
 211 
 212     /*
 213      * Compute length of pathname as 5 * number of name segments.
 214      * Go back up the parent tree to the root
 215      */
 216     Size = 0;
 217     NextNode = Node;
 218 
 219     while (NextNode && (NextNode != AcpiGbl_RootNode))
 220     {
 221         if (ACPI_GET_DESCRIPTOR_TYPE (NextNode) != ACPI_DESC_TYPE_NAMED)
 222         {
 223             ACPI_ERROR ((AE_INFO,
 224                 "Invalid Namespace Node (%p) while traversing namespace",
 225                 NextNode));
 226             return (0);
 227         }
 228         Size += ACPI_PATH_SEGMENT_LENGTH;
 229         NextNode = NextNode->Parent;
 230     }
 231 
 232     if (!Size)
 233     {
 234         Size = 1; /* Root node case */
 235     }
 236 
 237     return (Size + 1);  /* +1 for null string terminator */
 238 }
 239 
 240 
 241 /*******************************************************************************
 242  *
 243  * FUNCTION:    AcpiNsHandleToPathname
 244  *
 245  * PARAMETERS:  TargetHandle            - Handle of named object whose name is
 246  *                                        to be found
 247  *              Buffer                  - Where the pathname is returned
 248  *
 249  * RETURN:      Status, Buffer is filled with pathname if status is AE_OK
 250  *
 251  * DESCRIPTION: Build and return a full namespace pathname
 252  *
 253  ******************************************************************************/
 254 
 255 ACPI_STATUS
 256 AcpiNsHandleToPathname (
 257     ACPI_HANDLE             TargetHandle,
 258     ACPI_BUFFER             *Buffer)
 259 {
 260     ACPI_STATUS             Status;
 261     ACPI_NAMESPACE_NODE     *Node;
 262     ACPI_SIZE               RequiredSize;
 263 
 264 
 265     ACPI_FUNCTION_TRACE_PTR (NsHandleToPathname, TargetHandle);
 266 
 267 
 268     Node = AcpiNsValidateHandle (TargetHandle);
 269     if (!Node)
 270     {
 271         return_ACPI_STATUS (AE_BAD_PARAMETER);
 272     }
 273 
 274     /* Determine size required for the caller buffer */
 275 
 276     RequiredSize = AcpiNsGetPathnameLength (Node);
 277     if (!RequiredSize)
 278     {
 279         return_ACPI_STATUS (AE_BAD_PARAMETER);
 280     }
 281 
 282     /* Validate/Allocate/Clear caller buffer */
 283 
 284     Status = AcpiUtInitializeBuffer (Buffer, RequiredSize);
 285     if (ACPI_FAILURE (Status))
 286     {
 287         return_ACPI_STATUS (Status);
 288     }
 289 
 290     /* Build the path in the caller buffer */
 291 
 292     Status = AcpiNsBuildExternalPath (Node, RequiredSize, Buffer->Pointer);
 293     if (ACPI_FAILURE (Status))
 294     {
 295         return_ACPI_STATUS (Status);
 296     }
 297 
 298     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X]\n",
 299         (char *) Buffer->Pointer, (UINT32) RequiredSize));
 300     return_ACPI_STATUS (AE_OK);
 301 }