linux/drivers/acpi/acpica/nsnames.c
<<
>>
Prefs
   1/*******************************************************************************
   2 *
   3 * Module Name: nsnames - Name manipulation and search
   4 *
   5 ******************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2016, 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#include <acpi/acpi.h>
  45#include "accommon.h"
  46#include "amlcode.h"
  47#include "acnamesp.h"
  48
  49#define _COMPONENT          ACPI_NAMESPACE
  50ACPI_MODULE_NAME("nsnames")
  51
  52/*******************************************************************************
  53 *
  54 * FUNCTION:    acpi_ns_get_external_pathname
  55 *
  56 * PARAMETERS:  node            - Namespace node whose pathname is needed
  57 *
  58 * RETURN:      Pointer to storage containing the fully qualified name of
  59 *              the node, In external format (name segments separated by path
  60 *              separators.)
  61 *
  62 * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
  63 *              for error and debug statements.
  64 *
  65 ******************************************************************************/
  66char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
  67{
  68        char *name_buffer;
  69
  70        ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node);
  71
  72        name_buffer = acpi_ns_get_normalized_pathname(node, FALSE);
  73        return_PTR(name_buffer);
  74}
  75
  76/*******************************************************************************
  77 *
  78 * FUNCTION:    acpi_ns_get_pathname_length
  79 *
  80 * PARAMETERS:  node        - Namespace node
  81 *
  82 * RETURN:      Length of path, including prefix
  83 *
  84 * DESCRIPTION: Get the length of the pathname string for this node
  85 *
  86 ******************************************************************************/
  87
  88acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
  89{
  90        acpi_size size;
  91
  92        ACPI_FUNCTION_ENTRY();
  93
  94        size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE);
  95        return (size);
  96}
  97
  98/*******************************************************************************
  99 *
 100 * FUNCTION:    acpi_ns_handle_to_pathname
 101 *
 102 * PARAMETERS:  target_handle           - Handle of named object whose name is
 103 *                                        to be found
 104 *              buffer                  - Where the pathname is returned
 105 *              no_trailing             - Remove trailing '_' for each name
 106 *                                        segment
 107 *
 108 * RETURN:      Status, Buffer is filled with pathname if status is AE_OK
 109 *
 110 * DESCRIPTION: Build and return a full namespace pathname
 111 *
 112 ******************************************************************************/
 113
 114acpi_status
 115acpi_ns_handle_to_pathname(acpi_handle target_handle,
 116                           struct acpi_buffer * buffer, u8 no_trailing)
 117{
 118        acpi_status status;
 119        struct acpi_namespace_node *node;
 120        acpi_size required_size;
 121
 122        ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle);
 123
 124        node = acpi_ns_validate_handle(target_handle);
 125        if (!node) {
 126                return_ACPI_STATUS(AE_BAD_PARAMETER);
 127        }
 128
 129        /* Determine size required for the caller buffer */
 130
 131        required_size =
 132            acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);
 133        if (!required_size) {
 134                return_ACPI_STATUS(AE_BAD_PARAMETER);
 135        }
 136
 137        /* Validate/Allocate/Clear caller buffer */
 138
 139        status = acpi_ut_initialize_buffer(buffer, required_size);
 140        if (ACPI_FAILURE(status)) {
 141                return_ACPI_STATUS(status);
 142        }
 143
 144        /* Build the path in the caller buffer */
 145
 146        (void)acpi_ns_build_normalized_path(node, buffer->pointer,
 147                                            required_size, no_trailing);
 148        if (ACPI_FAILURE(status)) {
 149                return_ACPI_STATUS(status);
 150        }
 151
 152        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n",
 153                          (char *)buffer->pointer, (u32) required_size));
 154        return_ACPI_STATUS(AE_OK);
 155}
 156
 157/*******************************************************************************
 158 *
 159 * FUNCTION:    acpi_ns_build_normalized_path
 160 *
 161 * PARAMETERS:  node        - Namespace node
 162 *              full_path   - Where the path name is returned
 163 *              path_size   - Size of returned path name buffer
 164 *              no_trailing - Remove trailing '_' from each name segment
 165 *
 166 * RETURN:      Return 1 if the AML path is empty, otherwise returning (length
 167 *              of pathname + 1) which means the 'FullPath' contains a trailing
 168 *              null.
 169 *
 170 * DESCRIPTION: Build and return a full namespace pathname.
 171 *              Note that if the size of 'FullPath' isn't large enough to
 172 *              contain the namespace node's path name, the actual required
 173 *              buffer length is returned, and it should be greater than
 174 *              'PathSize'. So callers are able to check the returning value
 175 *              to determine the buffer size of 'FullPath'.
 176 *
 177 ******************************************************************************/
 178
 179u32
 180acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
 181                              char *full_path, u32 path_size, u8 no_trailing)
 182{
 183        u32 length = 0, i;
 184        char name[ACPI_NAME_SIZE];
 185        u8 do_no_trailing;
 186        char c, *left, *right;
 187        struct acpi_namespace_node *next_node;
 188
 189        ACPI_FUNCTION_TRACE_PTR(ns_build_normalized_path, node);
 190
 191#define ACPI_PATH_PUT8(path, size, byte, length)    \
 192        do {                                            \
 193                if ((length) < (size))                      \
 194                {                                           \
 195                        (path)[(length)] = (byte);              \
 196                }                                           \
 197                (length)++;                                 \
 198        } while (0)
 199
 200        /*
 201         * Make sure the path_size is correct, so that we don't need to
 202         * validate both full_path and path_size.
 203         */
 204        if (!full_path) {
 205                path_size = 0;
 206        }
 207
 208        if (!node) {
 209                goto build_trailing_null;
 210        }
 211
 212        next_node = node;
 213        while (next_node && next_node != acpi_gbl_root_node) {
 214                if (next_node != node) {
 215                        ACPI_PATH_PUT8(full_path, path_size,
 216                                       AML_DUAL_NAME_PREFIX, length);
 217                }
 218
 219                ACPI_MOVE_32_TO_32(name, &next_node->name);
 220                do_no_trailing = no_trailing;
 221                for (i = 0; i < 4; i++) {
 222                        c = name[4 - i - 1];
 223                        if (do_no_trailing && c != '_') {
 224                                do_no_trailing = FALSE;
 225                        }
 226                        if (!do_no_trailing) {
 227                                ACPI_PATH_PUT8(full_path, path_size, c, length);
 228                        }
 229                }
 230
 231                next_node = next_node->parent;
 232        }
 233
 234        ACPI_PATH_PUT8(full_path, path_size, AML_ROOT_PREFIX, length);
 235
 236        /* Reverse the path string */
 237
 238        if (length <= path_size) {
 239                left = full_path;
 240                right = full_path + length - 1;
 241
 242                while (left < right) {
 243                        c = *left;
 244                        *left++ = *right;
 245                        *right-- = c;
 246                }
 247        }
 248
 249        /* Append the trailing null */
 250
 251build_trailing_null:
 252        ACPI_PATH_PUT8(full_path, path_size, '\0', length);
 253
 254#undef ACPI_PATH_PUT8
 255
 256        return_UINT32(length);
 257}
 258
 259/*******************************************************************************
 260 *
 261 * FUNCTION:    acpi_ns_get_normalized_pathname
 262 *
 263 * PARAMETERS:  node            - Namespace node whose pathname is needed
 264 *              no_trailing     - Remove trailing '_' from each name segment
 265 *
 266 * RETURN:      Pointer to storage containing the fully qualified name of
 267 *              the node, In external format (name segments separated by path
 268 *              separators.)
 269 *
 270 * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
 271 *              for error and debug statements. All trailing '_' will be
 272 *              removed from the full pathname if 'NoTrailing' is specified..
 273 *
 274 ******************************************************************************/
 275
 276char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node,
 277                                      u8 no_trailing)
 278{
 279        char *name_buffer;
 280        acpi_size size;
 281
 282        ACPI_FUNCTION_TRACE_PTR(ns_get_normalized_pathname, node);
 283
 284        /* Calculate required buffer size based on depth below root */
 285
 286        size = acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);
 287        if (!size) {
 288                return_PTR(NULL);
 289        }
 290
 291        /* Allocate a buffer to be returned to caller */
 292
 293        name_buffer = ACPI_ALLOCATE_ZEROED(size);
 294        if (!name_buffer) {
 295                ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size));
 296                return_PTR(NULL);
 297        }
 298
 299        /* Build the path in the allocated buffer */
 300
 301        (void)acpi_ns_build_normalized_path(node, name_buffer, size,
 302                                            no_trailing);
 303
 304        return_PTR(name_buffer);
 305}
 306