1/******************************************************************************
2 *
3 * Module Name: aslmapoutput - Output/emit the resource descriptor/device maps
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, 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
61static void
62MpEmitGpioInfo (
63    void);
64
65static void
66MpEmitSerialInfo (
67    void);
68
69static void
70MpEmitDeviceTree (
71    void);
72
73static ACPI_STATUS
74MpEmitOneDevice (
75    ACPI_HANDLE             ObjHandle,
76    UINT32                  NestingLevel,
77    void                    *Context,
78    void                    **ReturnValue);
79
80static void
81MpXrefDevices (
82    ACPI_GPIO_INFO          *Info);
83
84static ACPI_STATUS
85MpNamespaceXrefBegin (
86    ACPI_PARSE_OBJECT       *Op,
87    UINT32                  Level,
88    void                    *Context);
89
90
91/* Strings used to decode flag bits */
92
93const char                  *DirectionDecode[] =
94{
95    "Both I/O   ",
96    "InputOnly  ",
97    "OutputOnly ",
98    "Preserve   "
99};
100
101const 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
125void
126MpEmitMappingInfo (
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
185static void
186MpEmitGpioInfo (
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
319static void
320MpEmitSerialInfo (
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
442static void
443MpEmitDeviceTree (
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
473static ACPI_STATUS
474MpEmitOneDevice (
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
529static void
530MpXrefDevices (
531    ACPI_GPIO_INFO          *Info)
532{
533
534    /* Walk the entire parse tree */
535
536    TrWalkParseTree (Gbl_ParseTreeRoot, 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
558static ACPI_STATUS
559MpNamespaceXrefBegin (
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