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>
51 #include <contrib/dev/acpica/include/acdebug.h>
53 #ifdef ACPI_DISASSEMBLER
55 #define _COMPONENT ACPI_CA_DEBUGGER
56 ACPI_MODULE_NAME ("dmopcode")
59 /* Local prototypes */
63 ACPI_PARSE_OBJECT *Op);
66 /*******************************************************************************
68 * FUNCTION: AcpiDmDisplayTargetPathname
70 * PARAMETERS: Op - Parse object
74 * DESCRIPTION: For AML opcodes that have a target operand, display the full
75 * pathname for the target, in a comment field. Handles Return()
78 ******************************************************************************/
81 AcpiDmDisplayTargetPathname (
82 ACPI_PARSE_OBJECT *Op)
84 ACPI_PARSE_OBJECT *NextOp;
85 ACPI_PARSE_OBJECT *PrevOp = NULL;
87 const ACPI_OPCODE_INFO *OpInfo;
90 if (Op->Common.AmlOpcode == AML_RETURN_OP)
92 PrevOp = Op->Asl.Value.Arg;
96 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
97 if (!(OpInfo->Flags & AML_HAS_TARGET))
102 /* Target is the last Op in the arg list */
104 NextOp = Op->Asl.Value.Arg;
108 NextOp = PrevOp->Asl.Next;
117 /* We must have a namepath AML opcode */
119 if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
124 /* A null string is the "no target specified" case */
126 if (!PrevOp->Asl.Value.String)
131 /* No node means "unresolved external reference" */
133 if (!PrevOp->Asl.Node)
135 AcpiOsPrintf (" /* External reference */");
139 /* Ignore if path is already from the root */
141 if (*PrevOp->Asl.Value.String == '\\')
146 /* Now: we can get the full pathname */
148 Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node);
154 AcpiOsPrintf (" /* %s */", Pathname);
155 ACPI_FREE (Pathname);
159 /*******************************************************************************
161 * FUNCTION: AcpiDmNotifyDescription
163 * PARAMETERS: Op - Name() parse object
167 * DESCRIPTION: Emit a description comment for the value associated with a
170 ******************************************************************************/
173 AcpiDmNotifyDescription (
174 ACPI_PARSE_OBJECT *Op)
176 ACPI_PARSE_OBJECT *NextOp;
177 ACPI_NAMESPACE_NODE *Node;
179 UINT8 Type = ACPI_TYPE_ANY;
182 /* The notify value is the second argument */
184 NextOp = Op->Asl.Value.Arg;
185 NextOp = NextOp->Asl.Next;
187 switch (NextOp->Common.AmlOpcode)
192 NotifyValue = (UINT8) NextOp->Common.AmlOpcode;
197 NotifyValue = (UINT8) NextOp->Asl.Value.Integer;
205 * Attempt to get the namespace node so we can determine the object type.
206 * Some notify values are dependent on the object type (Device, Thermal,
215 AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type));
219 /*******************************************************************************
221 * FUNCTION: AcpiDmPredefinedDescription
223 * PARAMETERS: Op - Name() parse object
227 * DESCRIPTION: Emit a description comment for a predefined ACPI name.
228 * Used for iASL compiler only.
230 ******************************************************************************/
233 AcpiDmPredefinedDescription (
234 ACPI_PARSE_OBJECT *Op)
236 #ifdef ACPI_ASL_COMPILER
237 const AH_PREDEFINED_NAME *Info;
248 /* Ensure that the comment field is emitted only once */
250 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEF_CHECKED)
254 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEF_CHECKED;
256 /* Predefined name must start with an underscore */
258 NameString = ACPI_CAST_PTR (char, &Op->Named.Name);
259 if (NameString[0] != '_')
265 * Check for the special ACPI names:
266 * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a
267 * (where d=decimal_digit, x=hex_digit, a=anything)
269 * Convert these to the generic name for table lookup.
270 * Note: NameString is guaranteed to be upper case here.
273 (isdigit ((int) NameString[3])); /* d */
275 (isxdigit ((int) NameString[2]) && /* xx */
276 isxdigit ((int) NameString[3]));
278 switch (NameString[1])
282 if ((NameString[2] == 'C') && (LastCharIsDigit))
286 else if ((NameString[2] == 'L') && (LastCharIsDigit))
294 if ((NameString[2] == 'J') && (LastCharIsDigit))
298 else if (LastCharsAreHex)
322 if (NameString[2] == '_')
341 /* Match the name in the info table */
343 Info = AcpiAhMatchPredefinedName (NameString);
346 AcpiOsPrintf (" // %4.4s: %s",
347 NameString, ACPI_CAST_PTR (char, Info->Description));
355 /*******************************************************************************
357 * FUNCTION: AcpiDmFieldPredefinedDescription
359 * PARAMETERS: Op - Parse object
363 * DESCRIPTION: Emit a description comment for a resource descriptor tag
364 * (which is a predefined ACPI name.) Used for iASL compiler only.
366 ******************************************************************************/
369 AcpiDmFieldPredefinedDescription (
370 ACPI_PARSE_OBJECT *Op)
372 #ifdef ACPI_ASL_COMPILER
373 ACPI_PARSE_OBJECT *IndexOp;
375 const ACPI_OPCODE_INFO *OpInfo;
376 const AH_PREDEFINED_NAME *Info;
384 /* Ensure that the comment field is emitted only once */
386 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEF_CHECKED)
390 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEF_CHECKED;
393 * Op must be one of the Create* operators: CreateField, CreateBitField,
394 * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField
396 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
397 if (!(OpInfo->Flags & AML_CREATE))
402 /* Second argument is the Index argument */
404 IndexOp = Op->Common.Value.Arg;
405 IndexOp = IndexOp->Common.Next;
407 /* Index argument must be a namepath */
409 if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
414 /* Major cheat: We previously put the Tag ptr in the Node field */
416 Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node);
422 /* Match the name in the info table */
424 Info = AcpiAhMatchPredefinedName (Tag);
427 AcpiOsPrintf (" // %4.4s: %s", Tag,
428 ACPI_CAST_PTR (char, Info->Description));
436 /*******************************************************************************
438 * FUNCTION: AcpiDmMethodFlags
440 * PARAMETERS: Op - Method Object to be examined
444 * DESCRIPTION: Decode control method flags
446 ******************************************************************************/
450 ACPI_PARSE_OBJECT *Op)
456 /* The next Op contains the flags */
458 Op = AcpiPsGetDepthNext (NULL, Op);
459 Flags = (UINT8) Op->Common.Value.Integer;
462 /* Mark the Op as completed */
464 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
466 /* 1) Method argument count */
468 AcpiOsPrintf (", %u, ", Args);
470 /* 2) Serialize rule */
474 AcpiOsPrintf ("Not");
477 AcpiOsPrintf ("Serialized");
483 AcpiOsPrintf (", %u", Flags >> 4);
488 /*******************************************************************************
490 * FUNCTION: AcpiDmFieldFlags
492 * PARAMETERS: Op - Field Object to be examined
496 * DESCRIPTION: Decode Field definition flags
498 ******************************************************************************/
502 ACPI_PARSE_OBJECT *Op)
507 Op = Op->Common.Next;
508 Flags = (UINT8) Op->Common.Value.Integer;
510 /* Mark the Op as completed */
512 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
514 AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
515 AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
516 AcpiOsPrintf ("%s)", AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
520 /*******************************************************************************
522 * FUNCTION: AcpiDmAddressSpace
524 * PARAMETERS: SpaceId - ID to be translated
528 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
530 ******************************************************************************/
537 if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
541 AcpiOsPrintf ("FFixedHW, ");
545 AcpiOsPrintf ("0x%.2X, ", SpaceId);
550 AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
555 /*******************************************************************************
557 * FUNCTION: AcpiDmRegionFlags
559 * PARAMETERS: Op - Object to be examined
563 * DESCRIPTION: Decode OperationRegion flags
565 ******************************************************************************/
569 ACPI_PARSE_OBJECT *Op)
572 /* The next Op contains the SpaceId */
574 Op = AcpiPsGetDepthNext (NULL, Op);
576 /* Mark the Op as completed */
578 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
581 AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
585 /*******************************************************************************
587 * FUNCTION: AcpiDmMatchOp
589 * PARAMETERS: Op - Match Object to be examined
593 * DESCRIPTION: Decode Match opcode operands
595 ******************************************************************************/
599 ACPI_PARSE_OBJECT *Op)
601 ACPI_PARSE_OBJECT *NextOp;
604 NextOp = AcpiPsGetDepthNext (NULL, Op);
605 NextOp = NextOp->Common.Next;
609 /* Handle partial tree during single-step */
614 /* Mark the two nodes that contain the encoding for the match keywords */
616 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
618 NextOp = NextOp->Common.Next;
619 NextOp = NextOp->Common.Next;
620 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
624 /*******************************************************************************
626 * FUNCTION: AcpiDmMatchKeyword
628 * PARAMETERS: Op - Match Object to be examined
632 * DESCRIPTION: Decode Match opcode operands
634 ******************************************************************************/
638 ACPI_PARSE_OBJECT *Op)
641 if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
643 AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
647 AcpiOsPrintf ("%s", ACPI_CAST_PTR (char,
648 AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]));
653 /*******************************************************************************
655 * FUNCTION: AcpiDmDisassembleOneOp
657 * PARAMETERS: WalkState - Current walk info
658 * Info - Parse tree walk info
659 * Op - Op that is to be printed
663 * DESCRIPTION: Disassemble a single AML opcode
665 ******************************************************************************/
668 AcpiDmDisassembleOneOp (
669 ACPI_WALK_STATE *WalkState,
670 ACPI_OP_WALK_INFO *Info,
671 ACPI_PARSE_OBJECT *Op)
673 const ACPI_OPCODE_INFO *OpInfo = NULL;
676 ACPI_PARSE_OBJECT *Child;
679 const AH_DEVICE_ID *IdInfo;
684 AcpiOsPrintf ("<NULL OP PTR>");
688 switch (Op->Common.DisasmOpcode)
690 case ACPI_DASM_MATCHOP:
692 AcpiDmMatchKeyword (Op);
695 case ACPI_DASM_LNOT_SUFFIX:
697 if (!AcpiGbl_CstyleDisassembly)
699 switch (Op->Common.AmlOpcode)
702 AcpiOsPrintf ("LNotEqual");
705 case AML_LGREATER_OP:
706 AcpiOsPrintf ("LLessEqual");
710 AcpiOsPrintf ("LGreaterEqual");
718 Op->Common.DisasmOpcode = 0;
719 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
726 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
728 /* The op and arguments */
730 switch (Op->Common.AmlOpcode)
734 Child = Op->Common.Value.Arg;
735 if ((Child->Common.AmlOpcode == AML_LEQUAL_OP) ||
736 (Child->Common.AmlOpcode == AML_LGREATER_OP) ||
737 (Child->Common.AmlOpcode == AML_LLESS_OP))
739 Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
740 Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
744 AcpiOsPrintf ("%s", OpInfo->Name);
750 AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
755 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
757 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
761 AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
767 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
769 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
773 AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
779 AcpiOsPrintf ("0x%8.8X%8.8X",
780 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
785 AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
787 /* For _HID/_CID strings, attempt to output a descriptive comment */
789 if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
791 /* If we know about the ID, emit the description */
793 IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
796 AcpiOsPrintf (" /* %s */", IdInfo->Description);
803 * Determine the type of buffer. We can have one of the following:
805 * 1) ResourceTemplate containing Resource Descriptors.
806 * 2) Unicode String buffer
807 * 3) ASCII String buffer
808 * 4) Raw data buffer (if none of the above)
810 * Since there are no special AML opcodes to differentiate these
811 * types of buffers, we have to closely look at the data in the
812 * buffer to determine the type.
814 if (!AcpiGbl_NoResourceDisassembly)
816 Status = AcpiDmIsResourceTemplate (WalkState, Op);
817 if (ACPI_SUCCESS (Status))
819 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
820 AcpiOsPrintf ("ResourceTemplate");
823 else if (Status == AE_AML_NO_RESOURCE_END_TAG)
825 AcpiOsPrintf ("/**** Is ResourceTemplate, but EndTag not at buffer end ****/ ");
829 if (AcpiDmIsUuidBuffer (Op))
831 Op->Common.DisasmOpcode = ACPI_DASM_UUID;
832 AcpiOsPrintf ("ToUUID (");
834 else if (AcpiDmIsUnicodeBuffer (Op))
836 Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
837 AcpiOsPrintf ("Unicode (");
839 else if (AcpiDmIsStringBuffer (Op))
841 Op->Common.DisasmOpcode = ACPI_DASM_STRING;
842 AcpiOsPrintf ("Buffer");
844 else if (AcpiDmIsPldBuffer (Op))
846 Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
847 AcpiOsPrintf ("ToPLD (");
851 Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
852 AcpiOsPrintf ("Buffer");
856 case AML_INT_NAMEPATH_OP:
858 AcpiDmNamestring (Op->Common.Value.Name);
861 case AML_INT_NAMEDFIELD_OP:
863 Length = AcpiDmDumpName (Op->Named.Name);
864 AcpiOsPrintf (",%*.s %u", (unsigned) (5 - Length), " ",
865 (UINT32) Op->Common.Value.Integer);
866 AcpiDmCommaIfFieldMember (Op);
868 Info->BitOffset += (UINT32) Op->Common.Value.Integer;
871 case AML_INT_RESERVEDFIELD_OP:
873 /* Offset() -- Must account for previous offsets */
875 Offset = (UINT32) Op->Common.Value.Integer;
876 Info->BitOffset += Offset;
878 if (Info->BitOffset % 8 == 0)
880 AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
884 AcpiOsPrintf (" , %u", Offset);
887 AcpiDmCommaIfFieldMember (Op);
890 case AML_INT_ACCESSFIELD_OP:
891 case AML_INT_EXTACCESSFIELD_OP:
893 AcpiOsPrintf ("AccessAs (%s, ",
894 AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
896 AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
898 if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
900 AcpiOsPrintf (" (0x%2.2X)", (unsigned) ((Op->Common.Value.Integer >> 16) & 0xFF));
904 AcpiDmCommaIfFieldMember (Op);
907 case AML_INT_CONNECTION_OP:
909 * Two types of Connection() - one with a buffer object, the
910 * other with a namestring that points to a buffer object.
912 AcpiOsPrintf ("Connection (");
913 Child = Op->Common.Value.Arg;
915 if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
919 Aml = Child->Named.Data;
920 Length = (UINT32) Child->Common.Value.Integer;
923 Info->MappingOp = Op;
924 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
926 AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
929 AcpiDmIndent (Info->Level);
933 AcpiDmNamestring (Child->Common.Value.Name);
937 AcpiDmCommaIfFieldMember (Op);
940 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
941 Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
944 case AML_INT_BYTELIST_OP:
946 AcpiDmByteList (Info, Op);
949 case AML_INT_METHODCALL_OP:
951 Op = AcpiPsGetDepthNext (NULL, Op);
952 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
954 AcpiDmNamestring (Op->Common.Value.Name);
959 /* Just get the opcode name and print it */
961 AcpiOsPrintf ("%s", OpInfo->Name);
966 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
968 (WalkState->Results) &&
969 (WalkState->ResultCount))
971 AcpiDbDecodeInternalObject (
972 WalkState->Results->Results.ObjDesc [
973 (WalkState->ResultCount - 1) %
974 ACPI_RESULTS_FRAME_OBJ_NUM]);
982 #endif /* ACPI_DISASSEMBLER */