adwalk.c revision 250838
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    case AML_WORD_OP:
377    case AML_DWORD_OP:
378
379        AcpiOsPrintf ("%X", (UINT32) Op->Common.Value.Integer);
380        break;
381
382    case AML_QWORD_OP:
383
384        AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
385        break;
386
387    case AML_INT_NAMEPATH_OP:
388
389        if (Op->Common.Value.String)
390        {
391            AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String,
392                            NULL, &Path);
393            AcpiOsPrintf ("%s %p", Path, Op->Common.Node);
394            ACPI_FREE (Path);
395        }
396        else
397        {
398            AcpiOsPrintf ("[NULL]");
399        }
400        break;
401
402    case AML_NAME_OP:
403    case AML_METHOD_OP:
404    case AML_DEVICE_OP:
405    case AML_INT_NAMEDFIELD_OP:
406
407        AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name));
408        break;
409
410    default:
411
412        break;
413    }
414
415    AcpiOsPrintf ("\n");
416    return (AE_OK);
417}
418
419
420/*******************************************************************************
421 *
422 * FUNCTION:    AcpiDmFindOrphanDescending
423 *
424 * PARAMETERS:  ASL_WALK_CALLBACK
425 *
426 * RETURN:      Status
427 *
428 * DESCRIPTION: Check namepath Ops for orphaned method invocations
429 *
430 * Note: Experimental.
431 *
432 ******************************************************************************/
433
434static ACPI_STATUS
435AcpiDmFindOrphanDescending (
436    ACPI_PARSE_OBJECT       *Op,
437    UINT32                  Level,
438    void                    *Context)
439{
440    const ACPI_OPCODE_INFO  *OpInfo;
441    ACPI_PARSE_OBJECT       *ChildOp;
442    ACPI_PARSE_OBJECT       *NextOp;
443    ACPI_PARSE_OBJECT       *ParentOp;
444    UINT32                  ArgCount;
445
446
447    if (!Op)
448    {
449        return (AE_OK);
450    }
451
452    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
453
454    switch (Op->Common.AmlOpcode)
455    {
456#ifdef ACPI_UNDER_DEVELOPMENT
457    case AML_ADD_OP:
458
459        ChildOp = Op->Common.Value.Arg;
460        if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
461            !ChildOp->Common.Node)
462        {
463            AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String,
464                            NULL, &Path);
465            AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s  */\n", Op->Common.AmlOpName, Path);
466            ACPI_FREE (Path);
467
468            NextOp = Op->Common.Next;
469            if (!NextOp)
470            {
471                /* This NamePath has no args, assume it is an integer */
472
473                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
474                return (AE_OK);
475            }
476
477            ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
478            AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n", ArgCount, AcpiDmCountChildren (Op));
479
480            if (ArgCount < 1)
481            {
482                /* One Arg means this is just a Store(Name,Target) */
483
484                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
485                return (AE_OK);
486            }
487
488            AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
489        }
490        break;
491#endif
492
493    case AML_STORE_OP:
494
495        ChildOp = Op->Common.Value.Arg;
496        if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
497            !ChildOp->Common.Node)
498        {
499            NextOp = Op->Common.Next;
500            if (!NextOp)
501            {
502                /* This NamePath has no args, assume it is an integer */
503
504                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
505                return (AE_OK);
506            }
507
508            ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
509            if (ArgCount <= 1)
510            {
511                /* One Arg means this is just a Store(Name,Target) */
512
513                AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
514                return (AE_OK);
515            }
516
517            AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
518        }
519        break;
520
521    case AML_INT_NAMEPATH_OP:
522
523        /* Must examine parent to see if this namepath is an argument */
524
525        ParentOp = Op->Common.Parent;
526        OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
527
528        if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
529            (OpInfo->Class != AML_CLASS_CREATE) &&
530            (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) &&
531            (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
532            !Op->Common.Node)
533        {
534            ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next);
535
536            /*
537             * Check if namepath is a predicate for if/while or lone parameter to
538             * a return.
539             */
540            if (ArgCount == 0)
541            {
542                if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
543                     (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
544                     (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
545
546                     /* And namepath is the first argument */
547                     (ParentOp->Common.Value.Arg == Op))
548                {
549                    AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_INTEGER, 0);
550                    break;
551                }
552            }
553
554            /*
555             * This is a standalone namestring (not a parameter to another
556             * operator) - it *must* be a method invocation, nothing else is
557             * grammatically possible.
558             */
559            AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
560
561        }
562        break;
563
564    default:
565
566        break;
567    }
568
569    return (AE_OK);
570}
571
572
573/*******************************************************************************
574 *
575 * FUNCTION:    AcpiDmLoadDescendingOp
576 *
577 * PARAMETERS:  ASL_WALK_CALLBACK
578 *
579 * RETURN:      Status
580 *
581 * DESCRIPTION: Descending handler for namespace control method object load
582 *
583 ******************************************************************************/
584
585static ACPI_STATUS
586AcpiDmLoadDescendingOp (
587    ACPI_PARSE_OBJECT       *Op,
588    UINT32                  Level,
589    void                    *Context)
590{
591    ACPI_OP_WALK_INFO       *Info = Context;
592    const ACPI_OPCODE_INFO  *OpInfo;
593    ACPI_WALK_STATE         *WalkState;
594    ACPI_OBJECT_TYPE        ObjectType;
595    ACPI_STATUS             Status;
596    char                    *Path = NULL;
597    ACPI_PARSE_OBJECT       *NextOp;
598    ACPI_NAMESPACE_NODE     *Node;
599    char                    FieldPath[5];
600    BOOLEAN                 PreDefined = FALSE;
601    UINT8                   PreDefineIndex = 0;
602
603
604    WalkState = Info->WalkState;
605    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
606    ObjectType = OpInfo->ObjectType;
607    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
608
609    /* Only interested in operators that create new names */
610
611    if (!(OpInfo->Flags & AML_NAMED) &&
612        !(OpInfo->Flags & AML_CREATE))
613    {
614        goto Exit;
615    }
616
617    /* Get the NamePath from the appropriate place */
618
619    if (OpInfo->Flags & AML_NAMED)
620    {
621        /* For all named operators, get the new name */
622
623        Path = (char *) Op->Named.Path;
624
625        if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
626        {
627            *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
628            FieldPath[4] = 0;
629            Path = FieldPath;
630        }
631    }
632    else if (OpInfo->Flags & AML_CREATE)
633    {
634        /* New name is the last child */
635
636        NextOp = Op->Common.Value.Arg;
637
638        while (NextOp->Common.Next)
639        {
640            NextOp = NextOp->Common.Next;
641        }
642        Path = NextOp->Common.Value.String;
643    }
644
645    if (!Path)
646    {
647        goto Exit;
648    }
649
650    /* Insert the name into the namespace */
651
652    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
653                ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
654                WalkState, &Node);
655
656    Op->Common.Node = Node;
657
658    if (ACPI_SUCCESS (Status))
659    {
660        /* Check if it's a predefined node */
661
662        while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
663        {
664            if (ACPI_COMPARE_NAME (Node->Name.Ascii,
665                AcpiGbl_PreDefinedNames[PreDefineIndex].Name))
666            {
667                PreDefined = TRUE;
668                break;
669            }
670
671            PreDefineIndex++;
672        }
673
674        /*
675         * Set node owner id if it satisfies all the following conditions:
676         * 1) Not a predefined node, _SB_ etc
677         * 2) Not the root node
678         * 3) Not a node created by Scope
679         */
680
681        if (!PreDefined && Node != AcpiGbl_RootNode &&
682            Op->Common.AmlOpcode != AML_SCOPE_OP)
683        {
684            Node->OwnerId = WalkState->OwnerId;
685        }
686    }
687
688
689Exit:
690
691    if (AcpiNsOpensScope (ObjectType))
692    {
693        if (Op->Common.Node)
694        {
695            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
696            if (ACPI_FAILURE (Status))
697            {
698                return (Status);
699            }
700        }
701    }
702
703    return (AE_OK);
704}
705
706
707/*******************************************************************************
708 *
709 * FUNCTION:    AcpiDmXrefDescendingOp
710 *
711 * PARAMETERS:  ASL_WALK_CALLBACK
712 *
713 * RETURN:      Status
714 *
715 * DESCRIPTION: Descending handler for namespace cross reference
716 *
717 ******************************************************************************/
718
719static ACPI_STATUS
720AcpiDmXrefDescendingOp (
721    ACPI_PARSE_OBJECT       *Op,
722    UINT32                  Level,
723    void                    *Context)
724{
725    ACPI_OP_WALK_INFO       *Info = Context;
726    const ACPI_OPCODE_INFO  *OpInfo;
727    ACPI_WALK_STATE         *WalkState;
728    ACPI_OBJECT_TYPE        ObjectType;
729    ACPI_OBJECT_TYPE        ObjectType2;
730    ACPI_STATUS             Status;
731    char                    *Path = NULL;
732    ACPI_PARSE_OBJECT       *NextOp;
733    ACPI_NAMESPACE_NODE     *Node;
734    ACPI_OPERAND_OBJECT     *Object;
735    UINT32                  ParamCount = 0;
736
737
738    WalkState = Info->WalkState;
739    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
740    ObjectType = OpInfo->ObjectType;
741    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
742
743    if ((!(OpInfo->Flags & AML_NAMED)) &&
744        (!(OpInfo->Flags & AML_CREATE)) &&
745        (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
746    {
747        goto Exit;
748    }
749
750    /* Get the NamePath from the appropriate place */
751
752    if (OpInfo->Flags & AML_NAMED)
753    {
754        /*
755         * Only these two operators (Alias, Scope) refer to an existing
756         * name, it is the first argument
757         */
758        if (Op->Common.AmlOpcode == AML_ALIAS_OP)
759        {
760            ObjectType = ACPI_TYPE_ANY;
761
762            NextOp = Op->Common.Value.Arg;
763            NextOp = NextOp->Common.Value.Arg;
764            if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
765            {
766                Path = NextOp->Common.Value.String;
767            }
768        }
769        else if (Op->Common.AmlOpcode == AML_SCOPE_OP)
770        {
771            Path = (char *) Op->Named.Path;
772        }
773    }
774    else if (OpInfo->Flags & AML_CREATE)
775    {
776        /* Referenced Buffer Name is the first child */
777
778        ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */
779
780        NextOp = Op->Common.Value.Arg;
781        if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
782        {
783            Path = NextOp->Common.Value.String;
784        }
785    }
786    else
787    {
788        Path = Op->Common.Value.String;
789    }
790
791    if (!Path)
792    {
793        goto Exit;
794    }
795
796    /*
797     * Lookup the name in the namespace. Name must exist at this point, or it
798     * is an invalid reference.
799     *
800     * The namespace is also used as a lookup table for references to resource
801     * descriptors and the fields within them.
802     */
803    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
804                ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
805                WalkState, &Node);
806    if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL))
807    {
808        Status = AE_NOT_FOUND;
809    }
810
811    if (ACPI_FAILURE (Status))
812    {
813        if (Status == AE_NOT_FOUND)
814        {
815            AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType, 0);
816
817            /*
818             * We could install this into the namespace, but we catch duplicate
819             * externals when they are added to the list.
820             */
821#if 0
822            Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
823                       ACPI_IMODE_LOAD_PASS1, ACPI_NS_DONT_OPEN_SCOPE,
824                       WalkState, &Node);
825#endif
826        }
827    }
828
829    /*
830     * Found the node in external table, add it to external list
831     * Node->OwnerId == 0 indicates built-in ACPI Names, _OS_ etc
832     */
833    else if (Node->OwnerId && WalkState->OwnerId != Node->OwnerId)
834    {
835        ObjectType2 = ObjectType;
836
837        Object = AcpiNsGetAttachedObject (Node);
838        if (Object)
839        {
840            ObjectType2 = Object->Common.Type;
841            if (ObjectType2 == ACPI_TYPE_METHOD)
842            {
843                ParamCount = Object->Method.ParamCount;
844            }
845        }
846
847        AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType2, ParamCount | 0x80);
848        Op->Common.Node = Node;
849    }
850    else
851    {
852        Op->Common.Node = Node;
853    }
854
855
856Exit:
857    /* Open new scope if necessary */
858
859    if (AcpiNsOpensScope (ObjectType))
860    {
861        if (Op->Common.Node)
862        {
863            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
864            if (ACPI_FAILURE (Status))
865            {
866                return (Status);
867            }
868        }
869    }
870
871    return (AE_OK);
872}
873
874
875/*******************************************************************************
876 *
877 * FUNCTION:    AcpiDmResourceDescendingOp
878 *
879 * PARAMETERS:  ASL_WALK_CALLBACK
880 *
881 * RETURN:      None
882 *
883 * DESCRIPTION: Process one parse op during symbolic resource index conversion.
884 *
885 ******************************************************************************/
886
887static ACPI_STATUS
888AcpiDmResourceDescendingOp (
889    ACPI_PARSE_OBJECT       *Op,
890    UINT32                  Level,
891    void                    *Context)
892{
893    ACPI_OP_WALK_INFO       *Info = Context;
894    const ACPI_OPCODE_INFO  *OpInfo;
895    ACPI_WALK_STATE         *WalkState;
896    ACPI_OBJECT_TYPE        ObjectType;
897    ACPI_STATUS             Status;
898
899
900    WalkState = Info->WalkState;
901    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
902
903    /* Open new scope if necessary */
904
905    ObjectType = OpInfo->ObjectType;
906    if (AcpiNsOpensScope (ObjectType))
907    {
908        if (Op->Common.Node)
909        {
910
911            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
912            if (ACPI_FAILURE (Status))
913            {
914                return (Status);
915            }
916        }
917    }
918
919    /*
920     * Check if this operator contains a reference to a resource descriptor.
921     * If so, convert the reference into a symbolic reference.
922     */
923    AcpiDmCheckResourceReference (Op, WalkState);
924    return (AE_OK);
925}
926
927
928/*******************************************************************************
929 *
930 * FUNCTION:    AcpiDmCommonAscendingOp
931 *
932 * PARAMETERS:  ASL_WALK_CALLBACK
933 *
934 * RETURN:      None
935 *
936 * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
937 *              scope if necessary.
938 *
939 ******************************************************************************/
940
941static ACPI_STATUS
942AcpiDmCommonAscendingOp (
943    ACPI_PARSE_OBJECT       *Op,
944    UINT32                  Level,
945    void                    *Context)
946{
947    ACPI_OP_WALK_INFO       *Info = Context;
948    const ACPI_OPCODE_INFO  *OpInfo;
949    ACPI_OBJECT_TYPE        ObjectType;
950
951
952    /* Close scope if necessary */
953
954    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
955    ObjectType = OpInfo->ObjectType;
956    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
957
958    if (AcpiNsOpensScope (ObjectType))
959    {
960        (void) AcpiDsScopeStackPop (Info->WalkState);
961    }
962
963    return (AE_OK);
964}
965
966
967/*******************************************************************************
968 *
969 * FUNCTION:    AcpiDmInspectPossibleArgs
970 *
971 * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
972 *                                    possible method invocation found
973 *              TargetCount         - Number of targets (0,1,2) for this op
974 *              Op                  - Parse op
975 *
976 * RETURN:      Status
977 *
978 * DESCRIPTION: Examine following args and next ops for possible arguments
979 *              for an unrecognized method invocation.
980 *
981 ******************************************************************************/
982
983static UINT32
984AcpiDmInspectPossibleArgs (
985    UINT32                  CurrentOpArgCount,
986    UINT32                  TargetCount,
987    ACPI_PARSE_OBJECT       *Op)
988{
989    const ACPI_OPCODE_INFO  *OpInfo;
990    UINT32                  i;
991    UINT32                  Last = 0;
992    UINT32                  Lookahead;
993
994
995    Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount;
996
997    /* Lookahead for the maximum number of possible arguments */
998
999    for (i = 0; i < Lookahead; i++)
1000    {
1001        if (!Op)
1002        {
1003            break;
1004        }
1005
1006        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1007
1008        /*
1009         * Any one of these operators is "very probably" not a method arg
1010         */
1011        if ((Op->Common.AmlOpcode == AML_STORE_OP) ||
1012            (Op->Common.AmlOpcode == AML_NOTIFY_OP))
1013        {
1014            break;
1015        }
1016
1017        if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
1018            (OpInfo->Class != AML_CLASS_CONTROL))
1019        {
1020            Last = i+1;
1021        }
1022
1023        Op = Op->Common.Next;
1024    }
1025
1026    return (Last);
1027}
1028