adwalk.c revision 1.1.1.3 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 "acpi.h"
46 #include "accommon.h"
47 #include "acparser.h"
48 #include "amlcode.h"
49 #include "acdisasm.h"
50 #include "acdispat.h"
51 #include "acnamesp.h"
52 #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 */
61 ACPI_OBJECT_TYPE
62 AslMapNamedOpcodeToDataType (
63 UINT16 Opcode);
64
65 /* Local prototypes */
66
67 static ACPI_STATUS
68 AcpiDmFindOrphanDescending (
69 ACPI_PARSE_OBJECT *Op,
70 UINT32 Level,
71 void *Context);
72
73 static ACPI_STATUS
74 AcpiDmDumpDescending (
75 ACPI_PARSE_OBJECT *Op,
76 UINT32 Level,
77 void *Context);
78
79 static ACPI_STATUS
80 AcpiDmXrefDescendingOp (
81 ACPI_PARSE_OBJECT *Op,
82 UINT32 Level,
83 void *Context);
84
85 static ACPI_STATUS
86 AcpiDmCommonAscendingOp (
87 ACPI_PARSE_OBJECT *Op,
88 UINT32 Level,
89 void *Context);
90
91 static ACPI_STATUS
92 AcpiDmLoadDescendingOp (
93 ACPI_PARSE_OBJECT *Op,
94 UINT32 Level,
95 void *Context);
96
97 static UINT32
98 AcpiDmInspectPossibleArgs (
99 UINT32 CurrentOpArgCount,
100 UINT32 TargetCount,
101 ACPI_PARSE_OBJECT *Op);
102
103 static ACPI_STATUS
104 AcpiDmResourceDescendingOp (
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
122 void
123 AcpiDmDumpTree (
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
157 void
158 AcpiDmFindOrphanMethods (
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
191 void
192 AcpiDmFinishNamespaceLoad (
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
244 void
245 AcpiDmCrossReferenceNamespace (
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
298 void
299 AcpiDmConvertResourceIndexes (
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
349 static ACPI_STATUS
350 AcpiDmDumpDescending (
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
442 static ACPI_STATUS
443 AcpiDmFindOrphanDescending (
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",
474 Op->Common.AmlOpName, Path);
475 ACPI_FREE (Path);
476
477 NextOp = Op->Common.Next;
478 if (!NextOp)
479 {
480 /* This NamePath has no args, assume it is an integer */
481
482 AcpiDmAddOpToExternalList (ChildOp,
483 ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
484 return (AE_OK);
485 }
486
487 ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
488 AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n",
489 ArgCount, AcpiDmCountChildren (Op));
490
491 if (ArgCount < 1)
492 {
493 /* One Arg means this is just a Store(Name,Target) */
494
495 AcpiDmAddOpToExternalList (ChildOp,
496 ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
497 return (AE_OK);
498 }
499
500 AcpiDmAddOpToExternalList (ChildOp,
501 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
502 }
503 break;
504 #endif
505
506 case AML_STORE_OP:
507
508 ChildOp = Op->Common.Value.Arg;
509 if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
510 !ChildOp->Common.Node)
511 {
512 NextOp = Op->Common.Next;
513 if (!NextOp)
514 {
515 /* This NamePath has no args, assume it is an integer */
516
517 AcpiDmAddOpToExternalList (ChildOp,
518 ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
519 return (AE_OK);
520 }
521
522 ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
523 if (ArgCount <= 1)
524 {
525 /* One Arg means this is just a Store(Name,Target) */
526
527 AcpiDmAddOpToExternalList (ChildOp,
528 ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
529 return (AE_OK);
530 }
531
532 AcpiDmAddOpToExternalList (ChildOp,
533 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
534 }
535 break;
536
537 case AML_INT_NAMEPATH_OP:
538
539 /* Must examine parent to see if this namepath is an argument */
540
541 ParentOp = Op->Common.Parent;
542 OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
543
544 if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
545 (OpInfo->Class != AML_CLASS_CREATE) &&
546 (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) &&
547 (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
548 !Op->Common.Node)
549 {
550 ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next);
551
552 /*
553 * Check if namepath is a predicate for if/while or lone parameter to
554 * a return.
555 */
556 if (ArgCount == 0)
557 {
558 if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
559 (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
560 (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
561
562 /* And namepath is the first argument */
563 (ParentOp->Common.Value.Arg == Op))
564 {
565 AcpiDmAddOpToExternalList (Op,
566 Op->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
567 break;
568 }
569 }
570
571 /*
572 * This is a standalone namestring (not a parameter to another
573 * operator) - it *must* be a method invocation, nothing else is
574 * grammatically possible.
575 */
576 AcpiDmAddOpToExternalList (Op,
577 Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
578 }
579 break;
580
581 default:
582
583 break;
584 }
585
586 return (AE_OK);
587 }
588
589
590 /*******************************************************************************
591 *
592 * FUNCTION: AcpiDmLoadDescendingOp
593 *
594 * PARAMETERS: ASL_WALK_CALLBACK
595 *
596 * RETURN: Status
597 *
598 * DESCRIPTION: Descending handler for namespace control method object load
599 *
600 ******************************************************************************/
601
602 static ACPI_STATUS
603 AcpiDmLoadDescendingOp (
604 ACPI_PARSE_OBJECT *Op,
605 UINT32 Level,
606 void *Context)
607 {
608 ACPI_OP_WALK_INFO *Info = Context;
609 const ACPI_OPCODE_INFO *OpInfo;
610 ACPI_WALK_STATE *WalkState;
611 ACPI_OBJECT_TYPE ObjectType;
612 ACPI_STATUS Status;
613 char *Path = NULL;
614 ACPI_PARSE_OBJECT *NextOp;
615 ACPI_NAMESPACE_NODE *Node;
616 char FieldPath[5];
617 BOOLEAN PreDefined = FALSE;
618 UINT8 PreDefineIndex = 0;
619
620
621 WalkState = Info->WalkState;
622 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
623 ObjectType = OpInfo->ObjectType;
624 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
625
626 /* Only interested in operators that create new names */
627
628 if (!(OpInfo->Flags & AML_NAMED) &&
629 !(OpInfo->Flags & AML_CREATE))
630 {
631 goto Exit;
632 }
633
634 /* Get the NamePath from the appropriate place */
635
636 if (OpInfo->Flags & AML_NAMED)
637 {
638 /* For all named operators, get the new name */
639
640 Path = (char *) Op->Named.Path;
641
642 if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
643 {
644 *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
645 FieldPath[4] = 0;
646 Path = FieldPath;
647 }
648 }
649 else if (OpInfo->Flags & AML_CREATE)
650 {
651 /* New name is the last child */
652
653 NextOp = Op->Common.Value.Arg;
654
655 while (NextOp->Common.Next)
656 {
657 NextOp = NextOp->Common.Next;
658 }
659 Path = NextOp->Common.Value.String;
660 }
661
662 if (!Path)
663 {
664 goto Exit;
665 }
666
667 /* Insert the name into the namespace */
668
669 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
670 ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
671 WalkState, &Node);
672
673 Op->Common.Node = Node;
674
675 if (ACPI_SUCCESS (Status))
676 {
677 /* Check if it's a predefined node */
678
679 while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
680 {
681 if (ACPI_COMPARE_NAME (Node->Name.Ascii,
682 AcpiGbl_PreDefinedNames[PreDefineIndex].Name))
683 {
684 PreDefined = TRUE;
685 break;
686 }
687
688 PreDefineIndex++;
689 }
690
691 /*
692 * Set node owner id if it satisfies all the following conditions:
693 * 1) Not a predefined node, _SB_ etc
694 * 2) Not the root node
695 * 3) Not a node created by Scope
696 */
697
698 if (!PreDefined && Node != AcpiGbl_RootNode &&
699 Op->Common.AmlOpcode != AML_SCOPE_OP)
700 {
701 Node->OwnerId = WalkState->OwnerId;
702 }
703 }
704
705
706 Exit:
707
708 if (AcpiNsOpensScope (ObjectType))
709 {
710 if (Op->Common.Node)
711 {
712 Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
713 if (ACPI_FAILURE (Status))
714 {
715 return (Status);
716 }
717 }
718 }
719
720 return (AE_OK);
721 }
722
723
724 /*******************************************************************************
725 *
726 * FUNCTION: AcpiDmXrefDescendingOp
727 *
728 * PARAMETERS: ASL_WALK_CALLBACK
729 *
730 * RETURN: Status
731 *
732 * DESCRIPTION: Descending handler for namespace cross reference
733 *
734 ******************************************************************************/
735
736 static ACPI_STATUS
737 AcpiDmXrefDescendingOp (
738 ACPI_PARSE_OBJECT *Op,
739 UINT32 Level,
740 void *Context)
741 {
742 ACPI_OP_WALK_INFO *Info = Context;
743 const ACPI_OPCODE_INFO *OpInfo;
744 ACPI_WALK_STATE *WalkState;
745 ACPI_OBJECT_TYPE ObjectType;
746 ACPI_OBJECT_TYPE ObjectType2;
747 ACPI_STATUS Status;
748 char *Path = NULL;
749 ACPI_PARSE_OBJECT *NextOp;
750 ACPI_NAMESPACE_NODE *Node;
751 ACPI_OPERAND_OBJECT *Object;
752 UINT32 ParamCount = 0;
753 char *Pathname;
754
755
756 WalkState = Info->WalkState;
757 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
758 ObjectType = OpInfo->ObjectType;
759 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
760
761 if ((!(OpInfo->Flags & AML_NAMED)) &&
762 (!(OpInfo->Flags & AML_CREATE)) &&
763 (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
764 {
765 goto Exit;
766 }
767
768 /* Get the NamePath from the appropriate place */
769
770 if (OpInfo->Flags & AML_NAMED)
771 {
772 /*
773 * Only these two operators (Alias, Scope) refer to an existing
774 * name, it is the first argument
775 */
776 if (Op->Common.AmlOpcode == AML_ALIAS_OP)
777 {
778 ObjectType = ACPI_TYPE_ANY;
779
780 NextOp = Op->Common.Value.Arg;
781 NextOp = NextOp->Common.Value.Arg;
782 if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
783 {
784 Path = NextOp->Common.Value.String;
785 }
786 }
787 else if (Op->Common.AmlOpcode == AML_SCOPE_OP)
788 {
789 Path = (char *) Op->Named.Path;
790 }
791 }
792 else if (OpInfo->Flags & AML_CREATE)
793 {
794 /* Referenced Buffer Name is the first child */
795
796 ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */
797
798 NextOp = Op->Common.Value.Arg;
799 if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
800 {
801 Path = NextOp->Common.Value.String;
802 }
803 }
804 else
805 {
806 Path = Op->Common.Value.String;
807 }
808
809 if (!Path)
810 {
811 goto Exit;
812 }
813
814 /*
815 * Lookup the name in the namespace. Name must exist at this point, or it
816 * is an invalid reference.
817 *
818 * The namespace is also used as a lookup table for references to resource
819 * descriptors and the fields within them.
820 */
821 Node = NULL;
822 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
823 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
824 WalkState, &Node);
825 if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL))
826 {
827 /* Node was created by an External() statement */
828
829 Status = AE_NOT_FOUND;
830 }
831
832 if (ACPI_FAILURE (Status))
833 {
834 if (Status == AE_NOT_FOUND)
835 {
836 /*
837 * Add this symbol as an external declaration, except if the
838 * parent is a CondRefOf operator. For this operator, we do not
839 * need an external, nor do we want one, since this can cause
840 * disassembly problems if the symbol is actually a control
841 * method.
842 */
843 if (!(Op->Asl.Parent &&
844 (Op->Asl.Parent->Asl.AmlOpcode == AML_COND_REF_OF_OP)))
845 {
846 if (Node)
847 {
848 AcpiDmAddNodeToExternalList (Node,
849 (UINT8) ObjectType, 0, 0);
850 }
851 else
852 {
853 AcpiDmAddOpToExternalList (Op, Path,
854 (UINT8) ObjectType, 0, 0);
855 }
856 }
857 }
858 }
859
860 /*
861 * Found the node, but check if it came from an external table.
862 * Add it to external list. Note: Node->OwnerId == 0 indicates
863 * one of the built-in ACPI Names (_OS_ etc.) which can safely
864 * be ignored.
865 */
866 else if (Node->OwnerId &&
867 (WalkState->OwnerId != Node->OwnerId))
868 {
869 ObjectType2 = ObjectType;
870
871 Object = AcpiNsGetAttachedObject (Node);
872 if (Object)
873 {
874 ObjectType2 = Object->Common.Type;
875 if (ObjectType2 == ACPI_TYPE_METHOD)
876 {
877 ParamCount = Object->Method.ParamCount;
878 }
879 }
880
881 Pathname = AcpiNsGetExternalPathname (Node);
882 if (!Pathname)
883 {
884 return (AE_NO_MEMORY);
885 }
886
887 AcpiDmAddNodeToExternalList (Node, (UINT8) ObjectType2,
888 ParamCount, ACPI_EXT_RESOLVED_REFERENCE);
889
890 ACPI_FREE (Pathname);
891 Op->Common.Node = Node;
892 }
893 else
894 {
895 Op->Common.Node = Node;
896 }
897
898
899 Exit:
900 /* Open new scope if necessary */
901
902 if (AcpiNsOpensScope (ObjectType))
903 {
904 if (Op->Common.Node)
905 {
906 Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
907 if (ACPI_FAILURE (Status))
908 {
909 return (Status);
910 }
911 }
912 }
913
914 return (AE_OK);
915 }
916
917
918 /*******************************************************************************
919 *
920 * FUNCTION: AcpiDmResourceDescendingOp
921 *
922 * PARAMETERS: ASL_WALK_CALLBACK
923 *
924 * RETURN: None
925 *
926 * DESCRIPTION: Process one parse op during symbolic resource index conversion.
927 *
928 ******************************************************************************/
929
930 static ACPI_STATUS
931 AcpiDmResourceDescendingOp (
932 ACPI_PARSE_OBJECT *Op,
933 UINT32 Level,
934 void *Context)
935 {
936 ACPI_OP_WALK_INFO *Info = Context;
937 const ACPI_OPCODE_INFO *OpInfo;
938 ACPI_WALK_STATE *WalkState;
939 ACPI_OBJECT_TYPE ObjectType;
940 ACPI_STATUS Status;
941
942
943 WalkState = Info->WalkState;
944 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
945
946 /* Open new scope if necessary */
947
948 ObjectType = OpInfo->ObjectType;
949 if (AcpiNsOpensScope (ObjectType))
950 {
951 if (Op->Common.Node)
952 {
953
954 Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
955 if (ACPI_FAILURE (Status))
956 {
957 return (Status);
958 }
959 }
960 }
961
962 /*
963 * Check if this operator contains a reference to a resource descriptor.
964 * If so, convert the reference into a symbolic reference.
965 */
966 AcpiDmCheckResourceReference (Op, WalkState);
967 return (AE_OK);
968 }
969
970
971 /*******************************************************************************
972 *
973 * FUNCTION: AcpiDmCommonAscendingOp
974 *
975 * PARAMETERS: ASL_WALK_CALLBACK
976 *
977 * RETURN: None
978 *
979 * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
980 * scope if necessary.
981 *
982 ******************************************************************************/
983
984 static ACPI_STATUS
985 AcpiDmCommonAscendingOp (
986 ACPI_PARSE_OBJECT *Op,
987 UINT32 Level,
988 void *Context)
989 {
990 ACPI_OP_WALK_INFO *Info = Context;
991 const ACPI_OPCODE_INFO *OpInfo;
992 ACPI_OBJECT_TYPE ObjectType;
993
994
995 /* Close scope if necessary */
996
997 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
998 ObjectType = OpInfo->ObjectType;
999 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
1000
1001 if (AcpiNsOpensScope (ObjectType))
1002 {
1003 (void) AcpiDsScopeStackPop (Info->WalkState);
1004 }
1005
1006 return (AE_OK);
1007 }
1008
1009
1010 /*******************************************************************************
1011 *
1012 * FUNCTION: AcpiDmInspectPossibleArgs
1013 *
1014 * PARAMETERS: CurrentOpArgCount - Which arg of the current op was the
1015 * possible method invocation found
1016 * TargetCount - Number of targets (0,1,2) for this op
1017 * Op - Parse op
1018 *
1019 * RETURN: Status
1020 *
1021 * DESCRIPTION: Examine following args and next ops for possible arguments
1022 * for an unrecognized method invocation.
1023 *
1024 ******************************************************************************/
1025
1026 static UINT32
1027 AcpiDmInspectPossibleArgs (
1028 UINT32 CurrentOpArgCount,
1029 UINT32 TargetCount,
1030 ACPI_PARSE_OBJECT *Op)
1031 {
1032 const ACPI_OPCODE_INFO *OpInfo;
1033 UINT32 i;
1034 UINT32 Last = 0;
1035 UINT32 Lookahead;
1036
1037
1038 Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount;
1039
1040 /* Lookahead for the maximum number of possible arguments */
1041
1042 for (i = 0; i < Lookahead; i++)
1043 {
1044 if (!Op)
1045 {
1046 break;
1047 }
1048
1049 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1050
1051 /*
1052 * Any one of these operators is "very probably" not a method arg
1053 */
1054 if ((Op->Common.AmlOpcode == AML_STORE_OP) ||
1055 (Op->Common.AmlOpcode == AML_NOTIFY_OP))
1056 {
1057 break;
1058 }
1059
1060 if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
1061 (OpInfo->Class != AML_CLASS_CONTROL))
1062 {
1063 Last = i+1;
1064 }
1065
1066 Op = Op->Common.Next;
1067 }
1068
1069 return (Last);
1070 }
1071