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 - 2011, 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.
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 #define __NSUTILS_C__
46
47 #include "acpi.h"
48 #include "accommon.h"
49 #include "acnamesp.h"
50 #include "amlcode.h"
51
52 #define _COMPONENT ACPI_NAMESPACE
53 ACPI_MODULE_NAME ("nsutils")
54
55 /* Local prototypes */
56
57 static BOOLEAN
58 AcpiNsValidPathSeparator (
59 char Sep);
60
61 #ifdef ACPI_OBSOLETE_FUNCTIONS
62 ACPI_NAME
63 AcpiNsFindParentName (
64 ACPI_NAMESPACE_NODE *NodeToSearch);
65 #endif
66
67
68 /*******************************************************************************
69 *
70 * FUNCTION: AcpiNsPrintNodePathname
71 *
72 * PARAMETERS: Node - Object
73 * Message - Prefix message
74 *
75 * DESCRIPTION: Print an object's full namespace pathname
76 * Manages allocation/freeing of a pathname buffer
77 *
78 ******************************************************************************/
79
80 void
95 /* Convert handle to full pathname and print it (with supplied message) */
96
97 Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
98
99 Status = AcpiNsHandleToPathname (Node, &Buffer);
100 if (ACPI_SUCCESS (Status))
101 {
102 if (Message)
103 {
104 AcpiOsPrintf ("%s ", Message);
105 }
106
107 AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node);
108 ACPI_FREE (Buffer.Pointer);
109 }
110 }
111
112
113 /*******************************************************************************
114 *
115 * FUNCTION: AcpiNsValidRootPrefix
116 *
117 * PARAMETERS: Prefix - Character to be checked
118 *
119 * RETURN: TRUE if a valid prefix
120 *
121 * DESCRIPTION: Check if a character is a valid ACPI Root prefix
122 *
123 ******************************************************************************/
124
125 BOOLEAN
126 AcpiNsValidRootPrefix (
127 char Prefix)
128 {
129
130 return ((BOOLEAN) (Prefix == '\\'));
131 }
132
133
134 /*******************************************************************************
135 *
136 * FUNCTION: AcpiNsValidPathSeparator
137 *
138 * PARAMETERS: Sep - Character to be checked
139 *
140 * RETURN: TRUE if a valid path separator
141 *
142 * DESCRIPTION: Check if a character is a valid ACPI path separator
143 *
144 ******************************************************************************/
145
146 static BOOLEAN
147 AcpiNsValidPathSeparator (
148 char Sep)
149 {
150
151 return ((BOOLEAN) (Sep == '.'));
152 }
153
154
155 /*******************************************************************************
156 *
157 * FUNCTION: AcpiNsGetType
158 *
159 * PARAMETERS: Node - Parent Node to be examined
160 *
161 * RETURN: Type field from Node whose handle is passed
162 *
163 * DESCRIPTION: Return the type of a Namespace node
164 *
165 ******************************************************************************/
166
167 ACPI_OBJECT_TYPE
168 AcpiNsGetType (
169 ACPI_NAMESPACE_NODE *Node)
170 {
171 ACPI_FUNCTION_TRACE (NsGetType);
172
173
174 if (!Node)
175 {
176 ACPI_WARNING ((AE_INFO, "Null Node parameter"));
177 return_UINT32 (ACPI_TYPE_ANY);
178 }
179
180 return_UINT32 ((ACPI_OBJECT_TYPE) Node->Type);
181 }
182
183
184 /*******************************************************************************
185 *
186 * FUNCTION: AcpiNsLocal
187 *
188 * PARAMETERS: Type - A namespace object type
189 *
190 * RETURN: LOCAL if names must be found locally in objects of the
191 * passed type, 0 if enclosing scopes should be searched
192 *
193 * DESCRIPTION: Returns scope rule for the given object type.
194 *
195 ******************************************************************************/
196
197 UINT32
198 AcpiNsLocal (
199 ACPI_OBJECT_TYPE Type)
200 {
201 ACPI_FUNCTION_TRACE (NsLocal);
202
203
204 if (!AcpiUtValidObjectType (Type))
205 {
206 /* Type code out of range */
207
208 ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
209 return_UINT32 (ACPI_NS_NORMAL);
210 }
211
212 return_UINT32 ((UINT32) AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
213 }
214
215
216 /*******************************************************************************
217 *
218 * FUNCTION: AcpiNsGetInternalNameLength
219 *
220 * PARAMETERS: Info - Info struct initialized with the
221 * external name pointer.
222 *
223 * RETURN: None
224 *
225 * DESCRIPTION: Calculate the length of the internal (AML) namestring
226 * corresponding to the external (ASL) namestring.
227 *
228 ******************************************************************************/
229
230 void
231 AcpiNsGetInternalNameLength (
232 ACPI_NAMESTRING_INFO *Info)
233 {
234 const char *NextExternalChar;
235 UINT32 i;
236
237
238 ACPI_FUNCTION_ENTRY ();
239
240
241 NextExternalChar = Info->ExternalName;
242 Info->NumCarats = 0;
243 Info->NumSegments = 0;
244 Info->FullyQualified = FALSE;
245
246 /*
247 * For the internal name, the required length is 4 bytes per segment, plus
248 * 1 each for RootPrefix, MultiNamePrefixOp, segment count, trailing null
249 * (which is not really needed, but no there's harm in putting it there)
250 *
251 * strlen() + 1 covers the first NameSeg, which has no path separator
252 */
253 if (AcpiNsValidRootPrefix (*NextExternalChar))
254 {
255 Info->FullyQualified = TRUE;
256 NextExternalChar++;
257
258 /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */
259
260 while (AcpiNsValidRootPrefix (*NextExternalChar))
261 {
262 NextExternalChar++;
263 }
264 }
265 else
266 {
267 /* Handle Carat prefixes */
268
269 while (*NextExternalChar == '^')
270 {
271 Info->NumCarats++;
272 NextExternalChar++;
273 }
274 }
275
276 /*
277 * Determine the number of ACPI name "segments" by counting the number of
278 * path separators within the string. Start with one segment since the
279 * segment count is [(# separators) + 1], and zero separators is ok.
280 */
281 if (*NextExternalChar)
282 {
283 Info->NumSegments = 1;
284 for (i = 0; NextExternalChar[i]; i++)
285 {
286 if (AcpiNsValidPathSeparator (NextExternalChar[i]))
287 {
288 Info->NumSegments++;
289 }
290 }
291 }
292
293 Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) +
294 4 + Info->NumCarats;
295
296 Info->NextExternalChar = NextExternalChar;
297 }
298
299
300 /*******************************************************************************
301 *
302 * FUNCTION: AcpiNsBuildInternalName
303 *
304 * PARAMETERS: Info - Info struct fully initialized
305 *
306 * RETURN: Status
311 ******************************************************************************/
312
313 ACPI_STATUS
314 AcpiNsBuildInternalName (
315 ACPI_NAMESTRING_INFO *Info)
316 {
317 UINT32 NumSegments = Info->NumSegments;
318 char *InternalName = Info->InternalName;
319 const char *ExternalName = Info->NextExternalChar;
320 char *Result = NULL;
321 UINT32 i;
322
323
324 ACPI_FUNCTION_TRACE (NsBuildInternalName);
325
326
327 /* Setup the correct prefixes, counts, and pointers */
328
329 if (Info->FullyQualified)
330 {
331 InternalName[0] = '\\';
332
333 if (NumSegments <= 1)
334 {
335 Result = &InternalName[1];
336 }
337 else if (NumSegments == 2)
338 {
339 InternalName[1] = AML_DUAL_NAME_PREFIX;
340 Result = &InternalName[2];
341 }
342 else
343 {
344 InternalName[1] = AML_MULTI_NAME_PREFIX_OP;
345 InternalName[2] = (char) NumSegments;
346 Result = &InternalName[3];
347 }
348 }
349 else
350 {
351 /*
352 * Not fully qualified.
353 * Handle Carats first, then append the name segments
354 */
355 i = 0;
356 if (Info->NumCarats)
357 {
358 for (i = 0; i < Info->NumCarats; i++)
359 {
360 InternalName[i] = '^';
361 }
362 }
363
364 if (NumSegments <= 1)
365 {
366 Result = &InternalName[i];
367 }
368 else if (NumSegments == 2)
369 {
370 InternalName[i] = AML_DUAL_NAME_PREFIX;
371 Result = &InternalName[(ACPI_SIZE) i+1];
372 }
373 else
374 {
375 InternalName[i] = AML_MULTI_NAME_PREFIX_OP;
376 InternalName[(ACPI_SIZE) i+1] = (char) NumSegments;
377 Result = &InternalName[(ACPI_SIZE) i+2];
378 }
379 }
380
381 /* Build the name (minus path separators) */
382
383 for (; NumSegments; NumSegments--)
384 {
385 for (i = 0; i < ACPI_NAME_SIZE; i++)
386 {
387 if (AcpiNsValidPathSeparator (*ExternalName) ||
388 (*ExternalName == 0))
389 {
390 /* Pad the segment with underscore(s) if segment is short */
391
392 Result[i] = '_';
393 }
394 else
395 {
396 /* Convert the character to uppercase and save it */
397
398 Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName);
399 ExternalName++;
400 }
401 }
402
403 /* Now we must have a path separator, or the pathname is bad */
404
405 if (!AcpiNsValidPathSeparator (*ExternalName) &&
406 (*ExternalName != 0))
407 {
408 return_ACPI_STATUS (AE_BAD_PARAMETER);
409 }
410
411 /* Move on the next segment */
412
413 ExternalName++;
414 Result += ACPI_NAME_SIZE;
415 }
416
417 /* Terminate the string */
418
419 *Result = 0;
420
421 if (Info->FullyQualified)
422 {
423 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
424 InternalName, InternalName));
425 }
426 else
427 {
428 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
525 UINT32 RequiredLength;
526 UINT32 PrefixLength = 0;
527 UINT32 i = 0;
528 UINT32 j = 0;
529
530
531 ACPI_FUNCTION_TRACE (NsExternalizeName);
532
533
534 if (!InternalNameLength ||
535 !InternalName ||
536 !ConvertedName)
537 {
538 return_ACPI_STATUS (AE_BAD_PARAMETER);
539 }
540
541 /* Check for a prefix (one '\' | one or more '^') */
542
543 switch (InternalName[0])
544 {
545 case '\\':
546 PrefixLength = 1;
547 break;
548
549 case '^':
550 for (i = 0; i < InternalNameLength; i++)
551 {
552 if (InternalName[i] == '^')
553 {
554 PrefixLength = i + 1;
555 }
556 else
557 {
558 break;
559 }
560 }
561
562 if (i == InternalNameLength)
563 {
564 PrefixLength = i;
565 }
566
567 break;
568
569 default:
570 break;
571 }
572
573 /*
574 * Check for object names. Note that there could be 0-255 of these
575 * 4-byte elements.
576 */
577 if (PrefixLength < InternalNameLength)
578 {
579 switch (InternalName[PrefixLength])
580 {
581 case AML_MULTI_NAME_PREFIX_OP:
582
583 /* <count> 4-byte names */
584
585 NamesIndex = PrefixLength + 2;
586 NumSegments = (UINT8)
587 InternalName[(ACPI_SIZE) PrefixLength + 1];
588 break;
589
638 {
639 return_ACPI_STATUS (AE_NO_MEMORY);
640 }
641
642 j = 0;
643
644 for (i = 0; i < PrefixLength; i++)
645 {
646 (*ConvertedName)[j++] = InternalName[i];
647 }
648
649 if (NumSegments > 0)
650 {
651 for (i = 0; i < NumSegments; i++)
652 {
653 if (i > 0)
654 {
655 (*ConvertedName)[j++] = '.';
656 }
657
658 (*ConvertedName)[j++] = InternalName[NamesIndex++];
659 (*ConvertedName)[j++] = InternalName[NamesIndex++];
660 (*ConvertedName)[j++] = InternalName[NamesIndex++];
661 (*ConvertedName)[j++] = InternalName[NamesIndex++];
662 }
663 }
664
665 if (ConvertedNameLength)
666 {
667 *ConvertedNameLength = (UINT32) RequiredLength;
668 }
669
670 return_ACPI_STATUS (AE_OK);
671 }
672
673
674 /*******************************************************************************
675 *
676 * FUNCTION: AcpiNsValidateHandle
677 *
678 * PARAMETERS: Handle - Handle to be validated and typecast to a
679 * namespace node.
680 *
681 * RETURN: A pointer to a namespace node
716 return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle));
717 }
718
719
720 /*******************************************************************************
721 *
722 * FUNCTION: AcpiNsTerminate
723 *
724 * PARAMETERS: none
725 *
726 * RETURN: none
727 *
728 * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
729 *
730 ******************************************************************************/
731
732 void
733 AcpiNsTerminate (
734 void)
735 {
736 ACPI_OPERAND_OBJECT *ObjDesc;
737
738
739 ACPI_FUNCTION_TRACE (NsTerminate);
740
741
742 /*
743 * 1) Free the entire namespace -- all nodes and objects
744 *
745 * Delete all object descriptors attached to namepsace nodes
746 */
747 AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
748
749 /* Detach any objects attached to the root */
750
751 ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode);
752 if (ObjDesc)
753 {
754 AcpiNsDetachObject (AcpiGbl_RootNode);
755 }
756
757 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
758 return_VOID;
759 }
760
761
762 /*******************************************************************************
763 *
764 * FUNCTION: AcpiNsOpensScope
765 *
766 * PARAMETERS: Type - A valid namespace type
767 *
768 * RETURN: NEWSCOPE if the passed type "opens a name scope" according
769 * to the ACPI specification, else 0
770 *
771 ******************************************************************************/
772
773 UINT32
774 AcpiNsOpensScope (
775 ACPI_OBJECT_TYPE Type)
776 {
777 ACPI_FUNCTION_TRACE_STR (NsOpensScope, AcpiUtGetTypeName (Type));
778
779
780 if (!AcpiUtValidObjectType (Type))
781 {
782 /* type code out of range */
783
784 ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
785 return_UINT32 (ACPI_NS_NORMAL);
786 }
787
788 return_UINT32 (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE);
789 }
790
791
792 /*******************************************************************************
793 *
794 * FUNCTION: AcpiNsGetNode
795 *
796 * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The
797 * \ (backslash) and ^ (carat) prefixes, and the
798 * . (period) to separate segments are supported.
799 * PrefixNode - Root of subtree to be searched, or NS_ALL for the
800 * root of the name space. If Name is fully
801 * qualified (first INT8 is '\'), the passed value
802 * of Scope will not be accessed.
803 * Flags - Used to indicate whether to perform upsearch or
804 * not.
805 * ReturnNode - Where the Node is returned
806 *
807 * DESCRIPTION: Look up a name relative to a given scope and return the
808 * corresponding Node. NOTE: Scope can be null.
809 *
810 * MUTEX: Locks namespace
811 *
812 ******************************************************************************/
813
814 ACPI_STATUS
815 AcpiNsGetNode (
816 ACPI_NAMESPACE_NODE *PrefixNode,
817 const char *Pathname,
818 UINT32 Flags,
819 ACPI_NAMESPACE_NODE **ReturnNode)
820 {
821 ACPI_GENERIC_STATE ScopeInfo;
822 ACPI_STATUS Status;
823 char *InternalPath;
824
825
826 ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));
827
828
829 if (!Pathname)
830 {
831 *ReturnNode = PrefixNode;
832 if (!PrefixNode)
833 {
834 *ReturnNode = AcpiGbl_RootNode;
835 }
836 return_ACPI_STATUS (AE_OK);
837 }
838
839 /* Convert path to internal representation */
840
841 Status = AcpiNsInternalizeName (Pathname, &InternalPath);
842 if (ACPI_FAILURE (Status))
843 {
844 return_ACPI_STATUS (Status);
845 }
846
847 /* Must lock namespace during lookup */
848
849 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
850 if (ACPI_FAILURE (Status))
851 {
852 goto Cleanup;
853 }
854
855 /* Setup lookup scope (search starting point) */
856
857 ScopeInfo.Scope.Node = PrefixNode;
|
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 - 2014, 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.
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 #define __NSUTILS_C__
46
47 #include "acpi.h"
48 #include "accommon.h"
49 #include "acnamesp.h"
50 #include "amlcode.h"
51
52 #define _COMPONENT ACPI_NAMESPACE
53 ACPI_MODULE_NAME ("nsutils")
54
55 /* Local prototypes */
56
57 #ifdef ACPI_OBSOLETE_FUNCTIONS
58 ACPI_NAME
59 AcpiNsFindParentName (
60 ACPI_NAMESPACE_NODE *NodeToSearch);
61 #endif
62
63
64 /*******************************************************************************
65 *
66 * FUNCTION: AcpiNsPrintNodePathname
67 *
68 * PARAMETERS: Node - Object
69 * Message - Prefix message
70 *
71 * DESCRIPTION: Print an object's full namespace pathname
72 * Manages allocation/freeing of a pathname buffer
73 *
74 ******************************************************************************/
75
76 void
91 /* Convert handle to full pathname and print it (with supplied message) */
92
93 Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
94
95 Status = AcpiNsHandleToPathname (Node, &Buffer);
96 if (ACPI_SUCCESS (Status))
97 {
98 if (Message)
99 {
100 AcpiOsPrintf ("%s ", Message);
101 }
102
103 AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node);
104 ACPI_FREE (Buffer.Pointer);
105 }
106 }
107
108
109 /*******************************************************************************
110 *
111 * FUNCTION: AcpiNsGetType
112 *
113 * PARAMETERS: Node - Parent Node to be examined
114 *
115 * RETURN: Type field from Node whose handle is passed
116 *
117 * DESCRIPTION: Return the type of a Namespace node
118 *
119 ******************************************************************************/
120
121 ACPI_OBJECT_TYPE
122 AcpiNsGetType (
123 ACPI_NAMESPACE_NODE *Node)
124 {
125 ACPI_FUNCTION_TRACE (NsGetType);
126
127
128 if (!Node)
129 {
130 ACPI_WARNING ((AE_INFO, "Null Node parameter"));
131 return_UINT8 (ACPI_TYPE_ANY);
132 }
133
134 return_UINT8 (Node->Type);
135 }
136
137
138 /*******************************************************************************
139 *
140 * FUNCTION: AcpiNsLocal
141 *
142 * PARAMETERS: Type - A namespace object type
143 *
144 * RETURN: LOCAL if names must be found locally in objects of the
145 * passed type, 0 if enclosing scopes should be searched
146 *
147 * DESCRIPTION: Returns scope rule for the given object type.
148 *
149 ******************************************************************************/
150
151 UINT32
152 AcpiNsLocal (
153 ACPI_OBJECT_TYPE Type)
154 {
155 ACPI_FUNCTION_TRACE (NsLocal);
156
157
158 if (!AcpiUtValidObjectType (Type))
159 {
160 /* Type code out of range */
161
162 ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
163 return_UINT32 (ACPI_NS_NORMAL);
164 }
165
166 return_UINT32 (AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
167 }
168
169
170 /*******************************************************************************
171 *
172 * FUNCTION: AcpiNsGetInternalNameLength
173 *
174 * PARAMETERS: Info - Info struct initialized with the
175 * external name pointer.
176 *
177 * RETURN: None
178 *
179 * DESCRIPTION: Calculate the length of the internal (AML) namestring
180 * corresponding to the external (ASL) namestring.
181 *
182 ******************************************************************************/
183
184 void
185 AcpiNsGetInternalNameLength (
186 ACPI_NAMESTRING_INFO *Info)
187 {
188 const char *NextExternalChar;
189 UINT32 i;
190
191
192 ACPI_FUNCTION_ENTRY ();
193
194
195 NextExternalChar = Info->ExternalName;
196 Info->NumCarats = 0;
197 Info->NumSegments = 0;
198 Info->FullyQualified = FALSE;
199
200 /*
201 * For the internal name, the required length is 4 bytes per segment, plus
202 * 1 each for RootPrefix, MultiNamePrefixOp, segment count, trailing null
203 * (which is not really needed, but no there's harm in putting it there)
204 *
205 * strlen() + 1 covers the first NameSeg, which has no path separator
206 */
207 if (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
208 {
209 Info->FullyQualified = TRUE;
210 NextExternalChar++;
211
212 /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */
213
214 while (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
215 {
216 NextExternalChar++;
217 }
218 }
219 else
220 {
221 /* Handle Carat prefixes */
222
223 while (ACPI_IS_PARENT_PREFIX (*NextExternalChar))
224 {
225 Info->NumCarats++;
226 NextExternalChar++;
227 }
228 }
229
230 /*
231 * Determine the number of ACPI name "segments" by counting the number of
232 * path separators within the string. Start with one segment since the
233 * segment count is [(# separators) + 1], and zero separators is ok.
234 */
235 if (*NextExternalChar)
236 {
237 Info->NumSegments = 1;
238 for (i = 0; NextExternalChar[i]; i++)
239 {
240 if (ACPI_IS_PATH_SEPARATOR (NextExternalChar[i]))
241 {
242 Info->NumSegments++;
243 }
244 }
245 }
246
247 Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) +
248 4 + Info->NumCarats;
249
250 Info->NextExternalChar = NextExternalChar;
251 }
252
253
254 /*******************************************************************************
255 *
256 * FUNCTION: AcpiNsBuildInternalName
257 *
258 * PARAMETERS: Info - Info struct fully initialized
259 *
260 * RETURN: Status
265 ******************************************************************************/
266
267 ACPI_STATUS
268 AcpiNsBuildInternalName (
269 ACPI_NAMESTRING_INFO *Info)
270 {
271 UINT32 NumSegments = Info->NumSegments;
272 char *InternalName = Info->InternalName;
273 const char *ExternalName = Info->NextExternalChar;
274 char *Result = NULL;
275 UINT32 i;
276
277
278 ACPI_FUNCTION_TRACE (NsBuildInternalName);
279
280
281 /* Setup the correct prefixes, counts, and pointers */
282
283 if (Info->FullyQualified)
284 {
285 InternalName[0] = AML_ROOT_PREFIX;
286
287 if (NumSegments <= 1)
288 {
289 Result = &InternalName[1];
290 }
291 else if (NumSegments == 2)
292 {
293 InternalName[1] = AML_DUAL_NAME_PREFIX;
294 Result = &InternalName[2];
295 }
296 else
297 {
298 InternalName[1] = AML_MULTI_NAME_PREFIX_OP;
299 InternalName[2] = (char) NumSegments;
300 Result = &InternalName[3];
301 }
302 }
303 else
304 {
305 /*
306 * Not fully qualified.
307 * Handle Carats first, then append the name segments
308 */
309 i = 0;
310 if (Info->NumCarats)
311 {
312 for (i = 0; i < Info->NumCarats; i++)
313 {
314 InternalName[i] = AML_PARENT_PREFIX;
315 }
316 }
317
318 if (NumSegments <= 1)
319 {
320 Result = &InternalName[i];
321 }
322 else if (NumSegments == 2)
323 {
324 InternalName[i] = AML_DUAL_NAME_PREFIX;
325 Result = &InternalName[(ACPI_SIZE) i+1];
326 }
327 else
328 {
329 InternalName[i] = AML_MULTI_NAME_PREFIX_OP;
330 InternalName[(ACPI_SIZE) i+1] = (char) NumSegments;
331 Result = &InternalName[(ACPI_SIZE) i+2];
332 }
333 }
334
335 /* Build the name (minus path separators) */
336
337 for (; NumSegments; NumSegments--)
338 {
339 for (i = 0; i < ACPI_NAME_SIZE; i++)
340 {
341 if (ACPI_IS_PATH_SEPARATOR (*ExternalName) ||
342 (*ExternalName == 0))
343 {
344 /* Pad the segment with underscore(s) if segment is short */
345
346 Result[i] = '_';
347 }
348 else
349 {
350 /* Convert the character to uppercase and save it */
351
352 Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName);
353 ExternalName++;
354 }
355 }
356
357 /* Now we must have a path separator, or the pathname is bad */
358
359 if (!ACPI_IS_PATH_SEPARATOR (*ExternalName) &&
360 (*ExternalName != 0))
361 {
362 return_ACPI_STATUS (AE_BAD_PATHNAME);
363 }
364
365 /* Move on the next segment */
366
367 ExternalName++;
368 Result += ACPI_NAME_SIZE;
369 }
370
371 /* Terminate the string */
372
373 *Result = 0;
374
375 if (Info->FullyQualified)
376 {
377 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
378 InternalName, InternalName));
379 }
380 else
381 {
382 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
479 UINT32 RequiredLength;
480 UINT32 PrefixLength = 0;
481 UINT32 i = 0;
482 UINT32 j = 0;
483
484
485 ACPI_FUNCTION_TRACE (NsExternalizeName);
486
487
488 if (!InternalNameLength ||
489 !InternalName ||
490 !ConvertedName)
491 {
492 return_ACPI_STATUS (AE_BAD_PARAMETER);
493 }
494
495 /* Check for a prefix (one '\' | one or more '^') */
496
497 switch (InternalName[0])
498 {
499 case AML_ROOT_PREFIX:
500
501 PrefixLength = 1;
502 break;
503
504 case AML_PARENT_PREFIX:
505
506 for (i = 0; i < InternalNameLength; i++)
507 {
508 if (ACPI_IS_PARENT_PREFIX (InternalName[i]))
509 {
510 PrefixLength = i + 1;
511 }
512 else
513 {
514 break;
515 }
516 }
517
518 if (i == InternalNameLength)
519 {
520 PrefixLength = i;
521 }
522
523 break;
524
525 default:
526
527 break;
528 }
529
530 /*
531 * Check for object names. Note that there could be 0-255 of these
532 * 4-byte elements.
533 */
534 if (PrefixLength < InternalNameLength)
535 {
536 switch (InternalName[PrefixLength])
537 {
538 case AML_MULTI_NAME_PREFIX_OP:
539
540 /* <count> 4-byte names */
541
542 NamesIndex = PrefixLength + 2;
543 NumSegments = (UINT8)
544 InternalName[(ACPI_SIZE) PrefixLength + 1];
545 break;
546
595 {
596 return_ACPI_STATUS (AE_NO_MEMORY);
597 }
598
599 j = 0;
600
601 for (i = 0; i < PrefixLength; i++)
602 {
603 (*ConvertedName)[j++] = InternalName[i];
604 }
605
606 if (NumSegments > 0)
607 {
608 for (i = 0; i < NumSegments; i++)
609 {
610 if (i > 0)
611 {
612 (*ConvertedName)[j++] = '.';
613 }
614
615 /* Copy and validate the 4-char name segment */
616
617 ACPI_MOVE_NAME (&(*ConvertedName)[j], &InternalName[NamesIndex]);
618 AcpiUtRepairName (&(*ConvertedName)[j]);
619
620 j += ACPI_NAME_SIZE;
621 NamesIndex += ACPI_NAME_SIZE;
622 }
623 }
624
625 if (ConvertedNameLength)
626 {
627 *ConvertedNameLength = (UINT32) RequiredLength;
628 }
629
630 return_ACPI_STATUS (AE_OK);
631 }
632
633
634 /*******************************************************************************
635 *
636 * FUNCTION: AcpiNsValidateHandle
637 *
638 * PARAMETERS: Handle - Handle to be validated and typecast to a
639 * namespace node.
640 *
641 * RETURN: A pointer to a namespace node
676 return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle));
677 }
678
679
680 /*******************************************************************************
681 *
682 * FUNCTION: AcpiNsTerminate
683 *
684 * PARAMETERS: none
685 *
686 * RETURN: none
687 *
688 * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
689 *
690 ******************************************************************************/
691
692 void
693 AcpiNsTerminate (
694 void)
695 {
696 ACPI_STATUS Status;
697
698
699 ACPI_FUNCTION_TRACE (NsTerminate);
700
701
702 /*
703 * Free the entire namespace -- all nodes and all objects
704 * attached to the nodes
705 */
706 AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
707
708 /* Delete any objects attached to the root node */
709
710 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
711 if (ACPI_FAILURE (Status))
712 {
713 return_VOID;
714 }
715
716 AcpiNsDeleteNode (AcpiGbl_RootNode);
717 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
718
719 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
720 return_VOID;
721 }
722
723
724 /*******************************************************************************
725 *
726 * FUNCTION: AcpiNsOpensScope
727 *
728 * PARAMETERS: Type - A valid namespace type
729 *
730 * RETURN: NEWSCOPE if the passed type "opens a name scope" according
731 * to the ACPI specification, else 0
732 *
733 ******************************************************************************/
734
735 UINT32
736 AcpiNsOpensScope (
737 ACPI_OBJECT_TYPE Type)
738 {
739 ACPI_FUNCTION_ENTRY ();
740
741
742 if (Type > ACPI_TYPE_LOCAL_MAX)
743 {
744 /* type code out of range */
745
746 ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
747 return (ACPI_NS_NORMAL);
748 }
749
750 return (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE);
751 }
752
753
754 /*******************************************************************************
755 *
756 * FUNCTION: AcpiNsGetNode
757 *
758 * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The
759 * \ (backslash) and ^ (carat) prefixes, and the
760 * . (period) to separate segments are supported.
761 * PrefixNode - Root of subtree to be searched, or NS_ALL for the
762 * root of the name space. If Name is fully
763 * qualified (first INT8 is '\'), the passed value
764 * of Scope will not be accessed.
765 * Flags - Used to indicate whether to perform upsearch or
766 * not.
767 * ReturnNode - Where the Node is returned
768 *
769 * DESCRIPTION: Look up a name relative to a given scope and return the
770 * corresponding Node. NOTE: Scope can be null.
771 *
772 * MUTEX: Locks namespace
773 *
774 ******************************************************************************/
775
776 ACPI_STATUS
777 AcpiNsGetNode (
778 ACPI_NAMESPACE_NODE *PrefixNode,
779 const char *Pathname,
780 UINT32 Flags,
781 ACPI_NAMESPACE_NODE **ReturnNode)
782 {
783 ACPI_GENERIC_STATE ScopeInfo;
784 ACPI_STATUS Status;
785 char *InternalPath;
786
787
788 ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));
789
790
791 /* Simplest case is a null pathname */
792
793 if (!Pathname)
794 {
795 *ReturnNode = PrefixNode;
796 if (!PrefixNode)
797 {
798 *ReturnNode = AcpiGbl_RootNode;
799 }
800 return_ACPI_STATUS (AE_OK);
801 }
802
803 /* Quick check for a reference to the root */
804
805 if (ACPI_IS_ROOT_PREFIX (Pathname[0]) && (!Pathname[1]))
806 {
807 *ReturnNode = AcpiGbl_RootNode;
808 return_ACPI_STATUS (AE_OK);
809 }
810
811 /* Convert path to internal representation */
812
813 Status = AcpiNsInternalizeName (Pathname, &InternalPath);
814 if (ACPI_FAILURE (Status))
815 {
816 return_ACPI_STATUS (Status);
817 }
818
819 /* Must lock namespace during lookup */
820
821 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
822 if (ACPI_FAILURE (Status))
823 {
824 goto Cleanup;
825 }
826
827 /* Setup lookup scope (search starting point) */
828
829 ScopeInfo.Scope.Node = PrefixNode;
|