adwalk.c revision 228110
1167802Sjkim/******************************************************************************
2167802Sjkim *
3167802Sjkim * Module Name: adwalk - Application-level disassembler parse tree walk routines
4167802Sjkim *
5167802Sjkim *****************************************************************************/
6167802Sjkim
7217365Sjkim/*
8217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp.
9167802Sjkim * All rights reserved.
10167802Sjkim *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25167802Sjkim *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29167802Sjkim *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43167802Sjkim
44167802Sjkim
45193529Sjkim#include <contrib/dev/acpica/include/acpi.h>
46193529Sjkim#include <contrib/dev/acpica/include/accommon.h>
47193529Sjkim#include <contrib/dev/acpica/include/acparser.h>
48193529Sjkim#include <contrib/dev/acpica/include/amlcode.h>
49193529Sjkim#include <contrib/dev/acpica/include/acdisasm.h>
50193529Sjkim#include <contrib/dev/acpica/include/acdispat.h>
51193529Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
52193529Sjkim#include <contrib/dev/acpica/include/acapps.h>
53167802Sjkim
54167802Sjkim
55167802Sjkim#define _COMPONENT          ACPI_TOOLS
56167802Sjkim        ACPI_MODULE_NAME    ("adwalk")
57167802Sjkim
58167802Sjkim/*
59167802Sjkim * aslmap - opcode mappings and reserved method names
60167802Sjkim */
61167802SjkimACPI_OBJECT_TYPE
62167802SjkimAslMapNamedOpcodeToDataType (
63167802Sjkim    UINT16                  Opcode);
64167802Sjkim
65167802Sjkim/* Local prototypes */
66167802Sjkim
67167802Sjkimstatic ACPI_STATUS
68167802SjkimAcpiDmFindOrphanDescending (
69167802Sjkim    ACPI_PARSE_OBJECT       *Op,
70167802Sjkim    UINT32                  Level,
71167802Sjkim    void                    *Context);
72167802Sjkim
73167802Sjkimstatic ACPI_STATUS
74167802SjkimAcpiDmDumpDescending (
75167802Sjkim    ACPI_PARSE_OBJECT       *Op,
76167802Sjkim    UINT32                  Level,
77167802Sjkim    void                    *Context);
78167802Sjkim
79167802Sjkimstatic ACPI_STATUS
80167802SjkimAcpiDmXrefDescendingOp (
81167802Sjkim    ACPI_PARSE_OBJECT       *Op,
82167802Sjkim    UINT32                  Level,
83167802Sjkim    void                    *Context);
84167802Sjkim
85167802Sjkimstatic ACPI_STATUS
86167802SjkimAcpiDmCommonAscendingOp (
87167802Sjkim    ACPI_PARSE_OBJECT       *Op,
88167802Sjkim    UINT32                  Level,
89167802Sjkim    void                    *Context);
90167802Sjkim
91167802Sjkimstatic ACPI_STATUS
92167802SjkimAcpiDmLoadDescendingOp (
93167802Sjkim    ACPI_PARSE_OBJECT       *Op,
94167802Sjkim    UINT32                  Level,
95167802Sjkim    void                    *Context);
96167802Sjkim
97167802Sjkimstatic UINT32
98167802SjkimAcpiDmInspectPossibleArgs (
99167802Sjkim    UINT32                  CurrentOpArgCount,
100167802Sjkim    UINT32                  TargetCount,
101167802Sjkim    ACPI_PARSE_OBJECT       *Op);
102167802Sjkim
103167802Sjkimstatic ACPI_STATUS
104167802SjkimAcpiDmResourceDescendingOp (
105167802Sjkim    ACPI_PARSE_OBJECT       *Op,
106167802Sjkim    UINT32                  Level,
107167802Sjkim    void                    *Context);
108167802Sjkim
109167802Sjkim
110167802Sjkim/*******************************************************************************
111167802Sjkim *
112167802Sjkim * FUNCTION:    AcpiDmDumpTree
113167802Sjkim *
114198237Sjkim * PARAMETERS:  Origin              - Starting object
115167802Sjkim *
116167802Sjkim * RETURN:      None
117167802Sjkim *
118167802Sjkim * DESCRIPTION: Parse tree walk to format and output the nodes
119167802Sjkim *
120167802Sjkim ******************************************************************************/
121167802Sjkim
122167802Sjkimvoid
123167802SjkimAcpiDmDumpTree (
124167802Sjkim    ACPI_PARSE_OBJECT       *Origin)
125167802Sjkim{
126167802Sjkim    ACPI_OP_WALK_INFO       Info;
127167802Sjkim
128167802Sjkim
129167802Sjkim    if (!Origin)
130167802Sjkim    {
131167802Sjkim        return;
132167802Sjkim    }
133167802Sjkim
134167802Sjkim    AcpiOsPrintf ("/*\nAML Parse Tree\n\n");
135167802Sjkim    Info.Flags = 0;
136167802Sjkim    Info.Count = 0;
137167802Sjkim    Info.Level = 0;
138167802Sjkim    Info.WalkState = NULL;
139167802Sjkim    AcpiDmWalkParseTree (Origin, AcpiDmDumpDescending, NULL, &Info);
140167802Sjkim    AcpiOsPrintf ("*/\n\n");
141167802Sjkim}
142167802Sjkim
143167802Sjkim
144167802Sjkim/*******************************************************************************
145167802Sjkim *
146167802Sjkim * FUNCTION:    AcpiDmFindOrphanMethods
147167802Sjkim *
148198237Sjkim * PARAMETERS:  Origin              - Starting object
149167802Sjkim *
150167802Sjkim * RETURN:      None
151167802Sjkim *
152167802Sjkim * DESCRIPTION: Parse tree walk to find "orphaned" method invocations -- methods
153167802Sjkim *              that are not resolved in the namespace
154167802Sjkim *
155167802Sjkim ******************************************************************************/
156167802Sjkim
157167802Sjkimvoid
158167802SjkimAcpiDmFindOrphanMethods (
159167802Sjkim    ACPI_PARSE_OBJECT       *Origin)
160167802Sjkim{
161167802Sjkim    ACPI_OP_WALK_INFO       Info;
162167802Sjkim
163167802Sjkim
164167802Sjkim    if (!Origin)
165167802Sjkim    {
166167802Sjkim        return;
167167802Sjkim    }
168167802Sjkim
169167802Sjkim    Info.Flags = 0;
170167802Sjkim    Info.Level = 0;
171167802Sjkim    Info.WalkState = NULL;
172167802Sjkim    AcpiDmWalkParseTree (Origin, AcpiDmFindOrphanDescending, NULL, &Info);
173167802Sjkim}
174167802Sjkim
175167802Sjkim
176167802Sjkim/*******************************************************************************
177167802Sjkim *
178167802Sjkim * FUNCTION:    AcpiDmFinishNamespaceLoad
179167802Sjkim *
180167802Sjkim * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
181167802Sjkim *              NamespaceRoot       - Root of the internal namespace
182193529Sjkim *              OwnerId             - OwnerId of the table to be disassembled
183167802Sjkim *
184167802Sjkim * RETURN:      None
185167802Sjkim *
186167802Sjkim * DESCRIPTION: Load all namespace items that are created within control
187167802Sjkim *              methods. Used before namespace cross reference
188167802Sjkim *
189167802Sjkim ******************************************************************************/
190167802Sjkim
191167802Sjkimvoid
192167802SjkimAcpiDmFinishNamespaceLoad (
193167802Sjkim    ACPI_PARSE_OBJECT       *ParseTreeRoot,
194193529Sjkim    ACPI_NAMESPACE_NODE     *NamespaceRoot,
195193529Sjkim    ACPI_OWNER_ID           OwnerId)
196167802Sjkim{
197167802Sjkim    ACPI_STATUS             Status;
198167802Sjkim    ACPI_OP_WALK_INFO       Info;
199167802Sjkim    ACPI_WALK_STATE         *WalkState;
200167802Sjkim
201167802Sjkim
202167802Sjkim    if (!ParseTreeRoot)
203167802Sjkim    {
204167802Sjkim        return;
205167802Sjkim    }
206167802Sjkim
207167802Sjkim    /* Create and initialize a new walk state */
208167802Sjkim
209193529Sjkim    WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL);
210167802Sjkim    if (!WalkState)
211167802Sjkim    {
212167802Sjkim        return;
213167802Sjkim    }
214167802Sjkim
215167802Sjkim    Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState);
216167802Sjkim    if (ACPI_FAILURE (Status))
217167802Sjkim    {
218167802Sjkim        return;
219167802Sjkim    }
220167802Sjkim
221167802Sjkim    Info.Flags = 0;
222167802Sjkim    Info.Level = 0;
223167802Sjkim    Info.WalkState = WalkState;
224167802Sjkim    AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmLoadDescendingOp,
225167802Sjkim        AcpiDmCommonAscendingOp, &Info);
226167802Sjkim    ACPI_FREE (WalkState);
227167802Sjkim}
228167802Sjkim
229167802Sjkim
230167802Sjkim/*******************************************************************************
231167802Sjkim *
232167802Sjkim * FUNCTION:    AcpiDmCrossReferenceNamespace
233167802Sjkim *
234167802Sjkim * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
235167802Sjkim *              NamespaceRoot       - Root of the internal namespace
236193529Sjkim *              OwnerId             - OwnerId of the table to be disassembled
237167802Sjkim *
238167802Sjkim * RETURN:      None
239167802Sjkim *
240167802Sjkim * DESCRIPTION: Cross reference the namespace to create externals
241167802Sjkim *
242167802Sjkim ******************************************************************************/
243167802Sjkim
244167802Sjkimvoid
245167802SjkimAcpiDmCrossReferenceNamespace (
246167802Sjkim    ACPI_PARSE_OBJECT       *ParseTreeRoot,
247193529Sjkim    ACPI_NAMESPACE_NODE     *NamespaceRoot,
248193529Sjkim    ACPI_OWNER_ID           OwnerId)
249167802Sjkim{
250167802Sjkim    ACPI_STATUS             Status;
251167802Sjkim    ACPI_OP_WALK_INFO       Info;
252167802Sjkim    ACPI_WALK_STATE         *WalkState;
253167802Sjkim
254167802Sjkim
255167802Sjkim    if (!ParseTreeRoot)
256167802Sjkim    {
257167802Sjkim        return;
258167802Sjkim    }
259167802Sjkim
260167802Sjkim    /* Create and initialize a new walk state */
261167802Sjkim
262193529Sjkim    WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL);
263167802Sjkim    if (!WalkState)
264167802Sjkim    {
265167802Sjkim        return;
266167802Sjkim    }
267167802Sjkim
268167802Sjkim    Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState);
269167802Sjkim    if (ACPI_FAILURE (Status))
270167802Sjkim    {
271167802Sjkim        return;
272167802Sjkim    }
273167802Sjkim
274167802Sjkim    Info.Flags = 0;
275167802Sjkim    Info.Level = 0;
276167802Sjkim    Info.WalkState = WalkState;
277167802Sjkim    AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmXrefDescendingOp,
278167802Sjkim        AcpiDmCommonAscendingOp, &Info);
279167802Sjkim    ACPI_FREE (WalkState);
280167802Sjkim}
281167802Sjkim
282167802Sjkim
283167802Sjkim/*******************************************************************************
284167802Sjkim *
285167802Sjkim * FUNCTION:    AcpiDmConvertResourceIndexes
286167802Sjkim *
287167802Sjkim * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
288167802Sjkim *              NamespaceRoot       - Root of the internal namespace
289167802Sjkim *
290167802Sjkim * RETURN:      None
291167802Sjkim *
292167802Sjkim * DESCRIPTION: Convert fixed-offset references to resource descriptors to
293167802Sjkim *              symbolic references. Should only be called after namespace has
294167802Sjkim *              been cross referenced.
295167802Sjkim *
296167802Sjkim ******************************************************************************/
297167802Sjkim
298167802Sjkimvoid
299167802SjkimAcpiDmConvertResourceIndexes (
300167802Sjkim    ACPI_PARSE_OBJECT       *ParseTreeRoot,
301167802Sjkim    ACPI_NAMESPACE_NODE     *NamespaceRoot)
302167802Sjkim{
303167802Sjkim    ACPI_STATUS             Status;
304167802Sjkim    ACPI_OP_WALK_INFO       Info;
305167802Sjkim    ACPI_WALK_STATE         *WalkState;
306167802Sjkim
307167802Sjkim
308167802Sjkim    if (!ParseTreeRoot)
309167802Sjkim    {
310167802Sjkim        return;
311167802Sjkim    }
312167802Sjkim
313167802Sjkim    /* Create and initialize a new walk state */
314167802Sjkim
315167802Sjkim    WalkState = AcpiDsCreateWalkState (0, ParseTreeRoot, NULL, NULL);
316167802Sjkim    if (!WalkState)
317167802Sjkim    {
318167802Sjkim        return;
319167802Sjkim    }
320167802Sjkim
321167802Sjkim    Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState);
322167802Sjkim    if (ACPI_FAILURE (Status))
323167802Sjkim    {
324167802Sjkim        return;
325167802Sjkim    }
326167802Sjkim
327167802Sjkim    Info.Flags = 0;
328167802Sjkim    Info.Level = 0;
329167802Sjkim    Info.WalkState = WalkState;
330167802Sjkim    AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmResourceDescendingOp,
331167802Sjkim        AcpiDmCommonAscendingOp, &Info);
332167802Sjkim    ACPI_FREE (WalkState);
333167802Sjkim    return;
334167802Sjkim}
335167802Sjkim
336167802Sjkim
337167802Sjkim/*******************************************************************************
338167802Sjkim *
339167802Sjkim * FUNCTION:    AcpiDmDumpDescending
340167802Sjkim *
341167802Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
342167802Sjkim *
343167802Sjkim * RETURN:      Status
344167802Sjkim *
345167802Sjkim * DESCRIPTION: Format and print contents of one parse Op.
346167802Sjkim *
347167802Sjkim ******************************************************************************/
348167802Sjkim
349167802Sjkimstatic ACPI_STATUS
350167802SjkimAcpiDmDumpDescending (
351167802Sjkim    ACPI_PARSE_OBJECT       *Op,
352167802Sjkim    UINT32                  Level,
353167802Sjkim    void                    *Context)
354167802Sjkim{
355167802Sjkim    ACPI_OP_WALK_INFO       *Info = Context;
356167802Sjkim    char                    *Path;
357167802Sjkim
358167802Sjkim
359167802Sjkim    if (!Op)
360167802Sjkim    {
361167802Sjkim        return (AE_OK);
362167802Sjkim    }
363167802Sjkim
364167802Sjkim    /* Most of the information (count, level, name) here */
365167802Sjkim
366198237Sjkim    Info->Count++;
367167802Sjkim    AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level);
368167802Sjkim    AcpiDmIndent (Level);
369167802Sjkim    AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode));
370167802Sjkim
371167802Sjkim    /* Extra info is helpful */
372167802Sjkim
373167802Sjkim    switch (Op->Common.AmlOpcode)
374167802Sjkim    {
375167802Sjkim    case AML_BYTE_OP:
376167802Sjkim    case AML_WORD_OP:
377167802Sjkim    case AML_DWORD_OP:
378167802Sjkim        AcpiOsPrintf ("%X", (UINT32) Op->Common.Value.Integer);
379167802Sjkim        break;
380167802Sjkim
381228110Sjkim    case AML_QWORD_OP:
382228110Sjkim        AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
383228110Sjkim        break;
384228110Sjkim
385167802Sjkim    case AML_INT_NAMEPATH_OP:
386167802Sjkim        if (Op->Common.Value.String)
387167802Sjkim        {
388167802Sjkim            AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String,
389167802Sjkim                            NULL, &Path);
390167802Sjkim            AcpiOsPrintf ("%s %p", Path, Op->Common.Node);
391167802Sjkim            ACPI_FREE (Path);
392167802Sjkim        }
393167802Sjkim        else
394167802Sjkim        {
395167802Sjkim            AcpiOsPrintf ("[NULL]");
396167802Sjkim        }
397167802Sjkim        break;
398167802Sjkim
399167802Sjkim    case AML_NAME_OP:
400167802Sjkim    case AML_METHOD_OP:
401167802Sjkim    case AML_DEVICE_OP:
402167802Sjkim    case AML_INT_NAMEDFIELD_OP:
403198237Sjkim        AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name));
404167802Sjkim        break;
405193529Sjkim
406193529Sjkim    default:
407193529Sjkim        break;
408167802Sjkim    }
409167802Sjkim
410167802Sjkim    AcpiOsPrintf ("\n");
411167802Sjkim    return (AE_OK);
412167802Sjkim}
413167802Sjkim
414167802Sjkim
415167802Sjkim/*******************************************************************************
416167802Sjkim *
417167802Sjkim * FUNCTION:    AcpiDmFindOrphanDescending
418167802Sjkim *
419167802Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
420167802Sjkim *
421167802Sjkim * RETURN:      Status
422167802Sjkim *
423167802Sjkim * DESCRIPTION: Check namepath Ops for orphaned method invocations
424167802Sjkim *
425167802Sjkim * Note: Experimental.
426167802Sjkim *
427167802Sjkim ******************************************************************************/
428167802Sjkim
429167802Sjkimstatic ACPI_STATUS
430167802SjkimAcpiDmFindOrphanDescending (
431167802Sjkim    ACPI_PARSE_OBJECT       *Op,
432167802Sjkim    UINT32                  Level,
433167802Sjkim    void                    *Context)
434167802Sjkim{
435167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
436167802Sjkim    ACPI_PARSE_OBJECT       *ChildOp;
437167802Sjkim    ACPI_PARSE_OBJECT       *NextOp;
438167802Sjkim    ACPI_PARSE_OBJECT       *ParentOp;
439167802Sjkim    UINT32                  ArgCount;
440167802Sjkim
441167802Sjkim
442167802Sjkim    if (!Op)
443167802Sjkim    {
444167802Sjkim        return (AE_OK);
445167802Sjkim    }
446167802Sjkim
447167802Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
448167802Sjkim
449167802Sjkim    switch (Op->Common.AmlOpcode)
450167802Sjkim    {
451167802Sjkim#ifdef ACPI_UNDER_DEVELOPMENT
452167802Sjkim    case AML_ADD_OP:
453167802Sjkim        ChildOp = Op->Common.Value.Arg;
454167802Sjkim        if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
455167802Sjkim            !ChildOp->Common.Node)
456167802Sjkim        {
457167802Sjkim            AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String,
458167802Sjkim                            NULL, &Path);
459167802Sjkim            AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s  */\n", Op->Common.AmlOpName, Path);
460167802Sjkim            ACPI_FREE (Path);
461167802Sjkim
462167802Sjkim            NextOp = Op->Common.Next;
463167802Sjkim            if (!NextOp)
464167802Sjkim            {
465167802Sjkim                /* This NamePath has no args, assume it is an integer */
466167802Sjkim
467198237Sjkim                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
468167802Sjkim                return (AE_OK);
469167802Sjkim            }
470167802Sjkim
471167802Sjkim            ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
472209746Sjkim            AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n", ArgCount, AcpiDmCountChildren (Op));
473167802Sjkim
474167802Sjkim            if (ArgCount < 1)
475167802Sjkim            {
476167802Sjkim                /* One Arg means this is just a Store(Name,Target) */
477167802Sjkim
478198237Sjkim                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
479167802Sjkim                return (AE_OK);
480167802Sjkim            }
481167802Sjkim
482198237Sjkim            AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
483167802Sjkim        }
484167802Sjkim        break;
485167802Sjkim#endif
486167802Sjkim
487167802Sjkim    case AML_STORE_OP:
488167802Sjkim
489167802Sjkim        ChildOp = Op->Common.Value.Arg;
490167802Sjkim        if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
491167802Sjkim            !ChildOp->Common.Node)
492167802Sjkim        {
493167802Sjkim            NextOp = Op->Common.Next;
494167802Sjkim            if (!NextOp)
495167802Sjkim            {
496167802Sjkim                /* This NamePath has no args, assume it is an integer */
497167802Sjkim
498198237Sjkim                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
499167802Sjkim                return (AE_OK);
500167802Sjkim            }
501167802Sjkim
502167802Sjkim            ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
503167802Sjkim            if (ArgCount <= 1)
504167802Sjkim            {
505167802Sjkim                /* One Arg means this is just a Store(Name,Target) */
506167802Sjkim
507198237Sjkim                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
508167802Sjkim                return (AE_OK);
509167802Sjkim            }
510167802Sjkim
511198237Sjkim            AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
512167802Sjkim        }
513167802Sjkim        break;
514167802Sjkim
515167802Sjkim    case AML_INT_NAMEPATH_OP:
516167802Sjkim
517167802Sjkim        /* Must examine parent to see if this namepath is an argument */
518167802Sjkim
519167802Sjkim        ParentOp = Op->Common.Parent;
520167802Sjkim        OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
521167802Sjkim
522167802Sjkim        if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
523167802Sjkim            (OpInfo->Class != AML_CLASS_CREATE) &&
524167802Sjkim            (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
525167802Sjkim            !Op->Common.Node)
526167802Sjkim        {
527167802Sjkim            ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next);
528167802Sjkim
529167802Sjkim            /*
530167802Sjkim             * Check if namepath is a predicate for if/while or lone parameter to
531167802Sjkim             * a return.
532167802Sjkim             */
533167802Sjkim            if (ArgCount == 0)
534167802Sjkim            {
535167802Sjkim                if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
536167802Sjkim                     (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
537167802Sjkim                     (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
538167802Sjkim
539167802Sjkim                     /* And namepath is the first argument */
540167802Sjkim                     (ParentOp->Common.Value.Arg == Op))
541167802Sjkim                {
542198237Sjkim                    AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_INTEGER, 0);
543167802Sjkim                    break;
544167802Sjkim                }
545167802Sjkim            }
546167802Sjkim
547167802Sjkim            /*
548167802Sjkim             * This is a standalone namestring (not a parameter to another
549167802Sjkim             * operator) - it *must* be a method invocation, nothing else is
550167802Sjkim             * grammatically possible.
551167802Sjkim             */
552198237Sjkim            AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
553167802Sjkim
554167802Sjkim        }
555167802Sjkim        break;
556193529Sjkim
557193529Sjkim    default:
558193529Sjkim        break;
559167802Sjkim    }
560167802Sjkim
561167802Sjkim    return (AE_OK);
562167802Sjkim}
563167802Sjkim
564167802Sjkim
565167802Sjkim/*******************************************************************************
566167802Sjkim *
567167802Sjkim * FUNCTION:    AcpiDmLoadDescendingOp
568167802Sjkim *
569167802Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
570167802Sjkim *
571167802Sjkim * RETURN:      Status
572167802Sjkim *
573167802Sjkim * DESCRIPTION: Descending handler for namespace control method object load
574167802Sjkim *
575167802Sjkim ******************************************************************************/
576167802Sjkim
577167802Sjkimstatic ACPI_STATUS
578167802SjkimAcpiDmLoadDescendingOp (
579167802Sjkim    ACPI_PARSE_OBJECT       *Op,
580167802Sjkim    UINT32                  Level,
581167802Sjkim    void                    *Context)
582167802Sjkim{
583167802Sjkim    ACPI_OP_WALK_INFO       *Info = Context;
584167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
585167802Sjkim    ACPI_WALK_STATE         *WalkState;
586167802Sjkim    ACPI_OBJECT_TYPE        ObjectType;
587167802Sjkim    ACPI_STATUS             Status;
588167802Sjkim    char                    *Path = NULL;
589167802Sjkim    ACPI_PARSE_OBJECT       *NextOp;
590167802Sjkim    ACPI_NAMESPACE_NODE     *Node;
591193529Sjkim    char                    FieldPath[5];
592193529Sjkim    BOOLEAN                 PreDefined = FALSE;
593193529Sjkim    UINT8                   PreDefineIndex = 0;
594167802Sjkim
595167802Sjkim
596167802Sjkim    WalkState = Info->WalkState;
597167802Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
598167802Sjkim    ObjectType = OpInfo->ObjectType;
599167802Sjkim    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
600167802Sjkim
601167802Sjkim    /* Only interested in operators that create new names */
602167802Sjkim
603167802Sjkim    if (!(OpInfo->Flags & AML_NAMED) &&
604167802Sjkim        !(OpInfo->Flags & AML_CREATE))
605167802Sjkim    {
606167802Sjkim        goto Exit;
607167802Sjkim    }
608167802Sjkim
609167802Sjkim    /* Get the NamePath from the appropriate place */
610167802Sjkim
611167802Sjkim    if (OpInfo->Flags & AML_NAMED)
612167802Sjkim    {
613167802Sjkim        /* For all named operators, get the new name */
614167802Sjkim
615167802Sjkim        Path = (char *) Op->Named.Path;
616193529Sjkim
617193529Sjkim        if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
618193529Sjkim        {
619193529Sjkim            *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
620193529Sjkim            FieldPath[4] = 0;
621193529Sjkim            Path = FieldPath;
622193529Sjkim        }
623167802Sjkim    }
624167802Sjkim    else if (OpInfo->Flags & AML_CREATE)
625167802Sjkim    {
626167802Sjkim        /* New name is the last child */
627167802Sjkim
628167802Sjkim        NextOp = Op->Common.Value.Arg;
629167802Sjkim
630167802Sjkim        while (NextOp->Common.Next)
631167802Sjkim        {
632167802Sjkim            NextOp = NextOp->Common.Next;
633167802Sjkim        }
634167802Sjkim        Path = NextOp->Common.Value.String;
635167802Sjkim    }
636167802Sjkim
637167802Sjkim    if (!Path)
638167802Sjkim    {
639167802Sjkim        goto Exit;
640167802Sjkim    }
641167802Sjkim
642167802Sjkim    /* Insert the name into the namespace */
643167802Sjkim
644167802Sjkim    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
645167802Sjkim                ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
646167802Sjkim                WalkState, &Node);
647167802Sjkim
648167802Sjkim    Op->Common.Node = Node;
649167802Sjkim
650193529Sjkim    if (ACPI_SUCCESS (Status))
651193529Sjkim    {
652193529Sjkim        /* Check if it's a predefined node */
653167802Sjkim
654193529Sjkim        while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
655193529Sjkim        {
656193529Sjkim            if (!ACPI_STRNCMP (Node->Name.Ascii,
657193529Sjkim                AcpiGbl_PreDefinedNames[PreDefineIndex].Name, 4))
658193529Sjkim            {
659193529Sjkim                PreDefined = TRUE;
660193529Sjkim                break;
661193529Sjkim            }
662193529Sjkim
663193529Sjkim            PreDefineIndex++;
664193529Sjkim        }
665193529Sjkim
666193529Sjkim        /*
667193529Sjkim         * Set node owner id if it satisfies all the following conditions:
668193529Sjkim         * 1) Not a predefined node, _SB_ etc
669193529Sjkim         * 2) Not the root node
670193529Sjkim         * 3) Not a node created by Scope
671193529Sjkim         */
672193529Sjkim
673193529Sjkim        if (!PreDefined && Node != AcpiGbl_RootNode &&
674193529Sjkim            Op->Common.AmlOpcode != AML_SCOPE_OP)
675193529Sjkim        {
676193529Sjkim            Node->OwnerId = WalkState->OwnerId;
677193529Sjkim        }
678193529Sjkim    }
679193529Sjkim
680193529Sjkim
681167802SjkimExit:
682167802Sjkim
683167802Sjkim    if (AcpiNsOpensScope (ObjectType))
684167802Sjkim    {
685167802Sjkim        if (Op->Common.Node)
686167802Sjkim        {
687167802Sjkim            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
688167802Sjkim            if (ACPI_FAILURE (Status))
689167802Sjkim            {
690167802Sjkim                return (Status);
691167802Sjkim            }
692167802Sjkim        }
693167802Sjkim    }
694167802Sjkim
695167802Sjkim    return (AE_OK);
696167802Sjkim}
697167802Sjkim
698167802Sjkim
699167802Sjkim/*******************************************************************************
700167802Sjkim *
701167802Sjkim * FUNCTION:    AcpiDmXrefDescendingOp
702167802Sjkim *
703167802Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
704167802Sjkim *
705167802Sjkim * RETURN:      Status
706167802Sjkim *
707167802Sjkim * DESCRIPTION: Descending handler for namespace cross reference
708167802Sjkim *
709167802Sjkim ******************************************************************************/
710167802Sjkim
711167802Sjkimstatic ACPI_STATUS
712167802SjkimAcpiDmXrefDescendingOp (
713167802Sjkim    ACPI_PARSE_OBJECT       *Op,
714167802Sjkim    UINT32                  Level,
715167802Sjkim    void                    *Context)
716167802Sjkim{
717167802Sjkim    ACPI_OP_WALK_INFO       *Info = Context;
718167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
719167802Sjkim    ACPI_WALK_STATE         *WalkState;
720167802Sjkim    ACPI_OBJECT_TYPE        ObjectType;
721193529Sjkim    ACPI_OBJECT_TYPE        ObjectType2;
722167802Sjkim    ACPI_STATUS             Status;
723167802Sjkim    char                    *Path = NULL;
724167802Sjkim    ACPI_PARSE_OBJECT       *NextOp;
725167802Sjkim    ACPI_NAMESPACE_NODE     *Node;
726193529Sjkim    ACPI_OPERAND_OBJECT     *Object;
727212761Sjkim    UINT32                  ParamCount = 0;
728167802Sjkim
729167802Sjkim
730167802Sjkim    WalkState = Info->WalkState;
731167802Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
732167802Sjkim    ObjectType = OpInfo->ObjectType;
733167802Sjkim    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
734167802Sjkim
735167802Sjkim    if ((!(OpInfo->Flags & AML_NAMED)) &&
736167802Sjkim        (!(OpInfo->Flags & AML_CREATE)) &&
737167802Sjkim        (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
738167802Sjkim    {
739167802Sjkim        goto Exit;
740167802Sjkim    }
741167802Sjkim
742167802Sjkim    /* Get the NamePath from the appropriate place */
743167802Sjkim
744167802Sjkim    if (OpInfo->Flags & AML_NAMED)
745167802Sjkim    {
746167802Sjkim        if ((Op->Common.AmlOpcode == AML_ALIAS_OP) ||
747167802Sjkim            (Op->Common.AmlOpcode == AML_SCOPE_OP))
748167802Sjkim        {
749167802Sjkim            /*
750167802Sjkim             * Only these two operators refer to an existing name,
751167802Sjkim             * first argument
752167802Sjkim             */
753167802Sjkim            Path = (char *) Op->Named.Path;
754167802Sjkim        }
755167802Sjkim    }
756167802Sjkim    else if (OpInfo->Flags & AML_CREATE)
757167802Sjkim    {
758167802Sjkim        /* Referenced Buffer Name is the first child */
759167802Sjkim
760167802Sjkim        NextOp = Op->Common.Value.Arg;
761167802Sjkim        if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
762167802Sjkim        {
763167802Sjkim            Path = NextOp->Common.Value.String;
764167802Sjkim        }
765167802Sjkim    }
766167802Sjkim    else
767167802Sjkim    {
768167802Sjkim        Path = Op->Common.Value.String;
769167802Sjkim    }
770167802Sjkim
771167802Sjkim    if (!Path)
772167802Sjkim    {
773167802Sjkim        goto Exit;
774167802Sjkim    }
775167802Sjkim
776167802Sjkim    /*
777167802Sjkim     * Lookup the name in the namespace.  Name must exist at this point, or it
778167802Sjkim     * is an invalid reference.
779167802Sjkim     *
780167802Sjkim     * The namespace is also used as a lookup table for references to resource
781167802Sjkim     * descriptors and the fields within them.
782167802Sjkim     */
783167802Sjkim    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
784167802Sjkim                ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
785167802Sjkim                WalkState, &Node);
786167802Sjkim    if (ACPI_FAILURE (Status))
787167802Sjkim    {
788167802Sjkim        if (Status == AE_NOT_FOUND)
789167802Sjkim        {
790198237Sjkim            AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType, 0);
791167802Sjkim
792167802Sjkim            /*
793167802Sjkim             * We could install this into the namespace, but we catch duplicate
794167802Sjkim             * externals when they are added to the list.
795167802Sjkim             */
796167802Sjkim#if 0
797167802Sjkim            Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
798167802Sjkim                       ACPI_IMODE_LOAD_PASS1, ACPI_NS_DONT_OPEN_SCOPE,
799167802Sjkim                       WalkState, &Node);
800167802Sjkim#endif
801167802Sjkim        }
802167802Sjkim    }
803193529Sjkim
804193529Sjkim    /*
805193529Sjkim     * Found the node in external table, add it to external list
806193529Sjkim     * Node->OwnerId == 0 indicates built-in ACPI Names, _OS_ etc
807193529Sjkim     */
808193529Sjkim    else if (Node->OwnerId && WalkState->OwnerId != Node->OwnerId)
809193529Sjkim    {
810193529Sjkim        ObjectType2 = ObjectType;
811193529Sjkim
812193529Sjkim        Object = AcpiNsGetAttachedObject (Node);
813193529Sjkim        if (Object)
814193529Sjkim        {
815193529Sjkim            ObjectType2 = Object->Common.Type;
816212761Sjkim            if (ObjectType2 == ACPI_TYPE_METHOD)
817212761Sjkim            {
818212761Sjkim                ParamCount = Object->Method.ParamCount;
819212761Sjkim            }
820193529Sjkim        }
821193529Sjkim
822212761Sjkim        AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType2, ParamCount);
823193529Sjkim        Op->Common.Node = Node;
824193529Sjkim    }
825167802Sjkim    else
826167802Sjkim    {
827167802Sjkim        Op->Common.Node = Node;
828167802Sjkim    }
829167802Sjkim
830167802Sjkim
831167802SjkimExit:
832167802Sjkim    /* Open new scope if necessary */
833167802Sjkim
834167802Sjkim    if (AcpiNsOpensScope (ObjectType))
835167802Sjkim    {
836167802Sjkim        if (Op->Common.Node)
837167802Sjkim        {
838167802Sjkim            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
839167802Sjkim            if (ACPI_FAILURE (Status))
840167802Sjkim            {
841167802Sjkim                return (Status);
842167802Sjkim            }
843167802Sjkim        }
844167802Sjkim    }
845167802Sjkim
846167802Sjkim    return (AE_OK);
847167802Sjkim}
848167802Sjkim
849167802Sjkim
850167802Sjkim/*******************************************************************************
851167802Sjkim *
852167802Sjkim * FUNCTION:    AcpiDmResourceDescendingOp
853167802Sjkim *
854167802Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
855167802Sjkim *
856167802Sjkim * RETURN:      None
857167802Sjkim *
858167802Sjkim * DESCRIPTION: Process one parse op during symbolic resource index conversion.
859167802Sjkim *
860167802Sjkim ******************************************************************************/
861167802Sjkim
862167802Sjkimstatic ACPI_STATUS
863167802SjkimAcpiDmResourceDescendingOp (
864167802Sjkim    ACPI_PARSE_OBJECT       *Op,
865167802Sjkim    UINT32                  Level,
866167802Sjkim    void                    *Context)
867167802Sjkim{
868167802Sjkim    ACPI_OP_WALK_INFO       *Info = Context;
869167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
870167802Sjkim    ACPI_WALK_STATE         *WalkState;
871167802Sjkim    ACPI_OBJECT_TYPE        ObjectType;
872167802Sjkim    ACPI_STATUS             Status;
873167802Sjkim
874167802Sjkim
875167802Sjkim    WalkState = Info->WalkState;
876167802Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
877167802Sjkim
878167802Sjkim    /* Open new scope if necessary */
879167802Sjkim
880167802Sjkim    ObjectType = OpInfo->ObjectType;
881167802Sjkim    if (AcpiNsOpensScope (ObjectType))
882167802Sjkim    {
883167802Sjkim        if (Op->Common.Node)
884167802Sjkim        {
885167802Sjkim
886167802Sjkim            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
887167802Sjkim            if (ACPI_FAILURE (Status))
888167802Sjkim            {
889167802Sjkim                return (Status);
890167802Sjkim            }
891167802Sjkim        }
892167802Sjkim    }
893167802Sjkim
894167802Sjkim    /*
895167802Sjkim     * Check if this operator contains a reference to a resource descriptor.
896167802Sjkim     * If so, convert the reference into a symbolic reference.
897167802Sjkim     */
898167802Sjkim    AcpiDmCheckResourceReference (Op, WalkState);
899167802Sjkim    return (AE_OK);
900167802Sjkim}
901167802Sjkim
902167802Sjkim
903167802Sjkim/*******************************************************************************
904167802Sjkim *
905167802Sjkim * FUNCTION:    AcpiDmCommonAscendingOp
906167802Sjkim *
907167802Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
908167802Sjkim *
909167802Sjkim * RETURN:      None
910167802Sjkim *
911167802Sjkim * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
912167802Sjkim *              scope if necessary.
913167802Sjkim *
914167802Sjkim ******************************************************************************/
915167802Sjkim
916167802Sjkimstatic ACPI_STATUS
917167802SjkimAcpiDmCommonAscendingOp (
918167802Sjkim    ACPI_PARSE_OBJECT       *Op,
919167802Sjkim    UINT32                  Level,
920167802Sjkim    void                    *Context)
921167802Sjkim{
922167802Sjkim    ACPI_OP_WALK_INFO       *Info = Context;
923167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
924167802Sjkim    ACPI_OBJECT_TYPE        ObjectType;
925167802Sjkim
926167802Sjkim
927167802Sjkim    /* Close scope if necessary */
928167802Sjkim
929167802Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
930167802Sjkim    ObjectType = OpInfo->ObjectType;
931167802Sjkim    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
932167802Sjkim
933167802Sjkim    if (AcpiNsOpensScope (ObjectType))
934167802Sjkim    {
935167802Sjkim        (void) AcpiDsScopeStackPop (Info->WalkState);
936167802Sjkim    }
937167802Sjkim
938167802Sjkim    return (AE_OK);
939167802Sjkim}
940167802Sjkim
941167802Sjkim
942167802Sjkim/*******************************************************************************
943167802Sjkim *
944167802Sjkim * FUNCTION:    AcpiDmInspectPossibleArgs
945167802Sjkim *
946167802Sjkim * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
947167802Sjkim *                                    possible method invocation found
948167802Sjkim *              TargetCount         - Number of targets (0,1,2) for this op
949167802Sjkim *              Op                  - Parse op
950167802Sjkim *
951167802Sjkim * RETURN:      Status
952167802Sjkim *
953167802Sjkim * DESCRIPTION: Examine following args and next ops for possible arguments
954167802Sjkim *              for an unrecognized method invocation.
955167802Sjkim *
956167802Sjkim ******************************************************************************/
957167802Sjkim
958167802Sjkimstatic UINT32
959167802SjkimAcpiDmInspectPossibleArgs (
960167802Sjkim    UINT32                  CurrentOpArgCount,
961167802Sjkim    UINT32                  TargetCount,
962167802Sjkim    ACPI_PARSE_OBJECT       *Op)
963167802Sjkim{
964167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
965167802Sjkim    UINT32                  i;
966167802Sjkim    UINT32                  Last = 0;
967167802Sjkim    UINT32                  Lookahead;
968167802Sjkim
969167802Sjkim
970167802Sjkim    Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount;
971167802Sjkim
972167802Sjkim    /* Lookahead for the maximum number of possible arguments */
973167802Sjkim
974167802Sjkim    for (i = 0; i < Lookahead; i++)
975167802Sjkim    {
976167802Sjkim        if (!Op)
977167802Sjkim        {
978167802Sjkim            break;
979167802Sjkim        }
980167802Sjkim
981167802Sjkim        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
982167802Sjkim
983167802Sjkim        /*
984167802Sjkim         * Any one of these operators is "very probably" not a method arg
985167802Sjkim         */
986167802Sjkim        if ((Op->Common.AmlOpcode == AML_STORE_OP) ||
987167802Sjkim            (Op->Common.AmlOpcode == AML_NOTIFY_OP))
988167802Sjkim        {
989167802Sjkim            break;
990167802Sjkim        }
991167802Sjkim
992167802Sjkim        if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
993167802Sjkim            (OpInfo->Class != AML_CLASS_CONTROL))
994167802Sjkim        {
995167802Sjkim            Last = i+1;
996167802Sjkim        }
997167802Sjkim
998167802Sjkim        Op = Op->Common.Next;
999167802Sjkim    }
1000167802Sjkim
1001167802Sjkim    return (Last);
1002167802Sjkim}
1003167802Sjkim
1004167802Sjkim
1005