1 /******************************************************************************
2  *
3  * Module Name: dttemplate - ACPI table template generation
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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 "acapps.h"
46 #include "dtcompiler.h"
47 #include "dttemplate.h" /* Contains the hex ACPI table templates */
48 
49 #define _COMPONENT          DT_COMPILER
50         ACPI_MODULE_NAME    ("dttemplate")
51 
52 
53 /* Local prototypes */
54 
55 static BOOLEAN
56 AcpiUtIsSpecialTable (
57     char                    *Signature);
58 
59 static ACPI_STATUS
60 DtCreateOneTemplateFile (
61     char                    *Signature,
62     UINT32                  TableCount);
63 
64 static ACPI_STATUS
65 DtCreateOneTemplate (
66     char                    *Signature,
67     UINT32                  TableCount,
68     const ACPI_DMTABLE_DATA *TableData);
69 
70 static ACPI_STATUS
71 DtCreateAllTemplates (
72     void);
73 
74 static int
75 DtEmitDefinitionBlock (
76     FILE                    *File,
77     char                    *Filename,
78     char                    *Signature,
79     UINT32                  Instance);
80 
81 
82 /*******************************************************************************
83  *
84  * FUNCTION:    AcpiUtIsSpecialTable
85  *
86  * PARAMETERS:  Signature           - ACPI table signature
87  *
88  * RETURN:      TRUE if signature is a special ACPI table
89  *
90  * DESCRIPTION: Check for valid ACPI tables that are not in the main ACPI
91  *              table data structure (AcpiDmTableData).
92  *
93  ******************************************************************************/
94 
95 static BOOLEAN
96 AcpiUtIsSpecialTable (
97     char                    *Signature)
98 {
99 
100     if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) ||
101         ACPI_COMPARE_NAME (Signature, ACPI_SIG_OSDT) ||
102         ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT) ||
103         ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS) ||
104         ACPI_COMPARE_NAME (Signature, ACPI_RSDP_NAME))
105     {
106         return (TRUE);
107     }
108 
109     return (FALSE);
110 }
111 
112 
113 /*******************************************************************************
114  *
115  * FUNCTION:    DtCreateTemplates
116  *
117  * PARAMETERS:  argv                - Standard command line arguments
118  *
119  * RETURN:      Status
120  *
121  * DESCRIPTION: Create one or more template files.
122  *
123  ******************************************************************************/
124 
125 ACPI_STATUS
126 DtCreateTemplates (
127     char                    **argv)
128 {
129     char                    *Signature;
130     char                    *End;
131     unsigned long           TableCount;
132     ACPI_STATUS             Status = AE_OK;
133 
134 
135     AslInitializeGlobals ();
136 
137     Status = AdInitialize ();
138     if (ACPI_FAILURE (Status))
139     {
140         return (Status);
141     }
142 
143     /*
144      * Special cases for DSDT, ALL, and '*'
145      */
146 
147     /* Default (no signature option) is DSDT */
148 
149     if (AcpiGbl_Optind < 3)
150     {
151         Status = DtCreateOneTemplateFile (ACPI_SIG_DSDT, 0);
152         goto Exit;
153     }
154 
155     AcpiGbl_Optind--;
156     Signature = argv[AcpiGbl_Optind];
157     AcpiUtStrupr (Signature);
158 
159     /*
160      * Multiple SSDT support (-T <ssdt count>)
161      */
162     TableCount = strtoul (Signature, &End, 0);
163     if (Signature != End)
164     {
165         /* The count is used for table ID and method name - max is 254(+1) */
166 
167         if (TableCount > 254)
168         {
169             fprintf (stderr, "%u SSDTs requested, maximum is 254\n",
170                 (unsigned int) TableCount);
171 
172             Status = AE_LIMIT;
173             goto Exit;
174         }
175 
176         Status = DtCreateOneTemplateFile (ACPI_SIG_DSDT, TableCount);
177         goto Exit;
178     }
179 
180     if (!strcmp (Signature, "ALL"))
181     {
182         /* Create all available/known templates */
183 
184         Status = DtCreateAllTemplates ();
185         goto Exit;
186     }
187 
188     /*
189      * Normal case: Create template for each signature
190      */
191     while (argv[AcpiGbl_Optind])
192     {
193         Signature = argv[AcpiGbl_Optind];
194         AcpiUtStrupr (Signature);
195 
196         Status = DtCreateOneTemplateFile (Signature, 0);
197         if (ACPI_FAILURE (Status))
198         {
199             goto Exit;
200         }
201 
202         AcpiGbl_Optind++;
203     }
204 
205 
206 Exit:
207     /* Shutdown ACPICA subsystem */
208 
209     (void) AcpiTerminate ();
210     CmDeleteCaches ();
211     return (Status);
212 }
213 
214 
215 /*******************************************************************************
216  *
217  * FUNCTION:    DtCreateOneTemplateFile
218  *
219  * PARAMETERS:  Signature           - ACPI table signature
220  *
221  * RETURN:      Status
222  *
223  * DESCRIPTION: Create one template file of the requested signature.
224  *
225  ******************************************************************************/
226 
227 static ACPI_STATUS
228 DtCreateOneTemplateFile (
229     char                    *Signature,
230     UINT32                  TableCount)
231 {
232     const ACPI_DMTABLE_DATA *TableData;
233     ACPI_STATUS             Status;
234 
235 
236     /*
237      * Validate signature and get the template data:
238      *  1) Signature must be 4 characters
239      *  2) Signature must be a recognized ACPI table
240      *  3) There must be a template associated with the signature
241      */
242     if (strlen (Signature) != ACPI_NAME_SIZE)
243     {
244         fprintf (stderr,
245             "%s: Invalid ACPI table signature "
246             "(length must be 4 characters)\n", Signature);
247         return (AE_ERROR);
248     }
249 
250     /*
251      * Some slack for the two strange tables whose name is different than
252      * their signatures: MADT->APIC and FADT->FACP.
253      */
254     if (!strcmp (Signature, "MADT"))
255     {
256         Signature = "APIC";
257     }
258     else if (!strcmp (Signature, "FADT"))
259     {
260         Signature = "FACP";
261     }
262 
263     /* TableData will point to the template */
264 
265     TableData = AcpiDmGetTableData (Signature);
266     if (TableData)
267     {
268         if (!TableData->Template)
269         {
270             fprintf (stderr, "%4.4s: No template available\n", Signature);
271             return (AE_ERROR);
272         }
273     }
274     else if (!AcpiUtIsSpecialTable (Signature))
275     {
276         fprintf (stderr,
277             "%4.4s: Unrecognized ACPI table signature\n", Signature);
278         return (AE_ERROR);
279     }
280 
281     Status = DtCreateOneTemplate (Signature, TableCount, TableData);
282     return (Status);
283 }
284 
285 
286 /*******************************************************************************
287  *
288  * FUNCTION:    DtCreateAllTemplates
289  *
290  * PARAMETERS:  None
291  *
292  * RETURN:      Status
293  *
294  * DESCRIPTION: Create all currently defined template files
295  *
296  ******************************************************************************/
297 
298 static ACPI_STATUS
299 DtCreateAllTemplates (
300     void)
301 {
302     const ACPI_DMTABLE_DATA *TableData;
303     ACPI_STATUS             Status;
304 
305 
306     fprintf (stderr, "Creating all supported Template files\n");
307 
308     /* Walk entire ACPI table data structure */
309 
310     for (TableData = AcpiDmTableData; TableData->Signature; TableData++)
311     {
312         /* If table has a template, create the template file */
313 
314         if (TableData->Template)
315         {
316             Status = DtCreateOneTemplate (TableData->Signature,
317                 0, TableData);
318             if (ACPI_FAILURE (Status))
319             {
320                 return (Status);
321             }
322         }
323     }
324 
325     /*
326      * Create the special ACPI tables:
327      * 1) DSDT/SSDT are AML tables, not data tables
328      * 2) FACS and RSDP have non-standard headers
329      */
330     Status = DtCreateOneTemplate (ACPI_SIG_DSDT, 0, NULL);
331     if (ACPI_FAILURE (Status))
332     {
333         return (Status);
334     }
335 
336     Status = DtCreateOneTemplate (ACPI_SIG_SSDT, 0, NULL);
337     if (ACPI_FAILURE (Status))
338     {
339         return (Status);
340     }
341 
342     Status = DtCreateOneTemplate (ACPI_SIG_OSDT, 0, NULL);
343     if (ACPI_FAILURE (Status))
344     {
345         return (Status);
346     }
347 
348     Status = DtCreateOneTemplate (ACPI_SIG_FACS, 0, NULL);
349     if (ACPI_FAILURE (Status))
350     {
351         return (Status);
352     }
353 
354     Status = DtCreateOneTemplate (ACPI_RSDP_NAME, 0, NULL);
355     if (ACPI_FAILURE (Status))
356     {
357         return (Status);
358     }
359 
360     return (AE_OK);
361 }
362 
363 
364 /*******************************************************************************
365  *
366  * FUNCTION:    DtCreateOneTemplate
367  *
368  * PARAMETERS:  Signature           - ACPI signature, NULL terminated.
369  *              TableCount          - Used for SSDTs in same file as DSDT
370  *              TableData           - Entry in ACPI table data structure.
371  *                                    NULL if a special ACPI table.
372  *
373  * RETURN:      Status
374  *
375  * DESCRIPTION: Create one template source file for the requested ACPI table.
376  *
377  ******************************************************************************/
378 
379 static ACPI_STATUS
380 DtCreateOneTemplate (
381     char                    *Signature,
382     UINT32                  TableCount,
383     const ACPI_DMTABLE_DATA  *TableData)
384 {
385     char                    *DisasmFilename;
386     FILE                    *File;
387     ACPI_STATUS             Status = AE_OK;
388     int                     Actual;
389     UINT32                  i;
390 
391 
392     /* New file will have a .asl suffix */
393 
394     DisasmFilename = FlGenerateFilename (
395         Signature, FILE_SUFFIX_ASL_CODE);
396     if (!DisasmFilename)
397     {
398         fprintf (stderr, "Could not generate output filename\n");
399         return (AE_ERROR);
400     }
401 
402     AcpiUtStrlwr (DisasmFilename);
403     if (!UtQueryForOverwrite (DisasmFilename))
404     {
405         return (AE_ERROR);
406     }
407 
408     File = fopen (DisasmFilename, "w+");
409     if (!File)
410     {
411         fprintf (stderr, "Could not open output file %s\n",
412             DisasmFilename);
413         return (AE_ERROR);
414     }
415 
416     /* Emit the common file header */
417 
418     AcpiOsRedirectOutput (File);
419 
420     AcpiOsPrintf ("/*\n");
421     AcpiOsPrintf (ACPI_COMMON_HEADER ("iASL Compiler/Disassembler", " * "));
422 
423     if (TableCount == 0)
424     {
425         AcpiOsPrintf (" * Template for [%4.4s] ACPI Table",
426             Signature);
427     }
428     else
429     {
430         AcpiOsPrintf (" * Template for [%4.4s] and %u [SSDT] ACPI Tables",
431             Signature, TableCount);
432     }
433 
434     /* Dump the actual ACPI table */
435 
436     if (TableData)
437     {
438         /* Normal case, tables that appear in AcpiDmTableData */
439 
440         AcpiOsPrintf (" (static data table)\n");
441 
442         if (Gbl_VerboseTemplates)
443         {
444             AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength]"
445                 "  FieldName : HexFieldValue\n */\n\n");
446         }
447         else
448         {
449             AcpiOsPrintf (" * Format: [ByteLength]"
450                 "  FieldName : HexFieldValue\n */\n");
451         }
452 
453         AcpiDmDumpDataTable (ACPI_CAST_PTR (ACPI_TABLE_HEADER,
454             TableData->Template));
455     }
456     else
457     {
458         /* Special ACPI tables - DSDT, SSDT, OSDT, FACS, RSDP */
459 
460         AcpiOsPrintf (" (AML byte code table)\n");
461         AcpiOsPrintf (" */\n");
462 
463         if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT))
464         {
465             Actual = DtEmitDefinitionBlock (
466                 File, DisasmFilename, ACPI_SIG_DSDT, 1);
467             if (Actual < 0)
468             {
469                 Status = AE_ERROR;
470                 goto Cleanup;
471             }
472 
473             /* Emit any requested SSDTs into the same file */
474 
475             for (i = 1; i <= TableCount; i++)
476             {
477                 Actual = DtEmitDefinitionBlock (
478                     File, DisasmFilename, ACPI_SIG_SSDT, i + 1);
479                 if (Actual < 0)
480                 {
481                     Status = AE_ERROR;
482                     goto Cleanup;
483                 }
484             }
485         }
486         else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT))
487         {
488             Actual = DtEmitDefinitionBlock (
489                 File, DisasmFilename, ACPI_SIG_SSDT, 1);
490             if (Actual < 0)
491             {
492                 Status = AE_ERROR;
493                 goto Cleanup;
494             }
495         }
496         else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_OSDT))
497         {
498             Actual = DtEmitDefinitionBlock (
499                 File, DisasmFilename, ACPI_SIG_OSDT, 1);
500             if (Actual < 0)
501             {
502                 Status = AE_ERROR;
503                 goto Cleanup;
504             }
505         }
506         else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
507         {
508             AcpiDmDumpDataTable (ACPI_CAST_PTR (ACPI_TABLE_HEADER,
509                 TemplateFacs));
510         }
511         else if (ACPI_COMPARE_NAME (Signature, ACPI_RSDP_NAME))
512         {
513             AcpiDmDumpDataTable (ACPI_CAST_PTR (ACPI_TABLE_HEADER,
514                 TemplateRsdp));
515         }
516         else
517         {
518             fprintf (stderr,
519                 "%4.4s, Unrecognized ACPI table signature\n", Signature);
520             Status = AE_ERROR;
521             goto Cleanup;
522         }
523     }
524 
525     if (TableCount == 0)
526     {
527         fprintf (stderr,
528             "Created ACPI table template for [%4.4s], "
529             "written to \"%s\"\n",
530             Signature, DisasmFilename);
531     }
532     else
533     {
534         fprintf (stderr,
535             "Created ACPI table templates for [%4.4s] "
536             "and %u [SSDT], written to \"%s\"\n",
537             Signature, TableCount, DisasmFilename);
538     }
539 
540 Cleanup:
541     fclose (File);
542     AcpiOsRedirectOutput (stdout);
543     return (Status);
544 }
545 
546 
547 /*******************************************************************************
548  *
549  * FUNCTION:    DtEmitDefinitionBlock
550  *
551  * PARAMETERS:  File                - An open file for the block
552  *              Filename            - Filename for same, for error msg(s)
553  *              Signature           - ACPI signature for the block
554  *              Instance            - Used for multiple SSDTs in the same file
555  *
556  * RETURN:      Status from fprintf
557  *
558  * DESCRIPTION: Emit the raw ASL for a complete Definition Block (DSDT or SSDT)
559  *
560  * Note: The AMLFileName parameter for DefinitionBlock is left as a NULL
561  * string. This allows the compiler to create the output AML filename from
562  * the input filename.
563  *
564  ******************************************************************************/
565 
566 static int
567 DtEmitDefinitionBlock (
568     FILE                    *File,
569     char                    *Filename,
570     char                    *Signature,
571     UINT32                  Instance)
572 {
573     int                     Status;
574 
575 
576     Status = fprintf (File,
577         "DefinitionBlock (\"\", \"%4.4s\", 2, \"Intel\", \"_%4.4s_%.2X\", 0x00000001)\n"
578         "{\n"
579         "    Method (%2.2s%.2X)\n"
580         "    {\n"
581         "    }\n"
582         "}\n\n",
583         Signature, Signature, Instance, Signature, Instance);
584 
585     if (Status < 0)
586     {
587         fprintf (stderr,
588             "Could not write %4.4s to output file %s\n",
589             Signature, Filename);
590     }
591 
592     return (Status);
593 }
594