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