/******************************************************************************* * * Module Name: nsnames - Name manipulation and search * $Revision: 1.1 $ * ******************************************************************************/ /* * Copyright (C) 2000, 2001 R. Byron Moore * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nsnames") /******************************************************************************* * * FUNCTION: Acpi_ns_get_table_pathname * * PARAMETERS: Node - Scope whose name is needed * * RETURN: Pointer to storage containing the fully qualified name of * the scope, in Label format (all segments strung together * with no separators) * * DESCRIPTION: Used for debug printing in Acpi_ns_search_table(). * ******************************************************************************/ NATIVE_CHAR * acpi_ns_get_table_pathname ( ACPI_NAMESPACE_NODE *node) { NATIVE_CHAR *name_buffer; u32 size; ACPI_NAME name; ACPI_NAMESPACE_NODE *child_node; ACPI_NAMESPACE_NODE *parent_node; if (!acpi_gbl_root_node || !node) { /* * If the name space has not been initialized, * this function should not have been called. */ return (NULL); } child_node = node->child; /* Calculate required buffer size based on depth below root */ size = 1; parent_node = child_node; while (parent_node) { parent_node = acpi_ns_get_parent_object (parent_node); if (parent_node) { size += ACPI_NAME_SIZE; } } /* Allocate a buffer to be returned to caller */ name_buffer = acpi_cm_callocate (size + 1); if (!name_buffer) { REPORT_ERROR (("Ns_get_table_pathname: allocation failure\n")); return (NULL); } /* Store terminator byte, then build name backwards */ name_buffer[size] = '\0'; while ((size > ACPI_NAME_SIZE) && acpi_ns_get_parent_object (child_node)) { size -= ACPI_NAME_SIZE; name = acpi_ns_find_parent_name (child_node); /* Put the name into the buffer */ MOVE_UNALIGNED32_TO_32 ((name_buffer + size), &name); child_node = acpi_ns_get_parent_object (child_node); } name_buffer[--size] = AML_ROOT_PREFIX; return (name_buffer); } /******************************************************************************* * * FUNCTION: Acpi_ns_get_pathname_length * * PARAMETERS: Node - Namespace node * * RETURN: Length of path, including prefix * * DESCRIPTION: Get the length of the pathname string for this node * ******************************************************************************/ u32 acpi_ns_get_pathname_length ( ACPI_NAMESPACE_NODE *node) { u32 size; ACPI_NAMESPACE_NODE *next_node; /* * Compute length of pathname as 5 * number of name segments. * Go back up the parent tree to the root */ for (size = 0, next_node = node; acpi_ns_get_parent_object (next_node); next_node = acpi_ns_get_parent_object (next_node)) { size += PATH_SEGMENT_LENGTH; } /* Special case for size still 0 - no parent for "special" nodes */ if (!size) { size = PATH_SEGMENT_LENGTH; } return (size + 1); } /******************************************************************************* * * FUNCTION: Acpi_ns_handle_to_pathname * * PARAMETERS: Target_handle - Handle of named object whose name is * to be found * Buf_size - Size of the buffer provided * User_buffer - Where the pathname is returned * * RETURN: Status, Buffer is filled with pathname if status is AE_OK * * DESCRIPTION: Build and return a full namespace pathname * * MUTEX: Locks Namespace * ******************************************************************************/ ACPI_STATUS acpi_ns_handle_to_pathname ( ACPI_HANDLE target_handle, u32 *buf_size, NATIVE_CHAR *user_buffer) { ACPI_STATUS status = AE_OK; ACPI_NAMESPACE_NODE *node; u32 path_length; u32 user_buf_size; ACPI_NAME name; u32 size; if (!acpi_gbl_root_node || !target_handle) { /* * If the name space has not been initialized, * this function should not have been called. */ return (AE_NO_NAMESPACE); } node = acpi_ns_convert_handle_to_entry (target_handle); if (!node) { return (AE_BAD_PARAMETER); } /* Set return length to the required path length */ path_length = acpi_ns_get_pathname_length (node); size = path_length - 1; user_buf_size = *buf_size; *buf_size = path_length; /* Check if the user buffer is sufficiently large */ if (path_length > user_buf_size) { status = AE_BUFFER_OVERFLOW; goto exit; } /* Store null terminator */ user_buffer[size] = 0; size -= ACPI_NAME_SIZE; /* Put the original ACPI name at the end of the path */ MOVE_UNALIGNED32_TO_32 ((user_buffer + size), &node->name); user_buffer[--size] = PATH_SEPARATOR; /* Build name backwards, putting "." between segments */ while ((size > ACPI_NAME_SIZE) && node) { size -= ACPI_NAME_SIZE; name = acpi_ns_find_parent_name (node); MOVE_UNALIGNED32_TO_32 ((user_buffer + size), &name); user_buffer[--size] = PATH_SEPARATOR; node = acpi_ns_get_parent_object (node); } /* * Overlay the "." preceding the first segment with * the root name "\" */ user_buffer[size] = '\\'; exit: return (status); }