xref: /freebsd/sys/contrib/dev/acpica/components/disassembler/dmresrc.c (revision a98ff317388a00b992f1bf8404dee596f9383f5e)
1 /*******************************************************************************
2  *
3  * Module Name: dmresrc.c - Resource Descriptor disassembly
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2013, 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 
45 #include <contrib/dev/acpica/include/acpi.h>
46 #include <contrib/dev/acpica/include/accommon.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    ("dbresrc")
54 
55 
56 /* Dispatch tables for Resource disassembly functions */
57 
58 static ACPI_RESOURCE_HANDLER    AcpiGbl_DmResourceDispatch [] =
59 {
60     /* Small descriptors */
61 
62     NULL,                           /* 0x00, Reserved */
63     NULL,                           /* 0x01, Reserved */
64     NULL,                           /* 0x02, Reserved */
65     NULL,                           /* 0x03, Reserved */
66     AcpiDmIrqDescriptor,            /* 0x04, ACPI_RESOURCE_NAME_IRQ_FORMAT */
67     AcpiDmDmaDescriptor,            /* 0x05, ACPI_RESOURCE_NAME_DMA_FORMAT */
68     AcpiDmStartDependentDescriptor, /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */
69     AcpiDmEndDependentDescriptor,   /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */
70     AcpiDmIoDescriptor,             /* 0x08, ACPI_RESOURCE_NAME_IO_PORT */
71     AcpiDmFixedIoDescriptor,        /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO_PORT */
72     AcpiDmFixedDmaDescriptor,       /* 0x0A, ACPI_RESOURCE_NAME_FIXED_DMA */
73     NULL,                           /* 0x0B, Reserved */
74     NULL,                           /* 0x0C, Reserved */
75     NULL,                           /* 0x0D, Reserved */
76     AcpiDmVendorSmallDescriptor,    /* 0x0E, ACPI_RESOURCE_NAME_SMALL_VENDOR */
77     NULL,                           /* 0x0F, ACPI_RESOURCE_NAME_END_TAG (not used) */
78 
79     /* Large descriptors */
80 
81     NULL,                           /* 0x00, Reserved */
82     AcpiDmMemory24Descriptor,       /* 0x01, ACPI_RESOURCE_NAME_MEMORY_24 */
83     AcpiDmGenericRegisterDescriptor,/* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */
84     NULL,                           /* 0x03, Reserved */
85     AcpiDmVendorLargeDescriptor,    /* 0x04, ACPI_RESOURCE_NAME_LARGE_VENDOR */
86     AcpiDmMemory32Descriptor,       /* 0x05, ACPI_RESOURCE_NAME_MEMORY_32 */
87     AcpiDmFixedMemory32Descriptor,  /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY_32 */
88     AcpiDmDwordDescriptor,          /* 0x07, ACPI_RESOURCE_NAME_DWORD_ADDRESS_SPACE */
89     AcpiDmWordDescriptor,           /* 0x08, ACPI_RESOURCE_NAME_WORD_ADDRESS_SPACE */
90     AcpiDmInterruptDescriptor,      /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_XRUPT */
91     AcpiDmQwordDescriptor,          /* 0x0A, ACPI_RESOURCE_NAME_QWORD_ADDRESS_SPACE */
92     AcpiDmExtendedDescriptor,       /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS_SPACE */
93     AcpiDmGpioDescriptor,           /* 0x0C, ACPI_RESOURCE_NAME_GPIO */
94     NULL,                           /* 0x0D, Reserved */
95     AcpiDmSerialBusDescriptor       /* 0x0E, ACPI_RESOURCE_NAME_SERIAL_BUS */
96 };
97 
98 
99 /* Only used for single-threaded applications */
100 /* TBD: remove when name is passed as parameter to the dump functions */
101 
102 static UINT32               ResourceName;
103 
104 
105 /*******************************************************************************
106  *
107  * FUNCTION:    AcpiDmDescriptorName
108  *
109  * PARAMETERS:  None
110  *
111  * RETURN:      None
112  *
113  * DESCRIPTION: Emit a name for the descriptor if one is present (indicated
114  *              by the name being changed from the default name.) A name is only
115  *              emitted if a reference to the descriptor has been made somewhere
116  *              in the original ASL code.
117  *
118  ******************************************************************************/
119 
120 void
121 AcpiDmDescriptorName (
122     void)
123 {
124 
125     if (ResourceName == ACPI_DEFAULT_RESNAME)
126     {
127         return;
128     }
129 
130     AcpiOsPrintf ("%4.4s", (char *) &ResourceName);
131 }
132 
133 
134 /*******************************************************************************
135  *
136  * FUNCTION:    AcpiDmDumpInteger*
137  *
138  * PARAMETERS:  Value               - Value to emit
139  *              Name                - Associated name (emitted as a comment)
140  *
141  * RETURN:      None
142  *
143  * DESCRIPTION: Integer output helper functions
144  *
145  ******************************************************************************/
146 
147 void
148 AcpiDmDumpInteger8 (
149     UINT8                   Value,
150     char                    *Name)
151 {
152     AcpiOsPrintf ("0x%2.2X,               // %s\n", Value, Name);
153 }
154 
155 void
156 AcpiDmDumpInteger16 (
157     UINT16                  Value,
158     char                    *Name)
159 {
160     AcpiOsPrintf ("0x%4.4X,             // %s\n", Value, Name);
161 }
162 
163 void
164 AcpiDmDumpInteger32 (
165     UINT32                  Value,
166     char                    *Name)
167 {
168     AcpiOsPrintf ("0x%8.8X,         // %s\n", Value, Name);
169 }
170 
171 void
172 AcpiDmDumpInteger64 (
173     UINT64                  Value,
174     char                    *Name)
175 {
176     AcpiOsPrintf ("0x%8.8X%8.8X, // %s\n", ACPI_FORMAT_UINT64 (Value), Name);
177 }
178 
179 
180 /*******************************************************************************
181  *
182  * FUNCTION:    AcpiDmBitList
183  *
184  * PARAMETERS:  Mask            - 16-bit value corresponding to 16 interrupt
185  *                                or DMA values
186  *
187  * RETURN:      None
188  *
189  * DESCRIPTION: Dump a bit mask as a list of individual interrupt/DMA levels.
190  *
191  ******************************************************************************/
192 
193 void
194 AcpiDmBitList (
195     UINT16                  Mask)
196 {
197     UINT32                  i;
198     BOOLEAN                 Previous = FALSE;
199 
200 
201     /* Open the initializer list */
202 
203     AcpiOsPrintf ("{");
204 
205     /* Examine each bit */
206 
207     for (i = 0; i < 16; i++)
208     {
209         /* Only interested in bits that are set to 1 */
210 
211         if (Mask & 1)
212         {
213             if (Previous)
214             {
215                 AcpiOsPrintf (",");
216             }
217             Previous = TRUE;
218             AcpiOsPrintf ("%u", i);
219         }
220 
221         Mask >>= 1;
222     }
223 
224     /* Close list */
225 
226     AcpiOsPrintf ("}\n");
227 }
228 
229 
230 /*******************************************************************************
231  *
232  * FUNCTION:    AcpiDmResourceTemplate
233  *
234  * PARAMETERS:  Info            - Curent parse tree walk info
235  *              ByteData        - Pointer to the byte list data
236  *              ByteCount       - Length of the byte list
237  *
238  * RETURN:      None
239  *
240  * DESCRIPTION: Dump the contents of a Resource Template containing a set of
241  *              Resource Descriptors.
242  *
243  ******************************************************************************/
244 
245 void
246 AcpiDmResourceTemplate (
247     ACPI_OP_WALK_INFO       *Info,
248     ACPI_PARSE_OBJECT       *Op,
249     UINT8                   *ByteData,
250     UINT32                  ByteCount)
251 {
252     ACPI_STATUS             Status;
253     UINT32                  CurrentByteOffset;
254     UINT8                   ResourceType;
255     UINT32                  ResourceLength;
256     void                    *Aml;
257     UINT32                  Level;
258     BOOLEAN                 DependentFns = FALSE;
259     UINT8                   ResourceIndex;
260     ACPI_NAMESPACE_NODE     *Node;
261 
262 
263     Level = Info->Level;
264     ResourceName = ACPI_DEFAULT_RESNAME;
265     Node = Op->Common.Node;
266     if (Node)
267     {
268         Node = Node->Child;
269     }
270 
271     for (CurrentByteOffset = 0; CurrentByteOffset < ByteCount;)
272     {
273         Aml = &ByteData[CurrentByteOffset];
274 
275         /* Get the descriptor type and length */
276 
277         ResourceType = AcpiUtGetResourceType (Aml);
278         ResourceLength = AcpiUtGetResourceLength (Aml);
279 
280         /* Validate the Resource Type and Resource Length */
281 
282         Status = AcpiUtValidateResource (NULL, Aml, &ResourceIndex);
283         if (ACPI_FAILURE (Status))
284         {
285             AcpiOsPrintf ("/*** Could not validate Resource, type (%X) %s***/\n",
286                 ResourceType, AcpiFormatException (Status));
287             return;
288         }
289 
290         /* Point to next descriptor */
291 
292         CurrentByteOffset += AcpiUtGetDescriptorLength (Aml);
293 
294         /* Descriptor pre-processing */
295 
296         switch (ResourceType)
297         {
298         case ACPI_RESOURCE_NAME_START_DEPENDENT:
299 
300             /* Finish a previous StartDependentFns */
301 
302             if (DependentFns)
303             {
304                 Level--;
305                 AcpiDmIndent (Level);
306                 AcpiOsPrintf ("}\n");
307             }
308             break;
309 
310         case ACPI_RESOURCE_NAME_END_DEPENDENT:
311 
312             Level--;
313             DependentFns = FALSE;
314             break;
315 
316         case ACPI_RESOURCE_NAME_END_TAG:
317 
318             /* Normal exit, the resource list is finished */
319 
320             if (DependentFns)
321             {
322                 /*
323                  * Close an open StartDependentDescriptor. This indicates a
324                  * missing EndDependentDescriptor.
325                  */
326                 Level--;
327                 DependentFns = FALSE;
328 
329                 /* Go ahead and insert EndDependentFn() */
330 
331                 AcpiDmEndDependentDescriptor (Aml, ResourceLength, Level);
332 
333                 AcpiDmIndent (Level);
334                 AcpiOsPrintf (
335                     "/*** Disassembler: inserted missing EndDependentFn () ***/\n");
336             }
337             return;
338 
339         default:
340 
341             break;
342         }
343 
344         /* Disassemble the resource structure */
345 
346         if (Node)
347         {
348             ResourceName = Node->Name.Integer;
349             Node = Node->Peer;
350         }
351 
352         AcpiGbl_DmResourceDispatch [ResourceIndex] (
353             Aml, ResourceLength, Level);
354 
355         /* Descriptor post-processing */
356 
357         if (ResourceType == ACPI_RESOURCE_NAME_START_DEPENDENT)
358         {
359             DependentFns = TRUE;
360             Level++;
361         }
362     }
363 }
364 
365 
366 /*******************************************************************************
367  *
368  * FUNCTION:    AcpiDmIsResourceTemplate
369  *
370  * PARAMETERS:  WalkState           - Current walk info
371  *              Op                  - Buffer Op to be examined
372  *
373  * RETURN:      Status. AE_OK if valid template
374  *
375  * DESCRIPTION: Walk a byte list to determine if it consists of a valid set
376  *              of resource descriptors. Nothing is output.
377  *
378  ******************************************************************************/
379 
380 ACPI_STATUS
381 AcpiDmIsResourceTemplate (
382     ACPI_WALK_STATE         *WalkState,
383     ACPI_PARSE_OBJECT       *Op)
384 {
385     ACPI_STATUS             Status;
386     ACPI_PARSE_OBJECT       *NextOp;
387     UINT8                   *Aml;
388     UINT8                   *EndAml;
389     ACPI_SIZE               Length;
390 
391 
392     /* This op must be a buffer */
393 
394     if (Op->Common.AmlOpcode != AML_BUFFER_OP)
395     {
396         return (AE_TYPE);
397     }
398 
399     /* Get the ByteData list and length */
400 
401     NextOp = Op->Common.Value.Arg;
402     if (!NextOp)
403     {
404         AcpiOsPrintf ("NULL byte list in buffer\n");
405         return (AE_TYPE);
406     }
407 
408     NextOp = NextOp->Common.Next;
409     if (!NextOp)
410     {
411         return (AE_TYPE);
412     }
413 
414     Aml = NextOp->Named.Data;
415     Length = (ACPI_SIZE) NextOp->Common.Value.Integer;
416 
417     /* Walk the byte list, abort on any invalid descriptor type or length */
418 
419     Status = AcpiUtWalkAmlResources (WalkState, Aml, Length,
420         NULL, ACPI_CAST_INDIRECT_PTR (void, &EndAml));
421     if (ACPI_FAILURE (Status))
422     {
423         return (AE_TYPE);
424     }
425 
426     /*
427      * For the resource template to be valid, one EndTag must appear
428      * at the very end of the ByteList, not before. (For proper disassembly
429      * of a ResourceTemplate, the buffer must not have any extra data after
430      * the EndTag.)
431      */
432     if ((Aml + Length - sizeof (AML_RESOURCE_END_TAG)) != EndAml)
433     {
434         return (AE_AML_NO_RESOURCE_END_TAG);
435     }
436 
437     /*
438      * All resource descriptors are valid, therefore this list appears
439      * to be a valid resource template
440      */
441     return (AE_OK);
442 }
443 
444 #endif
445