xref: /freebsd-src/sys/contrib/dev/acpica/components/disassembler/dmopcode.c (revision ae77177087c655fc883075af4f425b37e032cd05)
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 
57 static void
58 AcpiDmMatchKeyword (
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 
74 void
75 AcpiDmMethodFlags (
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 
126 void
127 AcpiDmFieldFlags (
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 
158 void
159 AcpiDmAddressSpace (
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 
193 void
194 AcpiDmRegionFlags (
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 
224 void
225 AcpiDmMatchOp (
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 
263 static void
264 AcpiDmMatchKeyword (
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 
295 void
296 AcpiDmDisassembleOneOp (
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