xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslutils.c (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
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