adwalk.c revision 217365
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
381167802Sjkim    case AML_INT_NAMEPATH_OP:
382167802Sjkim        if (Op->Common.Value.String)
383167802Sjkim        {
384167802Sjkim            AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String,
385167802Sjkim                            NULL, &Path);
386167802Sjkim            AcpiOsPrintf ("%s %p", Path, Op->Common.Node);
387167802Sjkim            ACPI_FREE (Path);
388167802Sjkim        }
389167802Sjkim        else
390167802Sjkim        {
391167802Sjkim            AcpiOsPrintf ("[NULL]");
392167802Sjkim        }
393167802Sjkim        break;
394167802Sjkim
395167802Sjkim    case AML_NAME_OP:
396167802Sjkim    case AML_METHOD_OP:
397167802Sjkim    case AML_DEVICE_OP:
398167802Sjkim    case AML_INT_NAMEDFIELD_OP:
399198237Sjkim        AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name));
400167802Sjkim        break;
401193529Sjkim
402193529Sjkim    default:
403193529Sjkim        break;
404167802Sjkim    }
405167802Sjkim
406167802Sjkim    AcpiOsPrintf ("\n");
407167802Sjkim    return (AE_OK);
408167802Sjkim}
409167802Sjkim
410167802Sjkim
411167802Sjkim/*******************************************************************************
412167802Sjkim *
413167802Sjkim * FUNCTION:    AcpiDmFindOrphanDescending
414167802Sjkim *
415167802Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
416167802Sjkim *
417167802Sjkim * RETURN:      Status
418167802Sjkim *
419167802Sjkim * DESCRIPTION: Check namepath Ops for orphaned method invocations
420167802Sjkim *
421167802Sjkim * Note: Experimental.
422167802Sjkim *
423167802Sjkim ******************************************************************************/
424167802Sjkim
425167802Sjkimstatic ACPI_STATUS
426167802SjkimAcpiDmFindOrphanDescending (
427167802Sjkim    ACPI_PARSE_OBJECT       *Op,
428167802Sjkim    UINT32                  Level,
429167802Sjkim    void                    *Context)
430167802Sjkim{
431167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
432167802Sjkim    ACPI_PARSE_OBJECT       *ChildOp;
433167802Sjkim    ACPI_PARSE_OBJECT       *NextOp;
434167802Sjkim    ACPI_PARSE_OBJECT       *ParentOp;
435167802Sjkim    UINT32                  ArgCount;
436167802Sjkim
437167802Sjkim
438167802Sjkim    if (!Op)
439167802Sjkim    {
440167802Sjkim        return (AE_OK);
441167802Sjkim    }
442167802Sjkim
443167802Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
444167802Sjkim
445167802Sjkim    switch (Op->Common.AmlOpcode)
446167802Sjkim    {
447167802Sjkim#ifdef ACPI_UNDER_DEVELOPMENT
448167802Sjkim    case AML_ADD_OP:
449167802Sjkim        ChildOp = Op->Common.Value.Arg;
450167802Sjkim        if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
451167802Sjkim            !ChildOp->Common.Node)
452167802Sjkim        {
453167802Sjkim            AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String,
454167802Sjkim                            NULL, &Path);
455167802Sjkim            AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s  */\n", Op->Common.AmlOpName, Path);
456167802Sjkim            ACPI_FREE (Path);
457167802Sjkim
458167802Sjkim            NextOp = Op->Common.Next;
459167802Sjkim            if (!NextOp)
460167802Sjkim            {
461167802Sjkim                /* This NamePath has no args, assume it is an integer */
462167802Sjkim
463198237Sjkim                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
464167802Sjkim                return (AE_OK);
465167802Sjkim            }
466167802Sjkim
467167802Sjkim            ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
468209746Sjkim            AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n", ArgCount, AcpiDmCountChildren (Op));
469167802Sjkim
470167802Sjkim            if (ArgCount < 1)
471167802Sjkim            {
472167802Sjkim                /* One Arg means this is just a Store(Name,Target) */
473167802Sjkim
474198237Sjkim                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
475167802Sjkim                return (AE_OK);
476167802Sjkim            }
477167802Sjkim
478198237Sjkim            AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
479167802Sjkim        }
480167802Sjkim        break;
481167802Sjkim#endif
482167802Sjkim
483167802Sjkim    case AML_STORE_OP:
484167802Sjkim
485167802Sjkim        ChildOp = Op->Common.Value.Arg;
486167802Sjkim        if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
487167802Sjkim            !ChildOp->Common.Node)
488167802Sjkim        {
489167802Sjkim            NextOp = Op->Common.Next;
490167802Sjkim            if (!NextOp)
491167802Sjkim            {
492167802Sjkim                /* This NamePath has no args, assume it is an integer */
493167802Sjkim
494198237Sjkim                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
495167802Sjkim                return (AE_OK);
496167802Sjkim            }
497167802Sjkim
498167802Sjkim            ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
499167802Sjkim            if (ArgCount <= 1)
500167802Sjkim            {
501167802Sjkim                /* One Arg means this is just a Store(Name,Target) */
502167802Sjkim
503198237Sjkim                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
504167802Sjkim                return (AE_OK);
505167802Sjkim            }
506167802Sjkim
507198237Sjkim            AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
508167802Sjkim        }
509167802Sjkim        break;
510167802Sjkim
511167802Sjkim    case AML_INT_NAMEPATH_OP:
512167802Sjkim
513167802Sjkim        /* Must examine parent to see if this namepath is an argument */
514167802Sjkim
515167802Sjkim        ParentOp = Op->Common.Parent;
516167802Sjkim        OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
517167802Sjkim
518167802Sjkim        if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
519167802Sjkim            (OpInfo->Class != AML_CLASS_CREATE) &&
520167802Sjkim            (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
521167802Sjkim            !Op->Common.Node)
522167802Sjkim        {
523167802Sjkim            ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next);
524167802Sjkim
525167802Sjkim            /*
526167802Sjkim             * Check if namepath is a predicate for if/while or lone parameter to
527167802Sjkim             * a return.
528167802Sjkim             */
529167802Sjkim            if (ArgCount == 0)
530167802Sjkim            {
531167802Sjkim                if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
532167802Sjkim                     (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
533167802Sjkim                     (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
534167802Sjkim
535167802Sjkim                     /* And namepath is the first argument */
536167802Sjkim                     (ParentOp->Common.Value.Arg == Op))
537167802Sjkim                {
538198237Sjkim                    AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_INTEGER, 0);
539167802Sjkim                    break;
540167802Sjkim                }
541167802Sjkim            }
542167802Sjkim
543167802Sjkim            /*
544167802Sjkim             * This is a standalone namestring (not a parameter to another
545167802Sjkim             * operator) - it *must* be a method invocation, nothing else is
546167802Sjkim             * grammatically possible.
547167802Sjkim             */
548198237Sjkim            AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
549167802Sjkim
550167802Sjkim        }
551167802Sjkim        break;
552193529Sjkim
553193529Sjkim    default:
554193529Sjkim        break;
555167802Sjkim    }
556167802Sjkim
557167802Sjkim    return (AE_OK);
558167802Sjkim}
559167802Sjkim
560167802Sjkim
561167802Sjkim/*******************************************************************************
562167802Sjkim *
563167802Sjkim * FUNCTION:    AcpiDmLoadDescendingOp
564167802Sjkim *
565167802Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
566167802Sjkim *
567167802Sjkim * RETURN:      Status
568167802Sjkim *
569167802Sjkim * DESCRIPTION: Descending handler for namespace control method object load
570167802Sjkim *
571167802Sjkim ******************************************************************************/
572167802Sjkim
573167802Sjkimstatic ACPI_STATUS
574167802SjkimAcpiDmLoadDescendingOp (
575167802Sjkim    ACPI_PARSE_OBJECT       *Op,
576167802Sjkim    UINT32                  Level,
577167802Sjkim    void                    *Context)
578167802Sjkim{
579167802Sjkim    ACPI_OP_WALK_INFO       *Info = Context;
580167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
581167802Sjkim    ACPI_WALK_STATE         *WalkState;
582167802Sjkim    ACPI_OBJECT_TYPE        ObjectType;
583167802Sjkim    ACPI_STATUS             Status;
584167802Sjkim    char                    *Path = NULL;
585167802Sjkim    ACPI_PARSE_OBJECT       *NextOp;
586167802Sjkim    ACPI_NAMESPACE_NODE     *Node;
587193529Sjkim    char                    FieldPath[5];
588193529Sjkim    BOOLEAN                 PreDefined = FALSE;
589193529Sjkim    UINT8                   PreDefineIndex = 0;
590167802Sjkim
591167802Sjkim
592167802Sjkim    WalkState = Info->WalkState;
593167802Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
594167802Sjkim    ObjectType = OpInfo->ObjectType;
595167802Sjkim    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
596167802Sjkim
597167802Sjkim    /* Only interested in operators that create new names */
598167802Sjkim
599167802Sjkim    if (!(OpInfo->Flags & AML_NAMED) &&
600167802Sjkim        !(OpInfo->Flags & AML_CREATE))
601167802Sjkim    {
602167802Sjkim        goto Exit;
603167802Sjkim    }
604167802Sjkim
605167802Sjkim    /* Get the NamePath from the appropriate place */
606167802Sjkim
607167802Sjkim    if (OpInfo->Flags & AML_NAMED)
608167802Sjkim    {
609167802Sjkim        /* For all named operators, get the new name */
610167802Sjkim
611167802Sjkim        Path = (char *) Op->Named.Path;
612193529Sjkim
613193529Sjkim        if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
614193529Sjkim        {
615193529Sjkim            *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
616193529Sjkim            FieldPath[4] = 0;
617193529Sjkim            Path = FieldPath;
618193529Sjkim        }
619167802Sjkim    }
620167802Sjkim    else if (OpInfo->Flags & AML_CREATE)
621167802Sjkim    {
622167802Sjkim        /* New name is the last child */
623167802Sjkim
624167802Sjkim        NextOp = Op->Common.Value.Arg;
625167802Sjkim
626167802Sjkim        while (NextOp->Common.Next)
627167802Sjkim        {
628167802Sjkim            NextOp = NextOp->Common.Next;
629167802Sjkim        }
630167802Sjkim        Path = NextOp->Common.Value.String;
631167802Sjkim    }
632167802Sjkim
633167802Sjkim    if (!Path)
634167802Sjkim    {
635167802Sjkim        goto Exit;
636167802Sjkim    }
637167802Sjkim
638167802Sjkim    /* Insert the name into the namespace */
639167802Sjkim
640167802Sjkim    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
641167802Sjkim                ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
642167802Sjkim                WalkState, &Node);
643167802Sjkim
644167802Sjkim    Op->Common.Node = Node;
645167802Sjkim
646193529Sjkim    if (ACPI_SUCCESS (Status))
647193529Sjkim    {
648193529Sjkim        /* Check if it's a predefined node */
649167802Sjkim
650193529Sjkim        while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
651193529Sjkim        {
652193529Sjkim            if (!ACPI_STRNCMP (Node->Name.Ascii,
653193529Sjkim                AcpiGbl_PreDefinedNames[PreDefineIndex].Name, 4))
654193529Sjkim            {
655193529Sjkim                PreDefined = TRUE;
656193529Sjkim                break;
657193529Sjkim            }
658193529Sjkim
659193529Sjkim            PreDefineIndex++;
660193529Sjkim        }
661193529Sjkim
662193529Sjkim        /*
663193529Sjkim         * Set node owner id if it satisfies all the following conditions:
664193529Sjkim         * 1) Not a predefined node, _SB_ etc
665193529Sjkim         * 2) Not the root node
666193529Sjkim         * 3) Not a node created by Scope
667193529Sjkim         */
668193529Sjkim
669193529Sjkim        if (!PreDefined && Node != AcpiGbl_RootNode &&
670193529Sjkim            Op->Common.AmlOpcode != AML_SCOPE_OP)
671193529Sjkim        {
672193529Sjkim            Node->OwnerId = WalkState->OwnerId;
673193529Sjkim        }
674193529Sjkim    }
675193529Sjkim
676193529Sjkim
677167802SjkimExit:
678167802Sjkim
679167802Sjkim    if (AcpiNsOpensScope (ObjectType))
680167802Sjkim    {
681167802Sjkim        if (Op->Common.Node)
682167802Sjkim        {
683167802Sjkim            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
684167802Sjkim            if (ACPI_FAILURE (Status))
685167802Sjkim            {
686167802Sjkim                return (Status);
687167802Sjkim            }
688167802Sjkim        }
689167802Sjkim    }
690167802Sjkim
691167802Sjkim    return (AE_OK);
692167802Sjkim}
693167802Sjkim
694167802Sjkim
695167802Sjkim/*******************************************************************************
696167802Sjkim *
697167802Sjkim * FUNCTION:    AcpiDmXrefDescendingOp
698167802Sjkim *
699167802Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
700167802Sjkim *
701167802Sjkim * RETURN:      Status
702167802Sjkim *
703167802Sjkim * DESCRIPTION: Descending handler for namespace cross reference
704167802Sjkim *
705167802Sjkim ******************************************************************************/
706167802Sjkim
707167802Sjkimstatic ACPI_STATUS
708167802SjkimAcpiDmXrefDescendingOp (
709167802Sjkim    ACPI_PARSE_OBJECT       *Op,
710167802Sjkim    UINT32                  Level,
711167802Sjkim    void                    *Context)
712167802Sjkim{
713167802Sjkim    ACPI_OP_WALK_INFO       *Info = Context;
714167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
715167802Sjkim    ACPI_WALK_STATE         *WalkState;
716167802Sjkim    ACPI_OBJECT_TYPE        ObjectType;
717193529Sjkim    ACPI_OBJECT_TYPE        ObjectType2;
718167802Sjkim    ACPI_STATUS             Status;
719167802Sjkim    char                    *Path = NULL;
720167802Sjkim    ACPI_PARSE_OBJECT       *NextOp;
721167802Sjkim    ACPI_NAMESPACE_NODE     *Node;
722193529Sjkim    ACPI_OPERAND_OBJECT     *Object;
723212761Sjkim    UINT32                  ParamCount = 0;
724167802Sjkim
725167802Sjkim
726167802Sjkim    WalkState = Info->WalkState;
727167802Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
728167802Sjkim    ObjectType = OpInfo->ObjectType;
729167802Sjkim    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
730167802Sjkim
731167802Sjkim    if ((!(OpInfo->Flags & AML_NAMED)) &&
732167802Sjkim        (!(OpInfo->Flags & AML_CREATE)) &&
733167802Sjkim        (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
734167802Sjkim    {
735167802Sjkim        goto Exit;
736167802Sjkim    }
737167802Sjkim
738167802Sjkim    /* Get the NamePath from the appropriate place */
739167802Sjkim
740167802Sjkim    if (OpInfo->Flags & AML_NAMED)
741167802Sjkim    {
742167802Sjkim        if ((Op->Common.AmlOpcode == AML_ALIAS_OP) ||
743167802Sjkim            (Op->Common.AmlOpcode == AML_SCOPE_OP))
744167802Sjkim        {
745167802Sjkim            /*
746167802Sjkim             * Only these two operators refer to an existing name,
747167802Sjkim             * first argument
748167802Sjkim             */
749167802Sjkim            Path = (char *) Op->Named.Path;
750167802Sjkim        }
751167802Sjkim    }
752167802Sjkim    else if (OpInfo->Flags & AML_CREATE)
753167802Sjkim    {
754167802Sjkim        /* Referenced Buffer Name is the first child */
755167802Sjkim
756167802Sjkim        NextOp = Op->Common.Value.Arg;
757167802Sjkim        if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
758167802Sjkim        {
759167802Sjkim            Path = NextOp->Common.Value.String;
760167802Sjkim        }
761167802Sjkim    }
762167802Sjkim    else
763167802Sjkim    {
764167802Sjkim        Path = Op->Common.Value.String;
765167802Sjkim    }
766167802Sjkim
767167802Sjkim    if (!Path)
768167802Sjkim    {
769167802Sjkim        goto Exit;
770167802Sjkim    }
771167802Sjkim
772167802Sjkim    /*
773167802Sjkim     * Lookup the name in the namespace.  Name must exist at this point, or it
774167802Sjkim     * is an invalid reference.
775167802Sjkim     *
776167802Sjkim     * The namespace is also used as a lookup table for references to resource
777167802Sjkim     * descriptors and the fields within them.
778167802Sjkim     */
779167802Sjkim    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
780167802Sjkim                ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
781167802Sjkim                WalkState, &Node);
782167802Sjkim    if (ACPI_FAILURE (Status))
783167802Sjkim    {
784167802Sjkim        if (Status == AE_NOT_FOUND)
785167802Sjkim        {
786198237Sjkim            AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType, 0);
787167802Sjkim
788167802Sjkim            /*
789167802Sjkim             * We could install this into the namespace, but we catch duplicate
790167802Sjkim             * externals when they are added to the list.
791167802Sjkim             */
792167802Sjkim#if 0
793167802Sjkim            Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
794167802Sjkim                       ACPI_IMODE_LOAD_PASS1, ACPI_NS_DONT_OPEN_SCOPE,
795167802Sjkim                       WalkState, &Node);
796167802Sjkim#endif
797167802Sjkim        }
798167802Sjkim    }
799193529Sjkim
800193529Sjkim    /*
801193529Sjkim     * Found the node in external table, add it to external list
802193529Sjkim     * Node->OwnerId == 0 indicates built-in ACPI Names, _OS_ etc
803193529Sjkim     */
804193529Sjkim    else if (Node->OwnerId && WalkState->OwnerId != Node->OwnerId)
805193529Sjkim    {
806193529Sjkim        ObjectType2 = ObjectType;
807193529Sjkim
808193529Sjkim        Object = AcpiNsGetAttachedObject (Node);
809193529Sjkim        if (Object)
810193529Sjkim        {
811193529Sjkim            ObjectType2 = Object->Common.Type;
812212761Sjkim            if (ObjectType2 == ACPI_TYPE_METHOD)
813212761Sjkim            {
814212761Sjkim                ParamCount = Object->Method.ParamCount;
815212761Sjkim            }
816193529Sjkim        }
817193529Sjkim
818212761Sjkim        AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType2, ParamCount);
819193529Sjkim        Op->Common.Node = Node;
820193529Sjkim    }
821167802Sjkim    else
822167802Sjkim    {
823167802Sjkim        Op->Common.Node = Node;
824167802Sjkim    }
825167802Sjkim
826167802Sjkim
827167802SjkimExit:
828167802Sjkim    /* Open new scope if necessary */
829167802Sjkim
830167802Sjkim    if (AcpiNsOpensScope (ObjectType))
831167802Sjkim    {
832167802Sjkim        if (Op->Common.Node)
833167802Sjkim        {
834167802Sjkim            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
835167802Sjkim            if (ACPI_FAILURE (Status))
836167802Sjkim            {
837167802Sjkim                return (Status);
838167802Sjkim            }
839167802Sjkim        }
840167802Sjkim    }
841167802Sjkim
842167802Sjkim    return (AE_OK);
843167802Sjkim}
844167802Sjkim
845167802Sjkim
846167802Sjkim/*******************************************************************************
847167802Sjkim *
848167802Sjkim * FUNCTION:    AcpiDmResourceDescendingOp
849167802Sjkim *
850167802Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
851167802Sjkim *
852167802Sjkim * RETURN:      None
853167802Sjkim *
854167802Sjkim * DESCRIPTION: Process one parse op during symbolic resource index conversion.
855167802Sjkim *
856167802Sjkim ******************************************************************************/
857167802Sjkim
858167802Sjkimstatic ACPI_STATUS
859167802SjkimAcpiDmResourceDescendingOp (
860167802Sjkim    ACPI_PARSE_OBJECT       *Op,
861167802Sjkim    UINT32                  Level,
862167802Sjkim    void                    *Context)
863167802Sjkim{
864167802Sjkim    ACPI_OP_WALK_INFO       *Info = Context;
865167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
866167802Sjkim    ACPI_WALK_STATE         *WalkState;
867167802Sjkim    ACPI_OBJECT_TYPE        ObjectType;
868167802Sjkim    ACPI_STATUS             Status;
869167802Sjkim
870167802Sjkim
871167802Sjkim    WalkState = Info->WalkState;
872167802Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
873167802Sjkim
874167802Sjkim    /* Open new scope if necessary */
875167802Sjkim
876167802Sjkim    ObjectType = OpInfo->ObjectType;
877167802Sjkim    if (AcpiNsOpensScope (ObjectType))
878167802Sjkim    {
879167802Sjkim        if (Op->Common.Node)
880167802Sjkim        {
881167802Sjkim
882167802Sjkim            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
883167802Sjkim            if (ACPI_FAILURE (Status))
884167802Sjkim            {
885167802Sjkim                return (Status);
886167802Sjkim            }
887167802Sjkim        }
888167802Sjkim    }
889167802Sjkim
890167802Sjkim    /*
891167802Sjkim     * Check if this operator contains a reference to a resource descriptor.
892167802Sjkim     * If so, convert the reference into a symbolic reference.
893167802Sjkim     */
894167802Sjkim    AcpiDmCheckResourceReference (Op, WalkState);
895167802Sjkim    return (AE_OK);
896167802Sjkim}
897167802Sjkim
898167802Sjkim
899167802Sjkim/*******************************************************************************
900167802Sjkim *
901167802Sjkim * FUNCTION:    AcpiDmCommonAscendingOp
902167802Sjkim *
903167802Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
904167802Sjkim *
905167802Sjkim * RETURN:      None
906167802Sjkim *
907167802Sjkim * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
908167802Sjkim *              scope if necessary.
909167802Sjkim *
910167802Sjkim ******************************************************************************/
911167802Sjkim
912167802Sjkimstatic ACPI_STATUS
913167802SjkimAcpiDmCommonAscendingOp (
914167802Sjkim    ACPI_PARSE_OBJECT       *Op,
915167802Sjkim    UINT32                  Level,
916167802Sjkim    void                    *Context)
917167802Sjkim{
918167802Sjkim    ACPI_OP_WALK_INFO       *Info = Context;
919167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
920167802Sjkim    ACPI_OBJECT_TYPE        ObjectType;
921167802Sjkim
922167802Sjkim
923167802Sjkim    /* Close scope if necessary */
924167802Sjkim
925167802Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
926167802Sjkim    ObjectType = OpInfo->ObjectType;
927167802Sjkim    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
928167802Sjkim
929167802Sjkim    if (AcpiNsOpensScope (ObjectType))
930167802Sjkim    {
931167802Sjkim        (void) AcpiDsScopeStackPop (Info->WalkState);
932167802Sjkim    }
933167802Sjkim
934167802Sjkim    return (AE_OK);
935167802Sjkim}
936167802Sjkim
937167802Sjkim
938167802Sjkim/*******************************************************************************
939167802Sjkim *
940167802Sjkim * FUNCTION:    AcpiDmInspectPossibleArgs
941167802Sjkim *
942167802Sjkim * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
943167802Sjkim *                                    possible method invocation found
944167802Sjkim *              TargetCount         - Number of targets (0,1,2) for this op
945167802Sjkim *              Op                  - Parse op
946167802Sjkim *
947167802Sjkim * RETURN:      Status
948167802Sjkim *
949167802Sjkim * DESCRIPTION: Examine following args and next ops for possible arguments
950167802Sjkim *              for an unrecognized method invocation.
951167802Sjkim *
952167802Sjkim ******************************************************************************/
953167802Sjkim
954167802Sjkimstatic UINT32
955167802SjkimAcpiDmInspectPossibleArgs (
956167802Sjkim    UINT32                  CurrentOpArgCount,
957167802Sjkim    UINT32                  TargetCount,
958167802Sjkim    ACPI_PARSE_OBJECT       *Op)
959167802Sjkim{
960167802Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
961167802Sjkim    UINT32                  i;
962167802Sjkim    UINT32                  Last = 0;
963167802Sjkim    UINT32                  Lookahead;
964167802Sjkim
965167802Sjkim
966167802Sjkim    Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount;
967167802Sjkim
968167802Sjkim    /* Lookahead for the maximum number of possible arguments */
969167802Sjkim
970167802Sjkim    for (i = 0; i < Lookahead; i++)
971167802Sjkim    {
972167802Sjkim        if (!Op)
973167802Sjkim        {
974167802Sjkim            break;
975167802Sjkim        }
976167802Sjkim
977167802Sjkim        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
978167802Sjkim
979167802Sjkim        /*
980167802Sjkim         * Any one of these operators is "very probably" not a method arg
981167802Sjkim         */
982167802Sjkim        if ((Op->Common.AmlOpcode == AML_STORE_OP) ||
983167802Sjkim            (Op->Common.AmlOpcode == AML_NOTIFY_OP))
984167802Sjkim        {
985167802Sjkim            break;
986167802Sjkim        }
987167802Sjkim
988167802Sjkim        if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
989167802Sjkim            (OpInfo->Class != AML_CLASS_CONTROL))
990167802Sjkim        {
991167802Sjkim            Last = i+1;
992167802Sjkim        }
993167802Sjkim
994167802Sjkim        Op = Op->Common.Next;
995167802Sjkim    }
996167802Sjkim
997167802Sjkim    return (Last);
998167802Sjkim}
999167802Sjkim
1000167802Sjkim
1001