xref: /titanic_44/usr/src/uts/intel/io/acpica/namespace/nsaccess.c (revision 70f9559bd0c02885d84a425eaafc8c280df10efb)
1 /*******************************************************************************
2  *
3  * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2011, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #define __NSACCESS_C__
45 
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "amlcode.h"
49 #include "acnamesp.h"
50 #include "acdispat.h"
51 
52 
53 #define _COMPONENT          ACPI_NAMESPACE
54         ACPI_MODULE_NAME    ("nsaccess")
55 
56 
57 /*******************************************************************************
58  *
59  * FUNCTION:    AcpiNsRootInitialize
60  *
61  * PARAMETERS:  None
62  *
63  * RETURN:      Status
64  *
65  * DESCRIPTION: Allocate and initialize the default root named objects
66  *
67  * MUTEX:       Locks namespace for entire execution
68  *
69  ******************************************************************************/
70 
71 ACPI_STATUS
72 AcpiNsRootInitialize (
73     void)
74 {
75     ACPI_STATUS                 Status;
76     const ACPI_PREDEFINED_NAMES *InitVal = NULL;
77     ACPI_NAMESPACE_NODE         *NewNode;
78     ACPI_OPERAND_OBJECT         *ObjDesc;
79     ACPI_STRING                 Val = NULL;
80 
81 
82     ACPI_FUNCTION_TRACE (NsRootInitialize);
83 
84 
85     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
86     if (ACPI_FAILURE (Status))
87     {
88         return_ACPI_STATUS (Status);
89     }
90 
91     /*
92      * The global root ptr is initially NULL, so a non-NULL value indicates
93      * that AcpiNsRootInitialize() has already been called; just return.
94      */
95     if (AcpiGbl_RootNode)
96     {
97         Status = AE_OK;
98         goto UnlockAndExit;
99     }
100 
101     /*
102      * Tell the rest of the subsystem that the root is initialized
103      * (This is OK because the namespace is locked)
104      */
105     AcpiGbl_RootNode = &AcpiGbl_RootNodeStruct;
106 
107     /* Enter the pre-defined names in the name table */
108 
109     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
110         "Entering predefined entries into namespace\n"));
111 
112     for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++)
113     {
114         /* _OSI is optional for now, will be permanent later */
115 
116         if (!ACPI_STRCMP (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod)
117         {
118             continue;
119         }
120 
121         Status = AcpiNsLookup (NULL, InitVal->Name, InitVal->Type,
122                         ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
123                         NULL, &NewNode);
124 
125         if (ACPI_FAILURE (Status) || (!NewNode)) /* Must be on same line for code converter */
126         {
127             ACPI_EXCEPTION ((AE_INFO, Status,
128                 "Could not create predefined name %s",
129                 InitVal->Name));
130         }
131 
132         /*
133          * Name entered successfully. If entry in PreDefinedNames[] specifies
134          * an initial value, create the initial value.
135          */
136         if (InitVal->Val)
137         {
138             Status = AcpiOsPredefinedOverride (InitVal, &Val);
139             if (ACPI_FAILURE (Status))
140             {
141                 ACPI_ERROR ((AE_INFO,
142                     "Could not override predefined %s",
143                     InitVal->Name));
144             }
145 
146             if (!Val)
147             {
148                 Val = InitVal->Val;
149             }
150 
151             /*
152              * Entry requests an initial value, allocate a
153              * descriptor for it.
154              */
155             ObjDesc = AcpiUtCreateInternalObject (InitVal->Type);
156             if (!ObjDesc)
157             {
158                 Status = AE_NO_MEMORY;
159                 goto UnlockAndExit;
160             }
161 
162             /*
163              * Convert value string from table entry to
164              * internal representation. Only types actually
165              * used for initial values are implemented here.
166              */
167             switch (InitVal->Type)
168             {
169             case ACPI_TYPE_METHOD:
170                 ObjDesc->Method.ParamCount = (UINT8) ACPI_TO_INTEGER (Val);
171                 ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID;
172 
173 #if defined (ACPI_ASL_COMPILER)
174 
175                 /* Save the parameter count for the iASL compiler */
176 
177                 NewNode->Value = ObjDesc->Method.ParamCount;
178 #else
179                 /* Mark this as a very SPECIAL method */
180 
181                 ObjDesc->Method.InfoFlags = ACPI_METHOD_INTERNAL_ONLY;
182                 ObjDesc->Method.Dispatch.Implementation = AcpiUtOsiImplementation;
183 #endif
184                 break;
185 
186             case ACPI_TYPE_INTEGER:
187 
188                 ObjDesc->Integer.Value = ACPI_TO_INTEGER (Val);
189                 break;
190 
191 
192             case ACPI_TYPE_STRING:
193 
194                 /* Build an object around the static string */
195 
196                 ObjDesc->String.Length = (UINT32) ACPI_STRLEN (Val);
197                 ObjDesc->String.Pointer = Val;
198                 ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
199                 break;
200 
201 
202             case ACPI_TYPE_MUTEX:
203 
204                 ObjDesc->Mutex.Node = NewNode;
205                 ObjDesc->Mutex.SyncLevel = (UINT8) (ACPI_TO_INTEGER (Val) - 1);
206 
207                 /* Create a mutex */
208 
209                 Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex);
210                 if (ACPI_FAILURE (Status))
211                 {
212                     AcpiUtRemoveReference (ObjDesc);
213                     goto UnlockAndExit;
214                 }
215 
216                 /* Special case for ACPI Global Lock */
217 
218                 if (ACPI_STRCMP (InitVal->Name, "_GL_") == 0)
219                 {
220                     AcpiGbl_GlobalLockMutex = ObjDesc;
221 
222                     /* Create additional counting semaphore for global lock */
223 
224                     Status = AcpiOsCreateSemaphore (
225                                 1, 0, &AcpiGbl_GlobalLockSemaphore);
226                     if (ACPI_FAILURE (Status))
227                     {
228                         AcpiUtRemoveReference (ObjDesc);
229                         goto UnlockAndExit;
230                     }
231                 }
232                 break;
233 
234 
235             default:
236 
237                 ACPI_ERROR ((AE_INFO, "Unsupported initial type value 0x%X",
238                     InitVal->Type));
239                 AcpiUtRemoveReference (ObjDesc);
240                 ObjDesc = NULL;
241                 continue;
242             }
243 
244             /* Store pointer to value descriptor in the Node */
245 
246             Status = AcpiNsAttachObject (NewNode, ObjDesc,
247                         ObjDesc->Common.Type);
248 
249             /* Remove local reference to the object */
250 
251             AcpiUtRemoveReference (ObjDesc);
252         }
253     }
254 
255 
256 UnlockAndExit:
257     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
258 
259     /* Save a handle to "_GPE", it is always present */
260 
261     if (ACPI_SUCCESS (Status))
262     {
263         Status = AcpiNsGetNode (NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH,
264                     &AcpiGbl_FadtGpeDevice);
265     }
266 
267     return_ACPI_STATUS (Status);
268 }
269 
270 
271 /*******************************************************************************
272  *
273  * FUNCTION:    AcpiNsLookup
274  *
275  * PARAMETERS:  ScopeInfo       - Current scope info block
276  *              Pathname        - Search pathname, in internal format
277  *                                (as represented in the AML stream)
278  *              Type            - Type associated with name
279  *              InterpreterMode - IMODE_LOAD_PASS2 => add name if not found
280  *              Flags           - Flags describing the search restrictions
281  *              WalkState       - Current state of the walk
282  *              ReturnNode      - Where the Node is placed (if found
283  *                                or created successfully)
284  *
285  * RETURN:      Status
286  *
287  * DESCRIPTION: Find or enter the passed name in the name space.
288  *              Log an error if name not found in Exec mode.
289  *
290  * MUTEX:       Assumes namespace is locked.
291  *
292  ******************************************************************************/
293 
294 ACPI_STATUS
295 AcpiNsLookup (
296     ACPI_GENERIC_STATE      *ScopeInfo,
297     char                    *Pathname,
298     ACPI_OBJECT_TYPE        Type,
299     ACPI_INTERPRETER_MODE   InterpreterMode,
300     UINT32                  Flags,
301     ACPI_WALK_STATE         *WalkState,
302     ACPI_NAMESPACE_NODE     **ReturnNode)
303 {
304     ACPI_STATUS             Status;
305     char                    *Path = Pathname;
306     ACPI_NAMESPACE_NODE     *PrefixNode;
307     ACPI_NAMESPACE_NODE     *CurrentNode = NULL;
308     ACPI_NAMESPACE_NODE     *ThisNode = NULL;
309     UINT32                  NumSegments;
310     UINT32                  NumCarats;
311     ACPI_NAME               SimpleName;
312     ACPI_OBJECT_TYPE        TypeToCheckFor;
313     ACPI_OBJECT_TYPE        ThisSearchType;
314     UINT32                  SearchParentFlag = ACPI_NS_SEARCH_PARENT;
315     UINT32                  LocalFlags;
316 
317 
318     ACPI_FUNCTION_TRACE (NsLookup);
319 
320 
321     if (!ReturnNode)
322     {
323         return_ACPI_STATUS (AE_BAD_PARAMETER);
324     }
325 
326     LocalFlags = Flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT);
327     *ReturnNode = ACPI_ENTRY_NOT_FOUND;
328     AcpiGbl_NsLookupCount++;
329 
330     if (!AcpiGbl_RootNode)
331     {
332         return_ACPI_STATUS (AE_NO_NAMESPACE);
333     }
334 
335     /* Get the prefix scope. A null scope means use the root scope */
336 
337     if ((!ScopeInfo) ||
338         (!ScopeInfo->Scope.Node))
339     {
340         ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
341             "Null scope prefix, using root node (%p)\n",
342             AcpiGbl_RootNode));
343 
344         PrefixNode = AcpiGbl_RootNode;
345     }
346     else
347     {
348         PrefixNode = ScopeInfo->Scope.Node;
349         if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED)
350         {
351             ACPI_ERROR ((AE_INFO, "%p is not a namespace node [%s]",
352                 PrefixNode, AcpiUtGetDescriptorName (PrefixNode)));
353             return_ACPI_STATUS (AE_AML_INTERNAL);
354         }
355 
356         if (!(Flags & ACPI_NS_PREFIX_IS_SCOPE))
357         {
358             /*
359              * This node might not be a actual "scope" node (such as a
360              * Device/Method, etc.)  It could be a Package or other object
361              * node. Backup up the tree to find the containing scope node.
362              */
363             while (!AcpiNsOpensScope (PrefixNode->Type) &&
364                     PrefixNode->Type != ACPI_TYPE_ANY)
365             {
366                 PrefixNode = PrefixNode->Parent;
367             }
368         }
369     }
370 
371     /* Save type. TBD: may be no longer necessary */
372 
373     TypeToCheckFor = Type;
374 
375     /*
376      * Begin examination of the actual pathname
377      */
378     if (!Pathname)
379     {
380         /* A Null NamePath is allowed and refers to the root */
381 
382         NumSegments = 0;
383         ThisNode = AcpiGbl_RootNode;
384         Path = "";
385 
386         ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
387             "Null Pathname (Zero segments), Flags=%X\n", Flags));
388     }
389     else
390     {
391         /*
392          * Name pointer is valid (and must be in internal name format)
393          *
394          * Check for scope prefixes:
395          *
396          * As represented in the AML stream, a namepath consists of an
397          * optional scope prefix followed by a name segment part.
398          *
399          * If present, the scope prefix is either a Root Prefix (in
400          * which case the name is fully qualified), or one or more
401          * Parent Prefixes (in which case the name's scope is relative
402          * to the current scope).
403          */
404         if (*Path == (UINT8) AML_ROOT_PREFIX)
405         {
406             /* Pathname is fully qualified, start from the root */
407 
408             ThisNode = AcpiGbl_RootNode;
409             SearchParentFlag = ACPI_NS_NO_UPSEARCH;
410 
411             /* Point to name segment part */
412 
413             Path++;
414 
415             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
416                 "Path is absolute from root [%p]\n", ThisNode));
417         }
418         else
419         {
420             /* Pathname is relative to current scope, start there */
421 
422             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
423                 "Searching relative to prefix scope [%4.4s] (%p)\n",
424                 AcpiUtGetNodeName (PrefixNode), PrefixNode));
425 
426             /*
427              * Handle multiple Parent Prefixes (carat) by just getting
428              * the parent node for each prefix instance.
429              */
430             ThisNode = PrefixNode;
431             NumCarats = 0;
432             while (*Path == (UINT8) AML_PARENT_PREFIX)
433             {
434                 /* Name is fully qualified, no search rules apply */
435 
436                 SearchParentFlag = ACPI_NS_NO_UPSEARCH;
437 
438                 /*
439                  * Point past this prefix to the name segment
440                  * part or the next Parent Prefix
441                  */
442                 Path++;
443 
444                 /* Backup to the parent node */
445 
446                 NumCarats++;
447                 ThisNode = ThisNode->Parent;
448                 if (!ThisNode)
449                 {
450                     /* Current scope has no parent scope */
451 
452                     ACPI_ERROR ((AE_INFO,
453                         "ACPI path has too many parent prefixes (^) "
454                         "- reached beyond root node"));
455                     return_ACPI_STATUS (AE_NOT_FOUND);
456                 }
457             }
458 
459             if (SearchParentFlag == ACPI_NS_NO_UPSEARCH)
460             {
461                 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
462                     "Search scope is [%4.4s], path has %u carat(s)\n",
463                     AcpiUtGetNodeName (ThisNode), NumCarats));
464             }
465         }
466 
467         /*
468          * Determine the number of ACPI name segments in this pathname.
469          *
470          * The segment part consists of either:
471          *  - A Null name segment (0)
472          *  - A DualNamePrefix followed by two 4-byte name segments
473          *  - A MultiNamePrefix followed by a byte indicating the
474          *      number of segments and the segments themselves.
475          *  - A single 4-byte name segment
476          *
477          * Examine the name prefix opcode, if any, to determine the number of
478          * segments.
479          */
480         switch (*Path)
481         {
482         case 0:
483             /*
484              * Null name after a root or parent prefixes. We already
485              * have the correct target node and there are no name segments.
486              */
487             NumSegments  = 0;
488             Type = ThisNode->Type;
489 
490             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
491                 "Prefix-only Pathname (Zero name segments), Flags=%X\n",
492                 Flags));
493             break;
494 
495         case AML_DUAL_NAME_PREFIX:
496 
497             /* More than one NameSeg, search rules do not apply */
498 
499             SearchParentFlag = ACPI_NS_NO_UPSEARCH;
500 
501             /* Two segments, point to first name segment */
502 
503             NumSegments = 2;
504             Path++;
505 
506             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
507                 "Dual Pathname (2 segments, Flags=%X)\n", Flags));
508             break;
509 
510         case AML_MULTI_NAME_PREFIX_OP:
511 
512             /* More than one NameSeg, search rules do not apply */
513 
514             SearchParentFlag = ACPI_NS_NO_UPSEARCH;
515 
516             /* Extract segment count, point to first name segment */
517 
518             Path++;
519             NumSegments = (UINT32) (UINT8) *Path;
520             Path++;
521 
522             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
523                 "Multi Pathname (%u Segments, Flags=%X)\n",
524                 NumSegments, Flags));
525             break;
526 
527         default:
528             /*
529              * Not a Null name, no Dual or Multi prefix, hence there is
530              * only one name segment and Pathname is already pointing to it.
531              */
532             NumSegments = 1;
533 
534             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
535                 "Simple Pathname (1 segment, Flags=%X)\n", Flags));
536             break;
537         }
538 
539         ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path));
540     }
541 
542 
543     /*
544      * Search namespace for each segment of the name. Loop through and
545      * verify (or add to the namespace) each name segment.
546      *
547      * The object type is significant only at the last name
548      * segment. (We don't care about the types along the path, only
549      * the type of the final target object.)
550      */
551     ThisSearchType = ACPI_TYPE_ANY;
552     CurrentNode = ThisNode;
553     while (NumSegments && CurrentNode)
554     {
555         NumSegments--;
556         if (!NumSegments)
557         {
558             /* This is the last segment, enable typechecking */
559 
560             ThisSearchType = Type;
561 
562             /*
563              * Only allow automatic parent search (search rules) if the caller
564              * requested it AND we have a single, non-fully-qualified NameSeg
565              */
566             if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) &&
567                 (Flags & ACPI_NS_SEARCH_PARENT))
568             {
569                 LocalFlags |= ACPI_NS_SEARCH_PARENT;
570             }
571 
572             /* Set error flag according to caller */
573 
574             if (Flags & ACPI_NS_ERROR_IF_FOUND)
575             {
576                 LocalFlags |= ACPI_NS_ERROR_IF_FOUND;
577             }
578         }
579 
580         /* Extract one ACPI name from the front of the pathname */
581 
582         ACPI_MOVE_32_TO_32 (&SimpleName, Path);
583 
584         /* Try to find the single (4 character) ACPI name */
585 
586         Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode,
587                     InterpreterMode, ThisSearchType, LocalFlags, &ThisNode);
588         if (ACPI_FAILURE (Status))
589         {
590             if (Status == AE_NOT_FOUND)
591             {
592                 /* Name not found in ACPI namespace */
593 
594                 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
595                     "Name [%4.4s] not found in scope [%4.4s] %p\n",
596                     (char *) &SimpleName, (char *) &CurrentNode->Name,
597                     CurrentNode));
598             }
599 
600             *ReturnNode = ThisNode;
601             return_ACPI_STATUS (Status);
602         }
603 
604         /* More segments to follow? */
605 
606         if (NumSegments > 0)
607         {
608             /*
609              * If we have an alias to an object that opens a scope (such as a
610              * device or processor), we need to dereference the alias here so
611              * that we can access any children of the original node (via the
612              * remaining segments).
613              */
614             if (ThisNode->Type == ACPI_TYPE_LOCAL_ALIAS)
615             {
616                 if (!ThisNode->Object)
617                 {
618                     return_ACPI_STATUS (AE_NOT_EXIST);
619                 }
620 
621                 if (AcpiNsOpensScope (((ACPI_NAMESPACE_NODE *)
622                         ThisNode->Object)->Type))
623                 {
624                     ThisNode = (ACPI_NAMESPACE_NODE *) ThisNode->Object;
625                 }
626             }
627         }
628 
629         /* Special handling for the last segment (NumSegments == 0) */
630 
631         else
632         {
633             /*
634              * Sanity typecheck of the target object:
635              *
636              * If 1) This is the last segment (NumSegments == 0)
637              *    2) And we are looking for a specific type
638              *       (Not checking for TYPE_ANY)
639              *    3) Which is not an alias
640              *    4) Which is not a local type (TYPE_SCOPE)
641              *    5) And the type of target object is known (not TYPE_ANY)
642              *    6) And target object does not match what we are looking for
643              *
644              * Then we have a type mismatch. Just warn and ignore it.
645              */
646             if ((TypeToCheckFor != ACPI_TYPE_ANY)                   &&
647                 (TypeToCheckFor != ACPI_TYPE_LOCAL_ALIAS)           &&
648                 (TypeToCheckFor != ACPI_TYPE_LOCAL_METHOD_ALIAS)    &&
649                 (TypeToCheckFor != ACPI_TYPE_LOCAL_SCOPE)           &&
650                 (ThisNode->Type != ACPI_TYPE_ANY)                   &&
651                 (ThisNode->Type != TypeToCheckFor))
652             {
653                 /* Complain about a type mismatch */
654 
655                 ACPI_WARNING ((AE_INFO,
656                     "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
657                     ACPI_CAST_PTR (char, &SimpleName),
658                     AcpiUtGetTypeName (ThisNode->Type),
659                     AcpiUtGetTypeName (TypeToCheckFor)));
660             }
661 
662             /*
663              * If this is the last name segment and we are not looking for a
664              * specific type, but the type of found object is known, use that
665              * type to (later) see if it opens a scope.
666              */
667             if (Type == ACPI_TYPE_ANY)
668             {
669                 Type = ThisNode->Type;
670             }
671         }
672 
673         /* Point to next name segment and make this node current */
674 
675         Path += ACPI_NAME_SIZE;
676         CurrentNode = ThisNode;
677     }
678 
679     /* Always check if we need to open a new scope */
680 
681     if (!(Flags & ACPI_NS_DONT_OPEN_SCOPE) && (WalkState))
682     {
683         /*
684          * If entry is a type which opens a scope, push the new scope on the
685          * scope stack.
686          */
687         if (AcpiNsOpensScope (Type))
688         {
689             Status = AcpiDsScopeStackPush (ThisNode, Type, WalkState);
690             if (ACPI_FAILURE (Status))
691             {
692                 return_ACPI_STATUS (Status);
693             }
694         }
695     }
696 
697     *ReturnNode = ThisNode;
698     return_ACPI_STATUS (AE_OK);
699 }
700 
701