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