dttemplate.c revision 306536
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 <contrib/dev/acpica/compiler/aslcompiler.h>
45#include <contrib/dev/acpica/include/acapps.h>
46#include <contrib/dev/acpica/compiler/dtcompiler.h>
47#include <contrib/dev/acpica/compiler/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
55static BOOLEAN
56AcpiUtIsSpecialTable (
57    char                    *Signature);
58
59static ACPI_STATUS
60DtCreateOneTemplateFile (
61    char                    *Signature,
62    UINT32                  TableCount);
63
64static ACPI_STATUS
65DtCreateOneTemplate (
66    char                    *Signature,
67    UINT32                  TableCount,
68    const ACPI_DMTABLE_DATA *TableData);
69
70static ACPI_STATUS
71DtCreateAllTemplates (
72    void);
73
74static int
75DtEmitDefinitionBlock (
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
95static BOOLEAN
96AcpiUtIsSpecialTable (
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
125ACPI_STATUS
126DtCreateTemplates (
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
206Exit:
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
227static ACPI_STATUS
228DtCreateOneTemplateFile (
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
298static ACPI_STATUS
299DtCreateAllTemplates (
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
379static ACPI_STATUS
380DtCreateOneTemplate (
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
540Cleanup:
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
566static int
567DtEmitDefinitionBlock (
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