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