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