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