1 /******************************************************************************
2 *
3 * Module Name: asllisting - Listing file generation
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 "amlcode.h"
47 #include "acparser.h"
48 #include "acnamesp.h"
49
50
51 #define _COMPONENT ACPI_COMPILER
52 ACPI_MODULE_NAME ("asllisting")
53
54
55 /* Local prototypes */
56
57 static void
58 LsGenerateListing (
59 UINT32 FileId);
60
61 static ACPI_STATUS
62 LsAmlListingWalk (
63 ACPI_PARSE_OBJECT *Op,
64 UINT32 Level,
65 void *Context);
66
67 static ACPI_STATUS
68 LsTreeWriteWalk (
69 ACPI_PARSE_OBJECT *Op,
70 UINT32 Level,
71 void *Context);
72
73 static void
74 LsWriteNodeToListing (
75 ACPI_PARSE_OBJECT *Op,
76 UINT32 FileId);
77
78 static void
79 LsFinishSourceListing (
80 UINT32 FileId);
81
82
83 /*******************************************************************************
84 *
85 * FUNCTION: LsDoListings
86 *
87 * PARAMETERS: None. Examines the various output file global flags.
88 *
89 * RETURN: None
90 *
91 * DESCRIPTION: Generate all requested listing files.
92 *
93 ******************************************************************************/
94
95 void
LsDoListings(void)96 LsDoListings (
97 void)
98 {
99
100 if (AslGbl_C_OutputFlag)
101 {
102 LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT);
103 }
104
105 if (AslGbl_ListingFlag)
106 {
107 LsGenerateListing (ASL_FILE_LISTING_OUTPUT);
108 }
109
110 if (AslGbl_AsmOutputFlag)
111 {
112 LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT);
113 }
114
115 if (AslGbl_C_IncludeOutputFlag)
116 {
117 LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT);
118 }
119
120 if (AslGbl_AsmIncludeOutputFlag)
121 {
122 LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT);
123 }
124
125 if (AslGbl_C_OffsetTableFlag)
126 {
127 LsGenerateListing (ASL_FILE_C_OFFSET_OUTPUT);
128 }
129 }
130
131
132 /*******************************************************************************
133 *
134 * FUNCTION: LsGenerateListing
135 *
136 * PARAMETERS: FileId - ID of listing file
137 *
138 * RETURN: None
139 *
140 * DESCRIPTION: Generate a listing file. This can be one of the several types
141 * of "listings" supported.
142 *
143 ******************************************************************************/
144
145 static void
LsGenerateListing(UINT32 FileId)146 LsGenerateListing (
147 UINT32 FileId)
148 {
149 UINT32 WalkMode = ASL_WALK_VISIT_DOWNWARD | ASL_WALK_VISIT_DB_SEPARATELY;
150
151 /* Start at the beginning of both the source and AML files */
152
153 FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0);
154 FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
155 AslGbl_SourceLine = 0;
156 AslGbl_CurrentHexColumn = 0;
157 LsPushNode (AslGbl_Files[ASL_FILE_INPUT].Filename);
158
159 if (FileId == ASL_FILE_C_OFFSET_OUTPUT)
160 {
161 AslGbl_CurrentAmlOffset = 0;
162
163 /* Offset table file has a special header and footer */
164
165 LsDoOffsetTableHeader (FileId);
166
167 TrWalkParseTree (AslGbl_CurrentDB, WalkMode,
168 LsAmlOffsetWalk, NULL, (void *) ACPI_TO_POINTER (FileId));
169 LsDoOffsetTableFooter (FileId);
170 return;
171 }
172
173 /* Process all parse nodes */
174
175 TrWalkParseTree (AslGbl_CurrentDB, WalkMode,
176 LsAmlListingWalk, NULL, (void *) ACPI_TO_POINTER (FileId));
177
178 /* Final processing */
179
180 LsFinishSourceListing (FileId);
181 }
182
183
184 /*******************************************************************************
185 *
186 * FUNCTION: LsAmlListingWalk
187 *
188 * PARAMETERS: ASL_WALK_CALLBACK
189 *
190 * RETURN: Status
191 *
192 * DESCRIPTION: Process one node during a listing file generation.
193 *
194 ******************************************************************************/
195
196 static ACPI_STATUS
LsAmlListingWalk(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)197 LsAmlListingWalk (
198 ACPI_PARSE_OBJECT *Op,
199 UINT32 Level,
200 void *Context)
201 {
202 UINT8 FileByte;
203 UINT32 i;
204 UINT32 FileId = (UINT32) ACPI_TO_INTEGER (Context);
205
206
207 LsWriteNodeToListing (Op, FileId);
208
209 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DATA)
210 {
211 /* Buffer is a resource template, don't dump the data all at once */
212
213 return (AE_OK);
214 }
215
216 if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
217 (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
218 {
219 return (AE_OK);
220 }
221
222 /* Write the hex bytes to the listing file(s) (if requested) */
223
224 for (i = 0; i < Op->Asl.FinalAmlLength; i++)
225 {
226 if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1)))
227 {
228 FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
229 AslAbort ();
230 }
231
232 LsWriteListingHexBytes (&FileByte, 1, FileId);
233 }
234
235 return (AE_OK);
236 }
237
238
239 /*******************************************************************************
240 *
241 * FUNCTION: LsDumpParseTree, LsTreeWriteWalk
242 *
243 * PARAMETERS: None
244 *
245 * RETURN: None
246 *
247 * DESCRIPTION: Dump entire parse tree, for compiler debug only
248 *
249 ******************************************************************************/
250
251 void
LsDumpParseTree(void)252 LsDumpParseTree (
253 void)
254 {
255
256 if (!AslGbl_DebugFlag)
257 {
258 return;
259 }
260
261 DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n");
262 DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER1);
263
264 TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
265 LsTreeWriteWalk, NULL, NULL);
266
267 DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER1);
268 }
269
270
271 static ACPI_STATUS
LsTreeWriteWalk(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)272 LsTreeWriteWalk (
273 ACPI_PARSE_OBJECT *Op,
274 UINT32 Level,
275 void *Context)
276 {
277
278 /* Dump ParseOp name and possible value */
279
280 switch (Op->Asl.ParseOpcode)
281 {
282 case PARSEOP_NAMESEG:
283 case PARSEOP_NAMESTRING:
284 case PARSEOP_METHODCALL:
285 case PARSEOP_STRING_LITERAL:
286
287 UtDumpStringOp (Op, Level);
288 break;
289
290 case PARSEOP_BYTECONST:
291
292 UtDumpIntegerOp (Op, Level, 2);
293 break;
294
295 case PARSEOP_WORDCONST:
296 case PARSEOP_PACKAGE_LENGTH:
297
298 UtDumpIntegerOp (Op, Level, 4);
299 break;
300
301 case PARSEOP_DWORDCONST:
302 case PARSEOP_EISAID:
303
304 UtDumpIntegerOp (Op, Level, 8);
305 break;
306
307 case PARSEOP_QWORDCONST:
308 case PARSEOP_INTEGER:
309 case PARSEOP_ONE:
310 case PARSEOP_ZERO:
311 case PARSEOP_ONES:
312
313 UtDumpIntegerOp (Op, Level, 16);
314 break;
315
316 case PARSEOP_INCLUDE:
317
318 DbgPrint (ASL_TREE_OUTPUT,
319 "Open: %s\n", Op->Asl.Value.String);
320 return (AE_OK);
321
322 case PARSEOP_INCLUDE_END:
323
324 DbgPrint (ASL_TREE_OUTPUT,
325 "Close: %s\n", Op->Asl.Filename);
326 return (AE_OK);
327
328 default:
329
330 UtDumpBasicOp (Op, Level);
331 break;
332 }
333
334 /* Dump the remaining data */
335
336 DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_DEBUG1,
337 Op->Asl.ParseOpcode, Op->Asl.CompileFlags,
338 Op->Asl.LineNumber, Op->Asl.EndLine,
339 Op->Asl.LogicalLineNumber, Op->Asl.EndLogicalLine);
340
341 TrPrintOpFlags (Op->Asl.CompileFlags, ASL_TREE_OUTPUT);
342 DbgPrint (ASL_TREE_OUTPUT, "\n");
343 return (AE_OK);
344 }
345
346
347 /*******************************************************************************
348 *
349 * FUNCTION: LsWriteNodeToListing
350 *
351 * PARAMETERS: Op - Parse node to write to the listing file.
352 * FileId - ID of current listing file
353 *
354 * RETURN: None.
355 *
356 * DESCRIPTION: Write "a node" to the listing file. This means to
357 * 1) Write out all of the source text associated with the node
358 * 2) Write out all of the AML bytes associated with the node
359 * 3) Write any compiler exceptions associated with the node
360 *
361 ******************************************************************************/
362
363 static void
LsWriteNodeToListing(ACPI_PARSE_OBJECT * Op,UINT32 FileId)364 LsWriteNodeToListing (
365 ACPI_PARSE_OBJECT *Op,
366 UINT32 FileId)
367 {
368 const ACPI_OPCODE_INFO *OpInfo;
369 UINT32 OpClass;
370 char *Pathname;
371 UINT32 Length;
372 UINT32 i;
373
374
375 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
376 OpClass = OpInfo->Class;
377
378 /* TBD: clean this up with a single flag that says:
379 * I start a named output block
380 */
381 if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
382 {
383 switch (Op->Asl.ParseOpcode)
384 {
385 case PARSEOP_DEFINITION_BLOCK:
386 case PARSEOP_METHODCALL:
387 case PARSEOP_INCLUDE:
388 case PARSEOP_INCLUDE_END:
389 case PARSEOP_DEFAULT_ARG:
390
391 break;
392
393 default:
394
395 switch (OpClass)
396 {
397 case AML_CLASS_NAMED_OBJECT:
398
399 switch (Op->Asl.AmlOpcode)
400 {
401 case AML_SCOPE_OP:
402 case AML_ALIAS_OP:
403
404 break;
405
406 default:
407
408 if (Op->Asl.ExternalName)
409 {
410 LsFlushListingBuffer (FileId);
411 FlPrintFile (FileId, " };\n");
412 }
413 break;
414 }
415 break;
416
417 default:
418
419 /* Don't care about other objects */
420
421 break;
422 }
423 break;
424 }
425 }
426
427 /* These cases do not have a corresponding AML opcode */
428
429 switch (Op->Asl.ParseOpcode)
430 {
431 case PARSEOP_DEFINITION_BLOCK:
432
433 /* Always start a definition block at AML offset zero */
434
435 AslGbl_CurrentAmlOffset = 0;
436 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId);
437
438 /* Use the table Signature and TableId to build a unique name */
439
440 switch (FileId)
441 {
442 case ASL_FILE_ASM_SOURCE_OUTPUT:
443
444 FlPrintFile (FileId,
445 "%s_%s_Header \\\n",
446 AslGbl_TableSignature, AslGbl_TableId);
447 break;
448
449 case ASL_FILE_C_SOURCE_OUTPUT:
450
451 FlPrintFile (FileId,
452 " unsigned char %s_%s_Header [] =\n {\n",
453 AslGbl_TableSignature, AslGbl_TableId);
454 break;
455
456 case ASL_FILE_ASM_INCLUDE_OUTPUT:
457
458 FlPrintFile (FileId,
459 "extrn %s_%s_Header : byte\n",
460 AslGbl_TableSignature, AslGbl_TableId);
461 break;
462
463 case ASL_FILE_C_INCLUDE_OUTPUT:
464
465 FlPrintFile (FileId,
466 "extern unsigned char %s_%s_Header [];\n",
467 AslGbl_TableSignature, AslGbl_TableId);
468 break;
469
470 default:
471 break;
472 }
473
474 return;
475
476
477 case PARSEOP_METHODCALL:
478
479 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
480 FileId);
481 return;
482
483
484 case PARSEOP_INCLUDE:
485
486 /* Flush everything up to and including the include source line */
487
488 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
489 FileId);
490
491 /* Create a new listing node and push it */
492
493 LsPushNode (Op->Asl.Value.String);
494 return;
495
496
497 case PARSEOP_INCLUDE_END:
498
499 /* Flush out the rest of the include file */
500
501 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
502 FileId);
503
504 /* Pop off this listing node and go back to the parent file */
505
506 (void) LsPopNode ();
507 return;
508
509
510 case PARSEOP_DEFAULT_ARG:
511
512 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC)
513 {
514 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine,
515 FileId);
516 }
517 return;
518
519
520 default:
521
522 /* All other opcodes have an AML opcode */
523
524 break;
525 }
526
527 /*
528 * Otherwise, we look at the AML opcode because we can
529 * switch on the opcode type, getting an entire class
530 * at once
531 */
532 switch (OpClass)
533 {
534 case AML_CLASS_ARGUMENT: /* argument type only */
535 case AML_CLASS_INTERNAL:
536
537 break;
538
539 case AML_CLASS_NAMED_OBJECT:
540
541 switch (Op->Asl.AmlOpcode)
542 {
543 case AML_FIELD_OP:
544 case AML_INDEX_FIELD_OP:
545 case AML_BANK_FIELD_OP:
546 /*
547 * For fields, we want to dump all the AML after the
548 * entire definition
549 */
550 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
551 FileId);
552 break;
553
554 case AML_NAME_OP:
555
556 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC)
557 {
558 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
559 FileId);
560 }
561 else
562 {
563 /*
564 * For fields, we want to dump all the AML after the
565 * entire definition
566 */
567 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
568 FileId);
569 }
570 break;
571
572 default:
573
574 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
575 FileId);
576 break;
577 }
578
579 switch (Op->Asl.AmlOpcode)
580 {
581 case AML_SCOPE_OP:
582 case AML_ALIAS_OP:
583
584 /* These opcodes do not declare a new object, ignore them */
585
586 break;
587
588 default:
589
590 /* All other named object opcodes come here */
591
592 switch (FileId)
593 {
594 case ASL_FILE_ASM_SOURCE_OUTPUT:
595 case ASL_FILE_C_SOURCE_OUTPUT:
596 case ASL_FILE_ASM_INCLUDE_OUTPUT:
597 case ASL_FILE_C_INCLUDE_OUTPUT:
598 /*
599 * For named objects, we will create a valid symbol so that the
600 * AML code can be referenced from C or ASM
601 */
602 if (Op->Asl.ExternalName)
603 {
604 /* Get the full pathname associated with this node */
605
606 Pathname = AcpiNsGetExternalPathname (Op->Asl.Node);
607 Length = strlen (Pathname);
608 if (Length >= 4)
609 {
610 /* Convert all dots in the path to underscores */
611
612 for (i = 0; i < Length; i++)
613 {
614 if (Pathname[i] == '.')
615 {
616 Pathname[i] = '_';
617 }
618 }
619
620 /* Create the appropriate symbol in the output file */
621
622 switch (FileId)
623 {
624 case ASL_FILE_ASM_SOURCE_OUTPUT:
625
626 FlPrintFile (FileId,
627 "%s_%s_%s \\\n",
628 AslGbl_TableSignature, AslGbl_TableId, &Pathname[1]);
629 break;
630
631 case ASL_FILE_C_SOURCE_OUTPUT:
632
633 FlPrintFile (FileId,
634 " unsigned char %s_%s_%s [] =\n {\n",
635 AslGbl_TableSignature, AslGbl_TableId, &Pathname[1]);
636 break;
637
638 case ASL_FILE_ASM_INCLUDE_OUTPUT:
639
640 FlPrintFile (FileId,
641 "extrn %s_%s_%s : byte\n",
642 AslGbl_TableSignature, AslGbl_TableId, &Pathname[1]);
643 break;
644
645 case ASL_FILE_C_INCLUDE_OUTPUT:
646
647 FlPrintFile (FileId,
648 "extern unsigned char %s_%s_%s [];\n",
649 AslGbl_TableSignature, AslGbl_TableId, &Pathname[1]);
650 break;
651
652 default:
653 break;
654 }
655 }
656
657 ACPI_FREE (Pathname);
658 }
659 break;
660
661 default:
662
663 /* Nothing to do for listing file */
664
665 break;
666 }
667 }
668 break;
669
670 case AML_CLASS_EXECUTE:
671 case AML_CLASS_CREATE:
672 default:
673
674 if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) &&
675 (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC))
676 {
677 return;
678 }
679
680 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
681 FileId);
682 break;
683
684 case AML_CLASS_UNKNOWN:
685
686 break;
687 }
688 }
689
690
691 /*******************************************************************************
692 *
693 * FUNCTION: LsFinishSourceListing
694 *
695 * PARAMETERS: FileId - ID of current listing file.
696 *
697 * RETURN: None
698 *
699 * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML
700 * listing buffer, and flush out any remaining lines in the
701 * source input file.
702 *
703 ******************************************************************************/
704
705 static void
LsFinishSourceListing(UINT32 FileId)706 LsFinishSourceListing (
707 UINT32 FileId)
708 {
709
710 if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
711 (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
712 {
713 return;
714 }
715
716 LsFlushListingBuffer (FileId);
717 AslGbl_CurrentAmlOffset = 0;
718
719 /* Flush any remaining text in the source file */
720
721 if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
722 {
723 FlPrintFile (FileId, " /*\n");
724 }
725
726 while (LsWriteOneSourceLine (FileId))
727 { ; }
728
729 if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
730 {
731 FlPrintFile (FileId, "\n */\n };\n");
732 }
733
734 FlPrintFile (FileId, "\n");
735
736 if (FileId == ASL_FILE_LISTING_OUTPUT)
737 {
738 /* Print a summary of the compile exceptions */
739
740 FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n");
741 AePrintErrorLog (FileId);
742 FlPrintFile (FileId, "\n");
743 UtDisplayOneSummary (FileId, TRUE);
744 FlPrintFile (FileId, "\n");
745 }
746 }
747