Home | History | Annotate | Line # | Download | only in compiler
aslutils.c revision 1.19
      1 /******************************************************************************
      2  *
      3  * Module Name: aslutils -- compiler utilities
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, 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 "aslcompiler.h"
     45 #include "aslcompiler.y.h"
     46 #include "acdisasm.h"
     47 #include "acnamesp.h"
     48 #include "amlcode.h"
     49 #include "acapps.h"
     50 #include <sys/stat.h>
     51 
     52 
     53 #define _COMPONENT          ACPI_COMPILER
     54         ACPI_MODULE_NAME    ("aslutils")
     55 
     56 
     57 /* Local prototypes */
     58 
     59 static void
     60 UtPadNameWithUnderscores (
     61     char                    *NameSeg,
     62     char                    *PaddedNameSeg);
     63 
     64 static void
     65 UtAttachNameseg (
     66     ACPI_PARSE_OBJECT       *Op,
     67     char                    *Name);
     68 
     69 
     70 /*******************************************************************************
     71  *
     72  * FUNCTION:    UtIsBigEndianMachine
     73  *
     74  * PARAMETERS:  None
     75  *
     76  * RETURN:      TRUE if machine is big endian
     77  *              FALSE if machine is little endian
     78  *
     79  * DESCRIPTION: Detect whether machine is little endian or big endian.
     80  *
     81  ******************************************************************************/
     82 
     83 UINT8
     84 UtIsBigEndianMachine (
     85     void)
     86 {
     87     union {
     88         UINT32              Integer;
     89         UINT8               Bytes[4];
     90     } Overlay =                 {0xFF000000};
     91 
     92 
     93     return (Overlay.Bytes[0]); /* Returns 0xFF (TRUE) for big endian */
     94 }
     95 
     96 
     97 /******************************************************************************
     98  *
     99  * FUNCTION:    UtQueryForOverwrite
    100  *
    101  * PARAMETERS:  Pathname            - Output filename
    102  *
    103  * RETURN:      TRUE if file does not exist or overwrite is authorized
    104  *
    105  * DESCRIPTION: Query for file overwrite if it already exists.
    106  *
    107  ******************************************************************************/
    108 
    109 BOOLEAN
    110 UtQueryForOverwrite (
    111     char                    *Pathname)
    112 {
    113     struct stat             StatInfo;
    114 
    115 
    116     if (!stat (Pathname, &StatInfo))
    117     {
    118         fprintf (stderr, "Target file \"%s\" already exists, overwrite? [y|n] ",
    119             Pathname);
    120 
    121         if (getchar () != 'y')
    122         {
    123             return (FALSE);
    124         }
    125     }
    126 
    127     return (TRUE);
    128 }
    129 
    130 
    131 /*******************************************************************************
    132  *
    133  * FUNCTION:    UtDisplaySupportedTables
    134  *
    135  * PARAMETERS:  None
    136  *
    137  * RETURN:      None
    138  *
    139  * DESCRIPTION: Print all supported ACPI table names.
    140  *
    141  ******************************************************************************/
    142 
    143 void
    144 UtDisplaySupportedTables (
    145     void)
    146 {
    147     const AH_TABLE          *TableData;
    148     UINT32                  i;
    149 
    150 
    151     printf ("\nACPI tables supported by iASL version %8.8X:\n"
    152         "  (Compiler, Disassembler, Template Generator)\n\n",
    153         ACPI_CA_VERSION);
    154 
    155     /* All ACPI tables with the common table header */
    156 
    157     printf ("\n  Supported ACPI tables:\n");
    158     for (TableData = Gbl_AcpiSupportedTables, i = 1;
    159          TableData->Signature; TableData++, i++)
    160     {
    161         printf ("%8u) %s    %s\n", i,
    162             TableData->Signature, TableData->Description);
    163     }
    164 }
    165 
    166 
    167 /*******************************************************************************
    168  *
    169  * FUNCTION:    UtDisplayConstantOpcodes
    170  *
    171  * PARAMETERS:  None
    172  *
    173  * RETURN:      None
    174  *
    175  * DESCRIPTION: Print AML opcodes that can be used in constant expressions.
    176  *
    177  ******************************************************************************/
    178 
    179 void
    180 UtDisplayConstantOpcodes (
    181     void)
    182 {
    183     UINT32                  i;
    184 
    185 
    186     printf ("Constant expression opcode information\n\n");
    187 
    188     for (i = 0; i < sizeof (AcpiGbl_AmlOpInfo) / sizeof (ACPI_OPCODE_INFO); i++)
    189     {
    190         if (AcpiGbl_AmlOpInfo[i].Flags & AML_CONSTANT)
    191         {
    192             printf ("%s\n", AcpiGbl_AmlOpInfo[i].Name);
    193         }
    194     }
    195 }
    196 
    197 
    198 /*******************************************************************************
    199  *
    200  * FUNCTION:    UtBeginEvent
    201  *
    202  * PARAMETERS:  Name                - Ascii name of this event
    203  *
    204  * RETURN:      Event number (integer index)
    205  *
    206  * DESCRIPTION: Saves the current time with this event
    207  *
    208  ******************************************************************************/
    209 
    210 UINT8
    211 UtBeginEvent (
    212     char                    *Name)
    213 {
    214 
    215     if (AslGbl_NextEvent >= ASL_NUM_EVENTS)
    216     {
    217         AcpiOsPrintf ("Ran out of compiler event structs!\n");
    218         return (AslGbl_NextEvent);
    219     }
    220 
    221     /* Init event with current (start) time */
    222 
    223     AslGbl_Events[AslGbl_NextEvent].StartTime = AcpiOsGetTimer ();
    224     AslGbl_Events[AslGbl_NextEvent].EventName = Name;
    225     AslGbl_Events[AslGbl_NextEvent].Valid = TRUE;
    226     return (AslGbl_NextEvent++);
    227 }
    228 
    229 
    230 /*******************************************************************************
    231  *
    232  * FUNCTION:    UtEndEvent
    233  *
    234  * PARAMETERS:  Event               - Event number (integer index)
    235  *
    236  * RETURN:      None
    237  *
    238  * DESCRIPTION: Saves the current time (end time) with this event
    239  *
    240  ******************************************************************************/
    241 
    242 void
    243 UtEndEvent (
    244     UINT8                   Event)
    245 {
    246 
    247     if (Event >= ASL_NUM_EVENTS)
    248     {
    249         return;
    250     }
    251 
    252     /* Insert end time for event */
    253 
    254     AslGbl_Events[Event].EndTime = AcpiOsGetTimer ();
    255 }
    256 
    257 
    258 /*******************************************************************************
    259  *
    260  * FUNCTION:    DbgPrint
    261  *
    262  * PARAMETERS:  Type                - Type of output
    263  *              Fmt                 - Printf format string
    264  *              ...                 - variable printf list
    265  *
    266  * RETURN:      None
    267  *
    268  * DESCRIPTION: Conditional print statement. Prints to stderr only if the
    269  *              debug flag is set.
    270  *
    271  ******************************************************************************/
    272 
    273 void
    274 DbgPrint (
    275     UINT32                  Type,
    276     char                    *Fmt,
    277     ...)
    278 {
    279     va_list                 Args;
    280 
    281 
    282     if (!Gbl_DebugFlag)
    283     {
    284         return;
    285     }
    286 
    287     if ((Type == ASL_PARSE_OUTPUT) &&
    288         (!(AslCompilerdebug)))
    289     {
    290         return;
    291     }
    292 
    293     va_start (Args, Fmt);
    294     (void) vfprintf (stderr, Fmt, Args);
    295     va_end (Args);
    296     return;
    297 }
    298 
    299 
    300 /*******************************************************************************
    301  *
    302  * FUNCTION:    UtSetParseOpName
    303  *
    304  * PARAMETERS:  Op                  - Parse op to be named.
    305  *
    306  * RETURN:      None
    307  *
    308  * DESCRIPTION: Insert the ascii name of the parse opcode
    309  *
    310  ******************************************************************************/
    311 
    312 void
    313 UtSetParseOpName (
    314     ACPI_PARSE_OBJECT       *Op)
    315 {
    316 
    317     strncpy (Op->Asl.ParseOpName, UtGetOpName (Op->Asl.ParseOpcode),
    318         ACPI_MAX_PARSEOP_NAME);
    319 }
    320 
    321 
    322 /*******************************************************************************
    323  *
    324  * FUNCTION:    UtDisplaySummary
    325  *
    326  * PARAMETERS:  FileID              - ID of outpout file
    327  *
    328  * RETURN:      None
    329  *
    330  * DESCRIPTION: Display compilation statistics
    331  *
    332  ******************************************************************************/
    333 
    334 void
    335 UtDisplaySummary (
    336     UINT32                  FileId)
    337 {
    338     UINT32                  i;
    339 
    340 
    341     if (FileId != ASL_FILE_STDOUT)
    342     {
    343         /* Compiler name and version number */
    344 
    345         FlPrintFile (FileId, "%s version %X [%s]\n\n",
    346             ASL_COMPILER_NAME, (UINT32) ACPI_CA_VERSION, "2017-01-19");
    347     }
    348 
    349     /* Summary of main input and output files */
    350 
    351     if (Gbl_FileType == ASL_INPUT_TYPE_ASCII_DATA)
    352     {
    353         FlPrintFile (FileId,
    354             "%-14s %s - %u lines, %u bytes, %u fields\n",
    355             "Table Input:",
    356             Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber,
    357             Gbl_InputByteCount, Gbl_InputFieldCount);
    358 
    359         if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors))
    360         {
    361             FlPrintFile (FileId,
    362                 "%-14s %s - %u bytes\n",
    363                 "Binary Output:",
    364                 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength);
    365         }
    366     }
    367     else
    368     {
    369         FlPrintFile (FileId,
    370             "%-14s %s - %u lines, %u bytes, %u keywords\n",
    371             "ASL Input:",
    372             Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber,
    373             Gbl_OriginalInputFileSize, TotalKeywords);
    374 
    375         /* AML summary */
    376 
    377         if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors))
    378         {
    379             if (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle)
    380             {
    381                 FlPrintFile (FileId,
    382                     "%-14s %s - %u bytes, %u named objects, "
    383                     "%u executable opcodes\n",
    384                     "AML Output:",
    385                     Gbl_Files[ASL_FILE_AML_OUTPUT].Filename,
    386                     FlGetFileSize (ASL_FILE_AML_OUTPUT),
    387                     TotalNamedObjects, TotalExecutableOpcodes);
    388             }
    389         }
    390     }
    391 
    392     /* Display summary of any optional files */
    393 
    394     for (i = ASL_FILE_SOURCE_OUTPUT; i <= ASL_MAX_FILE_TYPE; i++)
    395     {
    396         if (!Gbl_Files[i].Filename || !Gbl_Files[i].Handle)
    397         {
    398             continue;
    399         }
    400 
    401         /* .SRC is a temp file unless specifically requested */
    402 
    403         if ((i == ASL_FILE_SOURCE_OUTPUT) && (!Gbl_SourceOutputFlag))
    404         {
    405             continue;
    406         }
    407 
    408         /* .PRE is the preprocessor intermediate file */
    409 
    410         if ((i == ASL_FILE_PREPROCESSOR)  && (!Gbl_KeepPreprocessorTempFile))
    411         {
    412             continue;
    413         }
    414 
    415         FlPrintFile (FileId, "%14s %s - %u bytes\n",
    416             Gbl_Files[i].ShortDescription,
    417             Gbl_Files[i].Filename, FlGetFileSize (i));
    418     }
    419 
    420     /* Error summary */
    421 
    422     FlPrintFile (FileId,
    423         "\nCompilation complete. %u Errors, %u Warnings, %u Remarks",
    424         Gbl_ExceptionCount[ASL_ERROR],
    425         Gbl_ExceptionCount[ASL_WARNING] +
    426             Gbl_ExceptionCount[ASL_WARNING2] +
    427             Gbl_ExceptionCount[ASL_WARNING3],
    428         Gbl_ExceptionCount[ASL_REMARK]);
    429 
    430     if (Gbl_FileType != ASL_INPUT_TYPE_ASCII_DATA)
    431     {
    432         FlPrintFile (FileId, ", %u Optimizations",
    433             Gbl_ExceptionCount[ASL_OPTIMIZATION]);
    434 
    435         if (TotalFolds)
    436         {
    437             FlPrintFile (FileId, ", %u Constants Folded", TotalFolds);
    438         }
    439     }
    440 
    441     FlPrintFile (FileId, "\n");
    442 }
    443 
    444 
    445 /*******************************************************************************
    446  *
    447  * FUNCTION:    UtCheckIntegerRange
    448  *
    449  * PARAMETERS:  Op                  - Integer parse node
    450  *              LowValue            - Smallest allowed value
    451  *              HighValue           - Largest allowed value
    452  *
    453  * RETURN:      Op if OK, otherwise NULL
    454  *
    455  * DESCRIPTION: Check integer for an allowable range
    456  *
    457  ******************************************************************************/
    458 
    459 ACPI_PARSE_OBJECT *
    460 UtCheckIntegerRange (
    461     ACPI_PARSE_OBJECT       *Op,
    462     UINT32                  LowValue,
    463     UINT32                  HighValue)
    464 {
    465 
    466     if (!Op)
    467     {
    468         return (NULL);
    469     }
    470 
    471     if ((Op->Asl.Value.Integer < LowValue) ||
    472         (Op->Asl.Value.Integer > HighValue))
    473     {
    474         snprintf (MsgBuffer, sizeof(MsgBuffer), "0x%X, allowable: 0x%X-0x%X",
    475             (UINT32) Op->Asl.Value.Integer, LowValue, HighValue);
    476 
    477         AslError (ASL_ERROR, ASL_MSG_RANGE, Op, MsgBuffer);
    478         return (NULL);
    479     }
    480 
    481     return (Op);
    482 }
    483 
    484 
    485 /*******************************************************************************
    486  *
    487  * FUNCTION:    UtInternalizeName
    488  *
    489  * PARAMETERS:  ExternalName        - Name to convert
    490  *              ConvertedName       - Where the converted name is returned
    491  *
    492  * RETURN:      Status
    493  *
    494  * DESCRIPTION: Convert an external (ASL) name to an internal (AML) name
    495  *
    496  ******************************************************************************/
    497 
    498 ACPI_STATUS
    499 UtInternalizeName (
    500     char                    *ExternalName,
    501     char                    **ConvertedName)
    502 {
    503     ACPI_NAMESTRING_INFO    Info;
    504     ACPI_STATUS             Status;
    505 
    506 
    507     if (!ExternalName)
    508     {
    509         return (AE_OK);
    510     }
    511 
    512     /* Get the length of the new internal name */
    513 
    514     Info.ExternalName = ExternalName;
    515     AcpiNsGetInternalNameLength (&Info);
    516 
    517     /* We need a segment to store the internal name */
    518 
    519     Info.InternalName = UtLocalCacheCalloc (Info.Length);
    520 
    521     /* Build the name */
    522 
    523     Status = AcpiNsBuildInternalName (&Info);
    524     if (ACPI_FAILURE (Status))
    525     {
    526         return (Status);
    527     }
    528 
    529     *ConvertedName = Info.InternalName;
    530     return (AE_OK);
    531 }
    532 
    533 
    534 /*******************************************************************************
    535  *
    536  * FUNCTION:    UtPadNameWithUnderscores
    537  *
    538  * PARAMETERS:  NameSeg             - Input nameseg
    539  *              PaddedNameSeg       - Output padded nameseg
    540  *
    541  * RETURN:      Padded nameseg.
    542  *
    543  * DESCRIPTION: Pads a NameSeg with underscores if necessary to form a full
    544  *              ACPI_NAME.
    545  *
    546  ******************************************************************************/
    547 
    548 static void
    549 UtPadNameWithUnderscores (
    550     char                    *NameSeg,
    551     char                    *PaddedNameSeg)
    552 {
    553     UINT32                  i;
    554 
    555 
    556     for (i = 0; (i < ACPI_NAME_SIZE); i++)
    557     {
    558         if (*NameSeg)
    559         {
    560             *PaddedNameSeg = *NameSeg;
    561             NameSeg++;
    562         }
    563         else
    564         {
    565             *PaddedNameSeg = '_';
    566         }
    567 
    568         PaddedNameSeg++;
    569     }
    570 }
    571 
    572 
    573 /*******************************************************************************
    574  *
    575  * FUNCTION:    UtAttachNameseg
    576  *
    577  * PARAMETERS:  Op                  - Parent parse node
    578  *              Name                - Full ExternalName
    579  *
    580  * RETURN:      None; Sets the NameSeg field in parent node
    581  *
    582  * DESCRIPTION: Extract the last nameseg of the ExternalName and store it
    583  *              in the NameSeg field of the Op.
    584  *
    585  ******************************************************************************/
    586 
    587 static void
    588 UtAttachNameseg (
    589     ACPI_PARSE_OBJECT       *Op,
    590     char                    *Name)
    591 {
    592     char                    *NameSeg;
    593     char                    PaddedNameSeg[4];
    594 
    595 
    596     if (!Name)
    597     {
    598         return;
    599     }
    600 
    601     /* Look for the last dot in the namepath */
    602 
    603     NameSeg = strrchr (Name, '.');
    604     if (NameSeg)
    605     {
    606         /* Found last dot, we have also found the final nameseg */
    607 
    608         NameSeg++;
    609         UtPadNameWithUnderscores (NameSeg, PaddedNameSeg);
    610     }
    611     else
    612     {
    613         /* No dots in the namepath, there is only a single nameseg. */
    614         /* Handle prefixes */
    615 
    616         while (ACPI_IS_ROOT_PREFIX (*Name) ||
    617                ACPI_IS_PARENT_PREFIX (*Name))
    618         {
    619             Name++;
    620         }
    621 
    622         /* Remaining string should be one single nameseg */
    623 
    624         UtPadNameWithUnderscores (Name, PaddedNameSeg);
    625     }
    626 
    627     ACPI_MOVE_NAME (Op->Asl.NameSeg, PaddedNameSeg);
    628 }
    629 
    630 
    631 /*******************************************************************************
    632  *
    633  * FUNCTION:    UtAttachNamepathToOwner
    634  *
    635  * PARAMETERS:  Op                  - Parent parse node
    636  *              NameOp              - Node that contains the name
    637  *
    638  * RETURN:      Sets the ExternalName and Namepath in the parent node
    639  *
    640  * DESCRIPTION: Store the name in two forms in the parent node: The original
    641  *              (external) name, and the internalized name that is used within
    642  *              the ACPI namespace manager.
    643  *
    644  ******************************************************************************/
    645 
    646 void
    647 UtAttachNamepathToOwner (
    648     ACPI_PARSE_OBJECT       *Op,
    649     ACPI_PARSE_OBJECT       *NameOp)
    650 {
    651     ACPI_STATUS             Status;
    652 
    653 
    654     /* Full external path */
    655 
    656     Op->Asl.ExternalName = NameOp->Asl.Value.String;
    657 
    658     /* Save the NameOp for possible error reporting later */
    659 
    660     Op->Asl.ParentMethod = (void *) NameOp;
    661 
    662     /* Last nameseg of the path */
    663 
    664     UtAttachNameseg (Op, Op->Asl.ExternalName);
    665 
    666     /* Create internalized path */
    667 
    668     Status = UtInternalizeName (NameOp->Asl.Value.String, &Op->Asl.Namepath);
    669     if (ACPI_FAILURE (Status))
    670     {
    671         /* TBD: abort on no memory */
    672     }
    673 }
    674 
    675 
    676 /*******************************************************************************
    677  *
    678  * FUNCTION:    UtDoConstant
    679  *
    680  * PARAMETERS:  String              - Hex/Decimal/Octal
    681  *
    682  * RETURN:      Converted Integer
    683  *
    684  * DESCRIPTION: Convert a string to an integer, with overflow/error checking.
    685  *
    686  ******************************************************************************/
    687 
    688 UINT64
    689 UtDoConstant (
    690     char                    *String)
    691 {
    692     ACPI_STATUS             Status;
    693     UINT64                  ConvertedInteger;
    694     char                    ErrBuf[64];
    695 
    696 
    697     Status = AcpiUtStrtoul64 (String, &ConvertedInteger);
    698     if (ACPI_FAILURE (Status))
    699     {
    700         snprintf (ErrBuf, sizeof(ErrBuf), "While creating 64-bit constant: %s\n",
    701             AcpiFormatException (Status));
    702 
    703         AslCommonError (ASL_ERROR, ASL_MSG_SYNTAX, Gbl_CurrentLineNumber,
    704             Gbl_LogicalLineNumber, Gbl_CurrentLineOffset,
    705             Gbl_CurrentColumn, Gbl_Files[ASL_FILE_INPUT].Filename, ErrBuf);
    706     }
    707 
    708     return (ConvertedInteger);
    709 }
    710