acpixtract.c revision 1.14 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 - 2021, 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 MERCHANTABILITY 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 int BytesConverted;
72 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, ACPI_NAMESEG_SIZE);
100 AcpiUtStrupr (UpperSignature);
101
102 /* Are there enough instances of the table to continue? */
103
104 AxNormalizeSignature (UpperSignature);
105 Instances = AxCountTableInstances (InputPathname, UpperSignature);
106
107 if (Instances < MinimumInstances)
108 {
109 printf ("Table [%s] was not found in %s\n",
110 UpperSignature, InputPathname);
111 fclose (InputFile);
112 return (0); /* Don't abort */
113 }
114
115 if (Instances == 0)
116 {
117 fclose (InputFile);
118 return (-1);
119 }
120 }
121
122 /* Convert all instances of the table to binary */
123
124 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
125 {
126 /*
127 * Check up front if we have a header line of the form:
128 * DSDT @ 0xdfffd0c0 (10999 bytes)
129 */
130 if (AX_IS_TABLE_BLOCK_HEADER &&
131 (State == AX_STATE_EXTRACT_DATA))
132 {
133 /* End of previous table, start of new table */
134
135 if (ThisTableBytesWritten)
136 {
137 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
138 ThisTableBytesWritten, Gbl_OutputFilename);
139 }
140 else
141 {
142 Gbl_TableCount--;
143 }
144
145 State = AX_STATE_FIND_HEADER;
146 }
147
148 switch (State)
149 {
150 case AX_STATE_FIND_HEADER:
151
152 if (!AxIsDataBlockHeader ())
153 {
154 continue;
155 }
156
157 ACPI_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer);
158 if (Signature)
159 {
160 /* Ignore signatures that don't match */
161
162 if (!ACPI_COMPARE_NAMESEG (ThisSignature, UpperSignature))
163 {
164 continue;
165 }
166 }
167
168 /*
169 * Get the instance number for this signature. Only the
170 * SSDT and PSDT tables can have multiple instances.
171 */
172 ThisInstance = AxGetNextInstance (InputPathname, ThisSignature);
173
174 /* Build an output filename and create/open the output file */
175
176 if (ThisInstance > 0)
177 {
178 /* Add instance number to the output filename */
179
180 sprintf (Gbl_OutputFilename, "%4.4s%u.dat",
181 ThisSignature, ThisInstance);
182 }
183 else
184 {
185 sprintf (Gbl_OutputFilename, "%4.4s.dat",
186 ThisSignature);
187 }
188
189 AcpiUtStrlwr (Gbl_OutputFilename);
190 OutputFile = fopen (Gbl_OutputFilename, "w+b");
191 if (!OutputFile)
192 {
193 printf ("Could not open output file %s\n",
194 Gbl_OutputFilename);
195 fclose (InputFile);
196 return (-1);
197 }
198
199 /*
200 * Toss this block header of the form "<sig> @ <addr>" line
201 * and move on to the actual data block
202 */
203 Gbl_TableCount++;
204 FoundTable = 1;
205 ThisTableBytesWritten = 0;
206 State = AX_STATE_EXTRACT_DATA;
207 continue;
208
209 case AX_STATE_EXTRACT_DATA:
210
211 if (!AxIsHexDataLine ())
212 {
213 continue; /* Toss any lines that are not raw hex data */
214 }
215
216 /* Empty line or non-data line terminates the data block */
217
218 BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature);
219 switch (BytesConverted)
220 {
221 case 0:
222
223 State = AX_STATE_FIND_HEADER; /* No more data block lines */
224 continue;
225
226 case -1:
227
228 Status = -1;
229 goto CleanupAndExit; /* There was a write error */
230
231 default: /* Normal case, get next line */
232
233 ThisTableBytesWritten += BytesConverted;
234 continue;
235 }
236
237 default:
238
239 Status = -1;
240 goto CleanupAndExit;
241 }
242 }
243
244 if (!FoundTable)
245 {
246 printf ("No ACPI tables were found in %s\n", InputPathname);
247 }
248
249
250 CleanupAndExit:
251
252 if (State == AX_STATE_EXTRACT_DATA)
253 {
254 /* Received an input file EOF while extracting data */
255
256 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
257 ThisTableBytesWritten, Gbl_OutputFilename);
258 }
259
260 if (OutputFile)
261 {
262 fclose (OutputFile);
263 }
264
265 fclose (InputFile);
266 return (Status);
267 }
268
269
270 /******************************************************************************
271 *
272 * FUNCTION: AxExtractToMultiAmlFile
273 *
274 * PARAMETERS: InputPathname - Filename for input acpidump file
275 *
276 * RETURN: Status
277 *
278 * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all
279 * into a single output file. Used to simplify the loading of
280 * multiple/many SSDTs into a utility like acpiexec -- instead
281 * of creating many separate output files.
282 *
283 ******************************************************************************/
284
285 int
286 AxExtractToMultiAmlFile (
287 char *InputPathname)
288 {
289 FILE *InputFile;
290 FILE *OutputFile;
291 int Status = 0;
292 int TotalBytesWritten = 0;
293 int ThisTableBytesWritten = 0;
294 unsigned int BytesConverted;
295 char ThisSignature[4];
296 unsigned int State = AX_STATE_FIND_HEADER;
297
298
299 strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME);
300
301 /* Open the input file in text mode */
302
303 InputFile = fopen (InputPathname, "r");
304 if (!InputFile)
305 {
306 printf ("Could not open input file %s\n", InputPathname);
307 return (-1);
308 }
309
310 if (!AxIsFileAscii (InputFile))
311 {
312 fclose (InputFile);
313 return (-1);
314 }
315
316 /* Open the output file in binary mode */
317
318 OutputFile = fopen (Gbl_OutputFilename, "w+b");
319 if (!OutputFile)
320 {
321 printf ("Could not open output file %s\n", Gbl_OutputFilename);
322 fclose (InputFile);
323 return (-1);
324 }
325
326 /* Convert the DSDT and all SSDTs to binary */
327
328 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
329 {
330 /*
331 * Check up front if we have a header line of the form:
332 * DSDT @ 0xdfffd0c0 (10999 bytes)
333 */
334 if (AX_IS_TABLE_BLOCK_HEADER &&
335 (State == AX_STATE_EXTRACT_DATA))
336 {
337 /* End of previous table, start of new table */
338
339 if (ThisTableBytesWritten)
340 {
341 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
342 ThisTableBytesWritten, Gbl_OutputFilename);
343 }
344 else
345 {
346 Gbl_TableCount--;
347 }
348
349 State = AX_STATE_FIND_HEADER;
350 }
351
352 switch (State)
353 {
354 case AX_STATE_FIND_HEADER:
355
356 if (!AxIsDataBlockHeader ())
357 {
358 continue;
359 }
360
361 ACPI_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer);
362
363 /* Only want DSDT and SSDTs */
364
365 if (!ACPI_COMPARE_NAMESEG (ThisSignature, ACPI_SIG_DSDT) &&
366 !ACPI_COMPARE_NAMESEG (ThisSignature, ACPI_SIG_SSDT))
367 {
368 continue;
369 }
370
371 /*
372 * Toss this block header of the form "<sig> @ <addr>" line
373 * and move on to the actual data block
374 */
375 Gbl_TableCount++;
376 ThisTableBytesWritten = 0;
377 State = AX_STATE_EXTRACT_DATA;
378 continue;
379
380 case AX_STATE_EXTRACT_DATA:
381
382 if (!AxIsHexDataLine ())
383 {
384 continue; /* Toss any lines that are not raw hex data */
385 }
386
387 /* Empty line or non-data line terminates the data block */
388
389 BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature);
390 switch (BytesConverted)
391 {
392 case 0:
393
394 State = AX_STATE_FIND_HEADER; /* No more data block lines */
395 continue;
396
397 case -1:
398
399 Status = -1;
400 goto CleanupAndExit; /* There was a write error */
401
402 default: /* Normal case, get next line */
403
404 ThisTableBytesWritten += BytesConverted;
405 TotalBytesWritten += BytesConverted;
406 continue;
407 }
408
409 default:
410
411 Status = -1;
412 goto CleanupAndExit;
413 }
414 }
415
416
417 CleanupAndExit:
418
419 if (State == AX_STATE_EXTRACT_DATA)
420 {
421 /* Received an input file EOF or error while writing data */
422
423 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
424 ThisTableBytesWritten, Gbl_OutputFilename);
425 }
426
427 printf ("\n%u binary ACPI tables extracted and written to %s (%u bytes)\n",
428 Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten);
429
430 fclose (InputFile);
431 fclose (OutputFile);
432 return (Status);
433 }
434
435
436 /******************************************************************************
437 *
438 * FUNCTION: AxListAllTables
439 *
440 * PARAMETERS: InputPathname - Filename for acpidump file
441 *
442 * RETURN: Status
443 *
444 * DESCRIPTION: Display info for all ACPI tables found in input. Does not
445 * perform an actual extraction of the tables.
446 *
447 ******************************************************************************/
448
449 int
450 AxListAllTables (
451 char *InputPathname)
452 {
453 FILE *InputFile;
454 unsigned char Header[48];
455 UINT32 ByteCount = 0;
456 UINT32 ThisLineByteCount;
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 ThisLineByteCount = AxConvertToBinary (Gbl_LineBuffer,
530 &Header[ByteCount]);
531 if (ThisLineByteCount == EOF)
532 {
533 fclose (InputFile);
534 return (-1);
535 }
536
537 ByteCount += ThisLineByteCount;
538 if (ByteCount >= sizeof (ACPI_TABLE_HEADER))
539 {
540 AxDumpTableHeader (Header);
541 State = AX_STATE_FIND_HEADER;
542 }
543 continue;
544
545 default:
546 break;
547 }
548 }
549
550 printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname);
551 fclose (InputFile);
552 return (0);
553 }
554