acpixtract.c revision 1.9 1 /******************************************************************************
2 *
3 * Module Name: acpixtract - Top level functions to convert ascii/hex
4 * ACPI tables to the original binary tables
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000 - 2017, Intel Corp.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45 #include "acpixtract.h"
46
47
48 /******************************************************************************
49 *
50 * FUNCTION: AxExtractTables
51 *
52 * PARAMETERS: InputPathname - Filename for input acpidump file
53 * Signature - Requested ACPI signature to extract.
54 * NULL means extract ALL tables.
55 * MinimumInstances - Min instances that are acceptable
56 *
57 * RETURN: Status
58 *
59 * DESCRIPTION: Convert text ACPI tables to binary
60 *
61 ******************************************************************************/
62
63 int
64 AxExtractTables (
65 char *InputPathname,
66 char *Signature,
67 unsigned int MinimumInstances)
68 {
69 FILE *InputFile;
70 FILE *OutputFile = NULL;
71 unsigned int BytesConverted;
72 unsigned int ThisTableBytesWritten = 0;
73 unsigned int FoundTable = 0;
74 unsigned int Instances = 0;
75 unsigned int ThisInstance;
76 char ThisSignature[5];
77 char UpperSignature[5];
78 int Status = 0;
79 unsigned int State = AX_STATE_FIND_HEADER;
80
81
82 /* Open input in text mode, output is in binary mode */
83
84 InputFile = fopen (InputPathname, "r");
85 if (!InputFile)
86 {
87 printf ("Could not open input file %s\n", InputPathname);
88 return (-1);
89 }
90
91 if (!AxIsFileAscii (InputFile))
92 {
93 fclose (InputFile);
94 return (-1);
95 }
96
97 if (Signature)
98 {
99 strncpy (UpperSignature, Signature, 4);
100 UpperSignature[4] = 0;
101 AcpiUtStrupr (UpperSignature);
102
103 /* Are there enough instances of the table to continue? */
104
105 AxNormalizeSignature (UpperSignature);
106 Instances = AxCountTableInstances (InputPathname, UpperSignature);
107
108 if (Instances < MinimumInstances)
109 {
110 printf ("Table [%s] was not found in %s\n",
111 UpperSignature, InputPathname);
112 fclose (InputFile);
113 return (0); /* Don't abort */
114 }
115
116 if (Instances == 0)
117 {
118 fclose (InputFile);
119 return (-1);
120 }
121 }
122
123 /* Convert all instances of the table to binary */
124
125 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
126 {
127 /*
128 * Check up front if we have a header line of the form:
129 * DSDT @ 0xdfffd0c0 (10999 bytes)
130 */
131 if (AX_IS_TABLE_BLOCK_HEADER &&
132 (State == AX_STATE_EXTRACT_DATA))
133 {
134 /* End of previous table, start of new table */
135
136 if (ThisTableBytesWritten)
137 {
138 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
139 ThisTableBytesWritten, Gbl_OutputFilename);
140 }
141 else
142 {
143 Gbl_TableCount--;
144 }
145
146 State = AX_STATE_FIND_HEADER;
147 }
148
149 switch (State)
150 {
151 case AX_STATE_FIND_HEADER:
152
153 if (!AxIsDataBlockHeader ())
154 {
155 continue;
156 }
157
158 ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
159 if (Signature)
160 {
161 /* Ignore signatures that don't match */
162
163 if (!ACPI_COMPARE_NAME (ThisSignature, UpperSignature))
164 {
165 continue;
166 }
167 }
168
169 /*
170 * Get the instance number for this signature. Only the
171 * SSDT and PSDT tables can have multiple instances.
172 */
173 ThisInstance = AxGetNextInstance (InputPathname, ThisSignature);
174
175 /* Build an output filename and create/open the output file */
176
177 if (ThisInstance > 0)
178 {
179 /* Add instance number to the output filename */
180
181 sprintf (Gbl_OutputFilename, "%4.4s%u.dat",
182 ThisSignature, ThisInstance);
183 }
184 else
185 {
186 sprintf (Gbl_OutputFilename, "%4.4s.dat",
187 ThisSignature);
188 }
189
190 AcpiUtStrlwr (Gbl_OutputFilename);
191 OutputFile = fopen (Gbl_OutputFilename, "w+b");
192 if (!OutputFile)
193 {
194 printf ("Could not open output file %s\n",
195 Gbl_OutputFilename);
196 fclose (InputFile);
197 return (-1);
198 }
199
200 /*
201 * Toss this block header of the form "<sig> @ <addr>" line
202 * and move on to the actual data block
203 */
204 Gbl_TableCount++;
205 FoundTable = 1;
206 ThisTableBytesWritten = 0;
207 State = AX_STATE_EXTRACT_DATA;
208 continue;
209
210 case AX_STATE_EXTRACT_DATA:
211
212 if (!AxIsHexDataLine ())
213 {
214 continue; /* Toss any lines that are not raw hex data */
215 }
216
217 /* Empty line or non-data line terminates the data block */
218
219 BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature,
220 ThisTableBytesWritten);
221 switch (BytesConverted)
222 {
223 case 0:
224
225 State = AX_STATE_FIND_HEADER; /* No more data block lines */
226 continue;
227
228 case -1:
229
230 goto CleanupAndExit; /* There was a write error */
231
232 default: /* Normal case, get next line */
233
234 ThisTableBytesWritten += BytesConverted;
235 continue;
236 }
237
238 default:
239
240 Status = -1;
241 goto CleanupAndExit;
242 }
243 }
244
245 if (!FoundTable)
246 {
247 printf ("No ACPI tables were found in %s\n", InputPathname);
248 }
249
250
251 CleanupAndExit:
252
253 if (State == AX_STATE_EXTRACT_DATA)
254 {
255 /* Received an input file EOF while extracting data */
256
257 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
258 ThisTableBytesWritten, Gbl_OutputFilename);
259 }
260
261 if (OutputFile)
262 {
263 fclose (OutputFile);
264 }
265
266 fclose (InputFile);
267 return (Status);
268 }
269
270
271 /******************************************************************************
272 *
273 * FUNCTION: AxExtractToMultiAmlFile
274 *
275 * PARAMETERS: InputPathname - Filename for input acpidump file
276 *
277 * RETURN: Status
278 *
279 * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all
280 * into a single output file. Used to simplify the loading of
281 * multiple/many SSDTs into a utility like acpiexec -- instead
282 * of creating many separate output files.
283 *
284 ******************************************************************************/
285
286 int
287 AxExtractToMultiAmlFile (
288 char *InputPathname)
289 {
290 FILE *InputFile;
291 FILE *OutputFile;
292 int Status = 0;
293 unsigned int TotalBytesWritten = 0;
294 unsigned int ThisTableBytesWritten = 0;
295 unsigned int BytesConverted;
296 char ThisSignature[4];
297 unsigned int State = AX_STATE_FIND_HEADER;
298
299
300 strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME);
301
302 /* Open the input file in text mode */
303
304 InputFile = fopen (InputPathname, "r");
305 if (!InputFile)
306 {
307 printf ("Could not open input file %s\n", InputPathname);
308 return (-1);
309 }
310
311 if (!AxIsFileAscii (InputFile))
312 {
313 fclose (InputFile);
314 return (-1);
315 }
316
317 /* Open the output file in binary mode */
318
319 OutputFile = fopen (Gbl_OutputFilename, "w+b");
320 if (!OutputFile)
321 {
322 printf ("Could not open output file %s\n", Gbl_OutputFilename);
323 fclose (InputFile);
324 return (-1);
325 }
326
327 /* Convert the DSDT and all SSDTs to binary */
328
329 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
330 {
331 /*
332 * Check up front if we have a header line of the form:
333 * DSDT @ 0xdfffd0c0 (10999 bytes)
334 */
335 if (AX_IS_TABLE_BLOCK_HEADER &&
336 (State == AX_STATE_EXTRACT_DATA))
337 {
338 /* End of previous table, start of new table */
339
340 if (ThisTableBytesWritten)
341 {
342 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
343 ThisTableBytesWritten, Gbl_OutputFilename);
344 }
345 else
346 {
347 Gbl_TableCount--;
348 }
349
350 State = AX_STATE_FIND_HEADER;
351 }
352
353 switch (State)
354 {
355 case AX_STATE_FIND_HEADER:
356
357 if (!AxIsDataBlockHeader ())
358 {
359 continue;
360 }
361
362 ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
363
364 /* Only want DSDT and SSDTs */
365
366 if (!ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_DSDT) &&
367 !ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_SSDT))
368 {
369 continue;
370 }
371
372 /*
373 * Toss this block header of the form "<sig> @ <addr>" line
374 * and move on to the actual data block
375 */
376 Gbl_TableCount++;
377 ThisTableBytesWritten = 0;
378 State = AX_STATE_EXTRACT_DATA;
379 continue;
380
381 case AX_STATE_EXTRACT_DATA:
382
383 if (!AxIsHexDataLine ())
384 {
385 continue; /* Toss any lines that are not raw hex data */
386 }
387
388 /* Empty line or non-data line terminates the data block */
389
390 BytesConverted = AxConvertAndWrite (
391 OutputFile, ThisSignature, ThisTableBytesWritten);
392 switch (BytesConverted)
393 {
394 case 0:
395
396 State = AX_STATE_FIND_HEADER; /* No more data block lines */
397 continue;
398
399 case -1:
400
401 goto CleanupAndExit; /* There was a write error */
402
403 default: /* Normal case, get next line */
404
405 ThisTableBytesWritten += BytesConverted;
406 TotalBytesWritten += BytesConverted;
407 continue;
408 }
409
410 default:
411
412 Status = -1;
413 goto CleanupAndExit;
414 }
415 }
416
417
418 CleanupAndExit:
419
420 if (State == AX_STATE_EXTRACT_DATA)
421 {
422 /* Received an input file EOF or error while writing data */
423
424 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
425 ThisTableBytesWritten, Gbl_OutputFilename);
426 }
427
428 printf ("\n%u binary ACPI tables extracted and written to %s (%u bytes)\n",
429 Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten);
430
431 fclose (InputFile);
432 fclose (OutputFile);
433 return (Status);
434 }
435
436
437 /******************************************************************************
438 *
439 * FUNCTION: AxListAllTables
440 *
441 * PARAMETERS: InputPathname - Filename for acpidump file
442 *
443 * RETURN: Status
444 *
445 * DESCRIPTION: Display info for all ACPI tables found in input. Does not
446 * perform an actual extraction of the tables.
447 *
448 ******************************************************************************/
449
450 int
451 AxListAllTables (
452 char *InputPathname)
453 {
454 FILE *InputFile;
455 unsigned char Header[48];
456 UINT32 ByteCount = 0;
457 unsigned int State = AX_STATE_FIND_HEADER;
458
459
460 /* Open input in text mode, output is in binary mode */
461
462 InputFile = fopen (InputPathname, "r");
463 if (!InputFile)
464 {
465 printf ("Could not open input file %s\n", InputPathname);
466 return (-1);
467 }
468
469 if (!AxIsFileAscii (InputFile))
470 {
471 fclose (InputFile);
472 return (-1);
473 }
474
475 /* Info header */
476
477 printf ("\n Signature Length Version Oem Oem "
478 "Oem Compiler Compiler\n");
479 printf ( " Id TableId "
480 "RevisionId Name Revision\n");
481 printf ( " _________ __________ ____ ________ __________ "
482 "__________ _______ __________\n\n");
483
484 /* Dump the headers for all tables found in the input file */
485
486 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
487 {
488 /* Ignore empty lines */
489
490 if (AxIsEmptyLine (Gbl_LineBuffer))
491 {
492 continue;
493 }
494
495 /*
496 * Check up front if we have a header line of the form:
497 * DSDT @ 0xdfffd0c0 (10999 bytes)
498 */
499 if (AX_IS_TABLE_BLOCK_HEADER &&
500 (State == AX_STATE_EXTRACT_DATA))
501 {
502 State = AX_STATE_FIND_HEADER;
503 }
504
505 switch (State)
506 {
507 case AX_STATE_FIND_HEADER:
508
509 ByteCount = 0;
510 if (!AxIsDataBlockHeader ())
511 {
512 continue;
513 }
514
515 State = AX_STATE_EXTRACT_DATA;
516 continue;
517
518 case AX_STATE_EXTRACT_DATA:
519
520 /* Ignore any lines that don't look like a data line */
521
522 if (!AxIsHexDataLine ())
523 {
524 continue; /* Toss any lines that are not raw hex data */
525 }
526
527 /* Convert header to hex and display it */
528
529 ByteCount += AxConvertToBinary (Gbl_LineBuffer, &Header[ByteCount]);
530 if (ByteCount >= sizeof (ACPI_TABLE_HEADER))
531 {
532 AxDumpTableHeader (Header);
533 State = AX_STATE_FIND_HEADER;
534 }
535 continue;
536
537 default:
538 break;
539 }
540 }
541
542 printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname);
543 fclose (InputFile);
544 return (0);
545 }
546