1 /*******************************************************************************
3 * Module Name: dmopcode - AML disassembler, specific AML opcodes
5 ******************************************************************************/
8 * Copyright (C) 2000 - 2014, 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.
52 #ifdef ACPI_DISASSEMBLER
54 #define _COMPONENT ACPI_CA_DEBUGGER
55 ACPI_MODULE_NAME ("dmopcode")
57 /* Local prototypes */
61 ACPI_PARSE_OBJECT *Op);
64 /*******************************************************************************
66 * FUNCTION: AcpiDmDisplayTargetPathname
68 * PARAMETERS: Op - Parse object
72 * DESCRIPTION: For AML opcodes that have a target operand, display the full
73 * pathname for the target, in a comment field. Handles Return()
76 ******************************************************************************/
79 AcpiDmDisplayTargetPathname (
80 ACPI_PARSE_OBJECT *Op)
82 ACPI_PARSE_OBJECT *NextOp;
83 ACPI_PARSE_OBJECT *PrevOp = NULL;
85 const ACPI_OPCODE_INFO *OpInfo;
88 if (Op->Common.AmlOpcode == AML_RETURN_OP)
90 PrevOp = Op->Asl.Value.Arg;
94 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
95 if (!(OpInfo->Flags & AML_HAS_TARGET))
100 /* Target is the last Op in the arg list */
102 NextOp = Op->Asl.Value.Arg;
106 NextOp = PrevOp->Asl.Next;
115 /* We must have a namepath AML opcode */
117 if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
122 /* A null string is the "no target specified" case */
124 if (!PrevOp->Asl.Value.String)
129 /* No node means "unresolved external reference" */
131 if (!PrevOp->Asl.Node)
133 AcpiOsPrintf (" /* External reference */");
137 /* Ignore if path is already from the root */
139 if (*PrevOp->Asl.Value.String == '\\')
144 /* Now: we can get the full pathname */
146 Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node);
152 AcpiOsPrintf (" /* %s */", Pathname);
153 ACPI_FREE (Pathname);
157 /*******************************************************************************
159 * FUNCTION: AcpiDmNotifyDescription
161 * PARAMETERS: Op - Name() parse object
165 * DESCRIPTION: Emit a description comment for the value associated with a
168 ******************************************************************************/
171 AcpiDmNotifyDescription (
172 ACPI_PARSE_OBJECT *Op)
174 ACPI_PARSE_OBJECT *NextOp;
175 ACPI_NAMESPACE_NODE *Node;
177 UINT8 Type = ACPI_TYPE_ANY;
180 /* The notify value is the second argument */
182 NextOp = Op->Asl.Value.Arg;
183 NextOp = NextOp->Asl.Next;
185 switch (NextOp->Common.AmlOpcode)
190 NotifyValue = (UINT8) NextOp->Common.AmlOpcode;
195 NotifyValue = (UINT8) NextOp->Asl.Value.Integer;
203 * Attempt to get the namespace node so we can determine the object type.
204 * Some notify values are dependent on the object type (Device, Thermal,
213 AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type));
217 /*******************************************************************************
219 * FUNCTION: AcpiDmPredefinedDescription
221 * PARAMETERS: Op - Name() parse object
225 * DESCRIPTION: Emit a description comment for a predefined ACPI name.
226 * Used for iASL compiler only.
228 ******************************************************************************/
231 AcpiDmPredefinedDescription (
232 ACPI_PARSE_OBJECT *Op)
234 #ifdef ACPI_ASL_COMPILER
235 const AH_PREDEFINED_NAME *Info;
246 /* Ensure that the comment field is emitted only once */
248 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEF_CHECKED)
252 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEF_CHECKED;
254 /* Predefined name must start with an underscore */
256 NameString = ACPI_CAST_PTR (char, &Op->Named.Name);
257 if (NameString[0] != '_')
263 * Check for the special ACPI names:
264 * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a
265 * (where d=decimal_digit, x=hex_digit, a=anything)
267 * Convert these to the generic name for table lookup.
268 * Note: NameString is guaranteed to be upper case here.
271 (ACPI_IS_DIGIT (NameString[3])); /* d */
273 (ACPI_IS_XDIGIT (NameString[2]) && /* xx */
274 ACPI_IS_XDIGIT (NameString[3]));
276 switch (NameString[1])
280 if ((NameString[2] == 'C') && (LastCharIsDigit))
284 else if ((NameString[2] == 'L') && (LastCharIsDigit))
292 if ((NameString[2] == 'J') && (LastCharIsDigit))
296 else if (LastCharsAreHex)
320 if (NameString[2] == '_')
339 /* Match the name in the info table */
341 Info = AcpiAhMatchPredefinedName (NameString);
344 AcpiOsPrintf (" // %4.4s: %s",
345 NameString, ACPI_CAST_PTR (char, Info->Description));
353 /*******************************************************************************
355 * FUNCTION: AcpiDmFieldPredefinedDescription
357 * PARAMETERS: Op - Parse object
361 * DESCRIPTION: Emit a description comment for a resource descriptor tag
362 * (which is a predefined ACPI name.) Used for iASL compiler only.
364 ******************************************************************************/
367 AcpiDmFieldPredefinedDescription (
368 ACPI_PARSE_OBJECT *Op)
370 #ifdef ACPI_ASL_COMPILER
371 ACPI_PARSE_OBJECT *IndexOp;
373 const ACPI_OPCODE_INFO *OpInfo;
374 const AH_PREDEFINED_NAME *Info;
382 /* Ensure that the comment field is emitted only once */
384 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEF_CHECKED)
388 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEF_CHECKED;
391 * Op must be one of the Create* operators: CreateField, CreateBitField,
392 * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField
394 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
395 if (!(OpInfo->Flags & AML_CREATE))
400 /* Second argument is the Index argument */
402 IndexOp = Op->Common.Value.Arg;
403 IndexOp = IndexOp->Common.Next;
405 /* Index argument must be a namepath */
407 if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
412 /* Major cheat: We previously put the Tag ptr in the Node field */
414 Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node);
420 /* Match the name in the info table */
422 Info = AcpiAhMatchPredefinedName (Tag);
425 AcpiOsPrintf (" // %4.4s: %s", Tag,
426 ACPI_CAST_PTR (char, Info->Description));
434 /*******************************************************************************
436 * FUNCTION: AcpiDmMethodFlags
438 * PARAMETERS: Op - Method Object to be examined
442 * DESCRIPTION: Decode control method flags
444 ******************************************************************************/
448 ACPI_PARSE_OBJECT *Op)
454 /* The next Op contains the flags */
456 Op = AcpiPsGetDepthNext (NULL, Op);
457 Flags = (UINT8) Op->Common.Value.Integer;
460 /* Mark the Op as completed */
462 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
464 /* 1) Method argument count */
466 AcpiOsPrintf (", %u, ", Args);
468 /* 2) Serialize rule */
472 AcpiOsPrintf ("Not");
475 AcpiOsPrintf ("Serialized");
481 AcpiOsPrintf (", %u", Flags >> 4);
486 /*******************************************************************************
488 * FUNCTION: AcpiDmFieldFlags
490 * PARAMETERS: Op - Field Object to be examined
494 * DESCRIPTION: Decode Field definition flags
496 ******************************************************************************/
500 ACPI_PARSE_OBJECT *Op)
505 Op = Op->Common.Next;
506 Flags = (UINT8) Op->Common.Value.Integer;
508 /* Mark the Op as completed */
510 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
512 AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
513 AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
514 AcpiOsPrintf ("%s)", AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
518 /*******************************************************************************
520 * FUNCTION: AcpiDmAddressSpace
522 * PARAMETERS: SpaceId - ID to be translated
526 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
528 ******************************************************************************/
535 if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
539 AcpiOsPrintf ("FFixedHW, ");
543 AcpiOsPrintf ("0x%.2X, ", SpaceId);
548 AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
553 /*******************************************************************************
555 * FUNCTION: AcpiDmRegionFlags
557 * PARAMETERS: Op - Object to be examined
561 * DESCRIPTION: Decode OperationRegion flags
563 ******************************************************************************/
567 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)
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 switch (Op->Common.AmlOpcode)
701 AcpiOsPrintf ("LNotEqual");
704 case AML_LGREATER_OP:
706 AcpiOsPrintf ("LLessEqual");
711 AcpiOsPrintf ("LGreaterEqual");
718 Op->Common.DisasmOpcode = 0;
719 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
727 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
729 /* The op and arguments */
731 switch (Op->Common.AmlOpcode)
735 Child = Op->Common.Value.Arg;
736 if ((Child->Common.AmlOpcode == AML_LEQUAL_OP) ||
737 (Child->Common.AmlOpcode == AML_LGREATER_OP) ||
738 (Child->Common.AmlOpcode == AML_LLESS_OP))
740 Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
741 Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
745 AcpiOsPrintf ("%s", OpInfo->Name);
751 AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
756 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
758 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
762 AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
768 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
770 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
774 AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
780 AcpiOsPrintf ("0x%8.8X%8.8X",
781 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
786 AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
788 /* For _HID/_CID strings, attempt to output a descriptive comment */
790 if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
792 /* If we know about the ID, emit the description */
794 IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
797 AcpiOsPrintf (" /* %s */", IdInfo->Description);
804 * Determine the type of buffer. We can have one of the following:
806 * 1) ResourceTemplate containing Resource Descriptors.
807 * 2) Unicode String buffer
808 * 3) ASCII String buffer
809 * 4) Raw data buffer (if none of the above)
811 * Since there are no special AML opcodes to differentiate these
812 * types of buffers, we have to closely look at the data in the
813 * buffer to determine the type.
815 if (!AcpiGbl_NoResourceDisassembly)
817 Status = AcpiDmIsResourceTemplate (WalkState, Op);
818 if (ACPI_SUCCESS (Status))
820 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
821 AcpiOsPrintf ("ResourceTemplate");
824 else if (Status == AE_AML_NO_RESOURCE_END_TAG)
826 AcpiOsPrintf ("/**** Is ResourceTemplate, but EndTag not at buffer end ****/ ");
830 if (AcpiDmIsUnicodeBuffer (Op))
832 Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
833 AcpiOsPrintf ("Unicode (");
835 else if (AcpiDmIsStringBuffer (Op))
837 Op->Common.DisasmOpcode = ACPI_DASM_STRING;
838 AcpiOsPrintf ("Buffer");
840 else if (AcpiDmIsPldBuffer (Op))
842 Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
843 AcpiOsPrintf ("Buffer");
847 Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
848 AcpiOsPrintf ("Buffer");
852 case AML_INT_STATICSTRING_OP:
854 if (Op->Common.Value.String)
856 AcpiOsPrintf ("%s", Op->Common.Value.String);
860 AcpiOsPrintf ("\"<NULL STATIC STRING PTR>\"");
864 case AML_INT_NAMEPATH_OP:
866 AcpiDmNamestring (Op->Common.Value.Name);
869 case AML_INT_NAMEDFIELD_OP:
871 Length = AcpiDmDumpName (Op->Named.Name);
872 AcpiOsPrintf (",%*.s %u", (unsigned) (5 - Length), " ",
873 (UINT32) Op->Common.Value.Integer);
874 AcpiDmCommaIfFieldMember (Op);
876 Info->BitOffset += (UINT32) Op->Common.Value.Integer;
879 case AML_INT_RESERVEDFIELD_OP:
881 /* Offset() -- Must account for previous offsets */
883 Offset = (UINT32) Op->Common.Value.Integer;
884 Info->BitOffset += Offset;
886 if (Info->BitOffset % 8 == 0)
888 AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
892 AcpiOsPrintf (" , %u", Offset);
895 AcpiDmCommaIfFieldMember (Op);
898 case AML_INT_ACCESSFIELD_OP:
899 case AML_INT_EXTACCESSFIELD_OP:
901 AcpiOsPrintf ("AccessAs (%s, ",
902 AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
904 AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
906 if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
908 AcpiOsPrintf (" (0x%2.2X)", (unsigned) ((Op->Common.Value.Integer >> 16) & 0xFF));
912 AcpiDmCommaIfFieldMember (Op);
915 case AML_INT_CONNECTION_OP:
917 * Two types of Connection() - one with a buffer object, the
918 * other with a namestring that points to a buffer object.
920 AcpiOsPrintf ("Connection (");
921 Child = Op->Common.Value.Arg;
923 if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
927 Aml = Child->Named.Data;
928 Length = (UINT32) Child->Common.Value.Integer;
931 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
932 AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
935 AcpiDmIndent (Info->Level);
939 AcpiDmNamestring (Child->Common.Value.Name);
943 AcpiDmCommaIfFieldMember (Op);
946 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
947 Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
950 case AML_INT_BYTELIST_OP:
952 AcpiDmByteList (Info, Op);
955 case AML_INT_METHODCALL_OP:
957 Op = AcpiPsGetDepthNext (NULL, Op);
958 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
960 AcpiDmNamestring (Op->Common.Value.Name);
965 /* Just get the opcode name and print it */
967 AcpiOsPrintf ("%s", OpInfo->Name);
972 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
974 (WalkState->Results) &&
975 (WalkState->ResultCount))
977 AcpiDmDecodeInternalObject (
978 WalkState->Results->Results.ObjDesc [
979 (WalkState->ResultCount - 1) %
980 ACPI_RESULTS_FRAME_OBJ_NUM]);
988 #endif /* ACPI_DISASSEMBLER */