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