1 /****************************************************************************** 2 * 3 * Module Name: abcompare - compare AML files 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 }