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