axutils.c revision 1.1.1.5 1 /******************************************************************************
2 *
3 * Module Name: axutils - Utility functions for acpixtract tool.
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2018, 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 char *ColonDelimiter;
328 int BytesConverted;
329 int Converted[16];
330 int i;
331
332
333 /*
334 * Terminate input line immediately after the data. Otherwise, the
335 * second line below will not scan correctly.
336 *
337 * This handles varying lengths for the offset: line prefix. This support
338 * for tables larger than 1mb was added 05/2018.
339 *
340 * 00b0: 03 00 00 00 43 48 41 36 0c 00 00 00 03 00 00 00 ....CHA6........
341 * 00c0: 43 48 41 37 CHA7
342 *
343 * 012340b0: 03 00 00 00 43 48 41 36 0c 00 00 00 03 00 00 00 ....CHA6........
344 * 012340c0: 43 48 41 37 CHA7
345 */
346 ColonDelimiter = strchr (InputLine, ':');
347 ColonDelimiter [AX_HEX_DATA_LENGTH] = 0;
348
349 /*
350 * Convert one line of table data, of the form:
351 * <offset>: <up to 16 bytes of hex data> <ASCII representation> <newline>
352 *
353 * Example:
354 * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08 _SB_LNKD........
355 */
356 BytesConverted = sscanf (InputLine,
357 "%*s %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X",
358 &Converted[0], &Converted[1], &Converted[2], &Converted[3],
359 &Converted[4], &Converted[5], &Converted[6], &Converted[7],
360 &Converted[8], &Converted[9], &Converted[10], &Converted[11],
361 &Converted[12], &Converted[13], &Converted[14], &Converted[15]);
362
363 /* Pack converted data into a byte array */
364
365 for (i = 0; i < BytesConverted; i++)
366 {
367 OutputData[i] = (unsigned char) Converted[i];
368 }
369
370 return ((size_t) BytesConverted);
371 }
372
373
374 /******************************************************************************
375 *
376 * FUNCTION: AxCountTableInstances
377 *
378 * PARAMETERS: InputPathname - Filename for acpidump file
379 * Signature - Requested signature to count
380 *
381 * RETURN: The number of instances of the signature
382 *
383 * DESCRIPTION: Count the instances of tables with the given signature within
384 * the input acpidump file.
385 *
386 ******************************************************************************/
387
388 unsigned int
389 AxCountTableInstances (
390 char *InputPathname,
391 char *Signature)
392 {
393 FILE *InputFile;
394 unsigned int Instances = 0;
395
396
397 InputFile = fopen (InputPathname, "r");
398 if (!InputFile)
399 {
400 printf ("Could not open input file %s\n", InputPathname);
401 return (0);
402 }
403
404 /* Count the number of instances of this signature */
405
406 while (fgets (Gbl_InstanceBuffer, AX_LINE_BUFFER_SIZE, InputFile))
407 {
408 /* Ignore empty lines and lines that start with a space */
409
410 if (AxIsEmptyLine (Gbl_InstanceBuffer) ||
411 (Gbl_InstanceBuffer[0] == ' '))
412 {
413 continue;
414 }
415
416 AxNormalizeSignature (Gbl_InstanceBuffer);
417 if (ACPI_COMPARE_NAME (Gbl_InstanceBuffer, Signature))
418 {
419 Instances++;
420 }
421 }
422
423 fclose (InputFile);
424 return (Instances);
425 }
426
427
428 /******************************************************************************
429 *
430 * FUNCTION: AxGetNextInstance
431 *
432 * PARAMETERS: InputPathname - Filename for acpidump file
433 * Signature - Requested ACPI signature
434 *
435 * RETURN: The next instance number for this signature. Zero if this
436 * is the first instance of this signature.
437 *
438 * DESCRIPTION: Get the next instance number of the specified table. If this
439 * is the first instance of the table, create a new instance
440 * block. Note: only SSDT and PSDT tables can have multiple
441 * instances.
442 *
443 ******************************************************************************/
444
445 unsigned int
446 AxGetNextInstance (
447 char *InputPathname,
448 char *Signature)
449 {
450 AX_TABLE_INFO *Info;
451
452
453 Info = Gbl_TableListHead;
454 while (Info)
455 {
456 if (*(UINT32 *) Signature == Info->Signature)
457 {
458 break;
459 }
460
461 Info = Info->Next;
462 }
463
464 if (!Info)
465 {
466 /* Signature not found, create new table info block */
467
468 Info = malloc (sizeof (AX_TABLE_INFO));
469 if (!Info)
470 {
471 printf ("Could not allocate memory (0x%X bytes)\n",
472 (unsigned int) sizeof (AX_TABLE_INFO));
473 exit (0);
474 }
475
476 Info->Signature = *(UINT32 *) Signature;
477 Info->Instances = AxCountTableInstances (InputPathname, Signature);
478 Info->NextInstance = 1;
479 Info->Next = Gbl_TableListHead;
480 Gbl_TableListHead = Info;
481 }
482
483 if (Info->Instances > 1)
484 {
485 return (Info->NextInstance++);
486 }
487
488 return (0);
489 }
490
491
492 /******************************************************************************
493 *
494 * FUNCTION: AxConvertAndWrite
495 *
496 * PARAMETERS: OutputFile - Where to write the binary data
497 * ThisSignature - Signature of current ACPI table
498 * ThisTableBytesWritten - Total count of data written
499 *
500 * RETURN: Length of the converted line
501 *
502 * DESCRIPTION: Convert one line of input hex ascii text to binary, and write
503 * the binary data to the table output file.
504 *
505 * NOTE: Assumes the input data line has been validated to be of the form:
506 *
507 * 0010: 48 53 57 55 4c 54 2d 52 01 00 00 00 49 4e 54 4c HSWULT-R....INTL
508 *
509 ******************************************************************************/
510
511 long
512 AxConvertAndWrite (
513 FILE *OutputFile,
514 char *ThisSignature,
515 unsigned int ThisTableBytesWritten)
516 {
517 size_t BytesWritten;
518 size_t BytesConverted;
519
520
521 /* Convert one line of ascii hex data to binary */
522
523 BytesConverted = AxConvertToBinary (Gbl_LineBuffer, Gbl_BinaryData);
524
525 /* Write the binary data */
526
527 if (!BytesConverted)
528 {
529 return (0);
530 }
531
532 BytesWritten = fwrite (Gbl_BinaryData, 1, BytesConverted, OutputFile);
533 if (BytesWritten != BytesConverted)
534 {
535 printf ("Error while writing file %s\n", Gbl_OutputFilename);
536 return (-1);
537 }
538
539 return (BytesWritten);
540 }
541
542
543 /******************************************************************************
544 *
545 * FUNCTION: AxDumpTableHeader
546 *
547 * PARAMETERS: Header - A binary ACPI table header
548 *
549 * RETURN: None
550 *
551 * DESCRIPTION: Display the contents of a standard ACPI table header
552 *
553 ******************************************************************************/
554
555 void
556 AxDumpTableHeader (
557 unsigned char *Header)
558 {
559 ACPI_TABLE_HEADER *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header;
560 ACPI_TABLE_RSDP *Rsdp = (ACPI_TABLE_RSDP *) (void *) Header;
561 ACPI_TABLE_FACS *Facs = (ACPI_TABLE_FACS *) (void *) Header;
562
563
564 /* RSDP has an oddball signature and header */
565
566 if (!strncmp (TableHeader->Signature, "RSD PTR ", 8))
567 {
568 AxCheckAscii ((char *) &Header[9], 6);
569
570 Gbl_TableCount++;
571 printf (" %.2u) %5.4s 0x%8.8X 0x%2.2X \"%6.6s\"\n",
572 Gbl_TableCount, "RSDP", Rsdp->Length, Rsdp->Revision, Rsdp->OemId);
573 return;
574 }
575
576 if (!AcpiUtValidNameseg (TableHeader->Signature))
577 {
578 return;
579 }
580
581 /* Signature and Table length */
582
583 Gbl_TableCount++;
584 printf (" %.2u) %5.4s 0x%8.8X", Gbl_TableCount, TableHeader->Signature,
585 TableHeader->Length);
586
587 /* FACS has only signature and length */
588
589 if (ACPI_COMPARE_NAME (TableHeader->Signature, "FACS"))
590 {
591 printf (" 0x%2.2X\n", Facs->Version);
592 return;
593 }
594
595 /* OEM IDs and Compiler IDs */
596
597 AxCheckAscii (TableHeader->OemId, 6);
598 AxCheckAscii (TableHeader->OemTableId, 8);
599 AxCheckAscii (TableHeader->AslCompilerId, 4);
600
601 printf (
602 " 0x%2.2X \"%6.6s\" \"%8.8s\" 0x%8.8X"
603 " \"%4.4s\" 0x%8.8X\n",
604 TableHeader->Revision, TableHeader->OemId,
605 TableHeader->OemTableId, TableHeader->OemRevision,
606 TableHeader->AslCompilerId, TableHeader->AslCompilerRevision);
607 }
608
609
610 #ifdef _AX_FUTURE_ENHANCEMENTS
611
612 /* Possible enhancement to validate table lengths */
613
614 void
615 AxCheckTableLengths (
616 UINT32 ByteCount,
617 UINT32 AmlByteCount)
618 {
619
620 if (AmlByteCount == 0)
621 {
622 return;
623 }
624
625 if (ByteCount == 0)
626 {
627 return;
628 }
629
630 if ((ByteCount < sizeof (ACPI_TABLE_HEADER)) &&
631 (ByteCount >= ACPI_NAME_SIZE))
632 {
633 printf (" : (Table too short for an ACPI table)");
634 }
635
636 else if (ByteCount != AmlByteCount)
637 {
638 printf (" : (Hex data length mismatch with AML length 0x%X)",
639 AmlByteCount);
640 }
641
642 printf ("\n");
643 }
644 #endif
645