1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
5*4882a593Smuzhiyun * parents and siblings and Scope manipulation
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (C) 2000 - 2020, Intel Corp.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun *****************************************************************************/
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <acpi/acpi.h>
12*4882a593Smuzhiyun #include "accommon.h"
13*4882a593Smuzhiyun #include "acnamesp.h"
14*4882a593Smuzhiyun #include "amlcode.h"
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #define _COMPONENT ACPI_NAMESPACE
17*4882a593Smuzhiyun ACPI_MODULE_NAME("nsutils")
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /* Local prototypes */
20*4882a593Smuzhiyun #ifdef ACPI_OBSOLETE_FUNCTIONS
21*4882a593Smuzhiyun acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
22*4882a593Smuzhiyun #endif
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /*******************************************************************************
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * FUNCTION: acpi_ns_print_node_pathname
27*4882a593Smuzhiyun *
28*4882a593Smuzhiyun * PARAMETERS: node - Object
29*4882a593Smuzhiyun * message - Prefix message
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * DESCRIPTION: Print an object's full namespace pathname
32*4882a593Smuzhiyun * Manages allocation/freeing of a pathname buffer
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun ******************************************************************************/
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun void
acpi_ns_print_node_pathname(struct acpi_namespace_node * node,const char * message)37*4882a593Smuzhiyun acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
38*4882a593Smuzhiyun const char *message)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun struct acpi_buffer buffer;
41*4882a593Smuzhiyun acpi_status status;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun if (!node) {
44*4882a593Smuzhiyun acpi_os_printf("[NULL NAME]");
45*4882a593Smuzhiyun return;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /* Convert handle to full pathname and print it (with supplied message) */
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
53*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
54*4882a593Smuzhiyun if (message) {
55*4882a593Smuzhiyun acpi_os_printf("%s ", message);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun acpi_os_printf("%s", (char *)buffer.pointer);
59*4882a593Smuzhiyun ACPI_FREE(buffer.pointer);
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun /*******************************************************************************
64*4882a593Smuzhiyun *
65*4882a593Smuzhiyun * FUNCTION: acpi_ns_get_type
66*4882a593Smuzhiyun *
67*4882a593Smuzhiyun * PARAMETERS: node - Parent Node to be examined
68*4882a593Smuzhiyun *
69*4882a593Smuzhiyun * RETURN: Type field from Node whose handle is passed
70*4882a593Smuzhiyun *
71*4882a593Smuzhiyun * DESCRIPTION: Return the type of a Namespace node
72*4882a593Smuzhiyun *
73*4882a593Smuzhiyun ******************************************************************************/
74*4882a593Smuzhiyun
acpi_ns_get_type(struct acpi_namespace_node * node)75*4882a593Smuzhiyun acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ns_get_type);
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun if (!node) {
80*4882a593Smuzhiyun ACPI_WARNING((AE_INFO, "Null Node parameter"));
81*4882a593Smuzhiyun return_UINT8(ACPI_TYPE_ANY);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun return_UINT8(node->type);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /*******************************************************************************
88*4882a593Smuzhiyun *
89*4882a593Smuzhiyun * FUNCTION: acpi_ns_local
90*4882a593Smuzhiyun *
91*4882a593Smuzhiyun * PARAMETERS: type - A namespace object type
92*4882a593Smuzhiyun *
93*4882a593Smuzhiyun * RETURN: LOCAL if names must be found locally in objects of the
94*4882a593Smuzhiyun * passed type, 0 if enclosing scopes should be searched
95*4882a593Smuzhiyun *
96*4882a593Smuzhiyun * DESCRIPTION: Returns scope rule for the given object type.
97*4882a593Smuzhiyun *
98*4882a593Smuzhiyun ******************************************************************************/
99*4882a593Smuzhiyun
acpi_ns_local(acpi_object_type type)100*4882a593Smuzhiyun u32 acpi_ns_local(acpi_object_type type)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ns_local);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun if (!acpi_ut_valid_object_type(type)) {
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /* Type code out of range */
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
109*4882a593Smuzhiyun return_UINT32(ACPI_NS_NORMAL);
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /*******************************************************************************
116*4882a593Smuzhiyun *
117*4882a593Smuzhiyun * FUNCTION: acpi_ns_get_internal_name_length
118*4882a593Smuzhiyun *
119*4882a593Smuzhiyun * PARAMETERS: info - Info struct initialized with the
120*4882a593Smuzhiyun * external name pointer.
121*4882a593Smuzhiyun *
122*4882a593Smuzhiyun * RETURN: None
123*4882a593Smuzhiyun *
124*4882a593Smuzhiyun * DESCRIPTION: Calculate the length of the internal (AML) namestring
125*4882a593Smuzhiyun * corresponding to the external (ASL) namestring.
126*4882a593Smuzhiyun *
127*4882a593Smuzhiyun ******************************************************************************/
128*4882a593Smuzhiyun
acpi_ns_get_internal_name_length(struct acpi_namestring_info * info)129*4882a593Smuzhiyun void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun const char *next_external_char;
132*4882a593Smuzhiyun u32 i;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun next_external_char = info->external_name;
137*4882a593Smuzhiyun info->num_carats = 0;
138*4882a593Smuzhiyun info->num_segments = 0;
139*4882a593Smuzhiyun info->fully_qualified = FALSE;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun /*
142*4882a593Smuzhiyun * For the internal name, the required length is 4 bytes per segment,
143*4882a593Smuzhiyun * plus 1 each for root_prefix, multi_name_prefix_op, segment count,
144*4882a593Smuzhiyun * trailing null (which is not really needed, but no there's harm in
145*4882a593Smuzhiyun * putting it there)
146*4882a593Smuzhiyun *
147*4882a593Smuzhiyun * strlen() + 1 covers the first name_seg, which has no path separator
148*4882a593Smuzhiyun */
149*4882a593Smuzhiyun if (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
150*4882a593Smuzhiyun info->fully_qualified = TRUE;
151*4882a593Smuzhiyun next_external_char++;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun while (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
156*4882a593Smuzhiyun next_external_char++;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun } else {
159*4882a593Smuzhiyun /* Handle Carat prefixes */
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun while (ACPI_IS_PARENT_PREFIX(*next_external_char)) {
162*4882a593Smuzhiyun info->num_carats++;
163*4882a593Smuzhiyun next_external_char++;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun /*
168*4882a593Smuzhiyun * Determine the number of ACPI name "segments" by counting the number of
169*4882a593Smuzhiyun * path separators within the string. Start with one segment since the
170*4882a593Smuzhiyun * segment count is [(# separators) + 1], and zero separators is ok.
171*4882a593Smuzhiyun */
172*4882a593Smuzhiyun if (*next_external_char) {
173*4882a593Smuzhiyun info->num_segments = 1;
174*4882a593Smuzhiyun for (i = 0; next_external_char[i]; i++) {
175*4882a593Smuzhiyun if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) {
176*4882a593Smuzhiyun info->num_segments++;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun info->length = (ACPI_NAMESEG_SIZE * info->num_segments) +
182*4882a593Smuzhiyun 4 + info->num_carats;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun info->next_external_char = next_external_char;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun /*******************************************************************************
188*4882a593Smuzhiyun *
189*4882a593Smuzhiyun * FUNCTION: acpi_ns_build_internal_name
190*4882a593Smuzhiyun *
191*4882a593Smuzhiyun * PARAMETERS: info - Info struct fully initialized
192*4882a593Smuzhiyun *
193*4882a593Smuzhiyun * RETURN: Status
194*4882a593Smuzhiyun *
195*4882a593Smuzhiyun * DESCRIPTION: Construct the internal (AML) namestring
196*4882a593Smuzhiyun * corresponding to the external (ASL) namestring.
197*4882a593Smuzhiyun *
198*4882a593Smuzhiyun ******************************************************************************/
199*4882a593Smuzhiyun
acpi_ns_build_internal_name(struct acpi_namestring_info * info)200*4882a593Smuzhiyun acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun u32 num_segments = info->num_segments;
203*4882a593Smuzhiyun char *internal_name = info->internal_name;
204*4882a593Smuzhiyun const char *external_name = info->next_external_char;
205*4882a593Smuzhiyun char *result = NULL;
206*4882a593Smuzhiyun u32 i;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ns_build_internal_name);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* Setup the correct prefixes, counts, and pointers */
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun if (info->fully_qualified) {
213*4882a593Smuzhiyun internal_name[0] = AML_ROOT_PREFIX;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun if (num_segments <= 1) {
216*4882a593Smuzhiyun result = &internal_name[1];
217*4882a593Smuzhiyun } else if (num_segments == 2) {
218*4882a593Smuzhiyun internal_name[1] = AML_DUAL_NAME_PREFIX;
219*4882a593Smuzhiyun result = &internal_name[2];
220*4882a593Smuzhiyun } else {
221*4882a593Smuzhiyun internal_name[1] = AML_MULTI_NAME_PREFIX;
222*4882a593Smuzhiyun internal_name[2] = (char)num_segments;
223*4882a593Smuzhiyun result = &internal_name[3];
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun } else {
226*4882a593Smuzhiyun /*
227*4882a593Smuzhiyun * Not fully qualified.
228*4882a593Smuzhiyun * Handle Carats first, then append the name segments
229*4882a593Smuzhiyun */
230*4882a593Smuzhiyun i = 0;
231*4882a593Smuzhiyun if (info->num_carats) {
232*4882a593Smuzhiyun for (i = 0; i < info->num_carats; i++) {
233*4882a593Smuzhiyun internal_name[i] = AML_PARENT_PREFIX;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun if (num_segments <= 1) {
238*4882a593Smuzhiyun result = &internal_name[i];
239*4882a593Smuzhiyun } else if (num_segments == 2) {
240*4882a593Smuzhiyun internal_name[i] = AML_DUAL_NAME_PREFIX;
241*4882a593Smuzhiyun result = &internal_name[(acpi_size)i + 1];
242*4882a593Smuzhiyun } else {
243*4882a593Smuzhiyun internal_name[i] = AML_MULTI_NAME_PREFIX;
244*4882a593Smuzhiyun internal_name[(acpi_size)i + 1] = (char)num_segments;
245*4882a593Smuzhiyun result = &internal_name[(acpi_size)i + 2];
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun /* Build the name (minus path separators) */
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun for (; num_segments; num_segments--) {
252*4882a593Smuzhiyun for (i = 0; i < ACPI_NAMESEG_SIZE; i++) {
253*4882a593Smuzhiyun if (ACPI_IS_PATH_SEPARATOR(*external_name) ||
254*4882a593Smuzhiyun (*external_name == 0)) {
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /* Pad the segment with underscore(s) if segment is short */
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun result[i] = '_';
259*4882a593Smuzhiyun } else {
260*4882a593Smuzhiyun /* Convert the character to uppercase and save it */
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun result[i] = (char)toupper((int)*external_name);
263*4882a593Smuzhiyun external_name++;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /* Now we must have a path separator, or the pathname is bad */
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun if (!ACPI_IS_PATH_SEPARATOR(*external_name) &&
270*4882a593Smuzhiyun (*external_name != 0)) {
271*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PATHNAME);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun /* Move on the next segment */
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun external_name++;
277*4882a593Smuzhiyun result += ACPI_NAMESEG_SIZE;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun /* Terminate the string */
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun *result = 0;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun if (info->fully_qualified) {
285*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
286*4882a593Smuzhiyun "Returning [%p] (abs) \"\\%s\"\n",
287*4882a593Smuzhiyun internal_name, internal_name));
288*4882a593Smuzhiyun } else {
289*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
290*4882a593Smuzhiyun internal_name, internal_name));
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun /*******************************************************************************
297*4882a593Smuzhiyun *
298*4882a593Smuzhiyun * FUNCTION: acpi_ns_internalize_name
299*4882a593Smuzhiyun *
300*4882a593Smuzhiyun * PARAMETERS: *external_name - External representation of name
301*4882a593Smuzhiyun * **Converted name - Where to return the resulting
302*4882a593Smuzhiyun * internal represention of the name
303*4882a593Smuzhiyun *
304*4882a593Smuzhiyun * RETURN: Status
305*4882a593Smuzhiyun *
306*4882a593Smuzhiyun * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
307*4882a593Smuzhiyun * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
308*4882a593Smuzhiyun *
309*4882a593Smuzhiyun *******************************************************************************/
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun acpi_status
acpi_ns_internalize_name(const char * external_name,char ** converted_name)312*4882a593Smuzhiyun acpi_ns_internalize_name(const char *external_name, char **converted_name)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun char *internal_name;
315*4882a593Smuzhiyun struct acpi_namestring_info info;
316*4882a593Smuzhiyun acpi_status status;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ns_internalize_name);
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun if ((!external_name) || (*external_name == 0) || (!converted_name)) {
321*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PARAMETER);
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun /* Get the length of the new internal name */
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun info.external_name = external_name;
327*4882a593Smuzhiyun acpi_ns_get_internal_name_length(&info);
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun /* We need a segment to store the internal name */
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun internal_name = ACPI_ALLOCATE_ZEROED(info.length);
332*4882a593Smuzhiyun if (!internal_name) {
333*4882a593Smuzhiyun return_ACPI_STATUS(AE_NO_MEMORY);
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun /* Build the name */
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun info.internal_name = internal_name;
339*4882a593Smuzhiyun status = acpi_ns_build_internal_name(&info);
340*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
341*4882a593Smuzhiyun ACPI_FREE(internal_name);
342*4882a593Smuzhiyun return_ACPI_STATUS(status);
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun *converted_name = internal_name;
346*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun /*******************************************************************************
350*4882a593Smuzhiyun *
351*4882a593Smuzhiyun * FUNCTION: acpi_ns_externalize_name
352*4882a593Smuzhiyun *
353*4882a593Smuzhiyun * PARAMETERS: internal_name_length - Length of the internal name below
354*4882a593Smuzhiyun * internal_name - Internal representation of name
355*4882a593Smuzhiyun * converted_name_length - Where the length is returned
356*4882a593Smuzhiyun * converted_name - Where the resulting external name
357*4882a593Smuzhiyun * is returned
358*4882a593Smuzhiyun *
359*4882a593Smuzhiyun * RETURN: Status
360*4882a593Smuzhiyun *
361*4882a593Smuzhiyun * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
362*4882a593Smuzhiyun * to its external (printable) form (e.g. "\_PR_.CPU0")
363*4882a593Smuzhiyun *
364*4882a593Smuzhiyun ******************************************************************************/
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun acpi_status
acpi_ns_externalize_name(u32 internal_name_length,const char * internal_name,u32 * converted_name_length,char ** converted_name)367*4882a593Smuzhiyun acpi_ns_externalize_name(u32 internal_name_length,
368*4882a593Smuzhiyun const char *internal_name,
369*4882a593Smuzhiyun u32 * converted_name_length, char **converted_name)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun u32 names_index = 0;
372*4882a593Smuzhiyun u32 num_segments = 0;
373*4882a593Smuzhiyun u32 required_length;
374*4882a593Smuzhiyun u32 prefix_length = 0;
375*4882a593Smuzhiyun u32 i = 0;
376*4882a593Smuzhiyun u32 j = 0;
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ns_externalize_name);
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun if (!internal_name_length || !internal_name || !converted_name) {
381*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PARAMETER);
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun /* Check for a prefix (one '\' | one or more '^') */
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun switch (internal_name[0]) {
387*4882a593Smuzhiyun case AML_ROOT_PREFIX:
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun prefix_length = 1;
390*4882a593Smuzhiyun break;
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun case AML_PARENT_PREFIX:
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun for (i = 0; i < internal_name_length; i++) {
395*4882a593Smuzhiyun if (ACPI_IS_PARENT_PREFIX(internal_name[i])) {
396*4882a593Smuzhiyun prefix_length = i + 1;
397*4882a593Smuzhiyun } else {
398*4882a593Smuzhiyun break;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun if (i == internal_name_length) {
403*4882a593Smuzhiyun prefix_length = i;
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun break;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun default:
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun break;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun /*
414*4882a593Smuzhiyun * Check for object names. Note that there could be 0-255 of these
415*4882a593Smuzhiyun * 4-byte elements.
416*4882a593Smuzhiyun */
417*4882a593Smuzhiyun if (prefix_length < internal_name_length) {
418*4882a593Smuzhiyun switch (internal_name[prefix_length]) {
419*4882a593Smuzhiyun case AML_MULTI_NAME_PREFIX:
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun /* <count> 4-byte names */
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun names_index = prefix_length + 2;
424*4882a593Smuzhiyun num_segments = (u8)
425*4882a593Smuzhiyun internal_name[(acpi_size)prefix_length + 1];
426*4882a593Smuzhiyun break;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun case AML_DUAL_NAME_PREFIX:
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun /* Two 4-byte names */
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun names_index = prefix_length + 1;
433*4882a593Smuzhiyun num_segments = 2;
434*4882a593Smuzhiyun break;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun case 0:
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun /* null_name */
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun names_index = 0;
441*4882a593Smuzhiyun num_segments = 0;
442*4882a593Smuzhiyun break;
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun default:
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun /* one 4-byte name */
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun names_index = prefix_length;
449*4882a593Smuzhiyun num_segments = 1;
450*4882a593Smuzhiyun break;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun /*
455*4882a593Smuzhiyun * Calculate the length of converted_name, which equals the length
456*4882a593Smuzhiyun * of the prefix, length of all object names, length of any required
457*4882a593Smuzhiyun * punctuation ('.') between object names, plus the NULL terminator.
458*4882a593Smuzhiyun */
459*4882a593Smuzhiyun required_length = prefix_length + (4 * num_segments) +
460*4882a593Smuzhiyun ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun /*
463*4882a593Smuzhiyun * Check to see if we're still in bounds. If not, there's a problem
464*4882a593Smuzhiyun * with internal_name (invalid format).
465*4882a593Smuzhiyun */
466*4882a593Smuzhiyun if (required_length > internal_name_length) {
467*4882a593Smuzhiyun ACPI_ERROR((AE_INFO, "Invalid internal name"));
468*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PATHNAME);
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun /* Build the converted_name */
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun *converted_name = ACPI_ALLOCATE_ZEROED(required_length);
474*4882a593Smuzhiyun if (!(*converted_name)) {
475*4882a593Smuzhiyun return_ACPI_STATUS(AE_NO_MEMORY);
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun j = 0;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun for (i = 0; i < prefix_length; i++) {
481*4882a593Smuzhiyun (*converted_name)[j++] = internal_name[i];
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun if (num_segments > 0) {
485*4882a593Smuzhiyun for (i = 0; i < num_segments; i++) {
486*4882a593Smuzhiyun if (i > 0) {
487*4882a593Smuzhiyun (*converted_name)[j++] = '.';
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun /* Copy and validate the 4-char name segment */
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun ACPI_COPY_NAMESEG(&(*converted_name)[j],
493*4882a593Smuzhiyun &internal_name[names_index]);
494*4882a593Smuzhiyun acpi_ut_repair_name(&(*converted_name)[j]);
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun j += ACPI_NAMESEG_SIZE;
497*4882a593Smuzhiyun names_index += ACPI_NAMESEG_SIZE;
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun if (converted_name_length) {
502*4882a593Smuzhiyun *converted_name_length = (u32) required_length;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun /*******************************************************************************
509*4882a593Smuzhiyun *
510*4882a593Smuzhiyun * FUNCTION: acpi_ns_validate_handle
511*4882a593Smuzhiyun *
512*4882a593Smuzhiyun * PARAMETERS: handle - Handle to be validated and typecast to a
513*4882a593Smuzhiyun * namespace node.
514*4882a593Smuzhiyun *
515*4882a593Smuzhiyun * RETURN: A pointer to a namespace node
516*4882a593Smuzhiyun *
517*4882a593Smuzhiyun * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
518*4882a593Smuzhiyun * cases for the root node.
519*4882a593Smuzhiyun *
520*4882a593Smuzhiyun * NOTE: Real integer handles would allow for more verification
521*4882a593Smuzhiyun * and keep all pointers within this subsystem - however this introduces
522*4882a593Smuzhiyun * more overhead and has not been necessary to this point. Drivers
523*4882a593Smuzhiyun * holding handles are typically notified before a node becomes invalid
524*4882a593Smuzhiyun * due to a table unload.
525*4882a593Smuzhiyun *
526*4882a593Smuzhiyun ******************************************************************************/
527*4882a593Smuzhiyun
acpi_ns_validate_handle(acpi_handle handle)528*4882a593Smuzhiyun struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
529*4882a593Smuzhiyun {
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun /* Parameter validation */
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
536*4882a593Smuzhiyun return (acpi_gbl_root_node);
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun /* We can at least attempt to verify the handle */
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
542*4882a593Smuzhiyun return (NULL);
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun /*******************************************************************************
549*4882a593Smuzhiyun *
550*4882a593Smuzhiyun * FUNCTION: acpi_ns_terminate
551*4882a593Smuzhiyun *
552*4882a593Smuzhiyun * PARAMETERS: none
553*4882a593Smuzhiyun *
554*4882a593Smuzhiyun * RETURN: none
555*4882a593Smuzhiyun *
556*4882a593Smuzhiyun * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
557*4882a593Smuzhiyun *
558*4882a593Smuzhiyun ******************************************************************************/
559*4882a593Smuzhiyun
acpi_ns_terminate(void)560*4882a593Smuzhiyun void acpi_ns_terminate(void)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun acpi_status status;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ns_terminate);
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun /*
567*4882a593Smuzhiyun * Free the entire namespace -- all nodes and all objects
568*4882a593Smuzhiyun * attached to the nodes
569*4882a593Smuzhiyun */
570*4882a593Smuzhiyun acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun /* Delete any objects attached to the root node */
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
575*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
576*4882a593Smuzhiyun return_VOID;
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun acpi_ns_delete_node(acpi_gbl_root_node);
580*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
583*4882a593Smuzhiyun return_VOID;
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun /*******************************************************************************
587*4882a593Smuzhiyun *
588*4882a593Smuzhiyun * FUNCTION: acpi_ns_opens_scope
589*4882a593Smuzhiyun *
590*4882a593Smuzhiyun * PARAMETERS: type - A valid namespace type
591*4882a593Smuzhiyun *
592*4882a593Smuzhiyun * RETURN: NEWSCOPE if the passed type "opens a name scope" according
593*4882a593Smuzhiyun * to the ACPI specification, else 0
594*4882a593Smuzhiyun *
595*4882a593Smuzhiyun ******************************************************************************/
596*4882a593Smuzhiyun
acpi_ns_opens_scope(acpi_object_type type)597*4882a593Smuzhiyun u32 acpi_ns_opens_scope(acpi_object_type type)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun if (type > ACPI_TYPE_LOCAL_MAX) {
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun /* type code out of range */
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
606*4882a593Smuzhiyun return (ACPI_NS_NORMAL);
607*4882a593Smuzhiyun }
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun /*******************************************************************************
613*4882a593Smuzhiyun *
614*4882a593Smuzhiyun * FUNCTION: acpi_ns_get_node_unlocked
615*4882a593Smuzhiyun *
616*4882a593Smuzhiyun * PARAMETERS: *pathname - Name to be found, in external (ASL) format. The
617*4882a593Smuzhiyun * \ (backslash) and ^ (carat) prefixes, and the
618*4882a593Smuzhiyun * . (period) to separate segments are supported.
619*4882a593Smuzhiyun * prefix_node - Root of subtree to be searched, or NS_ALL for the
620*4882a593Smuzhiyun * root of the name space. If Name is fully
621*4882a593Smuzhiyun * qualified (first s8 is '\'), the passed value
622*4882a593Smuzhiyun * of Scope will not be accessed.
623*4882a593Smuzhiyun * flags - Used to indicate whether to perform upsearch or
624*4882a593Smuzhiyun * not.
625*4882a593Smuzhiyun * return_node - Where the Node is returned
626*4882a593Smuzhiyun *
627*4882a593Smuzhiyun * DESCRIPTION: Look up a name relative to a given scope and return the
628*4882a593Smuzhiyun * corresponding Node. NOTE: Scope can be null.
629*4882a593Smuzhiyun *
630*4882a593Smuzhiyun * MUTEX: Doesn't locks namespace
631*4882a593Smuzhiyun *
632*4882a593Smuzhiyun ******************************************************************************/
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun acpi_status
acpi_ns_get_node_unlocked(struct acpi_namespace_node * prefix_node,const char * pathname,u32 flags,struct acpi_namespace_node ** return_node)635*4882a593Smuzhiyun acpi_ns_get_node_unlocked(struct acpi_namespace_node *prefix_node,
636*4882a593Smuzhiyun const char *pathname,
637*4882a593Smuzhiyun u32 flags, struct acpi_namespace_node **return_node)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun union acpi_generic_state scope_info;
640*4882a593Smuzhiyun acpi_status status;
641*4882a593Smuzhiyun char *internal_path;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_PTR(ns_get_node_unlocked,
644*4882a593Smuzhiyun ACPI_CAST_PTR(char, pathname));
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun /* Simplest case is a null pathname */
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun if (!pathname) {
649*4882a593Smuzhiyun *return_node = prefix_node;
650*4882a593Smuzhiyun if (!prefix_node) {
651*4882a593Smuzhiyun *return_node = acpi_gbl_root_node;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun /* Quick check for a reference to the root */
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) {
660*4882a593Smuzhiyun *return_node = acpi_gbl_root_node;
661*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun /* Convert path to internal representation */
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun status = acpi_ns_internalize_name(pathname, &internal_path);
667*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
668*4882a593Smuzhiyun return_ACPI_STATUS(status);
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun /* Setup lookup scope (search starting point) */
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun scope_info.scope.node = prefix_node;
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun /* Lookup the name in the namespace */
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY,
678*4882a593Smuzhiyun ACPI_IMODE_EXECUTE,
679*4882a593Smuzhiyun (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL,
680*4882a593Smuzhiyun return_node);
681*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
682*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n",
683*4882a593Smuzhiyun pathname, acpi_format_exception(status)));
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun ACPI_FREE(internal_path);
687*4882a593Smuzhiyun return_ACPI_STATUS(status);
688*4882a593Smuzhiyun }
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun /*******************************************************************************
691*4882a593Smuzhiyun *
692*4882a593Smuzhiyun * FUNCTION: acpi_ns_get_node
693*4882a593Smuzhiyun *
694*4882a593Smuzhiyun * PARAMETERS: *pathname - Name to be found, in external (ASL) format. The
695*4882a593Smuzhiyun * \ (backslash) and ^ (carat) prefixes, and the
696*4882a593Smuzhiyun * . (period) to separate segments are supported.
697*4882a593Smuzhiyun * prefix_node - Root of subtree to be searched, or NS_ALL for the
698*4882a593Smuzhiyun * root of the name space. If Name is fully
699*4882a593Smuzhiyun * qualified (first s8 is '\'), the passed value
700*4882a593Smuzhiyun * of Scope will not be accessed.
701*4882a593Smuzhiyun * flags - Used to indicate whether to perform upsearch or
702*4882a593Smuzhiyun * not.
703*4882a593Smuzhiyun * return_node - Where the Node is returned
704*4882a593Smuzhiyun *
705*4882a593Smuzhiyun * DESCRIPTION: Look up a name relative to a given scope and return the
706*4882a593Smuzhiyun * corresponding Node. NOTE: Scope can be null.
707*4882a593Smuzhiyun *
708*4882a593Smuzhiyun * MUTEX: Locks namespace
709*4882a593Smuzhiyun *
710*4882a593Smuzhiyun ******************************************************************************/
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun acpi_status
acpi_ns_get_node(struct acpi_namespace_node * prefix_node,const char * pathname,u32 flags,struct acpi_namespace_node ** return_node)713*4882a593Smuzhiyun acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
714*4882a593Smuzhiyun const char *pathname,
715*4882a593Smuzhiyun u32 flags, struct acpi_namespace_node **return_node)
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun acpi_status status;
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
722*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
723*4882a593Smuzhiyun return_ACPI_STATUS(status);
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun status = acpi_ns_get_node_unlocked(prefix_node, pathname,
727*4882a593Smuzhiyun flags, return_node);
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
730*4882a593Smuzhiyun return_ACPI_STATUS(status);
731*4882a593Smuzhiyun }
732