Sync ACPICA with Intel's version 20170224.
[dragonfly.git] / sys / contrib / dev / acpica / source / components / disassembler / dmwalk.c
blob20b3cb9c891bba33af33fdcf77f6eb37c5c0085b
1 /*******************************************************************************
3 * Module Name: dmwalk - AML disassembly tree walk
5 ******************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved.
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.
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.
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.
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acparser.h"
47 #include "amlcode.h"
48 #include "acdebug.h"
49 #include "acconvert.h"
52 #ifdef ACPI_DISASSEMBLER
54 #define _COMPONENT ACPI_CA_DEBUGGER
55 ACPI_MODULE_NAME ("dmwalk")
58 #define DB_FULL_OP_INFO "[%4.4s] @%5.5X #%4.4X: "
60 /* Stub for non-compiler code */
62 #ifndef ACPI_ASL_COMPILER
63 void
64 AcpiDmEmitExternals (
65 void)
67 return;
70 void
71 AcpiDmEmitExternal (
72 ACPI_PARSE_OBJECT *NameOp,
73 ACPI_PARSE_OBJECT *TypeOp)
75 return;
77 #endif
79 /* Local prototypes */
81 static ACPI_STATUS
82 AcpiDmDescendingOp (
83 ACPI_PARSE_OBJECT *Op,
84 UINT32 Level,
85 void *Context);
87 static ACPI_STATUS
88 AcpiDmAscendingOp (
89 ACPI_PARSE_OBJECT *Op,
90 UINT32 Level,
91 void *Context);
94 /*******************************************************************************
96 * FUNCTION: AcpiDmDisassemble
98 * PARAMETERS: WalkState - Current state
99 * Origin - Starting object
100 * NumOpcodes - Max number of opcodes to be displayed
102 * RETURN: None
104 * DESCRIPTION: Disassemble parser object and its children. This is the
105 * main entry point of the disassembler.
107 ******************************************************************************/
109 void
110 AcpiDmDisassemble (
111 ACPI_WALK_STATE *WalkState,
112 ACPI_PARSE_OBJECT *Origin,
113 UINT32 NumOpcodes)
115 ACPI_PARSE_OBJECT *Op = Origin;
116 ACPI_OP_WALK_INFO Info;
119 if (!Op)
121 return;
124 memset (&Info, 0, sizeof (ACPI_OP_WALK_INFO));
125 Info.WalkState = WalkState;
126 Info.StartAml = Op->Common.Aml - sizeof (ACPI_TABLE_HEADER);
127 Info.AmlOffset = Op->Common.Aml - Info.StartAml;
129 AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info);
130 return;
134 /*******************************************************************************
136 * FUNCTION: AcpiDmWalkParseTree
138 * PARAMETERS: Op - Root Op object
139 * DescendingCallback - Called during tree descent
140 * AscendingCallback - Called during tree ascent
141 * Context - To be passed to the callbacks
143 * RETURN: Status from callback(s)
145 * DESCRIPTION: Walk the entire parse tree.
147 ******************************************************************************/
149 void
150 AcpiDmWalkParseTree (
151 ACPI_PARSE_OBJECT *Op,
152 ASL_WALK_CALLBACK DescendingCallback,
153 ASL_WALK_CALLBACK AscendingCallback,
154 void *Context)
156 BOOLEAN NodePreviouslyVisited;
157 ACPI_PARSE_OBJECT *StartOp = Op;
158 ACPI_STATUS Status;
159 ACPI_PARSE_OBJECT *Next;
160 ACPI_OP_WALK_INFO *Info = Context;
163 Info->Level = 0;
164 NodePreviouslyVisited = FALSE;
166 while (Op)
168 if (NodePreviouslyVisited)
170 if (AscendingCallback)
172 Status = AscendingCallback (Op, Info->Level, Context);
173 if (ACPI_FAILURE (Status))
175 return;
179 else
181 /* Let the callback process the node */
183 Status = DescendingCallback (Op, Info->Level, Context);
184 if (ACPI_SUCCESS (Status))
186 /* Visit children first, once */
188 Next = AcpiPsGetArg (Op, 0);
189 if (Next)
191 Info->Level++;
192 Op = Next;
193 continue;
196 else if (Status != AE_CTRL_DEPTH)
198 /* Exit immediately on any error */
200 return;
204 /* Terminate walk at start op */
206 if (Op == StartOp)
208 break;
211 /* No more children, re-visit this node */
213 if (!NodePreviouslyVisited)
215 NodePreviouslyVisited = TRUE;
216 continue;
219 /* No more children, visit peers */
221 if (Op->Common.Next)
223 Op = Op->Common.Next;
224 NodePreviouslyVisited = FALSE;
226 else
228 /* No peers, re-visit parent */
230 if (Info->Level != 0 )
232 Info->Level--;
235 Op = Op->Common.Parent;
236 NodePreviouslyVisited = TRUE;
240 /* If we get here, the walk completed with no errors */
242 return;
246 /*******************************************************************************
248 * FUNCTION: AcpiDmBlockType
250 * PARAMETERS: Op - Object to be examined
252 * RETURN: BlockType - not a block, parens, braces, or even both.
254 * DESCRIPTION: Type of block for this op (parens or braces)
256 ******************************************************************************/
258 UINT32
259 AcpiDmBlockType (
260 ACPI_PARSE_OBJECT *Op)
262 const ACPI_OPCODE_INFO *OpInfo;
265 if (!Op)
267 return (BLOCK_NONE);
270 switch (Op->Common.AmlOpcode)
272 case AML_ELSE_OP:
274 return (BLOCK_BRACE);
276 case AML_METHOD_OP:
277 case AML_DEVICE_OP:
278 case AML_SCOPE_OP:
279 case AML_PROCESSOR_OP:
280 case AML_POWER_RESOURCE_OP:
281 case AML_THERMAL_ZONE_OP:
282 case AML_IF_OP:
283 case AML_WHILE_OP:
284 case AML_FIELD_OP:
285 case AML_INDEX_FIELD_OP:
286 case AML_BANK_FIELD_OP:
288 return (BLOCK_PAREN | BLOCK_BRACE);
290 case AML_BUFFER_OP:
292 if ((Op->Common.DisasmOpcode == ACPI_DASM_UNICODE) ||
293 (Op->Common.DisasmOpcode == ACPI_DASM_UUID) ||
294 (Op->Common.DisasmOpcode == ACPI_DASM_PLD_METHOD))
296 return (BLOCK_NONE);
299 /*lint -fallthrough */
301 case AML_PACKAGE_OP:
302 case AML_VARIABLE_PACKAGE_OP:
304 return (BLOCK_PAREN | BLOCK_BRACE);
306 case AML_EVENT_OP:
308 return (BLOCK_PAREN);
310 case AML_INT_METHODCALL_OP:
312 if (Op->Common.Parent &&
313 ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
314 (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
316 /* This is a reference to a method, not an invocation */
318 return (BLOCK_NONE);
321 /*lint -fallthrough */
323 default:
325 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
326 if (OpInfo->Flags & AML_HAS_ARGS)
328 return (BLOCK_PAREN);
331 return (BLOCK_NONE);
336 /*******************************************************************************
338 * FUNCTION: AcpiDmListType
340 * PARAMETERS: Op - Object to be examined
342 * RETURN: ListType - has commas or not.
344 * DESCRIPTION: Type of block for this op (parens or braces)
346 ******************************************************************************/
348 UINT32
349 AcpiDmListType (
350 ACPI_PARSE_OBJECT *Op)
352 const ACPI_OPCODE_INFO *OpInfo;
355 if (!Op)
357 return (BLOCK_NONE);
360 switch (Op->Common.AmlOpcode)
363 case AML_ELSE_OP:
364 case AML_METHOD_OP:
365 case AML_DEVICE_OP:
366 case AML_SCOPE_OP:
367 case AML_POWER_RESOURCE_OP:
368 case AML_PROCESSOR_OP:
369 case AML_THERMAL_ZONE_OP:
370 case AML_IF_OP:
371 case AML_WHILE_OP:
372 case AML_FIELD_OP:
373 case AML_INDEX_FIELD_OP:
374 case AML_BANK_FIELD_OP:
376 return (BLOCK_NONE);
378 case AML_BUFFER_OP:
379 case AML_PACKAGE_OP:
380 case AML_VARIABLE_PACKAGE_OP:
382 return (BLOCK_COMMA_LIST);
384 default:
386 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
387 if (OpInfo->Flags & AML_HAS_ARGS)
389 return (BLOCK_COMMA_LIST);
392 return (BLOCK_NONE);
397 /*******************************************************************************
399 * FUNCTION: AcpiDmDescendingOp
401 * PARAMETERS: ASL_WALK_CALLBACK
403 * RETURN: Status
405 * DESCRIPTION: First visitation of a parse object during tree descent.
406 * Decode opcode name and begin parameter list(s), if any.
408 ******************************************************************************/
410 static ACPI_STATUS
411 AcpiDmDescendingOp (
412 ACPI_PARSE_OBJECT *Op,
413 UINT32 Level,
414 void *Context)
416 ACPI_OP_WALK_INFO *Info = Context;
417 const ACPI_OPCODE_INFO *OpInfo;
418 UINT32 Name;
419 ACPI_PARSE_OBJECT *NextOp;
420 ACPI_PARSE_OBJECT *NextOp2;
421 UINT32 AmlOffset;
424 /* Determine which file this parse node is contained in. */
426 if (Gbl_CaptureComments)
428 ASL_CV_LABEL_FILENODE (Op);
430 if (Level != 0 && ASL_CV_FILE_HAS_SWITCHED (Op))
432 ASL_CV_SWITCH_FILES (Level, Op);
435 /* If this parse node has regular comments, print them here. */
437 ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_STANDARD, NULL, Level);
440 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
442 /* Listing support to dump the AML code after the ASL statement */
444 if (AcpiGbl_DmOpt_Listing)
446 /* We only care about these classes of objects */
448 if ((OpInfo->Class == AML_CLASS_NAMED_OBJECT) ||
449 (OpInfo->Class == AML_CLASS_CONTROL) ||
450 (OpInfo->Class == AML_CLASS_CREATE) ||
451 ((OpInfo->Class == AML_CLASS_EXECUTE) && (!Op->Common.Next)))
453 if (AcpiGbl_DmOpt_Listing && Info->PreviousAml)
455 /* Dump the AML byte code for the previous Op */
457 if (Op->Common.Aml > Info->PreviousAml)
459 AcpiOsPrintf ("\n");
460 AcpiUtDumpBuffer (
461 (Info->StartAml + Info->AmlOffset),
462 (Op->Common.Aml - Info->PreviousAml),
463 DB_BYTE_DISPLAY, Info->AmlOffset);
464 AcpiOsPrintf ("\n");
467 Info->AmlOffset = (Op->Common.Aml - Info->StartAml);
470 Info->PreviousAml = Op->Common.Aml;
474 if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
476 /* Ignore this op -- it was handled elsewhere */
478 return (AE_CTRL_DEPTH);
481 if (AcpiDmIsTempName(Op))
483 /* Ignore compiler generated temporary names */
485 return (AE_CTRL_DEPTH);
488 if (Op->Common.DisasmOpcode == ACPI_DASM_IGNORE_SINGLE)
490 /* Ignore this op, but not it's children */
492 return (AE_OK);
495 if (Op->Common.AmlOpcode == AML_IF_OP)
497 NextOp = AcpiPsGetDepthNext (NULL, Op);
498 if (NextOp)
500 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
502 /* Don't emit the actual embedded externals unless asked */
504 if (!AcpiGbl_DmEmitExternalOpcodes)
507 * A Zero predicate indicates the possibility of one or more
508 * External() opcodes within the If() block.
510 if (NextOp->Common.AmlOpcode == AML_ZERO_OP)
512 NextOp2 = NextOp->Common.Next;
514 if (NextOp2 &&
515 (NextOp2->Common.AmlOpcode == AML_EXTERNAL_OP))
517 /* Ignore the If 0 block and all children */
519 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
520 return (AE_CTRL_DEPTH);
527 /* Level 0 is at the Definition Block level */
529 if (Level == 0)
531 /* In verbose mode, print the AML offset, opcode and depth count */
533 if (Info->WalkState)
535 AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml,
536 Info->WalkState->ParserState.AmlStart);
537 if (AcpiGbl_DmOpt_Verbose)
539 AcpiOsPrintf (DB_FULL_OP_INFO,
540 (Info->WalkState->MethodNode ?
541 Info->WalkState->MethodNode->Name.Ascii : " "),
542 AmlOffset, (UINT32) Op->Common.AmlOpcode);
546 if (Op->Common.AmlOpcode == AML_SCOPE_OP)
548 /* This is the beginning of the Definition Block */
550 AcpiOsPrintf ("{\n");
552 /* Emit all External() declarations here */
554 if (!AcpiGbl_DmEmitExternalOpcodes)
556 AcpiDmEmitExternals ();
559 return (AE_OK);
562 else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
563 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
564 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)) &&
565 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
568 * This is a first-level element of a term list,
569 * indent a new line
571 switch (Op->Common.AmlOpcode)
573 case AML_NOOP_OP:
575 * Optionally just ignore this opcode. Some tables use
576 * NoOp opcodes for "padding" out packages that the BIOS
577 * changes dynamically. This can leave hundreds or
578 * thousands of NoOp opcodes that if disassembled,
579 * cannot be compiled because they are syntactically
580 * incorrect.
582 if (AcpiGbl_IgnoreNoopOperator)
584 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
585 return (AE_OK);
588 /* Fallthrough */
590 default:
592 AcpiDmIndent (Level);
593 break;
596 Info->LastLevel = Level;
597 Info->Count = 0;
601 * This is an inexpensive mechanism to try and keep lines from getting
602 * too long. When the limit is hit, start a new line at the previous
603 * indent plus one. A better but more expensive mechanism would be to
604 * keep track of the current column.
606 Info->Count++;
607 if (Info->Count /* +Info->LastLevel */ > 12)
609 Info->Count = 0;
610 AcpiOsPrintf ("\n");
611 AcpiDmIndent (Info->LastLevel + 1);
614 /* If ASL+ is enabled, check for a C-style operator */
616 if (AcpiDmCheckForSymbolicOpcode (Op, Info))
618 return (AE_OK);
621 /* Print the opcode name */
623 AcpiDmDisassembleOneOp (NULL, Info, Op);
625 if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) ||
626 (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP))
628 return (AE_OK);
631 if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
632 (Op->Common.AmlOpcode == AML_RETURN_OP))
634 Info->Level--;
637 if (Op->Common.AmlOpcode == AML_EXTERNAL_OP)
639 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
640 return (AE_CTRL_DEPTH);
643 /* Start the opcode argument list if necessary */
645 if ((OpInfo->Flags & AML_HAS_ARGS) ||
646 (Op->Common.AmlOpcode == AML_EVENT_OP))
648 /* This opcode has an argument list */
650 if (AcpiDmBlockType (Op) & BLOCK_PAREN)
652 AcpiOsPrintf (" (");
653 if (!(AcpiDmBlockType (Op) & BLOCK_BRACE))
655 ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, " ", 0);
659 /* If this is a named opcode, print the associated name value */
661 if (OpInfo->Flags & AML_NAMED)
663 switch (Op->Common.AmlOpcode)
665 case AML_ALIAS_OP:
667 NextOp = AcpiPsGetDepthNext (NULL, Op);
668 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
669 AcpiDmNamestring (NextOp->Common.Value.Name);
670 AcpiOsPrintf (", ");
672 /*lint -fallthrough */
674 default:
676 Name = AcpiPsGetName (Op);
677 if (Op->Named.Path)
679 AcpiDmNamestring ((char *) Op->Named.Path);
681 else
683 AcpiDmDumpName (Name);
686 if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
688 if (AcpiGbl_DmOpt_Verbose)
690 (void) AcpiPsDisplayObjectPathname (NULL, Op);
693 break;
696 switch (Op->Common.AmlOpcode)
698 case AML_METHOD_OP:
700 AcpiDmMethodFlags (Op);
701 ASL_CV_CLOSE_PAREN (Op, Level);
703 /* Emit description comment for Method() with a predefined ACPI name */
705 AcpiDmPredefinedDescription (Op);
706 break;
708 case AML_NAME_OP:
710 /* Check for _HID and related EISAID() */
712 AcpiDmCheckForHardwareId (Op);
713 AcpiOsPrintf (", ");
714 ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0);
715 break;
717 case AML_REGION_OP:
719 AcpiDmRegionFlags (Op);
720 break;
722 case AML_POWER_RESOURCE_OP:
724 /* Mark the next two Ops as part of the parameter list */
726 AcpiOsPrintf (", ");
727 NextOp = AcpiPsGetDepthNext (NULL, Op);
728 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
730 NextOp = NextOp->Common.Next;
731 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
732 return (AE_OK);
734 case AML_PROCESSOR_OP:
736 /* Mark the next three Ops as part of the parameter list */
738 AcpiOsPrintf (", ");
739 NextOp = AcpiPsGetDepthNext (NULL, Op);
740 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
742 NextOp = NextOp->Common.Next;
743 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
745 NextOp = NextOp->Common.Next;
746 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
747 return (AE_OK);
749 case AML_MUTEX_OP:
750 case AML_DATA_REGION_OP:
752 AcpiOsPrintf (", ");
753 return (AE_OK);
755 case AML_EVENT_OP:
756 case AML_ALIAS_OP:
758 return (AE_OK);
760 case AML_SCOPE_OP:
761 case AML_DEVICE_OP:
762 case AML_THERMAL_ZONE_OP:
764 ASL_CV_CLOSE_PAREN (Op, Level);
765 break;
767 default:
769 AcpiOsPrintf ("*** Unhandled named opcode %X\n",
770 Op->Common.AmlOpcode);
771 break;
775 else switch (Op->Common.AmlOpcode)
777 case AML_FIELD_OP:
778 case AML_BANK_FIELD_OP:
779 case AML_INDEX_FIELD_OP:
781 Info->BitOffset = 0;
783 /* Name of the parent OperationRegion */
785 NextOp = AcpiPsGetDepthNext (NULL, Op);
786 AcpiDmNamestring (NextOp->Common.Value.Name);
787 AcpiOsPrintf (", ");
788 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
790 switch (Op->Common.AmlOpcode)
792 case AML_BANK_FIELD_OP:
794 /* Namestring - Bank Name */
796 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
797 AcpiDmNamestring (NextOp->Common.Value.Name);
798 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
799 AcpiOsPrintf (", ");
802 * Bank Value. This is a TermArg in the middle of the parameter
803 * list, must handle it here.
805 * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMETER_LIST
806 * eliminates newline in the output.
808 NextOp = NextOp->Common.Next;
810 Info->Flags = ACPI_PARSEOP_PARAMETER_LIST;
811 AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp,
812 AcpiDmAscendingOp, Info);
813 Info->Flags = 0;
814 Info->Level = Level;
816 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
817 AcpiOsPrintf (", ");
818 break;
820 case AML_INDEX_FIELD_OP:
822 /* Namestring - Data Name */
824 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
825 AcpiDmNamestring (NextOp->Common.Value.Name);
826 AcpiOsPrintf (", ");
827 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
828 break;
830 default:
832 break;
835 AcpiDmFieldFlags (NextOp);
836 break;
838 case AML_BUFFER_OP:
840 /* The next op is the size parameter */
842 NextOp = AcpiPsGetDepthNext (NULL, Op);
843 if (!NextOp)
845 /* Single-step support */
847 return (AE_OK);
850 if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
853 * We have a resource list. Don't need to output
854 * the buffer size Op. Open up a new block
856 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
857 NextOp = NextOp->Common.Next;
858 ASL_CV_CLOSE_PAREN (Op, Level);
860 /* Emit description comment for Name() with a predefined ACPI name */
862 AcpiDmPredefinedDescription (Op->Asl.Parent);
864 AcpiOsPrintf ("\n");
865 AcpiDmIndent (Info->Level);
866 AcpiOsPrintf ("{\n");
867 return (AE_OK);
870 /* Normal Buffer, mark size as in the parameter list */
872 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
873 return (AE_OK);
875 case AML_IF_OP:
876 case AML_VARIABLE_PACKAGE_OP:
877 case AML_WHILE_OP:
879 /* The next op is the size or predicate parameter */
881 NextOp = AcpiPsGetDepthNext (NULL, Op);
882 if (NextOp)
884 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
886 return (AE_OK);
888 case AML_PACKAGE_OP:
890 /* The next op is the size parameter */
892 NextOp = AcpiPsGetDepthNext (NULL, Op);
893 if (NextOp)
895 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
897 return (AE_OK);
899 case AML_MATCH_OP:
901 AcpiDmMatchOp (Op);
902 break;
904 default:
906 break;
909 if (AcpiDmBlockType (Op) & BLOCK_BRACE)
911 AcpiOsPrintf ("\n");
912 AcpiDmIndent (Level);
913 AcpiOsPrintf ("{\n");
917 return (AE_OK);
921 /*******************************************************************************
923 * FUNCTION: AcpiDmAscendingOp
925 * PARAMETERS: ASL_WALK_CALLBACK
927 * RETURN: Status
929 * DESCRIPTION: Second visitation of a parse object, during ascent of parse
930 * tree. Close out any parameter lists and complete the opcode.
932 ******************************************************************************/
934 static ACPI_STATUS
935 AcpiDmAscendingOp (
936 ACPI_PARSE_OBJECT *Op,
937 UINT32 Level,
938 void *Context)
940 ACPI_OP_WALK_INFO *Info = Context;
941 ACPI_PARSE_OBJECT *ParentOp;
944 /* Point the Op's filename pointer to the proper file */
946 if (Gbl_CaptureComments)
948 ASL_CV_LABEL_FILENODE (Op);
950 /* Switch the output of these files if necessary */
952 if (ASL_CV_FILE_HAS_SWITCHED (Op))
954 ASL_CV_SWITCH_FILES (Level, Op);
958 if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE ||
959 Op->Common.DisasmOpcode == ACPI_DASM_IGNORE_SINGLE)
961 /* Ignore this op -- it was handled elsewhere */
963 return (AE_OK);
966 if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
968 /* Indicates the end of the current descriptor block (table) */
970 ASL_CV_CLOSE_BRACE (Op, Level);
972 /* Print any comments that are at the end of the file here */
974 if (Gbl_CaptureComments && AcpiGbl_LastListHead)
976 AcpiOsPrintf ("\n");
977 ASL_CV_PRINT_ONE_COMMENT_LIST (AcpiGbl_LastListHead, 0);
979 AcpiOsPrintf ("\n\n");
981 return (AE_OK);
984 switch (AcpiDmBlockType (Op))
986 case BLOCK_PAREN:
988 /* Completed an op that has arguments, add closing paren if needed */
990 AcpiDmCloseOperator (Op);
992 if (Op->Common.AmlOpcode == AML_NAME_OP)
994 /* Emit description comment for Name() with a predefined ACPI name */
996 AcpiDmPredefinedDescription (Op);
998 else
1000 /* For Create* operators, attempt to emit resource tag description */
1002 AcpiDmFieldPredefinedDescription (Op);
1005 /* Decode Notify() values */
1007 if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
1009 AcpiDmNotifyDescription (Op);
1012 AcpiDmDisplayTargetPathname (Op);
1014 /* Could be a nested operator, check if comma required */
1016 if (!AcpiDmCommaIfListMember (Op))
1018 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1019 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
1020 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
1023 * This is a first-level element of a term list
1024 * start a new line
1026 if (!(Info->Flags & ACPI_PARSEOP_PARAMETER_LIST))
1028 AcpiOsPrintf ("\n");
1032 break;
1034 case BLOCK_BRACE:
1035 case (BLOCK_BRACE | BLOCK_PAREN):
1037 /* Completed an op that has a term list, add closing brace */
1039 if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
1041 ASL_CV_CLOSE_BRACE (Op, Level);
1043 else
1045 AcpiDmIndent (Level);
1046 ASL_CV_CLOSE_BRACE (Op, Level);
1049 AcpiDmCommaIfListMember (Op);
1051 if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
1053 AcpiOsPrintf ("\n");
1054 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
1056 if ((Op->Common.AmlOpcode == AML_IF_OP) &&
1057 (Op->Common.Next) &&
1058 (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
1060 break;
1063 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1064 (!Op->Common.Next))
1066 break;
1068 AcpiOsPrintf ("\n");
1071 break;
1073 case BLOCK_NONE:
1074 default:
1076 /* Could be a nested operator, check if comma required */
1078 if (!AcpiDmCommaIfListMember (Op))
1080 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1081 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
1082 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
1085 * This is a first-level element of a term list
1086 * start a new line
1088 AcpiOsPrintf ("\n");
1091 else if (Op->Common.Parent)
1093 switch (Op->Common.Parent->Common.AmlOpcode)
1095 case AML_PACKAGE_OP:
1096 case AML_VARIABLE_PACKAGE_OP:
1098 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST))
1100 AcpiOsPrintf ("\n");
1102 break;
1104 default:
1106 break;
1109 break;
1112 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)
1114 if ((Op->Common.Next) &&
1115 (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST))
1117 return (AE_OK);
1121 * The parent Op is guaranteed to be valid because of the flag
1122 * ACPI_PARSEOP_PARAMETER_LIST -- which means that this op is part of
1123 * a parameter list and thus has a valid parent.
1125 ParentOp = Op->Common.Parent;
1128 * Just completed a parameter node for something like "Buffer (param)".
1129 * Close the paren and open up the term list block with a brace.
1131 * Switch predicates don't have a Next node but require a closing paren
1132 * and opening brace.
1134 if (Op->Common.Next || Op->Common.DisasmOpcode == ACPI_DASM_SWITCH_PREDICATE)
1136 ASL_CV_CLOSE_PAREN (Op, Level);
1139 * Emit a description comment for a Name() operator that is a
1140 * predefined ACPI name. Must check the grandparent.
1142 ParentOp = ParentOp->Common.Parent;
1143 if (ParentOp &&
1144 (ParentOp->Asl.AmlOpcode == AML_NAME_OP))
1146 AcpiDmPredefinedDescription (ParentOp);
1149 /* Correct the indentation level for Switch and Case predicates */
1151 if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH_PREDICATE)
1153 --Level;
1156 AcpiOsPrintf ("\n");
1157 AcpiDmIndent (Level - 1);
1158 AcpiOsPrintf ("{\n");
1160 else
1162 ParentOp->Common.DisasmFlags |= ACPI_PARSEOP_EMPTY_TERMLIST;
1163 ASL_CV_CLOSE_PAREN (Op, Level);
1164 AcpiOsPrintf ("{");
1168 if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
1169 (Op->Common.AmlOpcode == AML_RETURN_OP))
1171 Info->Level++;
1175 * For ASL+, check for and emit a C-style symbol. If valid, the
1176 * symbol string has been deferred until after the first operand
1178 if (AcpiGbl_CstyleDisassembly)
1180 if (Op->Asl.OperatorSymbol)
1182 AcpiOsPrintf ("%s", Op->Asl.OperatorSymbol);
1183 Op->Asl.OperatorSymbol = NULL;
1187 return (AE_OK);
1190 #endif /* ACPI_DISASSEMBLER */