xref: /freebsd/sys/contrib/dev/acpica/compiler/aslmapoutput.c (revision 88f578841fd49ff796b62a8d3531bd73afd1a88e)
1 /******************************************************************************
2  *
3  * Module Name: aslmapoutput - Output/emit the resource descriptor/device maps
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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/acapps.h>
47 #include <contrib/dev/acpica/compiler/aslcompiler.h>
48 #include "aslcompiler.y.h"
49 #include <contrib/dev/acpica/include/acinterp.h>
50 #include <contrib/dev/acpica/include/acparser.h>
51 #include <contrib/dev/acpica/include/acnamesp.h>
52 #include <contrib/dev/acpica/include/amlcode.h>
53 
54 /* This module used for application-level code only */
55 
56 #define _COMPONENT          ACPI_COMPILER
57         ACPI_MODULE_NAME    ("aslmapoutput")
58 
59 /* Local prototypes */
60 
61 static void
62 MpEmitGpioInfo (
63     void);
64 
65 static void
66 MpEmitSerialInfo (
67     void);
68 
69 static void
70 MpEmitDeviceTree (
71     void);
72 
73 static ACPI_STATUS
74 MpEmitOneDevice (
75     ACPI_HANDLE             ObjHandle,
76     UINT32                  NestingLevel,
77     void                    *Context,
78     void                    **ReturnValue);
79 
80 static void
81 MpXrefDevices (
82     ACPI_GPIO_INFO          *Info);
83 
84 static ACPI_STATUS
85 MpNamespaceXrefBegin (
86     ACPI_PARSE_OBJECT       *Op,
87     UINT32                  Level,
88     void                    *Context);
89 
90 
91 /* Strings used to decode flag bits */
92 
93 const char                  *DirectionDecode[] =
94 {
95     "Both I/O   ",
96     "InputOnly  ",
97     "OutputOnly ",
98     "Preserve   "
99 };
100 
101 const char                  *PolarityDecode[] =
102 {
103     "ActiveHigh",
104     "ActiveLow ",
105     "ActiveBoth",
106     "Reserved  "
107 };
108 
109 
110 /*******************************************************************************
111  *
112  * FUNCTION:    MpEmitMappingInfo
113  *
114  * PARAMETERS:  None
115  *
116  * RETURN:      None
117  *
118  * DESCRIPTION: External interface.
119  *              Map file has already been opened. Emit all of the collected
120  *              hardware mapping information. Includes: GPIO information,
121  *              Serial information, and a dump of the entire ACPI device tree.
122  *
123  ******************************************************************************/
124 
125 void
126 MpEmitMappingInfo (
127     void)
128 {
129 
130     /* Mapfile option enabled? */
131 
132     if (!Gbl_MapfileFlag)
133     {
134         return;
135     }
136 
137     if (!Gbl_GpioList)
138     {
139         FlPrintFile (ASL_FILE_MAP_OUTPUT,
140             "\nNo GPIO devices found\n");
141     }
142 
143     if (!Gbl_SerialList)
144     {
145         FlPrintFile (ASL_FILE_MAP_OUTPUT,
146             "\nNo Serial devices found (I2C/SPI/UART)\n");
147     }
148 
149     if (!Gbl_GpioList && !Gbl_SerialList)
150     {
151         return;
152     }
153 
154     /* Headers */
155 
156     FlPrintFile (ASL_FILE_MAP_OUTPUT, "\nResource Descriptor Connectivity Map\n");
157     FlPrintFile (ASL_FILE_MAP_OUTPUT,   "------------------------------------\n");
158 
159     /* Emit GPIO and Serial descriptors, then entire ACPI device tree */
160 
161     MpEmitGpioInfo ();
162     MpEmitSerialInfo ();
163     MpEmitDeviceTree ();
164 
165     /* Clear the lists - no need to free memory here */
166 
167     Gbl_SerialList = NULL;
168     Gbl_GpioList = NULL;
169 }
170 
171 
172 /*******************************************************************************
173  *
174  * FUNCTION:    MpEmitGpioInfo
175  *
176  * PARAMETERS:  None
177  *
178  * RETURN:      None
179  *
180  * DESCRIPTION: Emit the info about all GPIO devices found during the
181  *              compile or disassembly.
182  *
183  ******************************************************************************/
184 
185 static void
186 MpEmitGpioInfo (
187     void)
188 {
189     ACPI_GPIO_INFO          *Info;
190     char                    *Type;
191     char                    *PrevDeviceName = NULL;
192     const char              *Direction;
193     const char              *Polarity;
194     char                    *ParentPathname;
195     const char              *Description;
196     char                    *HidString;
197     const AH_DEVICE_ID      *HidInfo;
198 
199 
200     /* Walk the GPIO descriptor list */
201 
202     Info = Gbl_GpioList;
203     while (Info)
204     {
205         HidString = MpGetHidViaNamestring (Info->DeviceName);
206 
207         /* Print header info for the controller itself */
208 
209         if (!PrevDeviceName ||
210             strcmp (PrevDeviceName, Info->DeviceName))
211         {
212             FlPrintFile (ASL_FILE_MAP_OUTPUT,
213                 "\n\nGPIO Controller:  %-8s  %-28s",
214                 HidString, Info->DeviceName);
215 
216             HidInfo = AcpiAhMatchHardwareId (HidString);
217             if (HidInfo)
218             {
219                 FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s",
220                     HidInfo->Description);
221             }
222 
223             FlPrintFile (ASL_FILE_MAP_OUTPUT,
224                 "\n\nPin   Type     Direction    Polarity"
225                 "    Dest _HID  Destination\n");
226         }
227 
228         PrevDeviceName = Info->DeviceName;
229 
230         /* Setup various strings based upon the type (GpioInt or GpioIo) */
231 
232         switch (Info->Type)
233         {
234         case AML_RESOURCE_GPIO_TYPE_INT:
235 
236             Type = "GpioInt";
237             Direction = "-Interrupt-";
238             Polarity = PolarityDecode[Info->Polarity];
239             break;
240 
241         case AML_RESOURCE_GPIO_TYPE_IO:
242 
243             Type = "GpioIo ";
244             Direction = DirectionDecode[Info->Direction];
245             Polarity = "          ";
246             break;
247 
248         default:
249             continue;
250         }
251 
252         /* Emit the GPIO info */
253 
254         FlPrintFile (ASL_FILE_MAP_OUTPUT, "%4.4X  %s  %s  %s  ",
255             Info->PinNumber, Type, Direction, Polarity);
256 
257         ParentPathname = NULL;
258         HidString = MpGetConnectionInfo (Info->Op, Info->PinIndex,
259             &Info->TargetNode, &ParentPathname);
260         if (HidString)
261         {
262             /*
263              * This is a Connection() field
264              * Attempt to find all references to the field.
265              */
266             FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s   %-28s",
267                 HidString, ParentPathname);
268 
269             MpXrefDevices (Info);
270         }
271         else
272         {
273             /*
274              * For Devices, attempt to get the _HID description string.
275              * Failing that (many _HIDs are not recognized), attempt to
276              * get the _DDN description string.
277              */
278             HidString = MpGetParentDeviceHid (Info->Op, &Info->TargetNode,
279                 &ParentPathname);
280 
281             FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s   %-28s",
282                 HidString, ParentPathname);
283 
284             /* Get the _HID description or _DDN string */
285 
286             HidInfo = AcpiAhMatchHardwareId (HidString);
287             if (HidInfo)
288             {
289                 FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s",
290                     HidInfo->Description);
291             }
292             else if ((Description = MpGetDdnValue (ParentPathname)))
293             {
294                 FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s (_DDN)",
295                     Description);
296             }
297         }
298 
299         FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n");
300         ACPI_FREE (ParentPathname);
301         Info = Info->Next;
302     }
303 }
304 
305 
306 /*******************************************************************************
307  *
308  * FUNCTION:    MpEmitSerialInfo
309  *
310  * PARAMETERS:  None
311  *
312  * RETURN:      None
313  *
314  * DESCRIPTION: Emit the info about all Serial devices found during the
315  *              compile or disassembly.
316  *
317  ******************************************************************************/
318 
319 static void
320 MpEmitSerialInfo (
321     void)
322 {
323     ACPI_SERIAL_INFO        *Info;
324     char                    *Type;
325     char                    *ParentPathname;
326     char                    *PrevDeviceName = NULL;
327     char                    *HidString;
328     const AH_DEVICE_ID      *HidInfo;
329     const char              *Description;
330     AML_RESOURCE            *Resource;
331 
332 
333     /* Walk the constructed serial descriptor list */
334 
335     Info = Gbl_SerialList;
336     while (Info)
337     {
338         Resource = Info->Resource;
339         switch (Resource->CommonSerialBus.Type)
340         {
341         case AML_RESOURCE_I2C_SERIALBUSTYPE:
342             Type = "I2C ";
343             break;
344 
345         case AML_RESOURCE_SPI_SERIALBUSTYPE:
346             Type = "SPI ";
347             break;
348 
349         case AML_RESOURCE_UART_SERIALBUSTYPE:
350             Type = "UART";
351             break;
352 
353         default:
354             Type = "UNKN";
355             break;
356         }
357 
358         HidString = MpGetHidViaNamestring (Info->DeviceName);
359 
360         /* Print header info for the controller itself */
361 
362         if (!PrevDeviceName ||
363             strcmp (PrevDeviceName, Info->DeviceName))
364         {
365             FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n\n%s Controller:  ",
366                 Type);
367             FlPrintFile (ASL_FILE_MAP_OUTPUT, "%-8s  %-28s",
368                 HidString, Info->DeviceName);
369 
370             HidInfo = AcpiAhMatchHardwareId (HidString);
371             if (HidInfo)
372             {
373                 FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s",
374                     HidInfo->Description);
375             }
376 
377             FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n\n");
378             FlPrintFile (ASL_FILE_MAP_OUTPUT,
379                 "Type  Address   Speed      Dest _HID  Destination\n");
380         }
381 
382         PrevDeviceName = Info->DeviceName;
383 
384         FlPrintFile (ASL_FILE_MAP_OUTPUT, "%s   %4.4X    %8.8X    ",
385             Type, Info->Address, Info->Speed);
386 
387         ParentPathname = NULL;
388         HidString = MpGetConnectionInfo (Info->Op, 0, &Info->TargetNode,
389             &ParentPathname);
390         if (HidString)
391         {
392             /*
393              * This is a Connection() field
394              * Attempt to find all references to the field.
395              */
396             FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s   %-28s",
397                 HidString, ParentPathname);
398         }
399         else
400         {
401             /* Normal resource template */
402 
403             HidString = MpGetParentDeviceHid (Info->Op, &Info->TargetNode,
404                 &ParentPathname);
405             FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s   %-28s",
406                 HidString, ParentPathname);
407 
408             /* Get the _HID description or _DDN string */
409 
410             HidInfo = AcpiAhMatchHardwareId (HidString);
411             if (HidInfo)
412             {
413                 FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s",
414                     HidInfo->Description);
415             }
416             else if ((Description = MpGetDdnValue (ParentPathname)))
417             {
418                 FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s (_DDN)",
419                     Description);
420             }
421         }
422 
423         FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n");
424         ACPI_FREE (ParentPathname);
425         Info = Info->Next;
426     }
427 }
428 
429 
430 /*******************************************************************************
431  *
432  * FUNCTION:    MpEmitDeviceTree
433  *
434  * PARAMETERS:  None
435  *
436  * RETURN:      None
437  *
438  * DESCRIPTION: Emit information about all devices within the ACPI namespace.
439  *
440  ******************************************************************************/
441 
442 static void
443 MpEmitDeviceTree (
444     void)
445 {
446 
447     FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n\nACPI Device Tree\n");
448     FlPrintFile (ASL_FILE_MAP_OUTPUT,     "----------------\n\n");
449 
450     FlPrintFile (ASL_FILE_MAP_OUTPUT, "Device Pathname                   "
451         "_HID      Description\n\n");
452 
453     /* Walk the namespace from the root */
454 
455     (void) AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
456             ACPI_UINT32_MAX, FALSE, MpEmitOneDevice, NULL, NULL, NULL);
457 }
458 
459 
460 /*******************************************************************************
461  *
462  * FUNCTION:    MpEmitOneDevice
463  *
464  * PARAMETERS:  ACPI_NAMESPACE_WALK callback
465  *
466  * RETURN:      Status
467  *
468  * DESCRIPTION: Emit information about one ACPI device in the namespace. Used
469  *              during dump of all device objects within the namespace.
470  *
471  ******************************************************************************/
472 
473 static ACPI_STATUS
474 MpEmitOneDevice (
475     ACPI_HANDLE             ObjHandle,
476     UINT32                  NestingLevel,
477     void                    *Context,
478     void                    **ReturnValue)
479 {
480     char                    *DevicePathname;
481     char                    *DdnString;
482     char                    *HidString;
483     const AH_DEVICE_ID      *HidInfo;
484 
485 
486     /* Device pathname */
487 
488     DevicePathname = AcpiNsGetExternalPathname (
489         ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle));
490 
491     FlPrintFile (ASL_FILE_MAP_OUTPUT, "%-32s", DevicePathname);
492 
493     /* _HID or _DDN */
494 
495     HidString = MpGetHidValue (
496         ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle));
497     FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s", HidString);
498 
499     HidInfo = AcpiAhMatchHardwareId (HidString);
500     if (HidInfo)
501     {
502         FlPrintFile (ASL_FILE_MAP_OUTPUT, "    // %s",
503             HidInfo->Description);
504     }
505     else if ((DdnString = MpGetDdnValue (DevicePathname)))
506     {
507         FlPrintFile (ASL_FILE_MAP_OUTPUT, "    // %s (_DDN)", DdnString);
508     }
509 
510     FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n");
511     ACPI_FREE (DevicePathname);
512     return (AE_OK);
513 }
514 
515 
516 /*******************************************************************************
517  *
518  * FUNCTION:    MpXrefDevices
519  *
520  * PARAMETERS:  Info                    - A GPIO Info block
521  *
522  * RETURN:      None
523  *
524  * DESCRIPTION: Cross-reference the parse tree and find all references to the
525  *              specified GPIO device.
526  *
527  ******************************************************************************/
528 
529 static void
530 MpXrefDevices (
531     ACPI_GPIO_INFO          *Info)
532 {
533 
534     /* Walk the entire parse tree */
535 
536     TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
537         MpNamespaceXrefBegin, NULL, Info);
538 
539     if (!Info->References)
540     {
541         FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // **** No references in table");
542     }
543 }
544 
545 
546 /*******************************************************************************
547  *
548  * FUNCTION:    MpNamespaceXrefBegin
549  *
550  * PARAMETERS:  WALK_PARSE_TREE callback
551  *
552  * RETURN:      Status
553  *
554  * DESCRIPTION: Walk parse tree callback used to cross-reference GPIO pins.
555  *
556  ******************************************************************************/
557 
558 static ACPI_STATUS
559 MpNamespaceXrefBegin (
560     ACPI_PARSE_OBJECT       *Op,
561     UINT32                  Level,
562     void                    *Context)
563 {
564     ACPI_GPIO_INFO          *Info = ACPI_CAST_PTR (ACPI_GPIO_INFO, Context);
565     const ACPI_OPCODE_INFO  *OpInfo;
566     char                    *DevicePathname;
567     ACPI_PARSE_OBJECT       *ParentOp;
568     char                    *HidString;
569 
570 
571     ACPI_FUNCTION_TRACE_PTR (MpNamespaceXrefBegin, Op);
572 
573     /*
574      * If this node is the actual declaration of a name
575      * [such as the XXXX name in "Method (XXXX)"],
576      * we are not interested in it here. We only care about names that
577      * are references to other objects within the namespace and the
578      * parent objects of name declarations
579      */
580     if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
581     {
582         return (AE_OK);
583     }
584 
585     /* We are only interested in opcodes that have an associated name */
586 
587     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
588 
589     if ((OpInfo->Flags & AML_NAMED) ||
590         (OpInfo->Flags & AML_CREATE))
591     {
592         return (AE_OK);
593     }
594 
595     if ((Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
596         (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
597         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
598     {
599         return (AE_OK);
600     }
601 
602     if (!Op->Asl.Node)
603     {
604         return (AE_OK);
605     }
606 
607     ParentOp = Op->Asl.Parent;
608     if (ParentOp->Asl.ParseOpcode == PARSEOP_FIELD)
609     {
610         return (AE_OK);
611     }
612 
613     if (Op->Asl.Node == Info->TargetNode)
614     {
615         while (ParentOp && (!ParentOp->Asl.Node))
616         {
617             ParentOp = ParentOp->Asl.Parent;
618         }
619 
620         if (ParentOp)
621         {
622             DevicePathname = AcpiNsGetExternalPathname (
623                 ParentOp->Asl.Node);
624 
625             if (!Info->References)
626             {
627                 FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // References:");
628             }
629 
630             HidString = MpGetHidViaNamestring (DevicePathname);
631 
632             FlPrintFile (ASL_FILE_MAP_OUTPUT, " %s [%s]",
633                 DevicePathname, HidString);
634 
635             Info->References++;
636 
637             ACPI_FREE (DevicePathname);
638         }
639     }
640 
641     return (AE_OK);
642 }
643