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