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