abcompare.c revision 1.1.1.2 1 /******************************************************************************
2 *
3 * Module Name: abcompare - compare AML files
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2013, 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 "acpibin.h"
45
46
47 FILE *File1;
48 FILE *File2;
49 ACPI_TABLE_HEADER Header1;
50 ACPI_TABLE_HEADER Header2;
51
52 #define BUFFER_SIZE 256
53 char Buffer[BUFFER_SIZE];
54
55
56 /* Local prototypes */
57
58 static BOOLEAN
59 AbValidateHeader (
60 ACPI_TABLE_HEADER *Header);
61
62 static UINT8
63 AcpiTbSumTable (
64 void *Buffer,
65 UINT32 Length);
66
67 static char *
68 AbGetFile (
69 char *Filename,
70 UINT32 *FileSize);
71
72 static UINT32
73 AbGetFileSize (
74 FILE *File);
75
76 static void
77 AbPrintHeaderInfo (
78 ACPI_TABLE_HEADER *Header);
79
80 static void
81 AbPrintHeadersInfo (
82 ACPI_TABLE_HEADER *Header,
83 ACPI_TABLE_HEADER *Header2);
84
85 ACPI_PHYSICAL_ADDRESS
86 AeLocalGetRootPointer (
87 void);
88
89
90 /*******************************************************************************
91 *
92 * FUNCTION: UtHexCharToValue
93 *
94 * PARAMETERS: HexChar - Hex character in Ascii
95 *
96 * RETURN: The binary value of the hex character
97 *
98 * DESCRIPTION: Perform ascii-to-hex translation
99 *
100 ******************************************************************************/
101
102 static UINT8
103 UtHexCharToValue (
104 int HexChar,
105 UINT8 *OutBinary)
106 {
107
108 if (HexChar >= 0x30 && HexChar <= 0x39)
109 {
110 *OutBinary = (UINT8) (HexChar - 0x30);
111 return (1);
112 }
113
114 else if (HexChar >= 0x41 && HexChar <= 0x46)
115 {
116 *OutBinary = (UINT8) (HexChar - 0x37);
117 return (1);
118 }
119
120 else if (HexChar >= 0x61 && HexChar <= 0x66)
121 {
122 *OutBinary = (UINT8) (HexChar - 0x57);
123 return (1);
124 }
125 return (0);
126 }
127
128 static UINT8
129 AbHexByteToBinary (
130 char *HexString,
131 char *OutBinary)
132 {
133 UINT8 Local1;
134 UINT8 Local2;
135
136
137 if (!UtHexCharToValue (HexString[0], &Local1))
138 {
139 return (0);
140 }
141 if (!UtHexCharToValue (HexString[1], &Local2))
142 {
143 return (0);
144 }
145
146 *OutBinary = (UINT8) ((Local1 << 4) | Local2);
147 return (2);
148
149 }
150
151
152 /******************************************************************************
153 *
154 * FUNCTION: AbValidateHeader
155 *
156 * DESCRIPTION: Check for valid ACPI table header
157 *
158 ******************************************************************************/
159
160 static BOOLEAN
161 AbValidateHeader (
162 ACPI_TABLE_HEADER *Header)
163 {
164
165 if (!AcpiUtValidAcpiName (Header->Signature))
166 {
167 printf ("Header signature is invalid\n");
168 return (FALSE);
169 }
170
171 return (TRUE);
172 }
173
174
175 /*******************************************************************************
176 *
177 * FUNCTION: AcpiTbSumTable
178 *
179 * PARAMETERS: Buffer - Buffer to checksum
180 * Length - Size of the buffer
181 *
182 * RETURNS 8 bit checksum of buffer
183 *
184 * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it.
185 *
186 ******************************************************************************/
187
188 static UINT8
189 AcpiTbSumTable (
190 void *Buffer,
191 UINT32 Length)
192 {
193 const UINT8 *limit;
194 const UINT8 *rover;
195 UINT8 sum = 0;
196
197
198 if (Buffer && Length)
199 {
200 /* Buffer and Length are valid */
201
202 limit = (UINT8 *) Buffer + Length;
203
204 for (rover = Buffer; rover < limit; rover++)
205 {
206 sum = (UINT8) (sum + *rover);
207 }
208 }
209 return (sum);
210 }
211
212
213 /*******************************************************************************
214 *
215 * FUNCTION: AbPrintHeaderInfo
216 *
217 * PARAMETERS: Header - An ACPI table header
218 *
219 * RETURNS None.
220 *
221 * DESCRIPTION: Format and display header contents.
222 *
223 ******************************************************************************/
224
225 static void
226 AbPrintHeaderInfo (
227 ACPI_TABLE_HEADER *Header)
228 {
229
230 /* Display header information */
231
232 printf ("Signature : %4.4s\n", Header->Signature);
233 printf ("Length : %8.8X\n", Header->Length);
234 printf ("Revision : %2.2X\n", Header->Revision);
235 printf ("Checksum : %2.2X\n", Header->Checksum);
236 printf ("OEM ID : %6.6s\n", Header->OemId);
237 printf ("OEM Table ID : %8.8s\n", Header->OemTableId);
238 printf ("OEM Revision : %8.8X\n", Header->OemRevision);
239 printf ("ASL Compiler ID : %4.4s\n", Header->AslCompilerId);
240 printf ("Compiler Revision : %8.8X\n", Header->AslCompilerRevision);
241 printf ("\n");
242 }
243
244 static void
245 AbPrintHeadersInfo (
246 ACPI_TABLE_HEADER *Header,
247 ACPI_TABLE_HEADER *Header2)
248 {
249
250 /* Display header information for both headers */
251
252 printf ("Signature %8.4s : %4.4s\n", Header->Signature, Header2->Signature);
253 printf ("Length %8.8X : %8.8X\n", Header->Length, Header2->Length);
254 printf ("Revision %8.2X : %2.2X\n", Header->Revision, Header2->Revision);
255 printf ("Checksum %8.2X : %2.2X\n", Header->Checksum, Header2->Checksum);
256 printf ("OEM ID %8.6s : %6.6s\n", Header->OemId, Header2->OemId);
257 printf ("OEM Table ID %8.8s : %8.8s\n", Header->OemTableId, Header2->OemTableId);
258 printf ("OEM Revision %8.8X : %8.8X\n", Header->OemRevision, Header2->OemRevision);
259 printf ("ASL Compiler ID %8.4s : %4.4s\n", Header->AslCompilerId, Header2->AslCompilerId);
260 printf ("Compiler Revision %8.8X : %8.8X\n", Header->AslCompilerRevision, Header2->AslCompilerRevision);
261 printf ("\n");
262 }
263
264
265 /******************************************************************************
266 *
267 * FUNCTION: AbDisplayHeader
268 *
269 * DESCRIPTION: Display an ACPI table header
270 *
271 ******************************************************************************/
272
273 void
274 AbDisplayHeader (
275 char *File1Path)
276 {
277 UINT32 Actual;
278
279
280 File1 = fopen (File1Path, "rb");
281 if (!File1)
282 {
283 printf ("Could not open file %s\n", File1Path);
284 return;
285 }
286
287 Actual = fread (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File1);
288 if (Actual != sizeof (ACPI_TABLE_HEADER))
289 {
290 printf ("File %s does not contain an ACPI table header\n", File1Path);
291 return;
292 }
293
294 if (!AbValidateHeader (&Header1))
295 {
296 return;
297 }
298
299 AbPrintHeaderInfo (&Header1);
300 }
301
302
303 /******************************************************************************
304 *
305 * FUNCTION: AbComputeChecksum
306 *
307 * DESCRIPTION: Compute proper checksum for an ACPI table
308 *
309 ******************************************************************************/
310
311 void
312 AbComputeChecksum (
313 char *File1Path)
314 {
315 UINT32 Actual;
316 ACPI_TABLE_HEADER *Table;
317 UINT8 Checksum;
318
319
320 File1 = fopen (File1Path, "rb");
321 if (!File1)
322 {
323 printf ("Could not open file %s\n", File1Path);
324 return;
325 }
326
327 Actual = fread (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File1);
328 if (Actual < sizeof (ACPI_TABLE_HEADER))
329 {
330 printf ("File %s does not contain an ACPI table header\n", File1Path);
331 return;
332 }
333
334 if (!AbValidateHeader (&Header1))
335 {
336 return;
337 }
338
339 if (!Gbl_TerseMode)
340 {
341 AbPrintHeaderInfo (&Header1);
342 }
343
344 /* Allocate a buffer to hold the entire table */
345
346 Table = AcpiOsAllocate (Header1.Length);
347 if (!Table)
348 {
349 printf ("could not allocate\n");
350 return;
351 }
352
353 /* Read the entire table, including header */
354
355 fseek (File1, 0, SEEK_SET);
356 Actual = fread (Table, 1, Header1.Length, File1);
357 if (Actual != Header1.Length)
358 {
359 printf ("could not read table, length %u\n", Header1.Length);
360 return;
361 }
362
363 /* Compute the checksum for the table */
364
365 Table->Checksum = 0;
366
367 Checksum = (UINT8) (0 - AcpiTbSumTable (Table, Table->Length));
368 printf ("Computed checksum: 0x%X\n\n", Checksum);
369
370 if (Header1.Checksum == Checksum)
371 {
372 printf ("Checksum ok in AML file, not updating\n");
373 return;
374 }
375
376 /* Open the target file for writing, to update checksum */
377
378 fclose (File1);
379 File1 = fopen (File1Path, "r+b");
380 if (!File1)
381 {
382 printf ("Could not open file %s for writing\n", File1Path);
383 return;
384 }
385
386 /* Set the checksum, write the new header */
387
388 Header1.Checksum = Checksum;
389
390 Actual = fwrite (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File1);
391 if (Actual != sizeof (ACPI_TABLE_HEADER))
392 {
393 printf ("Could not write updated table header\n");
394 return;
395 }
396
397 printf ("Wrote new checksum\n");
398 return;
399 }
400
401
402 /******************************************************************************
403 *
404 * FUNCTION: AbCompareAmlFiles
405 *
406 * DESCRIPTION: Compare two AML files
407 *
408 ******************************************************************************/
409
410 int
411 AbCompareAmlFiles (
412 char *File1Path,
413 char *File2Path)
414 {
415 UINT32 Actual1;
416 UINT32 Actual2;
417 UINT32 Offset;
418 UINT8 Char1;
419 UINT8 Char2;
420 UINT8 Mismatches = 0;
421 BOOLEAN HeaderMismatch = FALSE;
422
423
424 File1 = fopen (File1Path, "rb");
425 if (!File1)
426 {
427 printf ("Could not open file %s\n", File1Path);
428 return (-1);
429 }
430
431 File2 = fopen (File2Path, "rb");
432 if (!File2)
433 {
434 printf ("Could not open file %s\n", File2Path);
435 return (-1);
436 }
437
438 /* Read the ACPI header from each file */
439
440 Actual1 = fread (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File1);
441 if (Actual1 != sizeof (ACPI_TABLE_HEADER))
442 {
443 printf ("File %s does not contain an ACPI table header\n", File1Path);
444 return (-1);
445 }
446
447 Actual2 = fread (&Header2, 1, sizeof (ACPI_TABLE_HEADER), File2);
448 if (Actual2 != sizeof (ACPI_TABLE_HEADER))
449 {
450 printf ("File %s does not contain an ACPI table header\n", File2Path);
451 return (-1);
452 }
453
454 if ((!AbValidateHeader (&Header1)) ||
455 (!AbValidateHeader (&Header2)))
456 {
457 return (-1);
458 }
459
460 /* Table signatures must match */
461
462 if (*((UINT32 *) Header1.Signature) != *((UINT32 *) Header2.Signature))
463 {
464 printf ("Table signatures do not match\n");
465 return (-1);
466 }
467
468 if (!Gbl_TerseMode)
469 {
470 /* Display header information */
471
472 AbPrintHeadersInfo (&Header1, &Header2);
473 }
474
475 if (memcmp (&Header1, &Header2, sizeof (ACPI_TABLE_HEADER)))
476 {
477 printf ("Headers do not match exactly\n");
478 HeaderMismatch = TRUE;
479 }
480
481 /* Do the byte-by-byte compare */
482
483 Actual1 = fread (&Char1, 1, 1, File1);
484 Actual2 = fread (&Char2, 1, 1, File2);
485 Offset = sizeof (ACPI_TABLE_HEADER);
486
487 while ((Actual1 == 1) && (Actual2 == 1))
488 {
489 if (Char1 != Char2)
490 {
491 printf ("Error - Byte mismatch at offset %8.8X: 0x%2.2X 0x%2.2X\n",
492 Offset, Char1, Char2);
493 Mismatches++;
494 if (Mismatches > 100)
495 {
496 printf ("100 Mismatches: Too many mismatches\n");
497 return (-1);
498 }
499 }
500
501 Offset++;
502 Actual1 = fread (&Char1, 1, 1, File1);
503 Actual2 = fread (&Char2, 1, 1, File2);
504 }
505
506 if (Actual1)
507 {
508 printf ("Error - file %s is longer than file %s\n", File1Path, File2Path);
509 Mismatches++;
510 }
511 else if (Actual2)
512 {
513 printf ("Error - file %s is shorter than file %s\n", File1Path, File2Path);
514 Mismatches++;
515 }
516 else if (!Mismatches)
517 {
518 if (HeaderMismatch)
519 {
520 printf ("Files compare exactly after header\n");
521 }
522 else
523 {
524 printf ("Files compare exactly\n");
525 }
526 }
527
528 printf ("%u Mismatches found\n", Mismatches);
529 return (0);
530 }
531
532
533 /******************************************************************************
534 *
535 * FUNCTION: AbGetFileSize
536 *
537 * DESCRIPTION: Get the size of an open file
538 *
539 ******************************************************************************/
540
541 static UINT32
542 AbGetFileSize (
543 FILE *File)
544 {
545 UINT32 FileSize;
546 long Offset;
547
548
549 Offset = ftell (File);
550
551 if (fseek (File, 0, SEEK_END))
552 {
553 return (0);
554 }
555
556 FileSize = (UINT32) ftell (File);
557
558 /* Restore file pointer */
559
560 if (fseek (File, Offset, SEEK_SET))
561 {
562 return (0);
563 }
564
565 return (FileSize);
566 }
567
568
569 /******************************************************************************
570 *
571 * FUNCTION: AbGetFile
572 *
573 * DESCRIPTION: Open a file and read it entirely into a new buffer
574 *
575 ******************************************************************************/
576
577 static char *
578 AbGetFile (
579 char *Filename,
580 UINT32 *FileSize)
581 {
582 FILE *File;
583 UINT32 Size;
584 char *Buffer = NULL;
585 size_t Actual;
586
587
588 /* Binary mode does not alter CR/LF pairs */
589
590 File = fopen (Filename, "rb");
591 if (!File)
592 {
593 printf ("Could not open file %s\n", Filename);
594 return (NULL);
595 }
596
597 /* Need file size to allocate a buffer */
598
599 Size = AbGetFileSize (File);
600 if (!Size)
601 {
602 printf ("Could not get file size (seek) for %s\n", Filename);
603 goto ErrorExit;
604 }
605
606 /* Allocate a buffer for the entire file */
607
608 Buffer = calloc (Size, 1);
609 if (!Buffer)
610 {
611 printf ("Could not allocate buffer of size %u\n", Size);
612 goto ErrorExit;
613 }
614
615 /* Read the entire file */
616
617 Actual = fread (Buffer, 1, Size, File);
618 if (Actual != Size)
619 {
620 printf ("Could not read the input file %s\n", Filename);
621 free (Buffer);
622 Buffer = NULL;
623 goto ErrorExit;
624 }
625
626 *FileSize = Size;
627
628 ErrorExit:
629 fclose (File);
630 return (Buffer);
631 }
632
633
634 /******************************************************************************
635 *
636 * FUNCTION: AbDumpAmlFile
637 *
638 * DESCRIPTION: Dump a binary AML file to a text file
639 *
640 ******************************************************************************/
641
642 int
643 AbDumpAmlFile (
644 char *File1Path,
645 char *File2Path)
646 {
647 char *FileBuffer;
648 FILE *FileOutHandle;
649 UINT32 FileSize = 0;
650
651
652 /* Get the entire AML file, validate header */
653
654 FileBuffer = AbGetFile (File1Path, &FileSize);
655 if (!FileBuffer)
656 {
657 return (-1);
658 }
659
660 printf ("Input file: %s contains %u (0x%X) bytes\n",
661 File1Path, FileSize, FileSize);
662
663 FileOutHandle = fopen (File2Path, "wb");
664 if (!FileOutHandle)
665 {
666 printf ("Could not open file %s\n", File2Path);
667 return (-1);
668 }
669
670 if (!AbValidateHeader ((ACPI_TABLE_HEADER *) FileBuffer))
671 {
672 return (-1);
673 }
674
675 /* Convert binary AML to text, using common dump buffer routine */
676
677 AcpiGbl_DebugFile = FileOutHandle;
678 AcpiGbl_DbOutputFlags = ACPI_DB_REDIRECTABLE_OUTPUT;
679
680 AcpiOsPrintf ("%4.4s @ 0x%8.8X\n",
681 ((ACPI_TABLE_HEADER *) FileBuffer)->Signature, 0);
682
683 AcpiUtDumpBuffer ((UINT8 *) FileBuffer, FileSize, DB_BYTE_DISPLAY, 0);
684
685 /* Summary for the output file */
686
687 FileSize = AbGetFileSize (FileOutHandle);
688 printf ("Output file: %s contains %u (0x%X) bytes\n\n",
689 File2Path, FileSize, FileSize);
690
691 return (0);
692 }
693
694
695 /******************************************************************************
696 *
697 * FUNCTION: AbExtractAmlFile
698 *
699 * DESCRIPTION: Extract a binary AML file from a text file (as produced by the
700 * DumpAmlFile procedure or the "acpidump" table utility.
701 *
702 ******************************************************************************/
703
704 int
705 AbExtractAmlFile (
706 char *TableSig,
707 char *File1Path,
708 char *File2Path)
709 {
710 char *Table;
711 char Value;
712 UINT32 i;
713 FILE *FileHandle;
714 FILE *FileOutHandle;
715 UINT32 Count = 0;
716 int Scanned;
717
718
719 /* Open in/out files. input is in text mode, output is in binary mode */
720
721 FileHandle = fopen (File1Path, "rt");
722 if (!FileHandle)
723 {
724 printf ("Could not open file %s\n", File1Path);
725 return (-1);
726 }
727
728 FileOutHandle = fopen (File2Path, "w+b");
729 if (!FileOutHandle)
730 {
731 printf ("Could not open file %s\n", File2Path);
732 return (-1);
733 }
734
735 /* Force input table sig to uppercase */
736
737 AcpiUtStrupr (TableSig);
738
739
740 /* TBD: examine input for ASCII */
741
742
743 /* We have an ascii file, grab one line at a time */
744
745 while (fgets (Buffer, BUFFER_SIZE, FileHandle))
746 {
747 /* The 4-char ACPI signature appears at the beginning of a line */
748
749 if (ACPI_COMPARE_NAME (Buffer, TableSig))
750 {
751 printf ("Found table [%4.4s]\n", TableSig);
752
753 /*
754 * Eat all lines in the table, of the form:
755 * <offset>: <16 bytes of hex data, separated by spaces> <ASCII representation> <newline>
756 *
757 * Example:
758 *
759 * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08 _SB_LNKD........
760 *
761 */
762 while (fgets (Buffer, BUFFER_SIZE, FileHandle))
763 {
764 /* Get past the offset, terminated by a colon */
765
766 Table = strchr (Buffer, ':');
767 if (!Table)
768 {
769 /* No colon, all done */
770 goto Exit;
771 }
772
773 Table += 2; /* Eat the colon + space */
774
775 for (i = 0; i < 16; i++)
776 {
777 Scanned = AbHexByteToBinary (Table, &Value);
778 if (!Scanned)
779 {
780 goto Exit;
781 }
782
783 Table += 3; /* Go past this hex byte and space */
784
785 /* Write the converted (binary) byte */
786
787 if (fwrite (&Value, 1, 1, FileOutHandle) != 1)
788 {
789 printf ("Error writing byte %u to output file: %s\n",
790 Count, File2Path);
791 goto Exit;
792 }
793 Count++;
794 }
795 }
796
797 /* No more lines, EOF, all done */
798
799 goto Exit;
800 }
801 }
802
803 /* Searched entire file, no match to table signature */
804
805 printf ("Could not match table signature\n");
806 fclose (FileHandle);
807 return (-1);
808
809 Exit:
810 printf ("%u (0x%X) bytes written to %s\n", Count, Count, File2Path);
811 fclose (FileHandle);
812 fclose (FileOutHandle);
813 return (0);
814 }
815
816
817 /******************************************************************************
818 *
819 * FUNCTION: Stubs
820 *
821 * DESCRIPTION: For linkage
822 *
823 ******************************************************************************/
824
825 ACPI_PHYSICAL_ADDRESS
826 AeLocalGetRootPointer (
827 void)
828 {
829 return (AE_OK);
830 }
831
832 ACPI_THREAD_ID
833 AcpiOsGetThreadId (
834 void)
835 {
836 return (0xFFFF);
837 }
838
839 ACPI_STATUS
840 AcpiOsExecute (
841 ACPI_EXECUTE_TYPE Type,
842 ACPI_OSD_EXEC_CALLBACK Function,
843 void *Context)
844 {
845 return (AE_SUPPORT);
846 }
847