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