1 /*******************************************************************************
 
   3  * Module Name: nsnames - Name manipulation and search
 
   5  ******************************************************************************/
 
   8  * Copyright (C) 2000 - 2008, Intel Corp.
 
  11  * Redistribution and use in source and binary forms, with or without
 
  12  * modification, are permitted provided that the following conditions
 
  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.
 
  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.
 
  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.
 
  44 #include <acpi/acpi.h>
 
  49 #define _COMPONENT          ACPI_NAMESPACE
 
  50 ACPI_MODULE_NAME("nsnames")
 
  52 /*******************************************************************************
 
  54  * FUNCTION:    acpi_ns_build_external_path
 
  56  * PARAMETERS:  Node            - NS node whose pathname is needed
 
  57  *              Size            - Size of the pathname
 
  58  *              *name_buffer    - Where to return the pathname
 
  61  *              Places the pathname into the name_buffer, in external format
 
  62  *              (name segments separated by path separators)
 
  64  * DESCRIPTION: Generate a full pathaname
 
  66  ******************************************************************************/
 
  68 acpi_ns_build_external_path(struct acpi_namespace_node *node,
 
  69                             acpi_size size, char *name_buffer)
 
  72         struct acpi_namespace_node *parent_node;
 
  74         ACPI_FUNCTION_ENTRY();
 
  76         /* Special case for root */
 
  79         if (index < ACPI_NAME_SIZE) {
 
  80                 name_buffer[0] = AML_ROOT_PREFIX;
 
  85         /* Store terminator byte, then build name backwards */
 
  88         name_buffer[index] = 0;
 
  90         while ((index > ACPI_NAME_SIZE) && (parent_node != acpi_gbl_root_node)) {
 
  91                 index -= ACPI_NAME_SIZE;
 
  93                 /* Put the name into the buffer */
 
  95                 ACPI_MOVE_32_TO_32((name_buffer + index), &parent_node->name);
 
  96                 parent_node = acpi_ns_get_parent_node(parent_node);
 
  98                 /* Prefix name with the path separator */
 
 101                 name_buffer[index] = ACPI_PATH_SEPARATOR;
 
 104         /* Overwrite final separator with the root prefix character */
 
 106         name_buffer[index] = AML_ROOT_PREFIX;
 
 110                             "Could not construct external pathname; index=%X, size=%X, Path=%s",
 
 111                             (u32) index, (u32) size, &name_buffer[size]));
 
 113                 return (AE_BAD_PARAMETER);
 
 119 /*******************************************************************************
 
 121  * FUNCTION:    acpi_ns_get_external_pathname
 
 123  * PARAMETERS:  Node            - Namespace node whose pathname is needed
 
 125  * RETURN:      Pointer to storage containing the fully qualified name of
 
 126  *              the node, In external format (name segments separated by path
 
 129  * DESCRIPTION: Used for debug printing in acpi_ns_search_table().
 
 131  ******************************************************************************/
 
 133 char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
 
 139         ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node);
 
 141         /* Calculate required buffer size based on depth below root */
 
 143         size = acpi_ns_get_pathname_length(node);
 
 148         /* Allocate a buffer to be returned to caller */
 
 150         name_buffer = ACPI_ALLOCATE_ZEROED(size);
 
 152                 ACPI_ERROR((AE_INFO, "Allocation failure"));
 
 156         /* Build the path in the allocated buffer */
 
 158         status = acpi_ns_build_external_path(node, size, name_buffer);
 
 159         if (ACPI_FAILURE(status)) {
 
 160                 ACPI_FREE(name_buffer);
 
 164         return_PTR(name_buffer);
 
 167 /*******************************************************************************
 
 169  * FUNCTION:    acpi_ns_get_pathname_length
 
 171  * PARAMETERS:  Node        - Namespace node
 
 173  * RETURN:      Length of path, including prefix
 
 175  * DESCRIPTION: Get the length of the pathname string for this node
 
 177  ******************************************************************************/
 
 179 acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
 
 182         struct acpi_namespace_node *next_node;
 
 184         ACPI_FUNCTION_ENTRY();
 
 187          * Compute length of pathname as 5 * number of name segments.
 
 188          * Go back up the parent tree to the root
 
 193         while (next_node && (next_node != acpi_gbl_root_node)) {
 
 194                 if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) {
 
 196                                     "Invalid Namespace Node (%p) while traversing namespace",
 
 200                 size += ACPI_PATH_SEGMENT_LENGTH;
 
 201                 next_node = acpi_ns_get_parent_node(next_node);
 
 205                 size = 1;       /* Root node case */
 
 208         return (size + 1);      /* +1 for null string terminator */
 
 211 /*******************************************************************************
 
 213  * FUNCTION:    acpi_ns_handle_to_pathname
 
 215  * PARAMETERS:  target_handle           - Handle of named object whose name is
 
 217  *              Buffer                  - Where the pathname is returned
 
 219  * RETURN:      Status, Buffer is filled with pathname if status is AE_OK
 
 221  * DESCRIPTION: Build and return a full namespace pathname
 
 223  ******************************************************************************/
 
 226 acpi_ns_handle_to_pathname(acpi_handle target_handle,
 
 227                            struct acpi_buffer * buffer)
 
 230         struct acpi_namespace_node *node;
 
 231         acpi_size required_size;
 
 233         ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle);
 
 235         node = acpi_ns_map_handle_to_node(target_handle);
 
 237                 return_ACPI_STATUS(AE_BAD_PARAMETER);
 
 240         /* Determine size required for the caller buffer */
 
 242         required_size = acpi_ns_get_pathname_length(node);
 
 243         if (!required_size) {
 
 244                 return_ACPI_STATUS(AE_BAD_PARAMETER);
 
 247         /* Validate/Allocate/Clear caller buffer */
 
 249         status = acpi_ut_initialize_buffer(buffer, required_size);
 
 250         if (ACPI_FAILURE(status)) {
 
 251                 return_ACPI_STATUS(status);
 
 254         /* Build the path in the caller buffer */
 
 257             acpi_ns_build_external_path(node, required_size, buffer->pointer);
 
 258         if (ACPI_FAILURE(status)) {
 
 259                 return_ACPI_STATUS(status);
 
 262         ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n",
 
 263                           (char *)buffer->pointer, (u32) required_size));
 
 264         return_ACPI_STATUS(AE_OK);