1 /******************************************************************************
2 *
3 * Module Name: acpixtract - convert ascii ACPI tables to binary
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 "acpixtract.h"
45
46
47 /* Local prototypes */
48
49 static BOOLEAN
50 AxIsFileAscii (
51 FILE *Handle);
52
53
54 /******************************************************************************
55 *
56 * FUNCTION: AxExtractTables
57 *
58 * PARAMETERS: InputPathname - Filename for input acpidump file
59 * Signature - Requested ACPI signature to extract.
60 * NULL means extract ALL tables.
61 * MinimumInstances - Min instances that are acceptable
62 *
63 * RETURN: Status
64 *
65 * DESCRIPTION: Convert text ACPI tables to binary
66 *
67 ******************************************************************************/
68
69 int
AxExtractTables(char * InputPathname,char * Signature,unsigned int MinimumInstances)70 AxExtractTables (
71 char *InputPathname,
72 char *Signature,
73 unsigned int MinimumInstances)
74 {
75 FILE *InputFile;
76 FILE *OutputFile = NULL;
77 unsigned int BytesConverted;
78 unsigned int ThisTableBytesWritten = 0;
79 unsigned int FoundTable = 0;
80 unsigned int Instances = 0;
81 unsigned int ThisInstance;
82 char ThisSignature[5];
83 char UpperSignature[5];
84 int Status = 0;
85 unsigned int State = AX_STATE_FIND_HEADER;
86
87
88 /* Open input in text mode, output is in binary mode */
89
90 InputFile = fopen (InputPathname, "rt");
91 if (!InputFile)
92 {
93 printf ("Could not open input file %s\n", InputPathname);
94 return (-1);
95 }
96
97 if (!AxIsFileAscii (InputFile))
98 {
99 fclose (InputFile);
100 return (-1);
101 }
102
103 if (Signature)
104 {
105 strncpy (UpperSignature, Signature, 4);
106 UpperSignature[4] = 0;
107 AcpiUtStrupr (UpperSignature);
108
109 /* Are there enough instances of the table to continue? */
110
111 AxNormalizeSignature (UpperSignature);
112
113 Instances = AxCountTableInstances (InputPathname, UpperSignature);
114 if (Instances < MinimumInstances)
115 {
116 printf ("Table [%s] was not found in %s\n",
117 UpperSignature, InputPathname);
118 fclose (InputFile);
119 return (-1);
120 }
121
122 if (Instances == 0)
123 {
124 fclose (InputFile);
125 return (-1);
126 }
127 }
128
129 /* Convert all instances of the table to binary */
130
131 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
132 {
133 switch (State)
134 {
135 case AX_STATE_FIND_HEADER:
136
137 if (!AxIsDataBlockHeader ())
138 {
139 continue;
140 }
141
142 ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
143 if (Signature)
144 {
145 /* Ignore signatures that don't match */
146
147 if (!ACPI_COMPARE_NAME (ThisSignature, UpperSignature))
148 {
149 continue;
150 }
151 }
152
153 /*
154 * Get the instance number for this signature. Only the
155 * SSDT and PSDT tables can have multiple instances.
156 */
157 ThisInstance = AxGetNextInstance (InputPathname, ThisSignature);
158
159 /* Build an output filename and create/open the output file */
160
161 if (ThisInstance > 0)
162 {
163 /* Add instance number to the output filename */
164
165 sprintf (Gbl_OutputFilename, "%4.4s%u.dat",
166 ThisSignature, ThisInstance);
167 }
168 else
169 {
170 sprintf (Gbl_OutputFilename, "%4.4s.dat",
171 ThisSignature);
172 }
173
174 AcpiUtStrlwr (Gbl_OutputFilename);
175 OutputFile = fopen (Gbl_OutputFilename, "w+b");
176 if (!OutputFile)
177 {
178 printf ("Could not open output file %s\n",
179 Gbl_OutputFilename);
180 fclose (InputFile);
181 return (-1);
182 }
183
184 /*
185 * Toss this block header of the form "<sig> @ <addr>" line
186 * and move on to the actual data block
187 */
188 Gbl_TableCount++;
189 FoundTable = 1;
190 ThisTableBytesWritten = 0;
191 State = AX_STATE_EXTRACT_DATA;
192 continue;
193
194 case AX_STATE_EXTRACT_DATA:
195
196 /* Empty line or non-data line terminates the data block */
197
198 BytesConverted = AxProcessOneTextLine (
199 OutputFile, ThisSignature, ThisTableBytesWritten);
200 switch (BytesConverted)
201 {
202 case 0:
203
204 State = AX_STATE_FIND_HEADER; /* No more data block lines */
205 continue;
206
207 case -1:
208
209 goto CleanupAndExit; /* There was a write error */
210
211 default: /* Normal case, get next line */
212
213 ThisTableBytesWritten += BytesConverted;
214 continue;
215 }
216
217 default:
218
219 Status = -1;
220 goto CleanupAndExit;
221 }
222 }
223
224 if (!FoundTable)
225 {
226 printf ("No ACPI tables were found in %s\n", InputPathname);
227 }
228
229
230 CleanupAndExit:
231
232 if (State == AX_STATE_EXTRACT_DATA)
233 {
234 /* Received an input file EOF while extracting data */
235
236 printf (AX_TABLE_INFO_FORMAT,
237 ThisSignature, ThisTableBytesWritten, Gbl_OutputFilename);
238 }
239
240 if (Gbl_TableCount > 1)
241 {
242 printf ("\n%u binary ACPI tables extracted\n",
243 Gbl_TableCount);
244 }
245
246 if (OutputFile)
247 {
248 fclose (OutputFile);
249 }
250
251 fclose (InputFile);
252 return (Status);
253 }
254
255
256 /******************************************************************************
257 *
258 * FUNCTION: AxExtractToMultiAmlFile
259 *
260 * PARAMETERS: InputPathname - Filename for input acpidump file
261 *
262 * RETURN: Status
263 *
264 * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all
265 * into a single output file. Used to simplify the loading of
266 * multiple/many SSDTs into a utility like acpiexec -- instead
267 * of creating many separate output files.
268 *
269 ******************************************************************************/
270
271 int
AxExtractToMultiAmlFile(char * InputPathname)272 AxExtractToMultiAmlFile (
273 char *InputPathname)
274 {
275 FILE *InputFile;
276 FILE *OutputFile;
277 int Status = 0;
278 unsigned int TotalBytesWritten = 0;
279 unsigned int ThisTableBytesWritten = 0;
280 unsigned int BytesConverted;
281 char ThisSignature[4];
282 unsigned int State = AX_STATE_FIND_HEADER;
283
284
285 strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME);
286
287 /* Open the input file in text mode */
288
289 InputFile = fopen (InputPathname, "rt");
290 if (!InputFile)
291 {
292 printf ("Could not open input file %s\n", InputPathname);
293 return (-1);
294 }
295
296 if (!AxIsFileAscii (InputFile))
297 {
298 fclose (InputFile);
299 return (-1);
300 }
301
302 /* Open the output file in binary mode */
303
304 OutputFile = fopen (Gbl_OutputFilename, "w+b");
305 if (!OutputFile)
306 {
307 printf ("Could not open output file %s\n", Gbl_OutputFilename);
308 fclose (InputFile);
309 return (-1);
310 }
311
312 /* Convert the DSDT and all SSDTs to binary */
313
314 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
315 {
316 switch (State)
317 {
318 case AX_STATE_FIND_HEADER:
319
320 if (!AxIsDataBlockHeader ())
321 {
322 continue;
323 }
324
325 ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
326
327 /* Only want DSDT and SSDTs */
328
329 if (!ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_DSDT) &&
330 !ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_SSDT))
331 {
332 continue;
333 }
334
335 /*
336 * Toss this block header of the form "<sig> @ <addr>" line
337 * and move on to the actual data block
338 */
339 Gbl_TableCount++;
340 ThisTableBytesWritten = 0;
341 State = AX_STATE_EXTRACT_DATA;
342 continue;
343
344 case AX_STATE_EXTRACT_DATA:
345
346 /* Empty line or non-data line terminates the data block */
347
348 BytesConverted = AxProcessOneTextLine (
349 OutputFile, ThisSignature, ThisTableBytesWritten);
350 switch (BytesConverted)
351 {
352 case 0:
353
354 State = AX_STATE_FIND_HEADER; /* No more data block lines */
355 continue;
356
357 case -1:
358
359 goto CleanupAndExit; /* There was a write error */
360
361 default: /* Normal case, get next line */
362
363 ThisTableBytesWritten += BytesConverted;
364 TotalBytesWritten += BytesConverted;
365 continue;
366 }
367
368 default:
369
370 Status = -1;
371 goto CleanupAndExit;
372 }
373 }
374
375
376 CleanupAndExit:
377
378 if (State == AX_STATE_EXTRACT_DATA)
379 {
380 /* Received an input file EOF or error while writing data */
381
382 printf (AX_TABLE_INFO_FORMAT,
383 ThisSignature, ThisTableBytesWritten, Gbl_OutputFilename);
384 }
385
386 printf ("\n%u binary ACPI tables extracted and written to %s (%u bytes)\n",
387 Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten);
388
389 fclose (InputFile);
390 fclose (OutputFile);
391 return (Status);
392 }
393
394
395 /******************************************************************************
396 *
397 * FUNCTION: AxListTables
398 *
399 * PARAMETERS: InputPathname - Filename for acpidump file
400 *
401 * RETURN: Status
402 *
403 * DESCRIPTION: Display info for all ACPI tables found in input. Does not
404 * perform an actual extraction of the tables.
405 *
406 ******************************************************************************/
407
408 int
AxListTables(char * InputPathname)409 AxListTables (
410 char *InputPathname)
411 {
412 FILE *InputFile;
413 size_t HeaderSize;
414 unsigned char Header[48];
415 ACPI_TABLE_HEADER *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header;
416
417
418 /* Open input in text mode, output is in binary mode */
419
420 InputFile = fopen (InputPathname, "rt");
421 if (!InputFile)
422 {
423 printf ("Could not open input file %s\n", InputPathname);
424 return (-1);
425 }
426
427 if (!AxIsFileAscii (InputFile))
428 {
429 fclose (InputFile);
430 return (-1);
431 }
432
433 /* Dump the headers for all tables found in the input file */
434
435 printf ("\nSignature Length Revision OemId OemTableId"
436 " OemRevision CompilerId CompilerRevision\n\n");
437
438 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
439 {
440 /* Ignore empty lines and lines that start with a space */
441
442 if (AxIsEmptyLine (Gbl_LineBuffer) ||
443 (Gbl_LineBuffer[0] == ' '))
444 {
445 continue;
446 }
447
448 /* Get the 36 byte header and display the fields */
449
450 HeaderSize = AxGetTableHeader (InputFile, Header);
451 if (HeaderSize < 16)
452 {
453 continue;
454 }
455
456 /* RSDP has an oddball signature and header */
457
458 if (!strncmp (TableHeader->Signature, "RSD PTR ", 8))
459 {
460 AxCheckAscii ((char *) &Header[9], 6);
461 printf ("%7.4s \"%6.6s\"\n", "RSDP",
462 &Header[9]);
463 Gbl_TableCount++;
464 continue;
465 }
466
467 /* Minimum size for table with standard header */
468
469 if (HeaderSize < sizeof (ACPI_TABLE_HEADER))
470 {
471 continue;
472 }
473
474 if (!AcpiUtValidNameseg (TableHeader->Signature))
475 {
476 continue;
477 }
478
479 /* Signature and Table length */
480
481 Gbl_TableCount++;
482 printf ("%7.4s 0x%8.8X", TableHeader->Signature,
483 TableHeader->Length);
484
485 /* FACS has only signature and length */
486
487 if (ACPI_COMPARE_NAME (TableHeader->Signature, "FACS"))
488 {
489 printf ("\n");
490 continue;
491 }
492
493 /* OEM IDs and Compiler IDs */
494
495 AxCheckAscii (TableHeader->OemId, 6);
496 AxCheckAscii (TableHeader->OemTableId, 8);
497 AxCheckAscii (TableHeader->AslCompilerId, 4);
498
499 printf (
500 " 0x%2.2X \"%6.6s\" \"%8.8s\" 0x%8.8X"
501 " \"%4.4s\" 0x%8.8X\n",
502 TableHeader->Revision, TableHeader->OemId,
503 TableHeader->OemTableId, TableHeader->OemRevision,
504 TableHeader->AslCompilerId, TableHeader->AslCompilerRevision);
505 }
506
507 printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname);
508 fclose (InputFile);
509 return (0);
510 }
511
512
513 /*******************************************************************************
514 *
515 * FUNCTION: AxIsFileAscii
516 *
517 * PARAMETERS: Handle - To open input file
518 *
519 * RETURN: TRUE if file is entirely ASCII and printable
520 *
521 * DESCRIPTION: Verify that the input file is entirely ASCII.
522 *
523 ******************************************************************************/
524
525 static BOOLEAN
AxIsFileAscii(FILE * Handle)526 AxIsFileAscii (
527 FILE *Handle)
528 {
529 UINT8 Byte;
530
531
532 /* Read the entire file */
533
534 while (fread (&Byte, 1, 1, Handle) == 1)
535 {
536 /* Check for an ASCII character */
537
538 if (!ACPI_IS_ASCII (Byte))
539 {
540 goto ErrorExit;
541 }
542
543 /* Ensure character is either printable or a "space" char */
544
545 else if (!isprint (Byte) && !isspace (Byte))
546 {
547 goto ErrorExit;
548 }
549 }
550
551 /* File is OK (100% ASCII) */
552
553 fseek (Handle, 0, SEEK_SET);
554 return (TRUE);
555
556 ErrorExit:
557
558 printf ("File is binary (contains non-text or non-ascii characters)\n");
559 fseek (Handle, 0, SEEK_SET);
560 return (FALSE);
561
562 }
563