1 /******************************************************************************
2 *
3 * Module Name: dttemplate - ACPI table template 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 "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
AcpiUtIsSpecialTable(char * Signature)95 AcpiUtIsSpecialTable (
96 char *Signature)
97 {
98
99 if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT) ||
100 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_OSDT) ||
101 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_SSDT) ||
102 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS) ||
103 ACPI_COMPARE_NAMESEG (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
DtCreateTemplates(char ** argv)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 fprintf (stderr, "Creating default template: [DSDT]\n");
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 UtDeleteLocalCaches ();
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
DtCreateOneTemplateFile(char * Signature,UINT32 TableCount)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_NAMESEG_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
DtCreateAllTemplates(void)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
DtCreateOneTemplate(char * Signature,UINT32 TableCount,const ACPI_DMTABLE_DATA * TableData)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_OK);
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 (AslGbl_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_NAMESEG (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_NAMESEG (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_NAMESEG (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_NAMESEG (Signature, ACPI_SIG_FACS))
507 {
508 AcpiDmDumpDataTable (ACPI_CAST_PTR (ACPI_TABLE_HEADER,
509 TemplateFacs));
510 }
511 else if (ACPI_COMPARE_NAMESEG (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] in same file, 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
DtEmitDefinitionBlock(FILE * File,char * Filename,char * Signature,UINT32 Instance)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