axutils.c revision 1.1.1.3 1 /******************************************************************************
2 *
3 * Module Name: axutils - Utility functions for acpixtract tool.
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2017, 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: AxCheckAscii
50 *
51 * PARAMETERS: Name - Ascii string, at least as long as Count
52 * Count - Number of characters to check
53 *
54 * RETURN: None
55 *
56 * DESCRIPTION: Ensure that the requested number of characters are printable
57 * Ascii characters. Sets non-printable and null chars to <space>.
58 *
59 ******************************************************************************/
60
61 void
62 AxCheckAscii (
63 char *Name,
64 int Count)
65 {
66 int i;
67
68
69 for (i = 0; i < Count; i++)
70 {
71 if (!Name[i] || !isprint ((int) Name[i]))
72 {
73 Name[i] = ' ';
74 }
75 }
76 }
77
78
79 /*******************************************************************************
80 *
81 * FUNCTION: AxIsFileAscii
82 *
83 * PARAMETERS: Handle - To open input file
84 *
85 * RETURN: TRUE if file is entirely ASCII and printable
86 *
87 * DESCRIPTION: Verify that the input file is entirely ASCII.
88 *
89 ******************************************************************************/
90
91 BOOLEAN
92 AxIsFileAscii (
93 FILE *Handle)
94 {
95 UINT8 Byte;
96 UINT32 Offset = 0;
97
98
99 /* Read the entire file */
100
101 fseek (Handle, 0, SEEK_SET);
102 while (fread (&Byte, 1, 1, Handle) == 1)
103 {
104 /*
105 * Ignore null characters. Some acpidump-type utilities insert
106 * a few of these, probably a bug in the utility. As long as these
107 * characters are in lines that are tossed (non-data), they
108 * won't cause a problem.
109 */
110 if (!Byte)
111 {
112 continue;
113 }
114
115 /* Check for an ASCII character */
116
117 if (!ACPI_IS_ASCII (Byte))
118 {
119 printf ("Found non-ascii char: %2.2X at file offset %u (0x%X)\n",
120 Byte, Offset, Offset);
121 if (!Gbl_ForceExtraction)
122 {
123 goto ErrorExit;
124 }
125 }
126
127 /* Ensure character is either printable or a "space" char */
128
129 else if (!isprint (Byte) && !isspace (Byte))
130 {
131 printf ("Found non-printable char: %2.2X at file offset %u (0x%X)\n",
132 Byte, Offset, Offset);
133 if (!Gbl_ForceExtraction)
134 {
135 goto ErrorExit;
136 }
137 }
138
139 Offset++;
140 }
141
142 /* File is OK (100% ASCII) */
143
144 fseek (Handle, 0, SEEK_SET);
145 return (TRUE);
146
147 ErrorExit:
148
149 printf ("File appears to be binary "
150 "(contains non-text or non-ascii characters)\n");
151 fseek (Handle, 0, SEEK_SET);
152 return (FALSE);
153 }
154
155
156 /******************************************************************************
157 *
158 * FUNCTION: AxIsEmptyLine
159 *
160 * PARAMETERS: Buffer - Line from input file
161 *
162 * RETURN: TRUE if line is empty (zero or more blanks only)
163 *
164 * DESCRIPTION: Determine if an input line is empty.
165 *
166 ******************************************************************************/
167
168 BOOLEAN
169 AxIsEmptyLine (
170 char *Buffer)
171 {
172
173 /* Skip all spaces */
174
175 while (*Buffer == ' ')
176 {
177 Buffer++;
178 }
179
180 /* Line is empty when a Unix or DOS-style line terminator is found. */
181
182 if ((*Buffer == '\r') || (*Buffer == '\n'))
183 {
184 return (1);
185 }
186
187 return (0);
188 }
189
190
191 /******************************************************************************
192 *
193 * FUNCTION: AxIsHexDataLine
194 *
195 * PARAMETERS: None
196 *
197 * RETURN: Status. 1 if the table header is valid, 0 otherwise.
198 *
199 * DESCRIPTION: Check for a valid line of hex data of the form:
200 *
201 * 00a0: 0c 00 00 00 03 00 00 00 43 48 41 35 0c 00 00 00 ........CHA5....
202 *
203 ******************************************************************************/
204
205 BOOLEAN
206 AxIsHexDataLine (
207 void)
208 {
209
210 if (AxIsEmptyLine (Gbl_LineBuffer) ||
211 (Gbl_LineBuffer[0] != ' '))
212 {
213 return (FALSE);
214 }
215
216 if (!strstr (Gbl_LineBuffer, ": "))
217 {
218 /* Not valid data line */
219
220 return (FALSE);
221 }
222
223 return (TRUE);
224 }
225
226
227 /******************************************************************************
228 *
229 * FUNCTION: AxIsDataBlockHeader
230 *
231 * PARAMETERS: None
232 *
233 * RETURN: Status. 1 if the table header is valid, 0 otherwise.
234 *
235 * DESCRIPTION: Check if the ACPI table identifier in the input acpidump text
236 * file is valid (of the form: <sig> @ <addr>).
237 *
238 ******************************************************************************/
239
240 BOOLEAN
241 AxIsDataBlockHeader (
242 void)
243 {
244
245 /* Ignore lines that are too short to be header lines */
246
247 if (strlen (Gbl_LineBuffer) < AX_MIN_BLOCK_HEADER_LENGTH)
248 {
249 return (FALSE);
250 }
251
252 /* Ignore empty lines and lines that start with a space */
253
254 if (AxIsEmptyLine (Gbl_LineBuffer) ||
255 (Gbl_LineBuffer[0] == ' '))
256 {
257 return (FALSE);
258 }
259
260 /*
261 * Ignore lines that are not headers of the form <sig> @ <addr>.
262 * Basically, just look for the '@' symbol, surrounded by spaces.
263 *
264 * Examples of headers that must be supported:
265 *
266 * DSDT @ 0x737e4000
267 * XSDT @ 0x737f2fff
268 * RSD PTR @ 0xf6cd0
269 * SSDT @ (nil)
270 */
271 if (!AX_IS_TABLE_BLOCK_HEADER)
272 {
273 return (FALSE);
274 }
275
276 AxNormalizeSignature (Gbl_LineBuffer);
277 return (TRUE);
278 }
279
280
281 /*******************************************************************************
282 *
283 * FUNCTION: AxNormalizeSignature
284 *
285 * PARAMETERS: Name - Ascii string containing an ACPI signature
286 *
287 * RETURN: None
288 *
289 * DESCRIPTION: Change "RSD PTR" to "RSDP"
290 *
291 ******************************************************************************/
292
293 void
294 AxNormalizeSignature (
295 char *Signature)
296 {
297
298 if (!strncmp (Signature, "RSD ", 4))
299 {
300 Signature[3] = 'P';
301 }
302 }
303
304
305 /******************************************************************************
306 *
307 * FUNCTION: AxConvertToBinary
308 *
309 * PARAMETERS: InputLine - One line from the input acpidump file
310 * OutputData - Where the converted data is returned
311 *
312 * RETURN: The number of bytes actually converted
313 *
314 * DESCRIPTION: Convert one line of ascii text binary (up to 16 bytes)
315 *
316 * NOTE: Assumes the input data line has been validated to be of the form:
317 *
318 * 0010: 48 53 57 55 4c 54 2d 52 01 00 00 00 49 4e 54 4c HSWULT-R....INTL
319 *
320 ******************************************************************************/
321
322 size_t
323 AxConvertToBinary (
324 char *InputLine,
325 unsigned char *OutputData)
326 {
327 int BytesConverted;
328 int Converted[16];
329 int i;
330
331
332 /*
333 * Terminate input line immediately after the data. Otherwise, the
334 * second line below will not scan correctly.
335 *
336 * 00b0: 03 00 00 00 43 48 41 36 0c 00 00 00 03 00 00 00 ....CHA6........
337 * 00c0: 43 48 41 37 CHA7
338 */
339 InputLine [AX_END_OF_HEX_DATA] = 0;
340
341 /*
342 * Convert one line of table data, of the form:
343 * <offset>: <up to 16 bytes of hex data> <ASCII representation> <newline>
344 *
345 * Example:
346 * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08 _SB_LNKD........
347 */
348 BytesConverted = sscanf (InputLine,
349 "%*s %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X",
350 &Converted[0], &Converted[1], &Converted[2], &Converted[3],
351 &Converted[4], &Converted[5], &Converted[6], &Converted[7],
352 &Converted[8], &Converted[9], &Converted[10], &Converted[11],
353 &Converted[12], &Converted[13], &Converted[14], &Converted[15]);
354
355 /* Pack converted data into a byte array */
356
357 for (i = 0; i < BytesConverted; i++)
358 {
359 OutputData[i] = (unsigned char) Converted[i];
360 }
361
362 return ((size_t) BytesConverted);
363 }
364
365
366 /******************************************************************************
367 *
368 * FUNCTION: AxCountTableInstances
369 *
370 * PARAMETERS: InputPathname - Filename for acpidump file
371 * Signature - Requested signature to count
372 *
373 * RETURN: The number of instances of the signature
374 *
375 * DESCRIPTION: Count the instances of tables with the given signature within
376 * the input acpidump file.
377 *
378 ******************************************************************************/
379
380 unsigned int
381 AxCountTableInstances (
382 char *InputPathname,
383 char *Signature)
384 {
385 FILE *InputFile;
386 unsigned int Instances = 0;
387
388
389 InputFile = fopen (InputPathname, "r");
390 if (!InputFile)
391 {
392 printf ("Could not open input file %s\n", InputPathname);
393 return (0);
394 }
395
396 /* Count the number of instances of this signature */
397
398 while (fgets (Gbl_InstanceBuffer, AX_LINE_BUFFER_SIZE, InputFile))
399 {
400 /* Ignore empty lines and lines that start with a space */
401
402 if (AxIsEmptyLine (Gbl_InstanceBuffer) ||
403 (Gbl_InstanceBuffer[0] == ' '))
404 {
405 continue;
406 }
407
408 AxNormalizeSignature (Gbl_InstanceBuffer);
409 if (ACPI_COMPARE_NAME (Gbl_InstanceBuffer, Signature))
410 {
411 Instances++;
412 }
413 }
414
415 fclose (InputFile);
416 return (Instances);
417 }
418
419
420 /******************************************************************************
421 *
422 * FUNCTION: AxGetNextInstance
423 *
424 * PARAMETERS: InputPathname - Filename for acpidump file
425 * Signature - Requested ACPI signature
426 *
427 * RETURN: The next instance number for this signature. Zero if this
428 * is the first instance of this signature.
429 *
430 * DESCRIPTION: Get the next instance number of the specified table. If this
431 * is the first instance of the table, create a new instance
432 * block. Note: only SSDT and PSDT tables can have multiple
433 * instances.
434 *
435 ******************************************************************************/
436
437 unsigned int
438 AxGetNextInstance (
439 char *InputPathname,
440 char *Signature)
441 {
442 AX_TABLE_INFO *Info;
443
444
445 Info = Gbl_TableListHead;
446 while (Info)
447 {
448 if (*(UINT32 *) Signature == Info->Signature)
449 {
450 break;
451 }
452
453 Info = Info->Next;
454 }
455
456 if (!Info)
457 {
458 /* Signature not found, create new table info block */
459
460 Info = malloc (sizeof (AX_TABLE_INFO));
461 if (!Info)
462 {
463 printf ("Could not allocate memory (0x%X bytes)\n",
464 (unsigned int) sizeof (AX_TABLE_INFO));
465 exit (0);
466 }
467
468 Info->Signature = *(UINT32 *) Signature;
469 Info->Instances = AxCountTableInstances (InputPathname, Signature);
470 Info->NextInstance = 1;
471 Info->Next = Gbl_TableListHead;
472 Gbl_TableListHead = Info;
473 }
474
475 if (Info->Instances > 1)
476 {
477 return (Info->NextInstance++);
478 }
479
480 return (0);
481 }
482
483
484 /******************************************************************************
485 *
486 * FUNCTION: AxConvertAndWrite
487 *
488 * PARAMETERS: OutputFile - Where to write the binary data
489 * ThisSignature - Signature of current ACPI table
490 * ThisTableBytesWritten - Total count of data written
491 *
492 * RETURN: Length of the converted line
493 *
494 * DESCRIPTION: Convert one line of input hex ascii text to binary, and write
495 * the binary data to the table output file.
496 *
497 * NOTE: Assumes the input data line has been validated to be of the form:
498 *
499 * 0010: 48 53 57 55 4c 54 2d 52 01 00 00 00 49 4e 54 4c HSWULT-R....INTL
500 *
501 ******************************************************************************/
502
503 long
504 AxConvertAndWrite (
505 FILE *OutputFile,
506 char *ThisSignature,
507 unsigned int ThisTableBytesWritten)
508 {
509 size_t BytesWritten;
510 size_t BytesConverted;
511
512
513 /* Convert one line of ascii hex data to binary */
514
515 BytesConverted = AxConvertToBinary (Gbl_LineBuffer, Gbl_BinaryData);
516
517 /* Write the binary data */
518
519 if (!BytesConverted)
520 {
521 return (0);
522 }
523
524 BytesWritten = fwrite (Gbl_BinaryData, 1, BytesConverted, OutputFile);
525 if (BytesWritten != BytesConverted)
526 {
527 printf ("Error while writing file %s\n", Gbl_OutputFilename);
528 return (-1);
529 }
530
531 return (BytesWritten);
532 }
533
534
535 /******************************************************************************
536 *
537 * FUNCTION: AxDumpTableHeader
538 *
539 * PARAMETERS: Header - A binary ACPI table header
540 *
541 * RETURN: None
542 *
543 * DESCRIPTION: Display the contents of a standard ACPI table header
544 *
545 ******************************************************************************/
546
547 void
548 AxDumpTableHeader (
549 unsigned char *Header)
550 {
551 ACPI_TABLE_HEADER *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header;
552 ACPI_TABLE_RSDP *Rsdp = (ACPI_TABLE_RSDP *) (void *) Header;
553 ACPI_TABLE_FACS *Facs = (ACPI_TABLE_FACS *) (void *) Header;
554
555
556 /* RSDP has an oddball signature and header */
557
558 if (!strncmp (TableHeader->Signature, "RSD PTR ", 8))
559 {
560 AxCheckAscii ((char *) &Header[9], 6);
561
562 Gbl_TableCount++;
563 printf (" %.2u) %5.4s 0x%8.8X 0x%2.2X \"%6.6s\"\n",
564 Gbl_TableCount, "RSDP", Rsdp->Length, Rsdp->Revision, Rsdp->OemId);
565 return;
566 }
567
568 if (!AcpiUtValidNameseg (TableHeader->Signature))
569 {
570 return;
571 }
572
573 /* Signature and Table length */
574
575 Gbl_TableCount++;
576 printf (" %.2u) %5.4s 0x%8.8X", Gbl_TableCount, TableHeader->Signature,
577 TableHeader->Length);
578
579 /* FACS has only signature and length */
580
581 if (ACPI_COMPARE_NAME (TableHeader->Signature, "FACS"))
582 {
583 printf (" 0x%2.2X\n", Facs->Version);
584 return;
585 }
586
587 /* OEM IDs and Compiler IDs */
588
589 AxCheckAscii (TableHeader->OemId, 6);
590 AxCheckAscii (TableHeader->OemTableId, 8);
591 AxCheckAscii (TableHeader->AslCompilerId, 4);
592
593 printf (
594 " 0x%2.2X \"%6.6s\" \"%8.8s\" 0x%8.8X"
595 " \"%4.4s\" 0x%8.8X\n",
596 TableHeader->Revision, TableHeader->OemId,
597 TableHeader->OemTableId, TableHeader->OemRevision,
598 TableHeader->AslCompilerId, TableHeader->AslCompilerRevision);
599 }
600
601
602 #ifdef _AX_FUTURE_ENHANCEMENTS
603
604 /* Possible enhancement to validate table lengths */
605
606 void
607 AxCheckTableLengths (
608 UINT32 ByteCount,
609 UINT32 AmlByteCount)
610 {
611
612 if (AmlByteCount == 0)
613 {
614 return;
615 }
616
617 if (ByteCount == 0)
618 {
619 return;
620 }
621
622 if ((ByteCount < sizeof (ACPI_TABLE_HEADER)) &&
623 (ByteCount >= ACPI_NAME_SIZE))
624 {
625 printf (" : (Table too short for an ACPI table)");
626 }
627
628 else if (ByteCount != AmlByteCount)
629 {
630 printf (" : (Hex data length mismatch with AML length 0x%X)",
631 AmlByteCount);
632 }
633
634 printf ("\n");
635 }
636 #endif
637