1 /*******************************************************************************
3 * Module Name: dmopcode - AML disassembler, specific AML opcodes
5 ******************************************************************************/
8 * Copyright (C) 2000 - 2016, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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 <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/acparser.h>
47 #include <contrib/dev/acpica/include/amlcode.h>
48 #include <contrib/dev/acpica/include/acinterp.h>
49 #include <contrib/dev/acpica/include/acnamesp.h>
50 #include <contrib/dev/acpica/include/acdebug.h>
53 #define _COMPONENT ACPI_CA_DEBUGGER
54 ACPI_MODULE_NAME ("dmopcode")
57 /* Local prototypes */
61 ACPI_PARSE_OBJECT *Op);
64 AcpiDmConvertToElseIf (
65 ACPI_PARSE_OBJECT *Op);
68 AcpiDmPromoteSubtree (
69 ACPI_PARSE_OBJECT *StartOp);
72 /*******************************************************************************
74 * FUNCTION: AcpiDmDisplayTargetPathname
76 * PARAMETERS: Op - Parse object
80 * DESCRIPTION: For AML opcodes that have a target operand, display the full
81 * pathname for the target, in a comment field. Handles Return()
84 ******************************************************************************/
87 AcpiDmDisplayTargetPathname (
88 ACPI_PARSE_OBJECT *Op)
90 ACPI_PARSE_OBJECT *NextOp;
91 ACPI_PARSE_OBJECT *PrevOp = NULL;
93 const ACPI_OPCODE_INFO *OpInfo;
96 if (Op->Common.AmlOpcode == AML_RETURN_OP)
98 PrevOp = Op->Asl.Value.Arg;
102 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
103 if (!(OpInfo->Flags & AML_HAS_TARGET))
108 /* Target is the last Op in the arg list */
110 NextOp = Op->Asl.Value.Arg;
114 NextOp = PrevOp->Asl.Next;
123 /* We must have a namepath AML opcode */
125 if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
130 /* A null string is the "no target specified" case */
132 if (!PrevOp->Asl.Value.String)
137 /* No node means "unresolved external reference" */
139 if (!PrevOp->Asl.Node)
141 AcpiOsPrintf (" /* External reference */");
145 /* Ignore if path is already from the root */
147 if (*PrevOp->Asl.Value.String == '\\')
152 /* Now: we can get the full pathname */
154 Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node);
160 AcpiOsPrintf (" /* %s */", Pathname);
161 ACPI_FREE (Pathname);
165 /*******************************************************************************
167 * FUNCTION: AcpiDmNotifyDescription
169 * PARAMETERS: Op - Name() parse object
173 * DESCRIPTION: Emit a description comment for the value associated with a
176 ******************************************************************************/
179 AcpiDmNotifyDescription (
180 ACPI_PARSE_OBJECT *Op)
182 ACPI_PARSE_OBJECT *NextOp;
183 ACPI_NAMESPACE_NODE *Node;
185 UINT8 Type = ACPI_TYPE_ANY;
188 /* The notify value is the second argument */
190 NextOp = Op->Asl.Value.Arg;
191 NextOp = NextOp->Asl.Next;
193 switch (NextOp->Common.AmlOpcode)
198 NotifyValue = (UINT8) NextOp->Common.AmlOpcode;
203 NotifyValue = (UINT8) NextOp->Asl.Value.Integer;
211 * Attempt to get the namespace node so we can determine the object type.
212 * Some notify values are dependent on the object type (Device, Thermal,
221 AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type));
225 /*******************************************************************************
227 * FUNCTION: AcpiDmPredefinedDescription
229 * PARAMETERS: Op - Name() parse object
233 * DESCRIPTION: Emit a description comment for a predefined ACPI name.
234 * Used for iASL compiler only.
236 ******************************************************************************/
239 AcpiDmPredefinedDescription (
240 ACPI_PARSE_OBJECT *Op)
242 #ifdef ACPI_ASL_COMPILER
243 const AH_PREDEFINED_NAME *Info;
254 /* Ensure that the comment field is emitted only once */
256 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
260 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
262 /* Predefined name must start with an underscore */
264 NameString = ACPI_CAST_PTR (char, &Op->Named.Name);
265 if (NameString[0] != '_')
271 * Check for the special ACPI names:
272 * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a
273 * (where d=decimal_digit, x=hex_digit, a=anything)
275 * Convert these to the generic name for table lookup.
276 * Note: NameString is guaranteed to be upper case here.
279 (isdigit ((int) NameString[3])); /* d */
281 (isxdigit ((int) NameString[2]) && /* xx */
282 isxdigit ((int) NameString[3]));
284 switch (NameString[1])
288 if ((NameString[2] == 'C') && (LastCharIsDigit))
292 else if ((NameString[2] == 'L') && (LastCharIsDigit))
300 if ((NameString[2] == 'J') && (LastCharIsDigit))
304 else if (LastCharsAreHex)
328 if (NameString[2] == '_')
347 /* Match the name in the info table */
349 Info = AcpiAhMatchPredefinedName (NameString);
352 AcpiOsPrintf (" // %4.4s: %s",
353 NameString, ACPI_CAST_PTR (char, Info->Description));
361 /*******************************************************************************
363 * FUNCTION: AcpiDmFieldPredefinedDescription
365 * PARAMETERS: Op - Parse object
369 * DESCRIPTION: Emit a description comment for a resource descriptor tag
370 * (which is a predefined ACPI name.) Used for iASL compiler only.
372 ******************************************************************************/
375 AcpiDmFieldPredefinedDescription (
376 ACPI_PARSE_OBJECT *Op)
378 #ifdef ACPI_ASL_COMPILER
379 ACPI_PARSE_OBJECT *IndexOp;
381 const ACPI_OPCODE_INFO *OpInfo;
382 const AH_PREDEFINED_NAME *Info;
390 /* Ensure that the comment field is emitted only once */
392 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
396 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
399 * Op must be one of the Create* operators: CreateField, CreateBitField,
400 * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField
402 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
403 if (!(OpInfo->Flags & AML_CREATE))
408 /* Second argument is the Index argument */
410 IndexOp = Op->Common.Value.Arg;
411 IndexOp = IndexOp->Common.Next;
413 /* Index argument must be a namepath */
415 if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
420 /* Major cheat: We previously put the Tag ptr in the Node field */
422 Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node);
428 /* Match the name in the info table */
430 Info = AcpiAhMatchPredefinedName (Tag);
433 AcpiOsPrintf (" // %4.4s: %s", Tag,
434 ACPI_CAST_PTR (char, Info->Description));
442 /*******************************************************************************
444 * FUNCTION: AcpiDmMethodFlags
446 * PARAMETERS: Op - Method Object to be examined
450 * DESCRIPTION: Decode control method flags
452 ******************************************************************************/
456 ACPI_PARSE_OBJECT *Op)
462 /* The next Op contains the flags */
464 Op = AcpiPsGetDepthNext (NULL, Op);
465 Flags = (UINT8) Op->Common.Value.Integer;
468 /* Mark the Op as completed */
470 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
472 /* 1) Method argument count */
474 AcpiOsPrintf (", %u, ", Args);
476 /* 2) Serialize rule */
480 AcpiOsPrintf ("Not");
483 AcpiOsPrintf ("Serialized");
489 AcpiOsPrintf (", %u", Flags >> 4);
494 /*******************************************************************************
496 * FUNCTION: AcpiDmFieldFlags
498 * PARAMETERS: Op - Field Object to be examined
502 * DESCRIPTION: Decode Field definition flags
504 ******************************************************************************/
508 ACPI_PARSE_OBJECT *Op)
513 Op = Op->Common.Next;
514 Flags = (UINT8) Op->Common.Value.Integer;
516 /* Mark the Op as completed */
518 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
520 AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
521 AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
522 AcpiOsPrintf ("%s)", AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
526 /*******************************************************************************
528 * FUNCTION: AcpiDmAddressSpace
530 * PARAMETERS: SpaceId - ID to be translated
534 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
536 ******************************************************************************/
543 if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
547 AcpiOsPrintf ("FFixedHW, ");
551 AcpiOsPrintf ("0x%.2X, ", SpaceId);
556 AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
561 /*******************************************************************************
563 * FUNCTION: AcpiDmRegionFlags
565 * PARAMETERS: Op - Object to be examined
569 * DESCRIPTION: Decode OperationRegion flags
571 ******************************************************************************/
575 ACPI_PARSE_OBJECT *Op)
578 /* The next Op contains the SpaceId */
580 Op = AcpiPsGetDepthNext (NULL, Op);
582 /* Mark the Op as completed */
584 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
587 AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
591 /*******************************************************************************
593 * FUNCTION: AcpiDmMatchOp
595 * PARAMETERS: Op - Match Object to be examined
599 * DESCRIPTION: Decode Match opcode operands
601 ******************************************************************************/
605 ACPI_PARSE_OBJECT *Op)
607 ACPI_PARSE_OBJECT *NextOp;
610 NextOp = AcpiPsGetDepthNext (NULL, Op);
611 NextOp = NextOp->Common.Next;
615 /* Handle partial tree during single-step */
620 /* Mark the two nodes that contain the encoding for the match keywords */
622 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
624 NextOp = NextOp->Common.Next;
625 NextOp = NextOp->Common.Next;
626 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
630 /*******************************************************************************
632 * FUNCTION: AcpiDmMatchKeyword
634 * PARAMETERS: Op - Match Object to be examined
638 * DESCRIPTION: Decode Match opcode operands
640 ******************************************************************************/
644 ACPI_PARSE_OBJECT *Op)
647 if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
649 AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
654 AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]);
659 /*******************************************************************************
661 * FUNCTION: AcpiDmDisassembleOneOp
663 * PARAMETERS: WalkState - Current walk info
664 * Info - Parse tree walk info
665 * Op - Op that is to be printed
669 * DESCRIPTION: Disassemble a single AML opcode
671 ******************************************************************************/
674 AcpiDmDisassembleOneOp (
675 ACPI_WALK_STATE *WalkState,
676 ACPI_OP_WALK_INFO *Info,
677 ACPI_PARSE_OBJECT *Op)
679 const ACPI_OPCODE_INFO *OpInfo = NULL;
682 ACPI_PARSE_OBJECT *Child;
685 const AH_DEVICE_ID *IdInfo;
690 AcpiOsPrintf ("<NULL OP PTR>");
694 if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)
696 return; /* ElseIf macro was already emitted */
699 switch (Op->Common.DisasmOpcode)
701 case ACPI_DASM_MATCHOP:
703 AcpiDmMatchKeyword (Op);
706 case ACPI_DASM_LNOT_SUFFIX:
708 if (!AcpiGbl_CstyleDisassembly)
710 switch (Op->Common.AmlOpcode)
713 AcpiOsPrintf ("LNotEqual");
716 case AML_LGREATER_OP:
717 AcpiOsPrintf ("LLessEqual");
721 AcpiOsPrintf ("LGreaterEqual");
729 Op->Common.DisasmOpcode = 0;
730 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
737 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
739 /* The op and arguments */
741 switch (Op->Common.AmlOpcode)
745 Child = Op->Common.Value.Arg;
746 if ((Child->Common.AmlOpcode == AML_LEQUAL_OP) ||
747 (Child->Common.AmlOpcode == AML_LGREATER_OP) ||
748 (Child->Common.AmlOpcode == AML_LLESS_OP))
750 Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
751 Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
755 AcpiOsPrintf ("%s", OpInfo->Name);
761 AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
766 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
768 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
772 AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
778 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
780 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
784 AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
790 AcpiOsPrintf ("0x%8.8X%8.8X",
791 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
796 AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
798 /* For _HID/_CID strings, attempt to output a descriptive comment */
800 if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
802 /* If we know about the ID, emit the description */
804 IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
807 AcpiOsPrintf (" /* %s */", IdInfo->Description);
814 * Determine the type of buffer. We can have one of the following:
816 * 1) ResourceTemplate containing Resource Descriptors.
817 * 2) Unicode String buffer
818 * 3) ASCII String buffer
819 * 4) Raw data buffer (if none of the above)
821 * Since there are no special AML opcodes to differentiate these
822 * types of buffers, we have to closely look at the data in the
823 * buffer to determine the type.
825 if (!AcpiGbl_NoResourceDisassembly)
827 Status = AcpiDmIsResourceTemplate (WalkState, Op);
828 if (ACPI_SUCCESS (Status))
830 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
831 AcpiOsPrintf ("ResourceTemplate");
834 else if (Status == AE_AML_NO_RESOURCE_END_TAG)
837 "/**** Is ResourceTemplate, "
838 "but EndTag not at buffer end ****/ ");
842 if (AcpiDmIsUuidBuffer (Op))
844 Op->Common.DisasmOpcode = ACPI_DASM_UUID;
845 AcpiOsPrintf ("ToUUID (");
847 else if (AcpiDmIsUnicodeBuffer (Op))
849 Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
850 AcpiOsPrintf ("Unicode (");
852 else if (AcpiDmIsStringBuffer (Op))
854 Op->Common.DisasmOpcode = ACPI_DASM_STRING;
855 AcpiOsPrintf ("Buffer");
857 else if (AcpiDmIsPldBuffer (Op))
859 Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
860 AcpiOsPrintf ("ToPLD (");
864 Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
865 AcpiOsPrintf ("Buffer");
869 case AML_INT_NAMEPATH_OP:
871 AcpiDmNamestring (Op->Common.Value.Name);
874 case AML_INT_NAMEDFIELD_OP:
876 Length = AcpiDmDumpName (Op->Named.Name);
877 AcpiOsPrintf (",%*.s %u", (unsigned) (5 - Length), " ",
878 (UINT32) Op->Common.Value.Integer);
879 AcpiDmCommaIfFieldMember (Op);
881 Info->BitOffset += (UINT32) Op->Common.Value.Integer;
884 case AML_INT_RESERVEDFIELD_OP:
886 /* Offset() -- Must account for previous offsets */
888 Offset = (UINT32) Op->Common.Value.Integer;
889 Info->BitOffset += Offset;
891 if (Info->BitOffset % 8 == 0)
893 AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
897 AcpiOsPrintf (" , %u", Offset);
900 AcpiDmCommaIfFieldMember (Op);
903 case AML_INT_ACCESSFIELD_OP:
904 case AML_INT_EXTACCESSFIELD_OP:
906 AcpiOsPrintf ("AccessAs (%s, ",
907 AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
909 AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
911 if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
913 AcpiOsPrintf (" (0x%2.2X)", (unsigned)
914 ((Op->Common.Value.Integer >> 16) & 0xFF));
918 AcpiDmCommaIfFieldMember (Op);
921 case AML_INT_CONNECTION_OP:
923 * Two types of Connection() - one with a buffer object, the
924 * other with a namestring that points to a buffer object.
926 AcpiOsPrintf ("Connection (");
927 Child = Op->Common.Value.Arg;
929 if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
933 Aml = Child->Named.Data;
934 Length = (UINT32) Child->Common.Value.Integer;
937 Info->MappingOp = Op;
938 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
940 AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
943 AcpiDmIndent (Info->Level);
947 AcpiDmNamestring (Child->Common.Value.Name);
951 AcpiDmCommaIfFieldMember (Op);
954 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
955 Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
958 case AML_INT_BYTELIST_OP:
960 AcpiDmByteList (Info, Op);
963 case AML_INT_METHODCALL_OP:
965 Op = AcpiPsGetDepthNext (NULL, Op);
966 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
968 AcpiDmNamestring (Op->Common.Value.Name);
973 AcpiDmConvertToElseIf (Op);
976 case AML_EXTERNAL_OP:
978 if (AcpiGbl_DmEmitExternalOpcodes)
980 AcpiOsPrintf ("/* Opcode 0x15 */ ");
991 /* Just get the opcode name and print it */
993 AcpiOsPrintf ("%s", OpInfo->Name);
998 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
1000 (WalkState->Results) &&
1001 (WalkState->ResultCount))
1003 AcpiDbDecodeInternalObject (
1004 WalkState->Results->Results.ObjDesc [
1005 (WalkState->ResultCount - 1) %
1006 ACPI_RESULTS_FRAME_OBJ_NUM]);
1015 /*******************************************************************************
1017 * FUNCTION: AcpiDmConvertToElseIf
1019 * PARAMETERS: OriginalElseOp - ELSE Object to be examined
1021 * RETURN: None. Emits either an "Else" or an "ElseIf" ASL operator.
1023 * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
1027 * This If..Else..If nested sequence:
1041 * Is converted to this simpler If..ElseIf sequence:
1047 * ElseIf (Arg0 == 2)
1052 * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
1053 * macro that emits an Else opcode followed by an If opcode. This function
1054 * reverses these AML sequences back to an ElseIf macro where possible. This
1055 * can make the disassembled ASL code simpler and more like the original code.
1057 ******************************************************************************/
1060 AcpiDmConvertToElseIf (
1061 ACPI_PARSE_OBJECT *OriginalElseOp)
1063 ACPI_PARSE_OBJECT *IfOp;
1064 ACPI_PARSE_OBJECT *ElseOp;
1068 * To be able to perform the conversion, two conditions must be satisfied:
1069 * 1) The first child of the Else must be an If statement.
1070 * 2) The If block can only be followed by an Else block and these must
1071 * be the only blocks under the original Else.
1073 IfOp = OriginalElseOp->Common.Value.Arg;
1076 (IfOp->Common.AmlOpcode != AML_IF_OP) ||
1077 (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP)))
1079 /* Not a proper Else..If sequence, cannot convert to ElseIf */
1081 AcpiOsPrintf ("%s", "Else");
1085 /* Cannot have anything following the If...Else block */
1087 ElseOp = IfOp->Common.Next;
1088 if (ElseOp && ElseOp->Common.Next)
1090 AcpiOsPrintf ("%s", "Else");
1094 /* Emit ElseIf, mark the IF as now an ELSEIF */
1096 AcpiOsPrintf ("%s", "ElseIf");
1097 IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF;
1099 /* The IF parent will now be the same as the original ELSE parent */
1101 IfOp->Common.Parent = OriginalElseOp->Common.Parent;
1104 * Update the NEXT pointers to restructure the parse tree, essentially
1105 * promoting an If..Else block up to the same level as the original
1108 * Check if the IF has a corresponding ELSE peer
1110 ElseOp = IfOp->Common.Next;
1112 (ElseOp->Common.AmlOpcode == AML_ELSE_OP))
1114 /* If an ELSE matches the IF, promote it also */
1116 ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
1118 /* Promote the entire block under the ElseIf (All Next OPs) */
1120 AcpiDmPromoteSubtree (OriginalElseOp);
1124 /* Otherwise, set the IF NEXT to the original ELSE NEXT */
1126 IfOp->Common.Next = OriginalElseOp->Common.Next;
1129 /* Detach the child IF block from the original ELSE */
1131 OriginalElseOp->Common.Value.Arg = NULL;
1133 /* Ignore the original ELSE from now on */
1135 OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1136 OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
1138 /* Insert IF (now ELSEIF) as next peer of the original ELSE */
1140 OriginalElseOp->Common.Next = IfOp;
1144 /*******************************************************************************
1146 * FUNCTION: AcpiDmPromoteSubtree
1148 * PARAMETERS: StartOpOp - Original parent of the entire subtree
1152 * DESCRIPTION: Promote an entire parse subtree up one level.
1154 ******************************************************************************/
1157 AcpiDmPromoteSubtree (
1158 ACPI_PARSE_OBJECT *StartOp)
1160 ACPI_PARSE_OBJECT *Op;
1161 ACPI_PARSE_OBJECT *ParentOp;
1164 /* New parent for subtree elements */
1166 ParentOp = StartOp->Common.Parent;
1168 /* First child starts the subtree */
1170 Op = StartOp->Common.Value.Arg;
1172 /* Walk the top-level elements of the subtree */
1176 Op->Common.Parent = ParentOp;
1177 if (!Op->Common.Next)
1179 /* Last Op in list, update its next field */
1181 Op->Common.Next = StartOp->Common.Next;
1184 Op = Op->Common.Next;