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