1 /*******************************************************************************
3 * Module Name: dmopcode - AML disassembler, specific AML opcodes
5 ******************************************************************************/
8 * Copyright (C) 2000 - 2015, 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/acdisasm.h>
49 #include <contrib/dev/acpica/include/acinterp.h>
50 #include <contrib/dev/acpica/include/acnamesp.h>
52 #ifdef ACPI_DISASSEMBLER
54 #define _COMPONENT ACPI_CA_DEBUGGER
55 ACPI_MODULE_NAME ("dmopcode")
58 /* Local prototypes */
62 ACPI_PARSE_OBJECT *Op);
65 /*******************************************************************************
67 * FUNCTION: AcpiDmDisplayTargetPathname
69 * PARAMETERS: Op - Parse object
73 * DESCRIPTION: For AML opcodes that have a target operand, display the full
74 * pathname for the target, in a comment field. Handles Return()
77 ******************************************************************************/
80 AcpiDmDisplayTargetPathname (
81 ACPI_PARSE_OBJECT *Op)
83 ACPI_PARSE_OBJECT *NextOp;
84 ACPI_PARSE_OBJECT *PrevOp = NULL;
86 const ACPI_OPCODE_INFO *OpInfo;
89 if (Op->Common.AmlOpcode == AML_RETURN_OP)
91 PrevOp = Op->Asl.Value.Arg;
95 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
96 if (!(OpInfo->Flags & AML_HAS_TARGET))
101 /* Target is the last Op in the arg list */
103 NextOp = Op->Asl.Value.Arg;
107 NextOp = PrevOp->Asl.Next;
116 /* We must have a namepath AML opcode */
118 if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
123 /* A null string is the "no target specified" case */
125 if (!PrevOp->Asl.Value.String)
130 /* No node means "unresolved external reference" */
132 if (!PrevOp->Asl.Node)
134 AcpiOsPrintf (" /* External reference */");
138 /* Ignore if path is already from the root */
140 if (*PrevOp->Asl.Value.String == '\\')
145 /* Now: we can get the full pathname */
147 Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node);
153 AcpiOsPrintf (" /* %s */", Pathname);
154 ACPI_FREE (Pathname);
158 /*******************************************************************************
160 * FUNCTION: AcpiDmNotifyDescription
162 * PARAMETERS: Op - Name() parse object
166 * DESCRIPTION: Emit a description comment for the value associated with a
169 ******************************************************************************/
172 AcpiDmNotifyDescription (
173 ACPI_PARSE_OBJECT *Op)
175 ACPI_PARSE_OBJECT *NextOp;
176 ACPI_NAMESPACE_NODE *Node;
178 UINT8 Type = ACPI_TYPE_ANY;
181 /* The notify value is the second argument */
183 NextOp = Op->Asl.Value.Arg;
184 NextOp = NextOp->Asl.Next;
186 switch (NextOp->Common.AmlOpcode)
191 NotifyValue = (UINT8) NextOp->Common.AmlOpcode;
196 NotifyValue = (UINT8) NextOp->Asl.Value.Integer;
204 * Attempt to get the namespace node so we can determine the object type.
205 * Some notify values are dependent on the object type (Device, Thermal,
214 AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type));
218 /*******************************************************************************
220 * FUNCTION: AcpiDmPredefinedDescription
222 * PARAMETERS: Op - Name() parse object
226 * DESCRIPTION: Emit a description comment for a predefined ACPI name.
227 * Used for iASL compiler only.
229 ******************************************************************************/
232 AcpiDmPredefinedDescription (
233 ACPI_PARSE_OBJECT *Op)
235 #ifdef ACPI_ASL_COMPILER
236 const AH_PREDEFINED_NAME *Info;
247 /* Ensure that the comment field is emitted only once */
249 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEF_CHECKED)
253 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEF_CHECKED;
255 /* Predefined name must start with an underscore */
257 NameString = ACPI_CAST_PTR (char, &Op->Named.Name);
258 if (NameString[0] != '_')
264 * Check for the special ACPI names:
265 * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a
266 * (where d=decimal_digit, x=hex_digit, a=anything)
268 * Convert these to the generic name for table lookup.
269 * Note: NameString is guaranteed to be upper case here.
272 (ACPI_IS_DIGIT (NameString[3])); /* d */
274 (ACPI_IS_XDIGIT (NameString[2]) && /* xx */
275 ACPI_IS_XDIGIT (NameString[3]));
277 switch (NameString[1])
281 if ((NameString[2] == 'C') && (LastCharIsDigit))
285 else if ((NameString[2] == 'L') && (LastCharIsDigit))
293 if ((NameString[2] == 'J') && (LastCharIsDigit))
297 else if (LastCharsAreHex)
321 if (NameString[2] == '_')
340 /* Match the name in the info table */
342 Info = AcpiAhMatchPredefinedName (NameString);
345 AcpiOsPrintf (" // %4.4s: %s",
346 NameString, ACPI_CAST_PTR (char, Info->Description));
354 /*******************************************************************************
356 * FUNCTION: AcpiDmFieldPredefinedDescription
358 * PARAMETERS: Op - Parse object
362 * DESCRIPTION: Emit a description comment for a resource descriptor tag
363 * (which is a predefined ACPI name.) Used for iASL compiler only.
365 ******************************************************************************/
368 AcpiDmFieldPredefinedDescription (
369 ACPI_PARSE_OBJECT *Op)
371 #ifdef ACPI_ASL_COMPILER
372 ACPI_PARSE_OBJECT *IndexOp;
374 const ACPI_OPCODE_INFO *OpInfo;
375 const AH_PREDEFINED_NAME *Info;
383 /* Ensure that the comment field is emitted only once */
385 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEF_CHECKED)
389 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEF_CHECKED;
392 * Op must be one of the Create* operators: CreateField, CreateBitField,
393 * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField
395 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
396 if (!(OpInfo->Flags & AML_CREATE))
401 /* Second argument is the Index argument */
403 IndexOp = Op->Common.Value.Arg;
404 IndexOp = IndexOp->Common.Next;
406 /* Index argument must be a namepath */
408 if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
413 /* Major cheat: We previously put the Tag ptr in the Node field */
415 Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node);
421 /* Match the name in the info table */
423 Info = AcpiAhMatchPredefinedName (Tag);
426 AcpiOsPrintf (" // %4.4s: %s", Tag,
427 ACPI_CAST_PTR (char, Info->Description));
435 /*******************************************************************************
437 * FUNCTION: AcpiDmMethodFlags
439 * PARAMETERS: Op - Method Object to be examined
443 * DESCRIPTION: Decode control method flags
445 ******************************************************************************/
449 ACPI_PARSE_OBJECT *Op)
455 /* The next Op contains the flags */
457 Op = AcpiPsGetDepthNext (NULL, Op);
458 Flags = (UINT8) Op->Common.Value.Integer;
461 /* Mark the Op as completed */
463 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
465 /* 1) Method argument count */
467 AcpiOsPrintf (", %u, ", Args);
469 /* 2) Serialize rule */
473 AcpiOsPrintf ("Not");
476 AcpiOsPrintf ("Serialized");
482 AcpiOsPrintf (", %u", Flags >> 4);
487 /*******************************************************************************
489 * FUNCTION: AcpiDmFieldFlags
491 * PARAMETERS: Op - Field Object to be examined
495 * DESCRIPTION: Decode Field definition flags
497 ******************************************************************************/
501 ACPI_PARSE_OBJECT *Op)
506 Op = Op->Common.Next;
507 Flags = (UINT8) Op->Common.Value.Integer;
509 /* Mark the Op as completed */
511 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
513 AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
514 AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
515 AcpiOsPrintf ("%s)", AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
519 /*******************************************************************************
521 * FUNCTION: AcpiDmAddressSpace
523 * PARAMETERS: SpaceId - ID to be translated
527 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
529 ******************************************************************************/
536 if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
540 AcpiOsPrintf ("FFixedHW, ");
544 AcpiOsPrintf ("0x%.2X, ", SpaceId);
549 AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
554 /*******************************************************************************
556 * FUNCTION: AcpiDmRegionFlags
558 * PARAMETERS: Op - Object to be examined
562 * DESCRIPTION: Decode OperationRegion flags
564 ******************************************************************************/
568 ACPI_PARSE_OBJECT *Op)
571 /* The next Op contains the SpaceId */
573 Op = AcpiPsGetDepthNext (NULL, Op);
575 /* Mark the Op as completed */
577 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
580 AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
584 /*******************************************************************************
586 * FUNCTION: AcpiDmMatchOp
588 * PARAMETERS: Op - Match Object to be examined
592 * DESCRIPTION: Decode Match opcode operands
594 ******************************************************************************/
598 ACPI_PARSE_OBJECT *Op)
600 ACPI_PARSE_OBJECT *NextOp;
603 NextOp = AcpiPsGetDepthNext (NULL, Op);
604 NextOp = NextOp->Common.Next;
608 /* Handle partial tree during single-step */
613 /* Mark the two nodes that contain the encoding for the match keywords */
615 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
617 NextOp = NextOp->Common.Next;
618 NextOp = NextOp->Common.Next;
619 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
623 /*******************************************************************************
625 * FUNCTION: AcpiDmMatchKeyword
627 * PARAMETERS: Op - Match Object to be examined
631 * DESCRIPTION: Decode Match opcode operands
633 ******************************************************************************/
637 ACPI_PARSE_OBJECT *Op)
640 if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
642 AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
646 AcpiOsPrintf ("%s", ACPI_CAST_PTR (char,
647 AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]));
652 /*******************************************************************************
654 * FUNCTION: AcpiDmDisassembleOneOp
656 * PARAMETERS: WalkState - Current walk info
657 * Info - Parse tree walk info
658 * Op - Op that is to be printed
662 * DESCRIPTION: Disassemble a single AML opcode
664 ******************************************************************************/
667 AcpiDmDisassembleOneOp (
668 ACPI_WALK_STATE *WalkState,
669 ACPI_OP_WALK_INFO *Info,
670 ACPI_PARSE_OBJECT *Op)
672 const ACPI_OPCODE_INFO *OpInfo = NULL;
675 ACPI_PARSE_OBJECT *Child;
678 const AH_DEVICE_ID *IdInfo;
683 AcpiOsPrintf ("<NULL OP PTR>");
687 switch (Op->Common.DisasmOpcode)
689 case ACPI_DASM_MATCHOP:
691 AcpiDmMatchKeyword (Op);
694 case ACPI_DASM_LNOT_SUFFIX:
696 if (!AcpiGbl_CstyleDisassembly)
698 switch (Op->Common.AmlOpcode)
701 AcpiOsPrintf ("LNotEqual");
704 case AML_LGREATER_OP:
705 AcpiOsPrintf ("LLessEqual");
709 AcpiOsPrintf ("LGreaterEqual");
717 Op->Common.DisasmOpcode = 0;
718 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
725 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
727 /* The op and arguments */
729 switch (Op->Common.AmlOpcode)
733 Child = Op->Common.Value.Arg;
734 if ((Child->Common.AmlOpcode == AML_LEQUAL_OP) ||
735 (Child->Common.AmlOpcode == AML_LGREATER_OP) ||
736 (Child->Common.AmlOpcode == AML_LLESS_OP))
738 Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
739 Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
743 AcpiOsPrintf ("%s", OpInfo->Name);
749 AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
754 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
756 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
760 AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
766 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
768 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
772 AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
778 AcpiOsPrintf ("0x%8.8X%8.8X",
779 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
784 AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
786 /* For _HID/_CID strings, attempt to output a descriptive comment */
788 if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
790 /* If we know about the ID, emit the description */
792 IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
795 AcpiOsPrintf (" /* %s */", IdInfo->Description);
802 * Determine the type of buffer. We can have one of the following:
804 * 1) ResourceTemplate containing Resource Descriptors.
805 * 2) Unicode String buffer
806 * 3) ASCII String buffer
807 * 4) Raw data buffer (if none of the above)
809 * Since there are no special AML opcodes to differentiate these
810 * types of buffers, we have to closely look at the data in the
811 * buffer to determine the type.
813 if (!AcpiGbl_NoResourceDisassembly)
815 Status = AcpiDmIsResourceTemplate (WalkState, Op);
816 if (ACPI_SUCCESS (Status))
818 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
819 AcpiOsPrintf ("ResourceTemplate");
822 else if (Status == AE_AML_NO_RESOURCE_END_TAG)
824 AcpiOsPrintf ("/**** Is ResourceTemplate, but EndTag not at buffer end ****/ ");
828 if (AcpiDmIsUuidBuffer (Op))
830 Op->Common.DisasmOpcode = ACPI_DASM_UUID;
831 AcpiOsPrintf ("ToUUID (");
833 else if (AcpiDmIsUnicodeBuffer (Op))
835 Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
836 AcpiOsPrintf ("Unicode (");
838 else if (AcpiDmIsStringBuffer (Op))
840 Op->Common.DisasmOpcode = ACPI_DASM_STRING;
841 AcpiOsPrintf ("Buffer");
843 else if (AcpiDmIsPldBuffer (Op))
845 Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
846 AcpiOsPrintf ("ToPLD (");
850 Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
851 AcpiOsPrintf ("Buffer");
855 case AML_INT_NAMEPATH_OP:
857 AcpiDmNamestring (Op->Common.Value.Name);
860 case AML_INT_NAMEDFIELD_OP:
862 Length = AcpiDmDumpName (Op->Named.Name);
863 AcpiOsPrintf (",%*.s %u", (unsigned) (5 - Length), " ",
864 (UINT32) Op->Common.Value.Integer);
865 AcpiDmCommaIfFieldMember (Op);
867 Info->BitOffset += (UINT32) Op->Common.Value.Integer;
870 case AML_INT_RESERVEDFIELD_OP:
872 /* Offset() -- Must account for previous offsets */
874 Offset = (UINT32) Op->Common.Value.Integer;
875 Info->BitOffset += Offset;
877 if (Info->BitOffset % 8 == 0)
879 AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
883 AcpiOsPrintf (" , %u", Offset);
886 AcpiDmCommaIfFieldMember (Op);
889 case AML_INT_ACCESSFIELD_OP:
890 case AML_INT_EXTACCESSFIELD_OP:
892 AcpiOsPrintf ("AccessAs (%s, ",
893 AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
895 AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
897 if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
899 AcpiOsPrintf (" (0x%2.2X)", (unsigned) ((Op->Common.Value.Integer >> 16) & 0xFF));
903 AcpiDmCommaIfFieldMember (Op);
906 case AML_INT_CONNECTION_OP:
908 * Two types of Connection() - one with a buffer object, the
909 * other with a namestring that points to a buffer object.
911 AcpiOsPrintf ("Connection (");
912 Child = Op->Common.Value.Arg;
914 if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
918 Aml = Child->Named.Data;
919 Length = (UINT32) Child->Common.Value.Integer;
922 Info->MappingOp = Op;
923 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
925 AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
928 AcpiDmIndent (Info->Level);
932 AcpiDmNamestring (Child->Common.Value.Name);
936 AcpiDmCommaIfFieldMember (Op);
939 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
940 Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
943 case AML_INT_BYTELIST_OP:
945 AcpiDmByteList (Info, Op);
948 case AML_INT_METHODCALL_OP:
950 Op = AcpiPsGetDepthNext (NULL, Op);
951 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
953 AcpiDmNamestring (Op->Common.Value.Name);
958 /* Just get the opcode name and print it */
960 AcpiOsPrintf ("%s", OpInfo->Name);
965 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
967 (WalkState->Results) &&
968 (WalkState->ResultCount))
970 AcpiDmDecodeInternalObject (
971 WalkState->Results->Results.ObjDesc [
972 (WalkState->ResultCount - 1) %
973 ACPI_RESULTS_FRAME_OBJ_NUM]);
981 #endif /* ACPI_DISASSEMBLER */