1 /*******************************************************************************
3 * Module Name: dmopcode - AML disassembler, specific AML opcodes
5 ******************************************************************************/
8 * Copyright (C) 2000 - 2013, 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>
50 #ifdef ACPI_DISASSEMBLER
52 #define _COMPONENT ACPI_CA_DEBUGGER
53 ACPI_MODULE_NAME ("dmopcode")
55 /* Local prototypes */
59 ACPI_PARSE_OBJECT *Op);
62 /*******************************************************************************
64 * FUNCTION: AcpiDmPredefinedDescription
66 * PARAMETERS: Op - Name() parse object
70 * DESCRIPTION: Emit a description comment for a predefined ACPI name.
71 * Used for iASL compiler only.
73 ******************************************************************************/
76 AcpiDmPredefinedDescription (
77 ACPI_PARSE_OBJECT *Op)
79 #ifdef ACPI_ASL_COMPILER
80 const AH_PREDEFINED_NAME *Info;
91 /* Ensure that the comment field is emitted only once */
93 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEF_CHECKED)
97 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEF_CHECKED;
99 /* Predefined name must start with an underscore */
101 NameString = ACPI_CAST_PTR (char, &Op->Named.Name);
102 if (NameString[0] != '_')
108 * Check for the special ACPI names:
109 * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a
110 * (where d=decimal_digit, x=hex_digit, a=anything)
112 * Convert these to the generic name for table lookup.
113 * Note: NameString is guaranteed to be upper case here.
116 (ACPI_IS_DIGIT (NameString[3])); /* d */
118 (ACPI_IS_XDIGIT (NameString[2]) && /* xx */
119 ACPI_IS_XDIGIT (NameString[3]));
121 switch (NameString[1])
125 if ((NameString[2] == 'C') && (LastCharIsDigit))
129 else if ((NameString[2] == 'L') && (LastCharIsDigit))
137 if ((NameString[2] == 'J') && (LastCharIsDigit))
141 else if (LastCharsAreHex)
165 if (NameString[2] == '_')
184 /* Match the name in the info table */
186 for (Info = AslPredefinedInfo; Info->Name; Info++)
188 if (ACPI_COMPARE_NAME (NameString, Info->Name))
190 AcpiOsPrintf (" // %4.4s: %s",
191 NameString, ACPI_CAST_PTR (char, Info->Description));
201 /*******************************************************************************
203 * FUNCTION: AcpiDmFieldPredefinedDescription
205 * PARAMETERS: Op - Parse object
209 * DESCRIPTION: Emit a description comment for a resource descriptor tag
210 * (which is a predefined ACPI name.) Used for iASL compiler only.
212 ******************************************************************************/
215 AcpiDmFieldPredefinedDescription (
216 ACPI_PARSE_OBJECT *Op)
218 #ifdef ACPI_ASL_COMPILER
219 ACPI_PARSE_OBJECT *IndexOp;
221 const ACPI_OPCODE_INFO *OpInfo;
222 const AH_PREDEFINED_NAME *Info;
230 /* Ensure that the comment field is emitted only once */
232 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEF_CHECKED)
236 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEF_CHECKED;
239 * Op must be one of the Create* operators: CreateField, CreateBitField,
240 * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField
242 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
243 if (!(OpInfo->Flags & AML_CREATE))
248 /* Second argument is the Index argument */
250 IndexOp = Op->Common.Value.Arg;
251 IndexOp = IndexOp->Common.Next;
253 /* Index argument must be a namepath */
255 if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
260 /* Major cheat: We previously put the Tag ptr in the Node field */
262 Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node);
268 /* Match the name in the info table */
270 for (Info = AslPredefinedInfo; Info->Name; Info++)
272 if (ACPI_COMPARE_NAME (Tag, Info->Name))
274 AcpiOsPrintf (" // %4.4s: %s", Tag,
275 ACPI_CAST_PTR (char, Info->Description));
285 /*******************************************************************************
287 * FUNCTION: AcpiDmMethodFlags
289 * PARAMETERS: Op - Method Object to be examined
293 * DESCRIPTION: Decode control method flags
295 ******************************************************************************/
299 ACPI_PARSE_OBJECT *Op)
305 /* The next Op contains the flags */
307 Op = AcpiPsGetDepthNext (NULL, Op);
308 Flags = (UINT8) Op->Common.Value.Integer;
311 /* Mark the Op as completed */
313 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
315 /* 1) Method argument count */
317 AcpiOsPrintf (", %u, ", Args);
319 /* 2) Serialize rule */
323 AcpiOsPrintf ("Not");
326 AcpiOsPrintf ("Serialized");
332 AcpiOsPrintf (", %u", Flags >> 4);
337 /*******************************************************************************
339 * FUNCTION: AcpiDmFieldFlags
341 * PARAMETERS: Op - Field Object to be examined
345 * DESCRIPTION: Decode Field definition flags
347 ******************************************************************************/
351 ACPI_PARSE_OBJECT *Op)
356 Op = Op->Common.Next;
357 Flags = (UINT8) Op->Common.Value.Integer;
359 /* Mark the Op as completed */
361 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
363 AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
364 AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
365 AcpiOsPrintf ("%s)", AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
369 /*******************************************************************************
371 * FUNCTION: AcpiDmAddressSpace
373 * PARAMETERS: SpaceId - ID to be translated
377 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
379 ******************************************************************************/
386 if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
390 AcpiOsPrintf ("FFixedHW, ");
394 AcpiOsPrintf ("0x%.2X, ", SpaceId);
399 AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
404 /*******************************************************************************
406 * FUNCTION: AcpiDmRegionFlags
408 * PARAMETERS: Op - Object to be examined
412 * DESCRIPTION: Decode OperationRegion flags
414 ******************************************************************************/
418 ACPI_PARSE_OBJECT *Op)
422 /* The next Op contains the SpaceId */
424 Op = AcpiPsGetDepthNext (NULL, Op);
426 /* Mark the Op as completed */
428 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
431 AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
435 /*******************************************************************************
437 * FUNCTION: AcpiDmMatchOp
439 * PARAMETERS: Op - Match Object to be examined
443 * DESCRIPTION: Decode Match opcode operands
445 ******************************************************************************/
449 ACPI_PARSE_OBJECT *Op)
451 ACPI_PARSE_OBJECT *NextOp;
454 NextOp = AcpiPsGetDepthNext (NULL, Op);
455 NextOp = NextOp->Common.Next;
459 /* Handle partial tree during single-step */
464 /* Mark the two nodes that contain the encoding for the match keywords */
466 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
468 NextOp = NextOp->Common.Next;
469 NextOp = NextOp->Common.Next;
470 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
474 /*******************************************************************************
476 * FUNCTION: AcpiDmMatchKeyword
478 * PARAMETERS: Op - Match Object to be examined
482 * DESCRIPTION: Decode Match opcode operands
484 ******************************************************************************/
488 ACPI_PARSE_OBJECT *Op)
492 if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
494 AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
498 AcpiOsPrintf ("%s", ACPI_CAST_PTR (char,
499 AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]));
504 /*******************************************************************************
506 * FUNCTION: AcpiDmDisassembleOneOp
508 * PARAMETERS: WalkState - Current walk info
509 * Info - Parse tree walk info
510 * Op - Op that is to be printed
514 * DESCRIPTION: Disassemble a single AML opcode
516 ******************************************************************************/
519 AcpiDmDisassembleOneOp (
520 ACPI_WALK_STATE *WalkState,
521 ACPI_OP_WALK_INFO *Info,
522 ACPI_PARSE_OBJECT *Op)
524 const ACPI_OPCODE_INFO *OpInfo = NULL;
527 ACPI_PARSE_OBJECT *Child;
534 AcpiOsPrintf ("<NULL OP PTR>");
538 switch (Op->Common.DisasmOpcode)
540 case ACPI_DASM_MATCHOP:
542 AcpiDmMatchKeyword (Op);
545 case ACPI_DASM_LNOT_SUFFIX:
547 switch (Op->Common.AmlOpcode)
551 AcpiOsPrintf ("LNotEqual");
554 case AML_LGREATER_OP:
556 AcpiOsPrintf ("LLessEqual");
561 AcpiOsPrintf ("LGreaterEqual");
568 Op->Common.DisasmOpcode = 0;
569 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
577 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
579 /* The op and arguments */
581 switch (Op->Common.AmlOpcode)
585 Child = Op->Common.Value.Arg;
586 if ((Child->Common.AmlOpcode == AML_LEQUAL_OP) ||
587 (Child->Common.AmlOpcode == AML_LGREATER_OP) ||
588 (Child->Common.AmlOpcode == AML_LLESS_OP))
590 Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
591 Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
595 AcpiOsPrintf ("%s", OpInfo->Name);
601 AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
606 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
608 AcpiDmEisaId ((UINT32) Op->Common.Value.Integer);
612 AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
618 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
620 AcpiDmEisaId ((UINT32) Op->Common.Value.Integer);
624 AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
630 AcpiOsPrintf ("0x%8.8X%8.8X",
631 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
636 AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
641 * Determine the type of buffer. We can have one of the following:
643 * 1) ResourceTemplate containing Resource Descriptors.
644 * 2) Unicode String buffer
645 * 3) ASCII String buffer
646 * 4) Raw data buffer (if none of the above)
648 * Since there are no special AML opcodes to differentiate these
649 * types of buffers, we have to closely look at the data in the
650 * buffer to determine the type.
652 if (!AcpiGbl_NoResourceDisassembly)
654 Status = AcpiDmIsResourceTemplate (WalkState, Op);
655 if (ACPI_SUCCESS (Status))
657 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
658 AcpiOsPrintf ("ResourceTemplate");
661 else if (Status == AE_AML_NO_RESOURCE_END_TAG)
663 AcpiOsPrintf ("/**** Is ResourceTemplate, but EndTag not at buffer end ****/ ");
667 if (AcpiDmIsUnicodeBuffer (Op))
669 Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
670 AcpiOsPrintf ("Unicode (");
672 else if (AcpiDmIsStringBuffer (Op))
674 Op->Common.DisasmOpcode = ACPI_DASM_STRING;
675 AcpiOsPrintf ("Buffer");
677 else if (AcpiDmIsPldBuffer (Op))
679 Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
680 AcpiOsPrintf ("Buffer");
684 Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
685 AcpiOsPrintf ("Buffer");
689 case AML_INT_STATICSTRING_OP:
691 if (Op->Common.Value.String)
693 AcpiOsPrintf ("%s", Op->Common.Value.String);
697 AcpiOsPrintf ("\"<NULL STATIC STRING PTR>\"");
701 case AML_INT_NAMEPATH_OP:
703 AcpiDmNamestring (Op->Common.Value.Name);
706 case AML_INT_NAMEDFIELD_OP:
708 Length = AcpiDmDumpName (Op->Named.Name);
709 AcpiOsPrintf (",%*.s %u", (unsigned) (5 - Length), " ",
710 (UINT32) Op->Common.Value.Integer);
711 AcpiDmCommaIfFieldMember (Op);
713 Info->BitOffset += (UINT32) Op->Common.Value.Integer;
716 case AML_INT_RESERVEDFIELD_OP:
718 /* Offset() -- Must account for previous offsets */
720 Offset = (UINT32) Op->Common.Value.Integer;
721 Info->BitOffset += Offset;
723 if (Info->BitOffset % 8 == 0)
725 AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
729 AcpiOsPrintf (" , %u", Offset);
732 AcpiDmCommaIfFieldMember (Op);
735 case AML_INT_ACCESSFIELD_OP:
736 case AML_INT_EXTACCESSFIELD_OP:
738 AcpiOsPrintf ("AccessAs (%s, ",
739 AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
741 AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
743 if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
745 AcpiOsPrintf (" (0x%2.2X)", (unsigned) ((Op->Common.Value.Integer >> 16) & 0xFF));
749 AcpiDmCommaIfFieldMember (Op);
752 case AML_INT_CONNECTION_OP:
754 * Two types of Connection() - one with a buffer object, the
755 * other with a namestring that points to a buffer object.
757 AcpiOsPrintf ("Connection (");
758 Child = Op->Common.Value.Arg;
760 if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
764 Aml = Child->Named.Data;
765 Length = (UINT32) Child->Common.Value.Integer;
768 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
769 AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
772 AcpiDmIndent (Info->Level);
776 AcpiDmNamestring (Child->Common.Value.Name);
780 AcpiDmCommaIfFieldMember (Op);
783 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
784 Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
787 case AML_INT_BYTELIST_OP:
789 AcpiDmByteList (Info, Op);
792 case AML_INT_METHODCALL_OP:
794 Op = AcpiPsGetDepthNext (NULL, Op);
795 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
797 AcpiDmNamestring (Op->Common.Value.Name);
802 /* Just get the opcode name and print it */
804 AcpiOsPrintf ("%s", OpInfo->Name);
809 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
811 (WalkState->Results) &&
812 (WalkState->ResultCount))
814 AcpiDmDecodeInternalObject (
815 WalkState->Results->Results.ObjDesc [
816 (WalkState->ResultCount - 1) %
817 ACPI_RESULTS_FRAME_OBJ_NUM]);
825 #endif /* ACPI_DISASSEMBLER */