1/*******************************************************************************
2 *
3 * Module Name: dmopcode - AML disassembler, specific AML opcodes
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2011, 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 "acpi.h"
45#include "accommon.h"
46#include "acparser.h"
47#include "amlcode.h"
48#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
307
308    if (!Op)
309    {
310        AcpiOsPrintf ("<NULL OP PTR>");
311        return;
312    }
313
314    switch (Op->Common.DisasmOpcode)
315    {
316    case ACPI_DASM_MATCHOP:
317
318        AcpiDmMatchKeyword (Op);
319        return;
320
321    case ACPI_DASM_LNOT_SUFFIX:
322        switch (Op->Common.AmlOpcode)
323        {
324        case AML_LEQUAL_OP:
325            AcpiOsPrintf ("LNotEqual");
326            break;
327
328        case AML_LGREATER_OP:
329            AcpiOsPrintf ("LLessEqual");
330            break;
331
332        case AML_LLESS_OP:
333            AcpiOsPrintf ("LGreaterEqual");
334            break;
335
336        default:
337            break;
338        }
339        Op->Common.DisasmOpcode = 0;
340        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
341        return;
342
343    default:
344        break;
345    }
346
347
348    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
349
350    /* The op and arguments */
351
352    switch (Op->Common.AmlOpcode)
353    {
354    case AML_LNOT_OP:
355
356        Child = Op->Common.Value.Arg;
357        if ((Child->Common.AmlOpcode == AML_LEQUAL_OP) ||
358            (Child->Common.AmlOpcode == AML_LGREATER_OP) ||
359            (Child->Common.AmlOpcode == AML_LLESS_OP))
360        {
361            Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
362            Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
363        }
364        else
365        {
366            AcpiOsPrintf ("%s", OpInfo->Name);
367        }
368        break;
369
370    case AML_BYTE_OP:
371
372        AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
373        break;
374
375
376    case AML_WORD_OP:
377
378        if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
379        {
380            AcpiDmEisaId ((UINT32) Op->Common.Value.Integer);
381        }
382        else
383        {
384            AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
385        }
386        break;
387
388
389    case AML_DWORD_OP:
390
391        if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
392        {
393            AcpiDmEisaId ((UINT32) Op->Common.Value.Integer);
394        }
395        else
396        {
397            AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
398        }
399        break;
400
401
402    case AML_QWORD_OP:
403
404        AcpiOsPrintf ("0x%8.8X%8.8X",
405            ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
406        break;
407
408
409    case AML_STRING_OP:
410
411        AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT8_MAX);
412        break;
413
414
415    case AML_BUFFER_OP:
416
417        /*
418         * Determine the type of buffer.  We can have one of the following:
419         *
420         * 1) ResourceTemplate containing Resource Descriptors.
421         * 2) Unicode String buffer
422         * 3) ASCII String buffer
423         * 4) Raw data buffer (if none of the above)
424         *
425         * Since there are no special AML opcodes to differentiate these
426         * types of buffers, we have to closely look at the data in the
427         * buffer to determine the type.
428         */
429        Status = AcpiDmIsResourceTemplate (Op);
430        if (ACPI_SUCCESS (Status))
431        {
432            Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
433            AcpiOsPrintf ("ResourceTemplate");
434            break;
435        }
436        else if (Status == AE_AML_NO_RESOURCE_END_TAG)
437        {
438            AcpiOsPrintf ("/**** Is ResourceTemplate, but EndTag not at buffer end ****/ ");
439        }
440
441        if (AcpiDmIsUnicodeBuffer (Op))
442        {
443            Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
444            AcpiOsPrintf ("Unicode (");
445        }
446        else if (AcpiDmIsStringBuffer (Op))
447        {
448            Op->Common.DisasmOpcode = ACPI_DASM_STRING;
449            AcpiOsPrintf ("Buffer");
450        }
451        else
452        {
453            Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
454            AcpiOsPrintf ("Buffer");
455        }
456        break;
457
458
459    case AML_INT_STATICSTRING_OP:
460
461        if (Op->Common.Value.String)
462        {
463            AcpiOsPrintf ("%s", Op->Common.Value.String);
464        }
465        else
466        {
467            AcpiOsPrintf ("\"<NULL STATIC STRING PTR>\"");
468        }
469        break;
470
471
472    case AML_INT_NAMEPATH_OP:
473
474        AcpiDmNamestring (Op->Common.Value.Name);
475        break;
476
477
478    case AML_INT_NAMEDFIELD_OP:
479
480        Length = AcpiDmDumpName (Op->Named.Name);
481        AcpiOsPrintf (",%*.s  %u", (unsigned) (5 - Length), " ",
482            (UINT32) Op->Common.Value.Integer);
483        AcpiDmCommaIfFieldMember (Op);
484
485        Info->BitOffset += (UINT32) Op->Common.Value.Integer;
486        break;
487
488
489    case AML_INT_RESERVEDFIELD_OP:
490
491        /* Offset() -- Must account for previous offsets */
492
493        Offset = (UINT32) Op->Common.Value.Integer;
494        Info->BitOffset += Offset;
495
496        if (Info->BitOffset % 8 == 0)
497        {
498            AcpiOsPrintf ("        Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
499        }
500        else
501        {
502            AcpiOsPrintf ("    ,   %u", Offset);
503        }
504
505        AcpiDmCommaIfFieldMember (Op);
506        break;
507
508
509    case AML_INT_ACCESSFIELD_OP:
510
511        AcpiOsPrintf ("        AccessAs (%s, ",
512            AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer >> 8) & 0x7]);
513
514        AcpiDmDecodeAttribute ((UINT8) Op->Common.Value.Integer);
515        AcpiOsPrintf (")");
516        AcpiDmCommaIfFieldMember (Op);
517        break;
518
519
520    case AML_INT_BYTELIST_OP:
521
522        AcpiDmByteList (Info, Op);
523        break;
524
525
526    case AML_INT_METHODCALL_OP:
527
528        Op = AcpiPsGetDepthNext (NULL, Op);
529        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
530
531        AcpiDmNamestring (Op->Common.Value.Name);
532        break;
533
534
535    default:
536
537        /* Just get the opcode name and print it */
538
539        AcpiOsPrintf ("%s", OpInfo->Name);
540
541
542#ifdef ACPI_DEBUGGER
543
544        if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
545            (WalkState) &&
546            (WalkState->Results) &&
547            (WalkState->ResultCount))
548        {
549            AcpiDmDecodeInternalObject (
550                WalkState->Results->Results.ObjDesc [
551                    (WalkState->ResultCount - 1) %
552                        ACPI_RESULTS_FRAME_OBJ_NUM]);
553        }
554#endif
555
556        break;
557    }
558}
559
560#endif  /* ACPI_DISASSEMBLER */
561