Home | History | Annotate | Line # | Download | only in compiler
aslmapoutput.c revision 1.1
      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