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