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 - 2017, 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        /* Validate the Node */
  93
  94        if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
  95                ACPI_ERROR((AE_INFO,
  96                            "Invalid/cached reference target node: %p, descriptor type %d",
  97                            node, ACPI_GET_DESCRIPTOR_TYPE(node)));
  98                return (0);
  99        }
 100
 101        size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE);
 102        return (size);
 103}
 104
 105/*******************************************************************************
 106 *
 107 * FUNCTION:    acpi_ns_handle_to_name
 108 *
 109 * PARAMETERS:  target_handle           - Handle of named object whose name is
 110 *                                        to be found
 111 *              buffer                  - Where the name is returned
 112 *
 113 * RETURN:      Status, Buffer is filled with name if status is AE_OK
 114 *
 115 * DESCRIPTION: Build and return a full namespace name
 116 *
 117 ******************************************************************************/
 118
 119acpi_status
 120acpi_ns_handle_to_name(acpi_handle target_handle, struct acpi_buffer *buffer)
 121{
 122        acpi_status status;
 123        struct acpi_namespace_node *node;
 124        const char *node_name;
 125
 126        ACPI_FUNCTION_TRACE_PTR(ns_handle_to_name, target_handle);
 127
 128        node = acpi_ns_validate_handle(target_handle);
 129        if (!node) {
 130                return_ACPI_STATUS(AE_BAD_PARAMETER);
 131        }
 132
 133        /* Validate/Allocate/Clear caller buffer */
 134
 135        status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH);
 136        if (ACPI_FAILURE(status)) {
 137                return_ACPI_STATUS(status);
 138        }
 139
 140        /* Just copy the ACPI name from the Node and zero terminate it */
 141
 142        node_name = acpi_ut_get_node_name(node);
 143        ACPI_MOVE_NAME(buffer->pointer, node_name);
 144        ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
 145
 146        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%4.4s\n", (char *)buffer->pointer));
 147        return_ACPI_STATUS(AE_OK);
 148}
 149
 150/*******************************************************************************
 151 *
 152 * FUNCTION:    acpi_ns_handle_to_pathname
 153 *
 154 * PARAMETERS:  target_handle           - Handle of named object whose name is
 155 *                                        to be found
 156 *              buffer                  - Where the pathname is returned
 157 *              no_trailing             - Remove trailing '_' for each name
 158 *                                        segment
 159 *
 160 * RETURN:      Status, Buffer is filled with pathname if status is AE_OK
 161 *
 162 * DESCRIPTION: Build and return a full namespace pathname
 163 *
 164 ******************************************************************************/
 165
 166acpi_status
 167acpi_ns_handle_to_pathname(acpi_handle target_handle,
 168                           struct acpi_buffer *buffer, u8 no_trailing)
 169{
 170        acpi_status status;
 171        struct acpi_namespace_node *node;
 172        acpi_size required_size;
 173
 174        ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle);
 175
 176        node = acpi_ns_validate_handle(target_handle);
 177        if (!node) {
 178                return_ACPI_STATUS(AE_BAD_PARAMETER);
 179        }
 180
 181        /* Determine size required for the caller buffer */
 182
 183        required_size =
 184            acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);
 185        if (!required_size) {
 186                return_ACPI_STATUS(AE_BAD_PARAMETER);
 187        }
 188
 189        /* Validate/Allocate/Clear caller buffer */
 190
 191        status = acpi_ut_initialize_buffer(buffer, required_size);
 192        if (ACPI_FAILURE(status)) {
 193                return_ACPI_STATUS(status);
 194        }
 195
 196        /* Build the path in the caller buffer */
 197
 198        (void)acpi_ns_build_normalized_path(node, buffer->pointer,
 199                                            required_size, no_trailing);
 200
 201        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n",
 202                          (char *)buffer->pointer, (u32) required_size));
 203        return_ACPI_STATUS(AE_OK);
 204}
 205
 206/*******************************************************************************
 207 *
 208 * FUNCTION:    acpi_ns_build_normalized_path
 209 *
 210 * PARAMETERS:  node        - Namespace node
 211 *              full_path   - Where the path name is returned
 212 *              path_size   - Size of returned path name buffer
 213 *              no_trailing - Remove trailing '_' from each name segment
 214 *
 215 * RETURN:      Return 1 if the AML path is empty, otherwise returning (length
 216 *              of pathname + 1) which means the 'FullPath' contains a trailing
 217 *              null.
 218 *
 219 * DESCRIPTION: Build and return a full namespace pathname.
 220 *              Note that if the size of 'FullPath' isn't large enough to
 221 *              contain the namespace node's path name, the actual required
 222 *              buffer length is returned, and it should be greater than
 223 *              'PathSize'. So callers are able to check the returning value
 224 *              to determine the buffer size of 'FullPath'.
 225 *
 226 ******************************************************************************/
 227
 228u32
 229acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
 230                              char *full_path, u32 path_size, u8 no_trailing)
 231{
 232        u32 length = 0, i;
 233        char name[ACPI_NAME_SIZE];
 234        u8 do_no_trailing;
 235        char c, *left, *right;
 236        struct acpi_namespace_node *next_node;
 237
 238        ACPI_FUNCTION_TRACE_PTR(ns_build_normalized_path, node);
 239
 240#define ACPI_PATH_PUT8(path, size, byte, length)    \
 241        do {                                            \
 242                if ((length) < (size))                      \
 243                {                                           \
 244                        (path)[(length)] = (byte);              \
 245                }                                           \
 246                (length)++;                                 \
 247        } while (0)
 248
 249        /*
 250         * Make sure the path_size is correct, so that we don't need to
 251         * validate both full_path and path_size.
 252         */
 253        if (!full_path) {
 254                path_size = 0;
 255        }
 256
 257        if (!node) {
 258                goto build_trailing_null;
 259        }
 260
 261        next_node = node;
 262        while (next_node && next_node != acpi_gbl_root_node) {
 263                if (next_node != node) {
 264                        ACPI_PATH_PUT8(full_path, path_size,
 265                                       AML_DUAL_NAME_PREFIX, length);
 266                }
 267
 268                ACPI_MOVE_32_TO_32(name, &next_node->name);
 269                do_no_trailing = no_trailing;
 270                for (i = 0; i < 4; i++) {
 271                        c = name[4 - i - 1];
 272                        if (do_no_trailing && c != '_') {
 273                                do_no_trailing = FALSE;
 274                        }
 275                        if (!do_no_trailing) {
 276                                ACPI_PATH_PUT8(full_path, path_size, c, length);
 277                        }
 278                }
 279
 280                next_node = next_node->parent;
 281        }
 282
 283        ACPI_PATH_PUT8(full_path, path_size, AML_ROOT_PREFIX, length);
 284
 285        /* Reverse the path string */
 286
 287        if (length <= path_size) {
 288                left = full_path;
 289                right = full_path + length - 1;
 290
 291                while (left < right) {
 292                        c = *left;
 293                        *left++ = *right;
 294                        *right-- = c;
 295                }
 296        }
 297
 298        /* Append the trailing null */
 299
 300build_trailing_null:
 301        ACPI_PATH_PUT8(full_path, path_size, '\0', length);
 302
 303#undef ACPI_PATH_PUT8
 304
 305        return_UINT32(length);
 306}
 307
 308/*******************************************************************************
 309 *
 310 * FUNCTION:    acpi_ns_get_normalized_pathname
 311 *
 312 * PARAMETERS:  node            - Namespace node whose pathname is needed
 313 *              no_trailing     - Remove trailing '_' from each name segment
 314 *
 315 * RETURN:      Pointer to storage containing the fully qualified name of
 316 *              the node, In external format (name segments separated by path
 317 *              separators.)
 318 *
 319 * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
 320 *              for error and debug statements. All trailing '_' will be
 321 *              removed from the full pathname if 'NoTrailing' is specified..
 322 *
 323 ******************************************************************************/
 324
 325char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node,
 326                                      u8 no_trailing)
 327{
 328        char *name_buffer;
 329        acpi_size size;
 330
 331        ACPI_FUNCTION_TRACE_PTR(ns_get_normalized_pathname, node);
 332
 333        /* Calculate required buffer size based on depth below root */
 334
 335        size = acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);
 336        if (!size) {
 337                return_PTR(NULL);
 338        }
 339
 340        /* Allocate a buffer to be returned to caller */
 341
 342        name_buffer = ACPI_ALLOCATE_ZEROED(size);
 343        if (!name_buffer) {
 344                ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size));
 345                return_PTR(NULL);
 346        }
 347
 348        /* Build the path in the allocated buffer */
 349
 350        (void)acpi_ns_build_normalized_path(node, name_buffer, size,
 351                                            no_trailing);
 352
 353        return_PTR(name_buffer);
 354}
 355