adwalk.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: adwalk - Application-level disassembler parse tree walk routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, 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#include <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/include/accommon.h>
46#include <contrib/dev/acpica/include/acparser.h>
47#include <contrib/dev/acpica/include/amlcode.h>
48#include <contrib/dev/acpica/include/acdisasm.h>
49#include <contrib/dev/acpica/include/acdispat.h>
50#include <contrib/dev/acpica/include/acnamesp.h>
51#include <contrib/dev/acpica/include/acapps.h>
52
53
54#define _COMPONENT          ACPI_TOOLS
55        ACPI_MODULE_NAME    ("adwalk")
56
57/*
58 * aslmap - opcode mappings and reserved method names
59 */
60ACPI_OBJECT_TYPE
61AslMapNamedOpcodeToDataType (
62    UINT16                  Opcode);
63
64/* Local prototypes */
65
66static ACPI_STATUS
67AcpiDmFindOrphanDescending (
68    ACPI_PARSE_OBJECT       *Op,
69    UINT32                  Level,
70    void                    *Context);
71
72static ACPI_STATUS
73AcpiDmDumpDescending (
74    ACPI_PARSE_OBJECT       *Op,
75    UINT32                  Level,
76    void                    *Context);
77
78static ACPI_STATUS
79AcpiDmXrefDescendingOp (
80    ACPI_PARSE_OBJECT       *Op,
81    UINT32                  Level,
82    void                    *Context);
83
84static ACPI_STATUS
85AcpiDmCommonAscendingOp (
86    ACPI_PARSE_OBJECT       *Op,
87    UINT32                  Level,
88    void                    *Context);
89
90static ACPI_STATUS
91AcpiDmLoadDescendingOp (
92    ACPI_PARSE_OBJECT       *Op,
93    UINT32                  Level,
94    void                    *Context);
95
96static UINT32
97AcpiDmInspectPossibleArgs (
98    UINT32                  CurrentOpArgCount,
99    UINT32                  TargetCount,
100    ACPI_PARSE_OBJECT       *Op);
101
102static ACPI_STATUS
103AcpiDmResourceDescendingOp (
104    ACPI_PARSE_OBJECT       *Op,
105    UINT32                  Level,
106    void                    *Context);
107
108
109/*******************************************************************************
110 *
111 * FUNCTION:    AcpiDmDumpTree
112 *
113 * PARAMETERS:  Origin              - Starting object
114 *
115 * RETURN:      None
116 *
117 * DESCRIPTION: Parse tree walk to format and output the nodes
118 *
119 ******************************************************************************/
120
121void
122AcpiDmDumpTree (
123    ACPI_PARSE_OBJECT       *Origin)
124{
125    ACPI_OP_WALK_INFO       Info;
126
127
128    if (!Origin)
129    {
130        return;
131    }
132
133    AcpiOsPrintf ("/*\nAML Parse Tree\n\n");
134    Info.Flags = 0;
135    Info.Count = 0;
136    Info.Level = 0;
137    Info.WalkState = NULL;
138    AcpiDmWalkParseTree (Origin, AcpiDmDumpDescending, NULL, &Info);
139    AcpiOsPrintf ("*/\n\n");
140}
141
142
143/*******************************************************************************
144 *
145 * FUNCTION:    AcpiDmFindOrphanMethods
146 *
147 * PARAMETERS:  Origin              - Starting object
148 *
149 * RETURN:      None
150 *
151 * DESCRIPTION: Parse tree walk to find "orphaned" method invocations -- methods
152 *              that are not resolved in the namespace
153 *
154 ******************************************************************************/
155
156void
157AcpiDmFindOrphanMethods (
158    ACPI_PARSE_OBJECT       *Origin)
159{
160    ACPI_OP_WALK_INFO       Info;
161
162
163    if (!Origin)
164    {
165        return;
166    }
167
168    Info.Flags = 0;
169    Info.Level = 0;
170    Info.WalkState = NULL;
171    AcpiDmWalkParseTree (Origin, AcpiDmFindOrphanDescending, NULL, &Info);
172}
173
174
175/*******************************************************************************
176 *
177 * FUNCTION:    AcpiDmFinishNamespaceLoad
178 *
179 * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
180 *              NamespaceRoot       - Root of the internal namespace
181 *              OwnerId             - OwnerId of the table to be disassembled
182 *
183 * RETURN:      None
184 *
185 * DESCRIPTION: Load all namespace items that are created within control
186 *              methods. Used before namespace cross reference
187 *
188 ******************************************************************************/
189
190void
191AcpiDmFinishNamespaceLoad (
192    ACPI_PARSE_OBJECT       *ParseTreeRoot,
193    ACPI_NAMESPACE_NODE     *NamespaceRoot,
194    ACPI_OWNER_ID           OwnerId)
195{
196    ACPI_STATUS             Status;
197    ACPI_OP_WALK_INFO       Info;
198    ACPI_WALK_STATE         *WalkState;
199
200
201    if (!ParseTreeRoot)
202    {
203        return;
204    }
205
206    /* Create and initialize a new walk state */
207
208    WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL);
209    if (!WalkState)
210    {
211        return;
212    }
213
214    Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState);
215    if (ACPI_FAILURE (Status))
216    {
217        return;
218    }
219
220    Info.Flags = 0;
221    Info.Level = 0;
222    Info.WalkState = WalkState;
223    AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmLoadDescendingOp,
224        AcpiDmCommonAscendingOp, &Info);
225    ACPI_FREE (WalkState);
226}
227
228
229/*******************************************************************************
230 *
231 * FUNCTION:    AcpiDmCrossReferenceNamespace
232 *
233 * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
234 *              NamespaceRoot       - Root of the internal namespace
235 *              OwnerId             - OwnerId of the table to be disassembled
236 *
237 * RETURN:      None
238 *
239 * DESCRIPTION: Cross reference the namespace to create externals
240 *
241 ******************************************************************************/
242
243void
244AcpiDmCrossReferenceNamespace (
245    ACPI_PARSE_OBJECT       *ParseTreeRoot,
246    ACPI_NAMESPACE_NODE     *NamespaceRoot,
247    ACPI_OWNER_ID           OwnerId)
248{
249    ACPI_STATUS             Status;
250    ACPI_OP_WALK_INFO       Info;
251    ACPI_WALK_STATE         *WalkState;
252
253
254    if (!ParseTreeRoot)
255    {
256        return;
257    }
258
259    /* Create and initialize a new walk state */
260
261    WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL);
262    if (!WalkState)
263    {
264        return;
265    }
266
267    Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState);
268    if (ACPI_FAILURE (Status))
269    {
270        return;
271    }
272
273    Info.Flags = 0;
274    Info.Level = 0;
275    Info.WalkState = WalkState;
276    AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmXrefDescendingOp,
277        AcpiDmCommonAscendingOp, &Info);
278    ACPI_FREE (WalkState);
279}
280
281
282/*******************************************************************************
283 *
284 * FUNCTION:    AcpiDmConvertResourceIndexes
285 *
286 * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
287 *              NamespaceRoot       - Root of the internal namespace
288 *
289 * RETURN:      None
290 *
291 * DESCRIPTION: Convert fixed-offset references to resource descriptors to
292 *              symbolic references. Should only be called after namespace has
293 *              been cross referenced.
294 *
295 ******************************************************************************/
296
297void
298AcpiDmConvertResourceIndexes (
299    ACPI_PARSE_OBJECT       *ParseTreeRoot,
300    ACPI_NAMESPACE_NODE     *NamespaceRoot)
301{
302    ACPI_STATUS             Status;
303    ACPI_OP_WALK_INFO       Info;
304    ACPI_WALK_STATE         *WalkState;
305
306
307    if (!ParseTreeRoot)
308    {
309        return;
310    }
311
312    /* Create and initialize a new walk state */
313
314    WalkState = AcpiDsCreateWalkState (0, ParseTreeRoot, NULL, NULL);
315    if (!WalkState)
316    {
317        return;
318    }
319
320    Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState);
321    if (ACPI_FAILURE (Status))
322    {
323        return;
324    }
325
326    Info.Flags = 0;
327    Info.Level = 0;
328    Info.WalkState = WalkState;
329    AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmResourceDescendingOp,
330        AcpiDmCommonAscendingOp, &Info);
331    ACPI_FREE (WalkState);
332    return;
333}
334
335
336/*******************************************************************************
337 *
338 * FUNCTION:    AcpiDmDumpDescending
339 *
340 * PARAMETERS:  ASL_WALK_CALLBACK
341 *
342 * RETURN:      Status
343 *
344 * DESCRIPTION: Format and print contents of one parse Op.
345 *
346 ******************************************************************************/
347
348static ACPI_STATUS
349AcpiDmDumpDescending (
350    ACPI_PARSE_OBJECT       *Op,
351    UINT32                  Level,
352    void                    *Context)
353{
354    ACPI_OP_WALK_INFO       *Info = Context;
355    char                    *Path;
356
357
358    if (!Op)
359    {
360        return (AE_OK);
361    }
362
363    /* Most of the information (count, level, name) here */
364
365    Info->Count++;
366    AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level);
367    AcpiDmIndent (Level);
368    AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode));
369
370    /* Extra info is helpful */
371
372    switch (Op->Common.AmlOpcode)
373    {
374    case AML_BYTE_OP:
375
376        AcpiOsPrintf ("%2.2X", (UINT32) Op->Common.Value.Integer);
377        break;
378
379    case AML_WORD_OP:
380
381        AcpiOsPrintf ("%4.4X", (UINT32) Op->Common.Value.Integer);
382        break;
383
384    case AML_DWORD_OP:
385
386        AcpiOsPrintf ("%8.8X", (UINT32) Op->Common.Value.Integer);
387        break;
388
389    case AML_QWORD_OP:
390
391        AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
392        break;
393
394    case AML_INT_NAMEPATH_OP:
395
396        if (Op->Common.Value.String)
397        {
398            AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String,
399                            NULL, &Path);
400            AcpiOsPrintf ("%s %p", Path, Op->Common.Node);
401            ACPI_FREE (Path);
402        }
403        else
404        {
405            AcpiOsPrintf ("[NULL]");
406        }
407        break;
408
409    case AML_NAME_OP:
410    case AML_METHOD_OP:
411    case AML_DEVICE_OP:
412    case AML_INT_NAMEDFIELD_OP:
413
414        AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name));
415        break;
416
417    default:
418
419        break;
420    }
421
422    AcpiOsPrintf ("\n");
423    return (AE_OK);
424}
425
426
427/*******************************************************************************
428 *
429 * FUNCTION:    AcpiDmFindOrphanDescending
430 *
431 * PARAMETERS:  ASL_WALK_CALLBACK
432 *
433 * RETURN:      Status
434 *
435 * DESCRIPTION: Check namepath Ops for orphaned method invocations
436 *
437 * Note: Experimental.
438 *
439 ******************************************************************************/
440
441static ACPI_STATUS
442AcpiDmFindOrphanDescending (
443    ACPI_PARSE_OBJECT       *Op,
444    UINT32                  Level,
445    void                    *Context)
446{
447    const ACPI_OPCODE_INFO  *OpInfo;
448    ACPI_PARSE_OBJECT       *ChildOp;
449    ACPI_PARSE_OBJECT       *NextOp;
450    ACPI_PARSE_OBJECT       *ParentOp;
451    UINT32                  ArgCount;
452
453
454    if (!Op)
455    {
456        return (AE_OK);
457    }
458
459    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
460
461    switch (Op->Common.AmlOpcode)
462    {
463#ifdef ACPI_UNDER_DEVELOPMENT
464    case AML_ADD_OP:
465
466        ChildOp = Op->Common.Value.Arg;
467        if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
468            !ChildOp->Common.Node)
469        {
470            AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String,
471                NULL, &Path);
472            AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s  */\n",
473                Op->Common.AmlOpName, Path);
474            ACPI_FREE (Path);
475
476            NextOp = Op->Common.Next;
477            if (!NextOp)
478            {
479                /* This NamePath has no args, assume it is an integer */
480
481                AcpiDmAddOpToExternalList (ChildOp,
482                    ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
483                return (AE_OK);
484            }
485
486            ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
487            AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n",
488                ArgCount, AcpiDmCountChildren (Op));
489
490            if (ArgCount < 1)
491            {
492                /* One Arg means this is just a Store(Name,Target) */
493
494                AcpiDmAddOpToExternalList (ChildOp,
495                    ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
496                return (AE_OK);
497            }
498
499            AcpiDmAddOpToExternalList (ChildOp,
500                ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
501        }
502        break;
503#endif
504
505    case AML_STORE_OP:
506
507        ChildOp = Op->Common.Value.Arg;
508        if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
509            !ChildOp->Common.Node)
510        {
511            NextOp = Op->Common.Next;
512            if (!NextOp)
513            {
514                /* This NamePath has no args, assume it is an integer */
515
516                AcpiDmAddOpToExternalList (ChildOp,
517                    ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
518                return (AE_OK);
519            }
520
521            ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
522            if (ArgCount <= 1)
523            {
524                /* One Arg means this is just a Store(Name,Target) */
525
526                AcpiDmAddOpToExternalList (ChildOp,
527                    ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
528                return (AE_OK);
529            }
530
531            AcpiDmAddOpToExternalList (ChildOp,
532                ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
533        }
534        break;
535
536    case AML_INT_NAMEPATH_OP:
537
538        /* Must examine parent to see if this namepath is an argument */
539
540        ParentOp = Op->Common.Parent;
541        OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
542
543        if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
544            (OpInfo->Class != AML_CLASS_CREATE) &&
545            (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) &&
546            (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
547            !Op->Common.Node)
548        {
549            ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next);
550
551            /*
552             * Check if namepath is a predicate for if/while or lone parameter to
553             * a return.
554             */
555            if (ArgCount == 0)
556            {
557                if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
558                     (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
559                     (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
560
561                     /* And namepath is the first argument */
562                     (ParentOp->Common.Value.Arg == Op))
563                {
564                    AcpiDmAddOpToExternalList (Op,
565                        Op->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
566                    break;
567                }
568            }
569
570            /*
571             * This is a standalone namestring (not a parameter to another
572             * operator) - it *must* be a method invocation, nothing else is
573             * grammatically possible.
574             */
575            AcpiDmAddOpToExternalList (Op,
576                Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
577        }
578        break;
579
580    default:
581
582        break;
583    }
584
585    return (AE_OK);
586}
587
588
589/*******************************************************************************
590 *
591 * FUNCTION:    AcpiDmLoadDescendingOp
592 *
593 * PARAMETERS:  ASL_WALK_CALLBACK
594 *
595 * RETURN:      Status
596 *
597 * DESCRIPTION: Descending handler for namespace control method object load
598 *
599 ******************************************************************************/
600
601static ACPI_STATUS
602AcpiDmLoadDescendingOp (
603    ACPI_PARSE_OBJECT       *Op,
604    UINT32                  Level,
605    void                    *Context)
606{
607    ACPI_OP_WALK_INFO       *Info = Context;
608    const ACPI_OPCODE_INFO  *OpInfo;
609    ACPI_WALK_STATE         *WalkState;
610    ACPI_OBJECT_TYPE        ObjectType;
611    ACPI_STATUS             Status;
612    char                    *Path = NULL;
613    ACPI_PARSE_OBJECT       *NextOp;
614    ACPI_NAMESPACE_NODE     *Node;
615    char                    FieldPath[5];
616    BOOLEAN                 PreDefined = FALSE;
617    UINT8                   PreDefineIndex = 0;
618
619
620    WalkState = Info->WalkState;
621    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
622    ObjectType = OpInfo->ObjectType;
623    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
624
625    /* Only interested in operators that create new names */
626
627    if (!(OpInfo->Flags & AML_NAMED) &&
628        !(OpInfo->Flags & AML_CREATE))
629    {
630        goto Exit;
631    }
632
633    /* Get the NamePath from the appropriate place */
634
635    if (OpInfo->Flags & AML_NAMED)
636    {
637        /* For all named operators, get the new name */
638
639        Path = (char *) Op->Named.Path;
640
641        if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
642        {
643            *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
644            FieldPath[4] = 0;
645            Path = FieldPath;
646        }
647    }
648    else if (OpInfo->Flags & AML_CREATE)
649    {
650        /* New name is the last child */
651
652        NextOp = Op->Common.Value.Arg;
653
654        while (NextOp->Common.Next)
655        {
656            NextOp = NextOp->Common.Next;
657        }
658        Path = NextOp->Common.Value.String;
659    }
660
661    if (!Path)
662    {
663        goto Exit;
664    }
665
666    /* Insert the name into the namespace */
667
668    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
669                ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
670                WalkState, &Node);
671
672    Op->Common.Node = Node;
673
674    if (ACPI_SUCCESS (Status))
675    {
676        /* Check if it's a predefined node */
677
678        while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
679        {
680            if (ACPI_COMPARE_NAME (Node->Name.Ascii,
681                AcpiGbl_PreDefinedNames[PreDefineIndex].Name))
682            {
683                PreDefined = TRUE;
684                break;
685            }
686
687            PreDefineIndex++;
688        }
689
690        /*
691         * Set node owner id if it satisfies all the following conditions:
692         * 1) Not a predefined node, _SB_ etc
693         * 2) Not the root node
694         * 3) Not a node created by Scope
695         */
696
697        if (!PreDefined && Node != AcpiGbl_RootNode &&
698            Op->Common.AmlOpcode != AML_SCOPE_OP)
699        {
700            Node->OwnerId = WalkState->OwnerId;
701        }
702    }
703
704
705Exit:
706
707    if (AcpiNsOpensScope (ObjectType))
708    {
709        if (Op->Common.Node)
710        {
711            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
712            if (ACPI_FAILURE (Status))
713            {
714                return (Status);
715            }
716        }
717    }
718
719    return (AE_OK);
720}
721
722
723/*******************************************************************************
724 *
725 * FUNCTION:    AcpiDmXrefDescendingOp
726 *
727 * PARAMETERS:  ASL_WALK_CALLBACK
728 *
729 * RETURN:      Status
730 *
731 * DESCRIPTION: Descending handler for namespace cross reference
732 *
733 ******************************************************************************/
734
735static ACPI_STATUS
736AcpiDmXrefDescendingOp (
737    ACPI_PARSE_OBJECT       *Op,
738    UINT32                  Level,
739    void                    *Context)
740{
741    ACPI_OP_WALK_INFO       *Info = Context;
742    const ACPI_OPCODE_INFO  *OpInfo;
743    ACPI_WALK_STATE         *WalkState;
744    ACPI_OBJECT_TYPE        ObjectType;
745    ACPI_OBJECT_TYPE        ObjectType2;
746    ACPI_STATUS             Status;
747    char                    *Path = NULL;
748    ACPI_PARSE_OBJECT       *NextOp;
749    ACPI_NAMESPACE_NODE     *Node;
750    ACPI_OPERAND_OBJECT     *Object;
751    UINT32                  ParamCount = 0;
752    char                    *Pathname;
753
754
755    WalkState = Info->WalkState;
756    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
757    ObjectType = OpInfo->ObjectType;
758    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
759
760    if ((!(OpInfo->Flags & AML_NAMED)) &&
761        (!(OpInfo->Flags & AML_CREATE)) &&
762        (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP) &&
763        (Op->Common.AmlOpcode != AML_NOTIFY_OP))
764    {
765        goto Exit;
766    }
767
768
769    /* Get the NamePath from the appropriate place */
770
771    if (OpInfo->Flags & AML_NAMED)
772    {
773        /*
774         * Only these two operators (Alias, Scope) refer to an existing
775         * name, it is the first argument
776         */
777        if (Op->Common.AmlOpcode == AML_ALIAS_OP)
778        {
779            ObjectType = ACPI_TYPE_ANY;
780
781            NextOp = Op->Common.Value.Arg;
782            NextOp = NextOp->Common.Value.Arg;
783            if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
784            {
785                Path = NextOp->Common.Value.String;
786            }
787        }
788        else if (Op->Common.AmlOpcode == AML_SCOPE_OP)
789        {
790            Path = (char *) Op->Named.Path;
791        }
792    }
793    else if (OpInfo->Flags & AML_CREATE)
794    {
795        /* Referenced Buffer Name is the first child */
796
797        ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */
798
799        NextOp = Op->Common.Value.Arg;
800        if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
801        {
802            Path = NextOp->Common.Value.String;
803        }
804    }
805    else if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
806    {
807        Path = Op->Common.Value.Arg->Asl.Value.String;
808    }
809    else
810    {
811        Path = Op->Common.Value.String;
812    }
813
814    if (!Path)
815    {
816        goto Exit;
817    }
818
819    /*
820     * Lookup the name in the namespace. Name must exist at this point, or it
821     * is an invalid reference.
822     *
823     * The namespace is also used as a lookup table for references to resource
824     * descriptors and the fields within them.
825     */
826    Node = NULL;
827    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
828                ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
829                WalkState, &Node);
830    if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL))
831    {
832        /* Node was created by an External() statement */
833
834        Status = AE_NOT_FOUND;
835    }
836
837    if (ACPI_FAILURE (Status))
838    {
839        if (Status == AE_NOT_FOUND)
840        {
841            /*
842             * Add this symbol as an external declaration, except if the
843             * parent is a CondRefOf operator. For this operator, we do not
844             * need an external, nor do we want one, since this can cause
845             * disassembly problems if the symbol is actually a control
846             * method.
847             */
848            if (!(Op->Asl.Parent &&
849                (Op->Asl.Parent->Asl.AmlOpcode == AML_COND_REF_OF_OP)))
850            {
851                if (Node)
852                {
853                    AcpiDmAddNodeToExternalList (Node,
854                        (UINT8) ObjectType, 0, 0);
855                }
856                else
857                {
858                    AcpiDmAddOpToExternalList (Op, Path,
859                        (UINT8) ObjectType, 0, 0);
860                }
861            }
862        }
863    }
864
865    /*
866     * Found the node, but check if it came from an external table.
867     * Add it to external list. Note: Node->OwnerId == 0 indicates
868     * one of the built-in ACPI Names (_OS_ etc.) which can safely
869     * be ignored.
870     */
871    else if (Node->OwnerId &&
872            (WalkState->OwnerId != Node->OwnerId))
873    {
874        ObjectType2 = ObjectType;
875
876        Object = AcpiNsGetAttachedObject (Node);
877        if (Object)
878        {
879            ObjectType2 = Object->Common.Type;
880            if (ObjectType2 == ACPI_TYPE_METHOD)
881            {
882                ParamCount = Object->Method.ParamCount;
883            }
884        }
885
886        Pathname = AcpiNsGetExternalPathname (Node);
887        if (!Pathname)
888        {
889            return (AE_NO_MEMORY);
890        }
891
892        AcpiDmAddNodeToExternalList (Node, (UINT8) ObjectType2,
893            ParamCount, ACPI_EXT_RESOLVED_REFERENCE);
894
895        ACPI_FREE (Pathname);
896        Op->Common.Node = Node;
897    }
898    else
899    {
900        Op->Common.Node = Node;
901    }
902
903
904Exit:
905    /* Open new scope if necessary */
906
907    if (AcpiNsOpensScope (ObjectType))
908    {
909        if (Op->Common.Node)
910        {
911            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
912            if (ACPI_FAILURE (Status))
913            {
914                return (Status);
915            }
916        }
917    }
918
919    return (AE_OK);
920}
921
922
923/*******************************************************************************
924 *
925 * FUNCTION:    AcpiDmResourceDescendingOp
926 *
927 * PARAMETERS:  ASL_WALK_CALLBACK
928 *
929 * RETURN:      None
930 *
931 * DESCRIPTION: Process one parse op during symbolic resource index conversion.
932 *
933 ******************************************************************************/
934
935static ACPI_STATUS
936AcpiDmResourceDescendingOp (
937    ACPI_PARSE_OBJECT       *Op,
938    UINT32                  Level,
939    void                    *Context)
940{
941    ACPI_OP_WALK_INFO       *Info = Context;
942    const ACPI_OPCODE_INFO  *OpInfo;
943    ACPI_WALK_STATE         *WalkState;
944    ACPI_OBJECT_TYPE        ObjectType;
945    ACPI_STATUS             Status;
946
947
948    WalkState = Info->WalkState;
949    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
950
951    /* Open new scope if necessary */
952
953    ObjectType = OpInfo->ObjectType;
954    if (AcpiNsOpensScope (ObjectType))
955    {
956        if (Op->Common.Node)
957        {
958
959            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
960            if (ACPI_FAILURE (Status))
961            {
962                return (Status);
963            }
964        }
965    }
966
967    /*
968     * Check if this operator contains a reference to a resource descriptor.
969     * If so, convert the reference into a symbolic reference.
970     */
971    AcpiDmCheckResourceReference (Op, WalkState);
972    return (AE_OK);
973}
974
975
976/*******************************************************************************
977 *
978 * FUNCTION:    AcpiDmCommonAscendingOp
979 *
980 * PARAMETERS:  ASL_WALK_CALLBACK
981 *
982 * RETURN:      None
983 *
984 * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
985 *              scope if necessary.
986 *
987 ******************************************************************************/
988
989static ACPI_STATUS
990AcpiDmCommonAscendingOp (
991    ACPI_PARSE_OBJECT       *Op,
992    UINT32                  Level,
993    void                    *Context)
994{
995    ACPI_OP_WALK_INFO       *Info = Context;
996    const ACPI_OPCODE_INFO  *OpInfo;
997    ACPI_OBJECT_TYPE        ObjectType;
998
999
1000    /* Close scope if necessary */
1001
1002    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1003    ObjectType = OpInfo->ObjectType;
1004    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
1005
1006    if (AcpiNsOpensScope (ObjectType))
1007    {
1008        (void) AcpiDsScopeStackPop (Info->WalkState);
1009    }
1010
1011    return (AE_OK);
1012}
1013
1014
1015/*******************************************************************************
1016 *
1017 * FUNCTION:    AcpiDmInspectPossibleArgs
1018 *
1019 * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
1020 *                                    possible method invocation found
1021 *              TargetCount         - Number of targets (0,1,2) for this op
1022 *              Op                  - Parse op
1023 *
1024 * RETURN:      Status
1025 *
1026 * DESCRIPTION: Examine following args and next ops for possible arguments
1027 *              for an unrecognized method invocation.
1028 *
1029 ******************************************************************************/
1030
1031static UINT32
1032AcpiDmInspectPossibleArgs (
1033    UINT32                  CurrentOpArgCount,
1034    UINT32                  TargetCount,
1035    ACPI_PARSE_OBJECT       *Op)
1036{
1037    const ACPI_OPCODE_INFO  *OpInfo;
1038    UINT32                  i;
1039    UINT32                  Last = 0;
1040    UINT32                  Lookahead;
1041
1042
1043    Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount;
1044
1045    /* Lookahead for the maximum number of possible arguments */
1046
1047    for (i = 0; i < Lookahead; i++)
1048    {
1049        if (!Op)
1050        {
1051            break;
1052        }
1053
1054        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1055
1056        /*
1057         * Any one of these operators is "very probably" not a method arg
1058         */
1059        if ((Op->Common.AmlOpcode == AML_STORE_OP) ||
1060            (Op->Common.AmlOpcode == AML_NOTIFY_OP))
1061        {
1062            break;
1063        }
1064
1065        if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
1066            (OpInfo->Class != AML_CLASS_CONTROL))
1067        {
1068            Last = i+1;
1069        }
1070
1071        Op = Op->Common.Next;
1072    }
1073
1074    return (Last);
1075}
1076