dmopcode.c revision 229989
1/*******************************************************************************
2 *
3 * Module Name: dmopcode - AML disassembler, specific AML opcodes
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2012, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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.
25 *
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.
29 *
30 * NO WARRANTY
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.
42 */
43
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
50#ifdef ACPI_DISASSEMBLER
51
52#define _COMPONENT          ACPI_CA_DEBUGGER
53        ACPI_MODULE_NAME    ("dmopcode")
54
55/* Local prototypes */
56
57static void
58AcpiDmMatchKeyword (
59    ACPI_PARSE_OBJECT       *Op);
60
61
62/*******************************************************************************
63 *
64 * FUNCTION:    AcpiDmMethodFlags
65 *
66 * PARAMETERS:  Op              - Method Object to be examined
67 *
68 * RETURN:      None
69 *
70 * DESCRIPTION: Decode control method flags
71 *
72 ******************************************************************************/
73
74void
75AcpiDmMethodFlags (
76    ACPI_PARSE_OBJECT       *Op)
77{
78    UINT32                  Flags;
79    UINT32                  Args;
80
81
82    /* The next Op contains the flags */
83
84    Op = AcpiPsGetDepthNext (NULL, Op);
85    Flags = (UINT8) Op->Common.Value.Integer;
86    Args = Flags & 0x07;
87
88    /* Mark the Op as completed */
89
90    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
91
92    /* 1) Method argument count */
93
94    AcpiOsPrintf (", %u, ", Args);
95
96    /* 2) Serialize rule */
97
98    if (!(Flags & 0x08))
99    {
100        AcpiOsPrintf ("Not");
101    }
102
103    AcpiOsPrintf ("Serialized");
104
105    /* 3) SyncLevel */
106
107    if (Flags & 0xF0)
108    {
109        AcpiOsPrintf (", %u", Flags >> 4);
110    }
111}
112
113
114/*******************************************************************************
115 *
116 * FUNCTION:    AcpiDmFieldFlags
117 *
118 * PARAMETERS:  Op              - Field Object to be examined
119 *
120 * RETURN:      None
121 *
122 * DESCRIPTION: Decode Field definition flags
123 *
124 ******************************************************************************/
125
126void
127AcpiDmFieldFlags (
128    ACPI_PARSE_OBJECT       *Op)
129{
130    UINT32                  Flags;
131
132
133    Op = Op->Common.Next;
134    Flags = (UINT8) Op->Common.Value.Integer;
135
136    /* Mark the Op as completed */
137
138    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
139
140    AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
141    AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
142    AcpiOsPrintf ("%s)",  AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
143}
144
145
146/*******************************************************************************
147 *
148 * FUNCTION:    AcpiDmAddressSpace
149 *
150 * PARAMETERS:  SpaceId         - ID to be translated
151 *
152 * RETURN:      None
153 *
154 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
155 *
156 ******************************************************************************/
157
158void
159AcpiDmAddressSpace (
160    UINT8                   SpaceId)
161{
162
163    if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
164    {
165        if (SpaceId == 0x7F)
166        {
167            AcpiOsPrintf ("FFixedHW, ");
168        }
169        else
170        {
171            AcpiOsPrintf ("0x%.2X, ", SpaceId);
172        }
173    }
174    else
175    {
176        AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
177    }
178}
179
180
181/*******************************************************************************
182 *
183 * FUNCTION:    AcpiDmRegionFlags
184 *
185 * PARAMETERS:  Op              - Object to be examined
186 *
187 * RETURN:      None
188 *
189 * DESCRIPTION: Decode OperationRegion flags
190 *
191 ******************************************************************************/
192
193void
194AcpiDmRegionFlags (
195    ACPI_PARSE_OBJECT       *Op)
196{
197
198
199    /* The next Op contains the SpaceId */
200
201    Op = AcpiPsGetDepthNext (NULL, Op);
202
203    /* Mark the Op as completed */
204
205    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
206
207    AcpiOsPrintf (", ");
208    AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
209}
210
211
212/*******************************************************************************
213 *
214 * FUNCTION:    AcpiDmMatchOp
215 *
216 * PARAMETERS:  Op              - Match Object to be examined
217 *
218 * RETURN:      None
219 *
220 * DESCRIPTION: Decode Match opcode operands
221 *
222 ******************************************************************************/
223
224void
225AcpiDmMatchOp (
226    ACPI_PARSE_OBJECT       *Op)
227{
228    ACPI_PARSE_OBJECT       *NextOp;
229
230
231    NextOp = AcpiPsGetDepthNext (NULL, Op);
232    NextOp = NextOp->Common.Next;
233
234    if (!NextOp)
235    {
236        /* Handle partial tree during single-step */
237
238        return;
239    }
240
241    /* Mark the two nodes that contain the encoding for the match keywords */
242
243    NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
244
245    NextOp = NextOp->Common.Next;
246    NextOp = NextOp->Common.Next;
247    NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
248}
249
250
251/*******************************************************************************
252 *
253 * FUNCTION:    AcpiDmMatchKeyword
254 *
255 * PARAMETERS:  Op              - Match Object to be examined
256 *
257 * RETURN:      None
258 *
259 * DESCRIPTION: Decode Match opcode operands
260 *
261 ******************************************************************************/
262
263static void
264AcpiDmMatchKeyword (
265    ACPI_PARSE_OBJECT       *Op)
266{
267
268
269    if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
270    {
271        AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
272    }
273    else
274    {
275        AcpiOsPrintf ("%s", ACPI_CAST_PTR (char,
276            AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]));
277    }
278}
279
280
281/*******************************************************************************
282 *
283 * FUNCTION:    AcpiDmDisassembleOneOp
284 *
285 * PARAMETERS:  WalkState           - Current walk info
286 *              Info                - Parse tree walk info
287 *              Op                  - Op that is to be printed
288 *
289 * RETURN:      None
290 *
291 * DESCRIPTION: Disassemble a single AML opcode
292 *
293 ******************************************************************************/
294
295void
296AcpiDmDisassembleOneOp (
297    ACPI_WALK_STATE         *WalkState,
298    ACPI_OP_WALK_INFO       *Info,
299    ACPI_PARSE_OBJECT       *Op)
300{
301    const ACPI_OPCODE_INFO  *OpInfo = NULL;
302    UINT32                  Offset;
303    UINT32                  Length;
304    ACPI_PARSE_OBJECT       *Child;
305    ACPI_STATUS             Status;
306    UINT8                   *Aml;
307
308
309    if (!Op)
310    {
311        AcpiOsPrintf ("<NULL OP PTR>");
312        return;
313    }
314
315    switch (Op->Common.DisasmOpcode)
316    {
317    case ACPI_DASM_MATCHOP:
318
319        AcpiDmMatchKeyword (Op);
320        return;
321
322    case ACPI_DASM_LNOT_SUFFIX:
323        switch (Op->Common.AmlOpcode)
324        {
325        case AML_LEQUAL_OP:
326            AcpiOsPrintf ("LNotEqual");
327            break;
328
329        case AML_LGREATER_OP:
330            AcpiOsPrintf ("LLessEqual");
331            break;
332
333        case AML_LLESS_OP:
334            AcpiOsPrintf ("LGreaterEqual");
335            break;
336
337        default:
338            break;
339        }
340        Op->Common.DisasmOpcode = 0;
341        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
342        return;
343
344    default:
345        break;
346    }
347
348
349    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
350
351    /* The op and arguments */
352
353    switch (Op->Common.AmlOpcode)
354    {
355    case AML_LNOT_OP:
356
357        Child = Op->Common.Value.Arg;
358        if ((Child->Common.AmlOpcode == AML_LEQUAL_OP) ||
359            (Child->Common.AmlOpcode == AML_LGREATER_OP) ||
360            (Child->Common.AmlOpcode == AML_LLESS_OP))
361        {
362            Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
363            Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
364        }
365        else
366        {
367            AcpiOsPrintf ("%s", OpInfo->Name);
368        }
369        break;
370
371    case AML_BYTE_OP:
372
373        AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
374        break;
375
376
377    case AML_WORD_OP:
378
379        if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
380        {
381            AcpiDmEisaId ((UINT32) Op->Common.Value.Integer);
382        }
383        else
384        {
385            AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
386        }
387        break;
388
389
390    case AML_DWORD_OP:
391
392        if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
393        {
394            AcpiDmEisaId ((UINT32) Op->Common.Value.Integer);
395        }
396        else
397        {
398            AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
399        }
400        break;
401
402
403    case AML_QWORD_OP:
404
405        AcpiOsPrintf ("0x%8.8X%8.8X",
406            ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
407        break;
408
409
410    case AML_STRING_OP:
411
412        AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT8_MAX);
413        break;
414
415
416    case AML_BUFFER_OP:
417
418        /*
419         * Determine the type of buffer.  We can have one of the following:
420         *
421         * 1) ResourceTemplate containing Resource Descriptors.
422         * 2) Unicode String buffer
423         * 3) ASCII String buffer
424         * 4) Raw data buffer (if none of the above)
425         *
426         * Since there are no special AML opcodes to differentiate these
427         * types of buffers, we have to closely look at the data in the
428         * buffer to determine the type.
429         */
430        if (!AcpiGbl_NoResourceDisassembly)
431        {
432            Status = AcpiDmIsResourceTemplate (Op);
433            if (ACPI_SUCCESS (Status))
434            {
435                Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
436                AcpiOsPrintf ("ResourceTemplate");
437                break;
438            }
439            else if (Status == AE_AML_NO_RESOURCE_END_TAG)
440            {
441                AcpiOsPrintf ("/**** Is ResourceTemplate, but EndTag not at buffer end ****/ ");
442            }
443        }
444
445        if (AcpiDmIsUnicodeBuffer (Op))
446        {
447            Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
448            AcpiOsPrintf ("Unicode (");
449        }
450        else if (AcpiDmIsStringBuffer (Op))
451        {
452            Op->Common.DisasmOpcode = ACPI_DASM_STRING;
453            AcpiOsPrintf ("Buffer");
454        }
455        else
456        {
457            Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
458            AcpiOsPrintf ("Buffer");
459        }
460        break;
461
462
463    case AML_INT_STATICSTRING_OP:
464
465        if (Op->Common.Value.String)
466        {
467            AcpiOsPrintf ("%s", Op->Common.Value.String);
468        }
469        else
470        {
471            AcpiOsPrintf ("\"<NULL STATIC STRING PTR>\"");
472        }
473        break;
474
475
476    case AML_INT_NAMEPATH_OP:
477
478        AcpiDmNamestring (Op->Common.Value.Name);
479        break;
480
481
482    case AML_INT_NAMEDFIELD_OP:
483
484        Length = AcpiDmDumpName (Op->Named.Name);
485        AcpiOsPrintf (",%*.s  %u", (unsigned) (5 - Length), " ",
486            (UINT32) Op->Common.Value.Integer);
487        AcpiDmCommaIfFieldMember (Op);
488
489        Info->BitOffset += (UINT32) Op->Common.Value.Integer;
490        break;
491
492
493    case AML_INT_RESERVEDFIELD_OP:
494
495        /* Offset() -- Must account for previous offsets */
496
497        Offset = (UINT32) Op->Common.Value.Integer;
498        Info->BitOffset += Offset;
499
500        if (Info->BitOffset % 8 == 0)
501        {
502            AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
503        }
504        else
505        {
506            AcpiOsPrintf ("    ,   %u", Offset);
507        }
508
509        AcpiDmCommaIfFieldMember (Op);
510        break;
511
512
513    case AML_INT_ACCESSFIELD_OP:
514    case AML_INT_EXTACCESSFIELD_OP:
515
516        AcpiOsPrintf ("AccessAs (%s, ",
517            AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
518
519        AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
520
521        if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
522        {
523            AcpiOsPrintf (" (0x%2.2X)", (unsigned) ((Op->Common.Value.Integer >> 16) & 0xFF));
524        }
525
526        AcpiOsPrintf (")");
527        AcpiDmCommaIfFieldMember (Op);
528        break;
529
530
531    case AML_INT_CONNECTION_OP:
532
533        /*
534         * Two types of Connection() - one with a buffer object, the
535         * other with a namestring that points to a buffer object.
536         */
537        AcpiOsPrintf ("Connection (");
538        Child = Op->Common.Value.Arg;
539
540        if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
541        {
542            AcpiOsPrintf ("\n");
543
544            Aml = Child->Named.Data;
545            Length = (UINT32) Child->Common.Value.Integer;
546
547            Info->Level += 1;
548            Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
549            AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
550
551            Info->Level -= 1;
552            AcpiDmIndent (Info->Level);
553        }
554        else
555        {
556            AcpiDmNamestring (Child->Common.Value.Name);
557        }
558
559        AcpiOsPrintf (")");
560        AcpiDmCommaIfFieldMember (Op);
561        AcpiOsPrintf ("\n");
562
563        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
564        Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
565        break;
566
567    case AML_INT_BYTELIST_OP:
568
569        AcpiDmByteList (Info, Op);
570        break;
571
572
573    case AML_INT_METHODCALL_OP:
574
575        Op = AcpiPsGetDepthNext (NULL, Op);
576        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
577
578        AcpiDmNamestring (Op->Common.Value.Name);
579        break;
580
581
582    default:
583
584        /* Just get the opcode name and print it */
585
586        AcpiOsPrintf ("%s", OpInfo->Name);
587
588
589#ifdef ACPI_DEBUGGER
590
591        if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
592            (WalkState) &&
593            (WalkState->Results) &&
594            (WalkState->ResultCount))
595        {
596            AcpiDmDecodeInternalObject (
597                WalkState->Results->Results.ObjDesc [
598                    (WalkState->ResultCount - 1) %
599                        ACPI_RESULTS_FRAME_OBJ_NUM]);
600        }
601#endif
602
603        break;
604    }
605}
606
607#endif  /* ACPI_DISASSEMBLER */
608