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