195b482a8SLen Brown /****************************************************************************** 295b482a8SLen Brown * 395b482a8SLen Brown * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing 495b482a8SLen Brown * parents and siblings and Scope manipulation 595b482a8SLen Brown * 695b482a8SLen Brown *****************************************************************************/ 795b482a8SLen Brown 895b482a8SLen Brown /* 995b482a8SLen Brown * Copyright (C) 2000 - 2008, Intel Corp. 1095b482a8SLen Brown * All rights reserved. 1195b482a8SLen Brown * 1295b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 1395b482a8SLen Brown * modification, are permitted provided that the following conditions 1495b482a8SLen Brown * are met: 1595b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 1695b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 1795b482a8SLen Brown * without modification. 1895b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1995b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 2095b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 2195b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 2295b482a8SLen Brown * binary redistribution. 2395b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 2495b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 2595b482a8SLen Brown * from this software without specific prior written permission. 2695b482a8SLen Brown * 2795b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 2895b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 2995b482a8SLen Brown * Software Foundation. 3095b482a8SLen Brown * 3195b482a8SLen Brown * NO WARRANTY 3295b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3395b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3495b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3595b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3695b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3795b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3895b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3995b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4095b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4195b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4295b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 4395b482a8SLen Brown */ 4495b482a8SLen Brown 4595b482a8SLen Brown #include <acpi/acpi.h> 46*e2f7a777SLen Brown #include "accommon.h" 47*e2f7a777SLen Brown #include "acnamesp.h" 48*e2f7a777SLen Brown #include "amlcode.h" 49*e2f7a777SLen Brown #include "actables.h" 5095b482a8SLen Brown 5195b482a8SLen Brown #define _COMPONENT ACPI_NAMESPACE 5295b482a8SLen Brown ACPI_MODULE_NAME("nsutils") 5395b482a8SLen Brown 5495b482a8SLen Brown /* Local prototypes */ 5595b482a8SLen Brown static u8 acpi_ns_valid_path_separator(char sep); 5695b482a8SLen Brown 5795b482a8SLen Brown #ifdef ACPI_OBSOLETE_FUNCTIONS 5895b482a8SLen Brown acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); 5995b482a8SLen Brown #endif 6095b482a8SLen Brown 6195b482a8SLen Brown /******************************************************************************* 6295b482a8SLen Brown * 6395b482a8SLen Brown * FUNCTION: acpi_ns_report_error 6495b482a8SLen Brown * 6595b482a8SLen Brown * PARAMETERS: module_name - Caller's module name (for error output) 6695b482a8SLen Brown * line_number - Caller's line number (for error output) 6795b482a8SLen Brown * internal_name - Name or path of the namespace node 6895b482a8SLen Brown * lookup_status - Exception code from NS lookup 6995b482a8SLen Brown * 7095b482a8SLen Brown * RETURN: None 7195b482a8SLen Brown * 7295b482a8SLen Brown * DESCRIPTION: Print warning message with full pathname 7395b482a8SLen Brown * 7495b482a8SLen Brown ******************************************************************************/ 7595b482a8SLen Brown 7695b482a8SLen Brown void 7795b482a8SLen Brown acpi_ns_report_error(const char *module_name, 7895b482a8SLen Brown u32 line_number, 7995b482a8SLen Brown const char *internal_name, acpi_status lookup_status) 8095b482a8SLen Brown { 8195b482a8SLen Brown acpi_status status; 8295b482a8SLen Brown u32 bad_name; 8395b482a8SLen Brown char *name = NULL; 8495b482a8SLen Brown 8595b482a8SLen Brown acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); 8695b482a8SLen Brown 8795b482a8SLen Brown if (lookup_status == AE_BAD_CHARACTER) { 8895b482a8SLen Brown 8995b482a8SLen Brown /* There is a non-ascii character in the name */ 9095b482a8SLen Brown 9195b482a8SLen Brown ACPI_MOVE_32_TO_32(&bad_name, internal_name); 9295b482a8SLen Brown acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); 9395b482a8SLen Brown } else { 9495b482a8SLen Brown /* Convert path to external format */ 9595b482a8SLen Brown 9695b482a8SLen Brown status = acpi_ns_externalize_name(ACPI_UINT32_MAX, 9795b482a8SLen Brown internal_name, NULL, &name); 9895b482a8SLen Brown 9995b482a8SLen Brown /* Print target name */ 10095b482a8SLen Brown 10195b482a8SLen Brown if (ACPI_SUCCESS(status)) { 10295b482a8SLen Brown acpi_os_printf("[%s]", name); 10395b482a8SLen Brown } else { 10495b482a8SLen Brown acpi_os_printf("[COULD NOT EXTERNALIZE NAME]"); 10595b482a8SLen Brown } 10695b482a8SLen Brown 10795b482a8SLen Brown if (name) { 10895b482a8SLen Brown ACPI_FREE(name); 10995b482a8SLen Brown } 11095b482a8SLen Brown } 11195b482a8SLen Brown 11295b482a8SLen Brown acpi_os_printf(" Namespace lookup failure, %s\n", 11395b482a8SLen Brown acpi_format_exception(lookup_status)); 11495b482a8SLen Brown } 11595b482a8SLen Brown 11695b482a8SLen Brown /******************************************************************************* 11795b482a8SLen Brown * 11895b482a8SLen Brown * FUNCTION: acpi_ns_report_method_error 11995b482a8SLen Brown * 12095b482a8SLen Brown * PARAMETERS: module_name - Caller's module name (for error output) 12195b482a8SLen Brown * line_number - Caller's line number (for error output) 12295b482a8SLen Brown * Message - Error message to use on failure 12395b482a8SLen Brown * prefix_node - Prefix relative to the path 12495b482a8SLen Brown * Path - Path to the node (optional) 12595b482a8SLen Brown * method_status - Execution status 12695b482a8SLen Brown * 12795b482a8SLen Brown * RETURN: None 12895b482a8SLen Brown * 12995b482a8SLen Brown * DESCRIPTION: Print warning message with full pathname 13095b482a8SLen Brown * 13195b482a8SLen Brown ******************************************************************************/ 13295b482a8SLen Brown 13395b482a8SLen Brown void 13495b482a8SLen Brown acpi_ns_report_method_error(const char *module_name, 13595b482a8SLen Brown u32 line_number, 13695b482a8SLen Brown const char *message, 13795b482a8SLen Brown struct acpi_namespace_node *prefix_node, 13895b482a8SLen Brown const char *path, acpi_status method_status) 13995b482a8SLen Brown { 14095b482a8SLen Brown acpi_status status; 14195b482a8SLen Brown struct acpi_namespace_node *node = prefix_node; 14295b482a8SLen Brown 14395b482a8SLen Brown acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); 14495b482a8SLen Brown 14595b482a8SLen Brown if (path) { 14695b482a8SLen Brown status = 14795b482a8SLen Brown acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, 14895b482a8SLen Brown &node); 14995b482a8SLen Brown if (ACPI_FAILURE(status)) { 15095b482a8SLen Brown acpi_os_printf("[Could not get node by pathname]"); 15195b482a8SLen Brown } 15295b482a8SLen Brown } 15395b482a8SLen Brown 15495b482a8SLen Brown acpi_ns_print_node_pathname(node, message); 15595b482a8SLen Brown acpi_os_printf(", %s\n", acpi_format_exception(method_status)); 15695b482a8SLen Brown } 15795b482a8SLen Brown 15895b482a8SLen Brown /******************************************************************************* 15995b482a8SLen Brown * 16095b482a8SLen Brown * FUNCTION: acpi_ns_print_node_pathname 16195b482a8SLen Brown * 16295b482a8SLen Brown * PARAMETERS: Node - Object 16395b482a8SLen Brown * Message - Prefix message 16495b482a8SLen Brown * 16595b482a8SLen Brown * DESCRIPTION: Print an object's full namespace pathname 16695b482a8SLen Brown * Manages allocation/freeing of a pathname buffer 16795b482a8SLen Brown * 16895b482a8SLen Brown ******************************************************************************/ 16995b482a8SLen Brown 17095b482a8SLen Brown void 17195b482a8SLen Brown acpi_ns_print_node_pathname(struct acpi_namespace_node *node, 17295b482a8SLen Brown const char *message) 17395b482a8SLen Brown { 17495b482a8SLen Brown struct acpi_buffer buffer; 17595b482a8SLen Brown acpi_status status; 17695b482a8SLen Brown 17795b482a8SLen Brown if (!node) { 17895b482a8SLen Brown acpi_os_printf("[NULL NAME]"); 17995b482a8SLen Brown return; 18095b482a8SLen Brown } 18195b482a8SLen Brown 18295b482a8SLen Brown /* Convert handle to full pathname and print it (with supplied message) */ 18395b482a8SLen Brown 18495b482a8SLen Brown buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 18595b482a8SLen Brown 18695b482a8SLen Brown status = acpi_ns_handle_to_pathname(node, &buffer); 18795b482a8SLen Brown if (ACPI_SUCCESS(status)) { 18895b482a8SLen Brown if (message) { 18995b482a8SLen Brown acpi_os_printf("%s ", message); 19095b482a8SLen Brown } 19195b482a8SLen Brown 19295b482a8SLen Brown acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node); 19395b482a8SLen Brown ACPI_FREE(buffer.pointer); 19495b482a8SLen Brown } 19595b482a8SLen Brown } 19695b482a8SLen Brown 19795b482a8SLen Brown /******************************************************************************* 19895b482a8SLen Brown * 19995b482a8SLen Brown * FUNCTION: acpi_ns_valid_root_prefix 20095b482a8SLen Brown * 20195b482a8SLen Brown * PARAMETERS: Prefix - Character to be checked 20295b482a8SLen Brown * 20395b482a8SLen Brown * RETURN: TRUE if a valid prefix 20495b482a8SLen Brown * 20595b482a8SLen Brown * DESCRIPTION: Check if a character is a valid ACPI Root prefix 20695b482a8SLen Brown * 20795b482a8SLen Brown ******************************************************************************/ 20895b482a8SLen Brown 20995b482a8SLen Brown u8 acpi_ns_valid_root_prefix(char prefix) 21095b482a8SLen Brown { 21195b482a8SLen Brown 21295b482a8SLen Brown return ((u8) (prefix == '\\')); 21395b482a8SLen Brown } 21495b482a8SLen Brown 21595b482a8SLen Brown /******************************************************************************* 21695b482a8SLen Brown * 21795b482a8SLen Brown * FUNCTION: acpi_ns_valid_path_separator 21895b482a8SLen Brown * 21995b482a8SLen Brown * PARAMETERS: Sep - Character to be checked 22095b482a8SLen Brown * 22195b482a8SLen Brown * RETURN: TRUE if a valid path separator 22295b482a8SLen Brown * 22395b482a8SLen Brown * DESCRIPTION: Check if a character is a valid ACPI path separator 22495b482a8SLen Brown * 22595b482a8SLen Brown ******************************************************************************/ 22695b482a8SLen Brown 22795b482a8SLen Brown static u8 acpi_ns_valid_path_separator(char sep) 22895b482a8SLen Brown { 22995b482a8SLen Brown 23095b482a8SLen Brown return ((u8) (sep == '.')); 23195b482a8SLen Brown } 23295b482a8SLen Brown 23395b482a8SLen Brown /******************************************************************************* 23495b482a8SLen Brown * 23595b482a8SLen Brown * FUNCTION: acpi_ns_get_type 23695b482a8SLen Brown * 23795b482a8SLen Brown * PARAMETERS: Node - Parent Node to be examined 23895b482a8SLen Brown * 23995b482a8SLen Brown * RETURN: Type field from Node whose handle is passed 24095b482a8SLen Brown * 24195b482a8SLen Brown * DESCRIPTION: Return the type of a Namespace node 24295b482a8SLen Brown * 24395b482a8SLen Brown ******************************************************************************/ 24495b482a8SLen Brown 24595b482a8SLen Brown acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) 24695b482a8SLen Brown { 24795b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_get_type); 24895b482a8SLen Brown 24995b482a8SLen Brown if (!node) { 25095b482a8SLen Brown ACPI_WARNING((AE_INFO, "Null Node parameter")); 25195b482a8SLen Brown return_UINT32(ACPI_TYPE_ANY); 25295b482a8SLen Brown } 25395b482a8SLen Brown 25495b482a8SLen Brown return_UINT32((acpi_object_type) node->type); 25595b482a8SLen Brown } 25695b482a8SLen Brown 25795b482a8SLen Brown /******************************************************************************* 25895b482a8SLen Brown * 25995b482a8SLen Brown * FUNCTION: acpi_ns_local 26095b482a8SLen Brown * 26195b482a8SLen Brown * PARAMETERS: Type - A namespace object type 26295b482a8SLen Brown * 26395b482a8SLen Brown * RETURN: LOCAL if names must be found locally in objects of the 26495b482a8SLen Brown * passed type, 0 if enclosing scopes should be searched 26595b482a8SLen Brown * 26695b482a8SLen Brown * DESCRIPTION: Returns scope rule for the given object type. 26795b482a8SLen Brown * 26895b482a8SLen Brown ******************************************************************************/ 26995b482a8SLen Brown 27095b482a8SLen Brown u32 acpi_ns_local(acpi_object_type type) 27195b482a8SLen Brown { 27295b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_local); 27395b482a8SLen Brown 27495b482a8SLen Brown if (!acpi_ut_valid_object_type(type)) { 27595b482a8SLen Brown 27695b482a8SLen Brown /* Type code out of range */ 27795b482a8SLen Brown 27895b482a8SLen Brown ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); 27995b482a8SLen Brown return_UINT32(ACPI_NS_NORMAL); 28095b482a8SLen Brown } 28195b482a8SLen Brown 28295b482a8SLen Brown return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); 28395b482a8SLen Brown } 28495b482a8SLen Brown 28595b482a8SLen Brown /******************************************************************************* 28695b482a8SLen Brown * 28795b482a8SLen Brown * FUNCTION: acpi_ns_get_internal_name_length 28895b482a8SLen Brown * 28995b482a8SLen Brown * PARAMETERS: Info - Info struct initialized with the 29095b482a8SLen Brown * external name pointer. 29195b482a8SLen Brown * 29295b482a8SLen Brown * RETURN: None 29395b482a8SLen Brown * 29495b482a8SLen Brown * DESCRIPTION: Calculate the length of the internal (AML) namestring 29595b482a8SLen Brown * corresponding to the external (ASL) namestring. 29695b482a8SLen Brown * 29795b482a8SLen Brown ******************************************************************************/ 29895b482a8SLen Brown 29995b482a8SLen Brown void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) 30095b482a8SLen Brown { 30195b482a8SLen Brown const char *next_external_char; 30295b482a8SLen Brown u32 i; 30395b482a8SLen Brown 30495b482a8SLen Brown ACPI_FUNCTION_ENTRY(); 30595b482a8SLen Brown 30695b482a8SLen Brown next_external_char = info->external_name; 30795b482a8SLen Brown info->num_carats = 0; 30895b482a8SLen Brown info->num_segments = 0; 30995b482a8SLen Brown info->fully_qualified = FALSE; 31095b482a8SLen Brown 31195b482a8SLen Brown /* 31295b482a8SLen Brown * For the internal name, the required length is 4 bytes per segment, plus 31395b482a8SLen Brown * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null 31495b482a8SLen Brown * (which is not really needed, but no there's harm in putting it there) 31595b482a8SLen Brown * 31695b482a8SLen Brown * strlen() + 1 covers the first name_seg, which has no path separator 31795b482a8SLen Brown */ 31895b482a8SLen Brown if (acpi_ns_valid_root_prefix(*next_external_char)) { 31995b482a8SLen Brown info->fully_qualified = TRUE; 32095b482a8SLen Brown next_external_char++; 32195b482a8SLen Brown 32295b482a8SLen Brown /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */ 32395b482a8SLen Brown 32495b482a8SLen Brown while (acpi_ns_valid_root_prefix(*next_external_char)) { 32595b482a8SLen Brown next_external_char++; 32695b482a8SLen Brown } 32795b482a8SLen Brown } else { 32895b482a8SLen Brown /* 32995b482a8SLen Brown * Handle Carat prefixes 33095b482a8SLen Brown */ 33195b482a8SLen Brown while (*next_external_char == '^') { 33295b482a8SLen Brown info->num_carats++; 33395b482a8SLen Brown next_external_char++; 33495b482a8SLen Brown } 33595b482a8SLen Brown } 33695b482a8SLen Brown 33795b482a8SLen Brown /* 33895b482a8SLen Brown * Determine the number of ACPI name "segments" by counting the number of 33995b482a8SLen Brown * path separators within the string. Start with one segment since the 34095b482a8SLen Brown * segment count is [(# separators) + 1], and zero separators is ok. 34195b482a8SLen Brown */ 34295b482a8SLen Brown if (*next_external_char) { 34395b482a8SLen Brown info->num_segments = 1; 34495b482a8SLen Brown for (i = 0; next_external_char[i]; i++) { 34595b482a8SLen Brown if (acpi_ns_valid_path_separator(next_external_char[i])) { 34695b482a8SLen Brown info->num_segments++; 34795b482a8SLen Brown } 34895b482a8SLen Brown } 34995b482a8SLen Brown } 35095b482a8SLen Brown 35195b482a8SLen Brown info->length = (ACPI_NAME_SIZE * info->num_segments) + 35295b482a8SLen Brown 4 + info->num_carats; 35395b482a8SLen Brown 35495b482a8SLen Brown info->next_external_char = next_external_char; 35595b482a8SLen Brown } 35695b482a8SLen Brown 35795b482a8SLen Brown /******************************************************************************* 35895b482a8SLen Brown * 35995b482a8SLen Brown * FUNCTION: acpi_ns_build_internal_name 36095b482a8SLen Brown * 36195b482a8SLen Brown * PARAMETERS: Info - Info struct fully initialized 36295b482a8SLen Brown * 36395b482a8SLen Brown * RETURN: Status 36495b482a8SLen Brown * 36595b482a8SLen Brown * DESCRIPTION: Construct the internal (AML) namestring 36695b482a8SLen Brown * corresponding to the external (ASL) namestring. 36795b482a8SLen Brown * 36895b482a8SLen Brown ******************************************************************************/ 36995b482a8SLen Brown 37095b482a8SLen Brown acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) 37195b482a8SLen Brown { 37295b482a8SLen Brown u32 num_segments = info->num_segments; 37395b482a8SLen Brown char *internal_name = info->internal_name; 37495b482a8SLen Brown const char *external_name = info->next_external_char; 37595b482a8SLen Brown char *result = NULL; 37695b482a8SLen Brown u32 i; 37795b482a8SLen Brown 37895b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_build_internal_name); 37995b482a8SLen Brown 38095b482a8SLen Brown /* Setup the correct prefixes, counts, and pointers */ 38195b482a8SLen Brown 38295b482a8SLen Brown if (info->fully_qualified) { 38395b482a8SLen Brown internal_name[0] = '\\'; 38495b482a8SLen Brown 38595b482a8SLen Brown if (num_segments <= 1) { 38695b482a8SLen Brown result = &internal_name[1]; 38795b482a8SLen Brown } else if (num_segments == 2) { 38895b482a8SLen Brown internal_name[1] = AML_DUAL_NAME_PREFIX; 38995b482a8SLen Brown result = &internal_name[2]; 39095b482a8SLen Brown } else { 39195b482a8SLen Brown internal_name[1] = AML_MULTI_NAME_PREFIX_OP; 39295b482a8SLen Brown internal_name[2] = (char)num_segments; 39395b482a8SLen Brown result = &internal_name[3]; 39495b482a8SLen Brown } 39595b482a8SLen Brown } else { 39695b482a8SLen Brown /* 39795b482a8SLen Brown * Not fully qualified. 39895b482a8SLen Brown * Handle Carats first, then append the name segments 39995b482a8SLen Brown */ 40095b482a8SLen Brown i = 0; 40195b482a8SLen Brown if (info->num_carats) { 40295b482a8SLen Brown for (i = 0; i < info->num_carats; i++) { 40395b482a8SLen Brown internal_name[i] = '^'; 40495b482a8SLen Brown } 40595b482a8SLen Brown } 40695b482a8SLen Brown 40795b482a8SLen Brown if (num_segments <= 1) { 40895b482a8SLen Brown result = &internal_name[i]; 40995b482a8SLen Brown } else if (num_segments == 2) { 41095b482a8SLen Brown internal_name[i] = AML_DUAL_NAME_PREFIX; 41195b482a8SLen Brown result = &internal_name[(acpi_size) i + 1]; 41295b482a8SLen Brown } else { 41395b482a8SLen Brown internal_name[i] = AML_MULTI_NAME_PREFIX_OP; 41495b482a8SLen Brown internal_name[(acpi_size) i + 1] = (char)num_segments; 41595b482a8SLen Brown result = &internal_name[(acpi_size) i + 2]; 41695b482a8SLen Brown } 41795b482a8SLen Brown } 41895b482a8SLen Brown 41995b482a8SLen Brown /* Build the name (minus path separators) */ 42095b482a8SLen Brown 42195b482a8SLen Brown for (; num_segments; num_segments--) { 42295b482a8SLen Brown for (i = 0; i < ACPI_NAME_SIZE; i++) { 42395b482a8SLen Brown if (acpi_ns_valid_path_separator(*external_name) || 42495b482a8SLen Brown (*external_name == 0)) { 42595b482a8SLen Brown 42695b482a8SLen Brown /* Pad the segment with underscore(s) if segment is short */ 42795b482a8SLen Brown 42895b482a8SLen Brown result[i] = '_'; 42995b482a8SLen Brown } else { 43095b482a8SLen Brown /* Convert the character to uppercase and save it */ 43195b482a8SLen Brown 43295b482a8SLen Brown result[i] = 43395b482a8SLen Brown (char)ACPI_TOUPPER((int)*external_name); 43495b482a8SLen Brown external_name++; 43595b482a8SLen Brown } 43695b482a8SLen Brown } 43795b482a8SLen Brown 43895b482a8SLen Brown /* Now we must have a path separator, or the pathname is bad */ 43995b482a8SLen Brown 44095b482a8SLen Brown if (!acpi_ns_valid_path_separator(*external_name) && 44195b482a8SLen Brown (*external_name != 0)) { 44295b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 44395b482a8SLen Brown } 44495b482a8SLen Brown 44595b482a8SLen Brown /* Move on the next segment */ 44695b482a8SLen Brown 44795b482a8SLen Brown external_name++; 44895b482a8SLen Brown result += ACPI_NAME_SIZE; 44995b482a8SLen Brown } 45095b482a8SLen Brown 45195b482a8SLen Brown /* Terminate the string */ 45295b482a8SLen Brown 45395b482a8SLen Brown *result = 0; 45495b482a8SLen Brown 45595b482a8SLen Brown if (info->fully_qualified) { 45695b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 45795b482a8SLen Brown "Returning [%p] (abs) \"\\%s\"\n", 45895b482a8SLen Brown internal_name, internal_name)); 45995b482a8SLen Brown } else { 46095b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n", 46195b482a8SLen Brown internal_name, internal_name)); 46295b482a8SLen Brown } 46395b482a8SLen Brown 46495b482a8SLen Brown return_ACPI_STATUS(AE_OK); 46595b482a8SLen Brown } 46695b482a8SLen Brown 46795b482a8SLen Brown /******************************************************************************* 46895b482a8SLen Brown * 46995b482a8SLen Brown * FUNCTION: acpi_ns_internalize_name 47095b482a8SLen Brown * 47195b482a8SLen Brown * PARAMETERS: *external_name - External representation of name 47295b482a8SLen Brown * **Converted Name - Where to return the resulting 47395b482a8SLen Brown * internal represention of the name 47495b482a8SLen Brown * 47595b482a8SLen Brown * RETURN: Status 47695b482a8SLen Brown * 47795b482a8SLen Brown * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") 47895b482a8SLen Brown * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 47995b482a8SLen Brown * 48095b482a8SLen Brown *******************************************************************************/ 48195b482a8SLen Brown 48295b482a8SLen Brown acpi_status 48395b482a8SLen Brown acpi_ns_internalize_name(const char *external_name, char **converted_name) 48495b482a8SLen Brown { 48595b482a8SLen Brown char *internal_name; 48695b482a8SLen Brown struct acpi_namestring_info info; 48795b482a8SLen Brown acpi_status status; 48895b482a8SLen Brown 48995b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_internalize_name); 49095b482a8SLen Brown 49195b482a8SLen Brown if ((!external_name) || (*external_name == 0) || (!converted_name)) { 49295b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 49395b482a8SLen Brown } 49495b482a8SLen Brown 49595b482a8SLen Brown /* Get the length of the new internal name */ 49695b482a8SLen Brown 49795b482a8SLen Brown info.external_name = external_name; 49895b482a8SLen Brown acpi_ns_get_internal_name_length(&info); 49995b482a8SLen Brown 50095b482a8SLen Brown /* We need a segment to store the internal name */ 50195b482a8SLen Brown 50295b482a8SLen Brown internal_name = ACPI_ALLOCATE_ZEROED(info.length); 50395b482a8SLen Brown if (!internal_name) { 50495b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 50595b482a8SLen Brown } 50695b482a8SLen Brown 50795b482a8SLen Brown /* Build the name */ 50895b482a8SLen Brown 50995b482a8SLen Brown info.internal_name = internal_name; 51095b482a8SLen Brown status = acpi_ns_build_internal_name(&info); 51195b482a8SLen Brown if (ACPI_FAILURE(status)) { 51295b482a8SLen Brown ACPI_FREE(internal_name); 51395b482a8SLen Brown return_ACPI_STATUS(status); 51495b482a8SLen Brown } 51595b482a8SLen Brown 51695b482a8SLen Brown *converted_name = internal_name; 51795b482a8SLen Brown return_ACPI_STATUS(AE_OK); 51895b482a8SLen Brown } 51995b482a8SLen Brown 52095b482a8SLen Brown /******************************************************************************* 52195b482a8SLen Brown * 52295b482a8SLen Brown * FUNCTION: acpi_ns_externalize_name 52395b482a8SLen Brown * 52495b482a8SLen Brown * PARAMETERS: internal_name_length - Lenth of the internal name below 52595b482a8SLen Brown * internal_name - Internal representation of name 52695b482a8SLen Brown * converted_name_length - Where the length is returned 52795b482a8SLen Brown * converted_name - Where the resulting external name 52895b482a8SLen Brown * is returned 52995b482a8SLen Brown * 53095b482a8SLen Brown * RETURN: Status 53195b482a8SLen Brown * 53295b482a8SLen Brown * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 53395b482a8SLen Brown * to its external (printable) form (e.g. "\_PR_.CPU0") 53495b482a8SLen Brown * 53595b482a8SLen Brown ******************************************************************************/ 53695b482a8SLen Brown 53795b482a8SLen Brown acpi_status 53895b482a8SLen Brown acpi_ns_externalize_name(u32 internal_name_length, 53995b482a8SLen Brown const char *internal_name, 54095b482a8SLen Brown u32 * converted_name_length, char **converted_name) 54195b482a8SLen Brown { 54295b482a8SLen Brown u32 names_index = 0; 54395b482a8SLen Brown u32 num_segments = 0; 54495b482a8SLen Brown u32 required_length; 54595b482a8SLen Brown u32 prefix_length = 0; 54695b482a8SLen Brown u32 i = 0; 54795b482a8SLen Brown u32 j = 0; 54895b482a8SLen Brown 54995b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_externalize_name); 55095b482a8SLen Brown 55195b482a8SLen Brown if (!internal_name_length || !internal_name || !converted_name) { 55295b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 55395b482a8SLen Brown } 55495b482a8SLen Brown 55595b482a8SLen Brown /* 55695b482a8SLen Brown * Check for a prefix (one '\' | one or more '^'). 55795b482a8SLen Brown */ 55895b482a8SLen Brown switch (internal_name[0]) { 55995b482a8SLen Brown case '\\': 56095b482a8SLen Brown prefix_length = 1; 56195b482a8SLen Brown break; 56295b482a8SLen Brown 56395b482a8SLen Brown case '^': 56495b482a8SLen Brown for (i = 0; i < internal_name_length; i++) { 56595b482a8SLen Brown if (internal_name[i] == '^') { 56695b482a8SLen Brown prefix_length = i + 1; 56795b482a8SLen Brown } else { 56895b482a8SLen Brown break; 56995b482a8SLen Brown } 57095b482a8SLen Brown } 57195b482a8SLen Brown 57295b482a8SLen Brown if (i == internal_name_length) { 57395b482a8SLen Brown prefix_length = i; 57495b482a8SLen Brown } 57595b482a8SLen Brown 57695b482a8SLen Brown break; 57795b482a8SLen Brown 57895b482a8SLen Brown default: 57995b482a8SLen Brown break; 58095b482a8SLen Brown } 58195b482a8SLen Brown 58295b482a8SLen Brown /* 58395b482a8SLen Brown * Check for object names. Note that there could be 0-255 of these 58495b482a8SLen Brown * 4-byte elements. 58595b482a8SLen Brown */ 58695b482a8SLen Brown if (prefix_length < internal_name_length) { 58795b482a8SLen Brown switch (internal_name[prefix_length]) { 58895b482a8SLen Brown case AML_MULTI_NAME_PREFIX_OP: 58995b482a8SLen Brown 59095b482a8SLen Brown /* <count> 4-byte names */ 59195b482a8SLen Brown 59295b482a8SLen Brown names_index = prefix_length + 2; 59395b482a8SLen Brown num_segments = (u8) 59495b482a8SLen Brown internal_name[(acpi_size) prefix_length + 1]; 59595b482a8SLen Brown break; 59695b482a8SLen Brown 59795b482a8SLen Brown case AML_DUAL_NAME_PREFIX: 59895b482a8SLen Brown 59995b482a8SLen Brown /* Two 4-byte names */ 60095b482a8SLen Brown 60195b482a8SLen Brown names_index = prefix_length + 1; 60295b482a8SLen Brown num_segments = 2; 60395b482a8SLen Brown break; 60495b482a8SLen Brown 60595b482a8SLen Brown case 0: 60695b482a8SLen Brown 60795b482a8SLen Brown /* null_name */ 60895b482a8SLen Brown 60995b482a8SLen Brown names_index = 0; 61095b482a8SLen Brown num_segments = 0; 61195b482a8SLen Brown break; 61295b482a8SLen Brown 61395b482a8SLen Brown default: 61495b482a8SLen Brown 61595b482a8SLen Brown /* one 4-byte name */ 61695b482a8SLen Brown 61795b482a8SLen Brown names_index = prefix_length; 61895b482a8SLen Brown num_segments = 1; 61995b482a8SLen Brown break; 62095b482a8SLen Brown } 62195b482a8SLen Brown } 62295b482a8SLen Brown 62395b482a8SLen Brown /* 62495b482a8SLen Brown * Calculate the length of converted_name, which equals the length 62595b482a8SLen Brown * of the prefix, length of all object names, length of any required 62695b482a8SLen Brown * punctuation ('.') between object names, plus the NULL terminator. 62795b482a8SLen Brown */ 62895b482a8SLen Brown required_length = prefix_length + (4 * num_segments) + 62995b482a8SLen Brown ((num_segments > 0) ? (num_segments - 1) : 0) + 1; 63095b482a8SLen Brown 63195b482a8SLen Brown /* 63295b482a8SLen Brown * Check to see if we're still in bounds. If not, there's a problem 63395b482a8SLen Brown * with internal_name (invalid format). 63495b482a8SLen Brown */ 63595b482a8SLen Brown if (required_length > internal_name_length) { 63695b482a8SLen Brown ACPI_ERROR((AE_INFO, "Invalid internal name")); 63795b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PATHNAME); 63895b482a8SLen Brown } 63995b482a8SLen Brown 64095b482a8SLen Brown /* 64195b482a8SLen Brown * Build converted_name 64295b482a8SLen Brown */ 64395b482a8SLen Brown *converted_name = ACPI_ALLOCATE_ZEROED(required_length); 64495b482a8SLen Brown if (!(*converted_name)) { 64595b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 64695b482a8SLen Brown } 64795b482a8SLen Brown 64895b482a8SLen Brown j = 0; 64995b482a8SLen Brown 65095b482a8SLen Brown for (i = 0; i < prefix_length; i++) { 65195b482a8SLen Brown (*converted_name)[j++] = internal_name[i]; 65295b482a8SLen Brown } 65395b482a8SLen Brown 65495b482a8SLen Brown if (num_segments > 0) { 65595b482a8SLen Brown for (i = 0; i < num_segments; i++) { 65695b482a8SLen Brown if (i > 0) { 65795b482a8SLen Brown (*converted_name)[j++] = '.'; 65895b482a8SLen Brown } 65995b482a8SLen Brown 66095b482a8SLen Brown (*converted_name)[j++] = internal_name[names_index++]; 66195b482a8SLen Brown (*converted_name)[j++] = internal_name[names_index++]; 66295b482a8SLen Brown (*converted_name)[j++] = internal_name[names_index++]; 66395b482a8SLen Brown (*converted_name)[j++] = internal_name[names_index++]; 66495b482a8SLen Brown } 66595b482a8SLen Brown } 66695b482a8SLen Brown 66795b482a8SLen Brown if (converted_name_length) { 66895b482a8SLen Brown *converted_name_length = (u32) required_length; 66995b482a8SLen Brown } 67095b482a8SLen Brown 67195b482a8SLen Brown return_ACPI_STATUS(AE_OK); 67295b482a8SLen Brown } 67395b482a8SLen Brown 67495b482a8SLen Brown /******************************************************************************* 67595b482a8SLen Brown * 67695b482a8SLen Brown * FUNCTION: acpi_ns_map_handle_to_node 67795b482a8SLen Brown * 67895b482a8SLen Brown * PARAMETERS: Handle - Handle to be converted to an Node 67995b482a8SLen Brown * 68095b482a8SLen Brown * RETURN: A Name table entry pointer 68195b482a8SLen Brown * 68295b482a8SLen Brown * DESCRIPTION: Convert a namespace handle to a real Node 68395b482a8SLen Brown * 68495b482a8SLen Brown * Note: Real integer handles would allow for more verification 68595b482a8SLen Brown * and keep all pointers within this subsystem - however this introduces 68695b482a8SLen Brown * more (and perhaps unnecessary) overhead. 68795b482a8SLen Brown * 68895b482a8SLen Brown ******************************************************************************/ 68995b482a8SLen Brown 69095b482a8SLen Brown struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) 69195b482a8SLen Brown { 69295b482a8SLen Brown 69395b482a8SLen Brown ACPI_FUNCTION_ENTRY(); 69495b482a8SLen Brown 69595b482a8SLen Brown /* 69695b482a8SLen Brown * Simple implementation 69795b482a8SLen Brown */ 69895b482a8SLen Brown if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { 69995b482a8SLen Brown return (acpi_gbl_root_node); 70095b482a8SLen Brown } 70195b482a8SLen Brown 70295b482a8SLen Brown /* We can at least attempt to verify the handle */ 70395b482a8SLen Brown 70495b482a8SLen Brown if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) { 70595b482a8SLen Brown return (NULL); 70695b482a8SLen Brown } 70795b482a8SLen Brown 70895b482a8SLen Brown return (ACPI_CAST_PTR(struct acpi_namespace_node, handle)); 70995b482a8SLen Brown } 71095b482a8SLen Brown 71195b482a8SLen Brown /******************************************************************************* 71295b482a8SLen Brown * 71395b482a8SLen Brown * FUNCTION: acpi_ns_convert_entry_to_handle 71495b482a8SLen Brown * 71595b482a8SLen Brown * PARAMETERS: Node - Node to be converted to a Handle 71695b482a8SLen Brown * 71795b482a8SLen Brown * RETURN: A user handle 71895b482a8SLen Brown * 71995b482a8SLen Brown * DESCRIPTION: Convert a real Node to a namespace handle 72095b482a8SLen Brown * 72195b482a8SLen Brown ******************************************************************************/ 72295b482a8SLen Brown 72395b482a8SLen Brown acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node) 72495b482a8SLen Brown { 72595b482a8SLen Brown 72695b482a8SLen Brown /* 72795b482a8SLen Brown * Simple implementation for now; 72895b482a8SLen Brown */ 72995b482a8SLen Brown return ((acpi_handle) node); 73095b482a8SLen Brown 73195b482a8SLen Brown /* Example future implementation --------------------- 73295b482a8SLen Brown 73395b482a8SLen Brown if (!Node) 73495b482a8SLen Brown { 73595b482a8SLen Brown return (NULL); 73695b482a8SLen Brown } 73795b482a8SLen Brown 73895b482a8SLen Brown if (Node == acpi_gbl_root_node) 73995b482a8SLen Brown { 74095b482a8SLen Brown return (ACPI_ROOT_OBJECT); 74195b482a8SLen Brown } 74295b482a8SLen Brown 74395b482a8SLen Brown return ((acpi_handle) Node); 74495b482a8SLen Brown ------------------------------------------------------*/ 74595b482a8SLen Brown } 74695b482a8SLen Brown 74795b482a8SLen Brown /******************************************************************************* 74895b482a8SLen Brown * 74995b482a8SLen Brown * FUNCTION: acpi_ns_terminate 75095b482a8SLen Brown * 75195b482a8SLen Brown * PARAMETERS: none 75295b482a8SLen Brown * 75395b482a8SLen Brown * RETURN: none 75495b482a8SLen Brown * 75595b482a8SLen Brown * DESCRIPTION: free memory allocated for namespace and ACPI table storage. 75695b482a8SLen Brown * 75795b482a8SLen Brown ******************************************************************************/ 75895b482a8SLen Brown 75995b482a8SLen Brown void acpi_ns_terminate(void) 76095b482a8SLen Brown { 76195b482a8SLen Brown union acpi_operand_object *obj_desc; 76295b482a8SLen Brown 76395b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_terminate); 76495b482a8SLen Brown 76595b482a8SLen Brown /* 76695b482a8SLen Brown * 1) Free the entire namespace -- all nodes and objects 76795b482a8SLen Brown * 76895b482a8SLen Brown * Delete all object descriptors attached to namepsace nodes 76995b482a8SLen Brown */ 77095b482a8SLen Brown acpi_ns_delete_namespace_subtree(acpi_gbl_root_node); 77195b482a8SLen Brown 77295b482a8SLen Brown /* Detach any objects attached to the root */ 77395b482a8SLen Brown 77495b482a8SLen Brown obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node); 77595b482a8SLen Brown if (obj_desc) { 77695b482a8SLen Brown acpi_ns_detach_object(acpi_gbl_root_node); 77795b482a8SLen Brown } 77895b482a8SLen Brown 77995b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); 78095b482a8SLen Brown return_VOID; 78195b482a8SLen Brown } 78295b482a8SLen Brown 78395b482a8SLen Brown /******************************************************************************* 78495b482a8SLen Brown * 78595b482a8SLen Brown * FUNCTION: acpi_ns_opens_scope 78695b482a8SLen Brown * 78795b482a8SLen Brown * PARAMETERS: Type - A valid namespace type 78895b482a8SLen Brown * 78995b482a8SLen Brown * RETURN: NEWSCOPE if the passed type "opens a name scope" according 79095b482a8SLen Brown * to the ACPI specification, else 0 79195b482a8SLen Brown * 79295b482a8SLen Brown ******************************************************************************/ 79395b482a8SLen Brown 79495b482a8SLen Brown u32 acpi_ns_opens_scope(acpi_object_type type) 79595b482a8SLen Brown { 79695b482a8SLen Brown ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); 79795b482a8SLen Brown 79895b482a8SLen Brown if (!acpi_ut_valid_object_type(type)) { 79995b482a8SLen Brown 80095b482a8SLen Brown /* type code out of range */ 80195b482a8SLen Brown 80295b482a8SLen Brown ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); 80395b482a8SLen Brown return_UINT32(ACPI_NS_NORMAL); 80495b482a8SLen Brown } 80595b482a8SLen Brown 80695b482a8SLen Brown return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); 80795b482a8SLen Brown } 80895b482a8SLen Brown 80995b482a8SLen Brown /******************************************************************************* 81095b482a8SLen Brown * 81195b482a8SLen Brown * FUNCTION: acpi_ns_get_node 81295b482a8SLen Brown * 81395b482a8SLen Brown * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The 81495b482a8SLen Brown * \ (backslash) and ^ (carat) prefixes, and the 81595b482a8SLen Brown * . (period) to separate segments are supported. 81695b482a8SLen Brown * prefix_node - Root of subtree to be searched, or NS_ALL for the 81795b482a8SLen Brown * root of the name space. If Name is fully 81895b482a8SLen Brown * qualified (first s8 is '\'), the passed value 81995b482a8SLen Brown * of Scope will not be accessed. 82095b482a8SLen Brown * Flags - Used to indicate whether to perform upsearch or 82195b482a8SLen Brown * not. 82295b482a8SLen Brown * return_node - Where the Node is returned 82395b482a8SLen Brown * 82495b482a8SLen Brown * DESCRIPTION: Look up a name relative to a given scope and return the 82595b482a8SLen Brown * corresponding Node. NOTE: Scope can be null. 82695b482a8SLen Brown * 82795b482a8SLen Brown * MUTEX: Locks namespace 82895b482a8SLen Brown * 82995b482a8SLen Brown ******************************************************************************/ 83095b482a8SLen Brown 83195b482a8SLen Brown acpi_status 83295b482a8SLen Brown acpi_ns_get_node(struct acpi_namespace_node *prefix_node, 83395b482a8SLen Brown const char *pathname, 83495b482a8SLen Brown u32 flags, struct acpi_namespace_node **return_node) 83595b482a8SLen Brown { 83695b482a8SLen Brown union acpi_generic_state scope_info; 83795b482a8SLen Brown acpi_status status; 83895b482a8SLen Brown char *internal_path; 83995b482a8SLen Brown 84095b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname); 84195b482a8SLen Brown 84295b482a8SLen Brown if (!pathname) { 84395b482a8SLen Brown *return_node = prefix_node; 84495b482a8SLen Brown if (!prefix_node) { 84595b482a8SLen Brown *return_node = acpi_gbl_root_node; 84695b482a8SLen Brown } 84795b482a8SLen Brown return_ACPI_STATUS(AE_OK); 84895b482a8SLen Brown } 84995b482a8SLen Brown 85095b482a8SLen Brown /* Convert path to internal representation */ 85195b482a8SLen Brown 85295b482a8SLen Brown status = acpi_ns_internalize_name(pathname, &internal_path); 85395b482a8SLen Brown if (ACPI_FAILURE(status)) { 85495b482a8SLen Brown return_ACPI_STATUS(status); 85595b482a8SLen Brown } 85695b482a8SLen Brown 85795b482a8SLen Brown /* Must lock namespace during lookup */ 85895b482a8SLen Brown 85995b482a8SLen Brown status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 86095b482a8SLen Brown if (ACPI_FAILURE(status)) { 86195b482a8SLen Brown goto cleanup; 86295b482a8SLen Brown } 86395b482a8SLen Brown 86495b482a8SLen Brown /* Setup lookup scope (search starting point) */ 86595b482a8SLen Brown 86695b482a8SLen Brown scope_info.scope.node = prefix_node; 86795b482a8SLen Brown 86895b482a8SLen Brown /* Lookup the name in the namespace */ 86995b482a8SLen Brown 87095b482a8SLen Brown status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY, 87195b482a8SLen Brown ACPI_IMODE_EXECUTE, 87295b482a8SLen Brown (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, 87395b482a8SLen Brown return_node); 87495b482a8SLen Brown if (ACPI_FAILURE(status)) { 87595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n", 87695b482a8SLen Brown pathname, acpi_format_exception(status))); 87795b482a8SLen Brown } 87895b482a8SLen Brown 87995b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 88095b482a8SLen Brown 88195b482a8SLen Brown cleanup: 88295b482a8SLen Brown ACPI_FREE(internal_path); 88395b482a8SLen Brown return_ACPI_STATUS(status); 88495b482a8SLen Brown } 88595b482a8SLen Brown 88695b482a8SLen Brown /******************************************************************************* 88795b482a8SLen Brown * 88895b482a8SLen Brown * FUNCTION: acpi_ns_get_parent_node 88995b482a8SLen Brown * 89095b482a8SLen Brown * PARAMETERS: Node - Current table entry 89195b482a8SLen Brown * 89295b482a8SLen Brown * RETURN: Parent entry of the given entry 89395b482a8SLen Brown * 89495b482a8SLen Brown * DESCRIPTION: Obtain the parent entry for a given entry in the namespace. 89595b482a8SLen Brown * 89695b482a8SLen Brown ******************************************************************************/ 89795b482a8SLen Brown 89895b482a8SLen Brown struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node 89995b482a8SLen Brown *node) 90095b482a8SLen Brown { 90195b482a8SLen Brown ACPI_FUNCTION_ENTRY(); 90295b482a8SLen Brown 90395b482a8SLen Brown if (!node) { 90495b482a8SLen Brown return (NULL); 90595b482a8SLen Brown } 90695b482a8SLen Brown 90795b482a8SLen Brown /* 90895b482a8SLen Brown * Walk to the end of this peer list. The last entry is marked with a flag 90995b482a8SLen Brown * and the peer pointer is really a pointer back to the parent. This saves 91095b482a8SLen Brown * putting a parent back pointer in each and every named object! 91195b482a8SLen Brown */ 91295b482a8SLen Brown while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) { 91395b482a8SLen Brown node = node->peer; 91495b482a8SLen Brown } 91595b482a8SLen Brown 91695b482a8SLen Brown return (node->peer); 91795b482a8SLen Brown } 91895b482a8SLen Brown 91995b482a8SLen Brown /******************************************************************************* 92095b482a8SLen Brown * 92195b482a8SLen Brown * FUNCTION: acpi_ns_get_next_valid_node 92295b482a8SLen Brown * 92395b482a8SLen Brown * PARAMETERS: Node - Current table entry 92495b482a8SLen Brown * 92595b482a8SLen Brown * RETURN: Next valid Node in the linked node list. NULL if no more valid 92695b482a8SLen Brown * nodes. 92795b482a8SLen Brown * 92895b482a8SLen Brown * DESCRIPTION: Find the next valid node within a name table. 92995b482a8SLen Brown * Useful for implementing NULL-end-of-list loops. 93095b482a8SLen Brown * 93195b482a8SLen Brown ******************************************************************************/ 93295b482a8SLen Brown 93395b482a8SLen Brown struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct 93495b482a8SLen Brown acpi_namespace_node 93595b482a8SLen Brown *node) 93695b482a8SLen Brown { 93795b482a8SLen Brown 93895b482a8SLen Brown /* If we are at the end of this peer list, return NULL */ 93995b482a8SLen Brown 94095b482a8SLen Brown if (node->flags & ANOBJ_END_OF_PEER_LIST) { 94195b482a8SLen Brown return NULL; 94295b482a8SLen Brown } 94395b482a8SLen Brown 94495b482a8SLen Brown /* Otherwise just return the next peer */ 94595b482a8SLen Brown 94695b482a8SLen Brown return (node->peer); 94795b482a8SLen Brown } 94895b482a8SLen Brown 94995b482a8SLen Brown #ifdef ACPI_OBSOLETE_FUNCTIONS 95095b482a8SLen Brown /******************************************************************************* 95195b482a8SLen Brown * 95295b482a8SLen Brown * FUNCTION: acpi_ns_find_parent_name 95395b482a8SLen Brown * 95495b482a8SLen Brown * PARAMETERS: *child_node - Named Obj whose name is to be found 95595b482a8SLen Brown * 95695b482a8SLen Brown * RETURN: The ACPI name 95795b482a8SLen Brown * 95895b482a8SLen Brown * DESCRIPTION: Search for the given obj in its parent scope and return the 95995b482a8SLen Brown * name segment, or "????" if the parent name can't be found 96095b482a8SLen Brown * (which "should not happen"). 96195b482a8SLen Brown * 96295b482a8SLen Brown ******************************************************************************/ 96395b482a8SLen Brown 96495b482a8SLen Brown acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node) 96595b482a8SLen Brown { 96695b482a8SLen Brown struct acpi_namespace_node *parent_node; 96795b482a8SLen Brown 96895b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_find_parent_name); 96995b482a8SLen Brown 97095b482a8SLen Brown if (child_node) { 97195b482a8SLen Brown 97295b482a8SLen Brown /* Valid entry. Get the parent Node */ 97395b482a8SLen Brown 97495b482a8SLen Brown parent_node = acpi_ns_get_parent_node(child_node); 97595b482a8SLen Brown if (parent_node) { 97695b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 97795b482a8SLen Brown "Parent of %p [%4.4s] is %p [%4.4s]\n", 97895b482a8SLen Brown child_node, 97995b482a8SLen Brown acpi_ut_get_node_name(child_node), 98095b482a8SLen Brown parent_node, 98195b482a8SLen Brown acpi_ut_get_node_name(parent_node))); 98295b482a8SLen Brown 98395b482a8SLen Brown if (parent_node->name.integer) { 98495b482a8SLen Brown return_VALUE((acpi_name) parent_node->name. 98595b482a8SLen Brown integer); 98695b482a8SLen Brown } 98795b482a8SLen Brown } 98895b482a8SLen Brown 98995b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 99095b482a8SLen Brown "Unable to find parent of %p (%4.4s)\n", 99195b482a8SLen Brown child_node, 99295b482a8SLen Brown acpi_ut_get_node_name(child_node))); 99395b482a8SLen Brown } 99495b482a8SLen Brown 99595b482a8SLen Brown return_VALUE(ACPI_UNKNOWN_NAME); 99695b482a8SLen Brown } 99795b482a8SLen Brown #endif 998