1 /****************************************************************************** 2 * 3 * Module Name: abcompare - compare AML files 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 "acpibin.h" 45 46 47 ACPI_TABLE_HEADER Header1; 48 ACPI_TABLE_HEADER Header2; 49 50 #define BUFFER_SIZE 256 51 char Buffer[BUFFER_SIZE]; 52 53 54 /* Local prototypes */ 55 56 static BOOLEAN 57 AbValidateHeader ( 58 ACPI_TABLE_HEADER *Header); 59 60 static UINT8 61 AcpiTbSumTable ( 62 void *Buffer, 63 UINT32 Length); 64 65 static char * 66 AbGetFile ( 67 char *Filename, 68 UINT32 *FileSize); 69 70 static void 71 AbPrintHeaderInfo ( 72 ACPI_TABLE_HEADER *Header); 73 74 static void 75 AbPrintHeadersInfo ( 76 ACPI_TABLE_HEADER *Header, 77 ACPI_TABLE_HEADER *Header2); 78 79 80 /****************************************************************************** 81 * 82 * FUNCTION: AbValidateHeader 83 * 84 * DESCRIPTION: Check for valid ACPI table header 85 * 86 ******************************************************************************/ 87 88 static BOOLEAN 89 AbValidateHeader ( 90 ACPI_TABLE_HEADER *Header) 91 { 92 93 if (!AcpiUtValidNameseg (Header->Signature)) 94 { 95 printf ("Header signature is invalid\n"); 96 return (FALSE); 97 } 98 99 return (TRUE); 100 } 101 102 103 /******************************************************************************* 104 * 105 * FUNCTION: AcpiTbSumTable 106 * 107 * PARAMETERS: Buffer - Buffer to checksum 108 * Length - Size of the buffer 109 * 110 * RETURNS 8 bit checksum of buffer 111 * 112 * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it. 113 * 114 ******************************************************************************/ 115 116 static UINT8 117 AcpiTbSumTable ( 118 void *Buffer, 119 UINT32 Length) 120 { 121 const UINT8 *Limit; 122 const UINT8 *Rover; 123 UINT8 Sum = 0; 124 125 126 if (Buffer && Length) 127 { 128 /* Buffer and Length are valid */ 129 130 Limit = (UINT8 *) Buffer + Length; 131 132 for (Rover = Buffer; Rover < Limit; Rover++) 133 { 134 Sum = (UINT8) (Sum + *Rover); 135 } 136 } 137 138 return (Sum); 139 } 140 141 142 /******************************************************************************* 143 * 144 * FUNCTION: AbPrintHeaderInfo 145 * 146 * PARAMETERS: Header - An ACPI table header 147 * 148 * RETURNS None. 149 * 150 * DESCRIPTION: Format and display header contents. 151 * 152 ******************************************************************************/ 153 154 static void 155 AbPrintHeaderInfo ( 156 ACPI_TABLE_HEADER *Header) 157 { 158 159 /* Display header information */ 160 161 printf ("Signature : %4.4s\n", Header->Signature); 162 printf ("Length : %8.8X\n", Header->Length); 163 printf ("Revision : %2.2X\n", Header->Revision); 164 printf ("Checksum : %2.2X\n", Header->Checksum); 165 printf ("OEM ID : %.6s\n", Header->OemId); 166 printf ("OEM Table ID : %.8s\n", Header->OemTableId); 167 printf ("OEM Revision : %8.8X\n", Header->OemRevision); 168 printf ("ASL Compiler ID : %.4s\n", Header->AslCompilerId); 169 printf ("Compiler Revision : %8.8X\n", Header->AslCompilerRevision); 170 printf ("\n"); 171 } 172 173 static void 174 AbPrintHeadersInfo ( 175 ACPI_TABLE_HEADER *Header, 176 ACPI_TABLE_HEADER *Header2) 177 { 178 179 /* Display header information for both headers */ 180 181 printf ("Signature %8.4s : %4.4s\n", Header->Signature, Header2->Signature); 182 printf ("Length %8.8X : %8.8X\n", Header->Length, Header2->Length); 183 printf ("Revision %8.2X : %2.2X\n", Header->Revision, Header2->Revision); 184 printf ("Checksum %8.2X : %2.2X\n", Header->Checksum, Header2->Checksum); 185 printf ("OEM ID %8.6s : %.6s\n", Header->OemId, Header2->OemId); 186 printf ("OEM Table ID %8.8s : %.8s\n", Header->OemTableId, Header2->OemTableId); 187 printf ("OEM Revision %8.8X : %8.8X\n", Header->OemRevision, Header2->OemRevision); 188 printf ("ASL Compiler ID %8.4s : %.4s\n", Header->AslCompilerId, Header2->AslCompilerId); 189 printf ("Compiler Revision %8.8X : %8.8X\n", Header->AslCompilerRevision, Header2->AslCompilerRevision); 190 printf ("\n"); 191 } 192 193 194 /****************************************************************************** 195 * 196 * FUNCTION: AbDisplayHeader 197 * 198 * DESCRIPTION: Display an ACPI table header 199 * 200 ******************************************************************************/ 201 202 void 203 AbDisplayHeader ( 204 char *FilePath) 205 { 206 UINT32 Actual; 207 FILE *File; 208 209 210 File = fopen (FilePath, "rb"); 211 if (!File) 212 { 213 printf ("Could not open file %s\n", FilePath); 214 return; 215 } 216 217 Actual = fread (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File); 218 fclose (File); 219 220 if (Actual != sizeof (ACPI_TABLE_HEADER)) 221 { 222 printf ("File %s does not contain a valid ACPI table header\n", FilePath); 223 return; 224 } 225 226 if (!AbValidateHeader (&Header1)) 227 { 228 return; 229 } 230 231 AbPrintHeaderInfo (&Header1); 232 } 233 234 235 /****************************************************************************** 236 * 237 * FUNCTION: AbComputeChecksum 238 * 239 * DESCRIPTION: Compute proper checksum for an ACPI table 240 * 241 ******************************************************************************/ 242 243 void 244 AbComputeChecksum ( 245 char *FilePath) 246 { 247 UINT32 Actual; 248 ACPI_TABLE_HEADER *Table; 249 UINT8 Checksum; 250 FILE *File; 251 252 253 File = fopen (FilePath, "rb"); 254 if (!File) 255 { 256 printf ("Could not open file %s\n", FilePath); 257 return; 258 } 259 260 Actual = fread (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File); 261 if (Actual < sizeof (ACPI_TABLE_HEADER)) 262 { 263 printf ("File %s does not contain a valid ACPI table header\n", FilePath); 264 goto Exit1; 265 } 266 267 if (!AbValidateHeader (&Header1)) 268 { 269 goto Exit1; 270 } 271 272 if (!Gbl_TerseMode) 273 { 274 AbPrintHeaderInfo (&Header1); 275 } 276 277 /* Allocate a buffer to hold the entire table */ 278 279 Table = AcpiOsAllocate (Header1.Length); 280 if (!Table) 281 { 282 printf ("Could not allocate buffer for table\n"); 283 goto Exit1; 284 } 285 286 /* Read the entire table, including header */ 287 288 fseek (File, 0, SEEK_SET); 289 Actual = fread (Table, 1, Header1.Length, File); 290 if (Actual != Header1.Length) 291 { 292 printf ("Could not read table, length %u\n", Header1.Length); 293 goto Exit2; 294 } 295 296 /* Compute the checksum for the table */ 297 298 Table->Checksum = 0; 299 300 Checksum = (UINT8) (0 - AcpiTbSumTable (Table, Table->Length)); 301 printf ("Computed checksum: 0x%X\n\n", Checksum); 302 303 if (Header1.Checksum == Checksum) 304 { 305 printf ("Checksum OK in AML file, not updating\n"); 306 goto Exit2; 307 } 308 309 /* Open the target file for writing, to update checksum */ 310 311 fclose (File); 312 File = fopen (FilePath, "r+b"); 313 if (!File) 314 { 315 printf ("Could not open file %s for writing\n", FilePath); 316 goto Exit2; 317 } 318 319 /* Set the checksum, write the new header */ 320 321 Header1.Checksum = Checksum; 322 323 Actual = fwrite (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File); 324 if (Actual != sizeof (ACPI_TABLE_HEADER)) 325 { 326 printf ("Could not write updated table header\n"); 327 goto Exit2; 328 } 329 330 printf ("Wrote new checksum\n"); 331 332 Exit2: 333 AcpiOsFree (Table); 334 335 Exit1: 336 if (File) 337 { 338 fclose (File); 339 } 340 return; 341 } 342 343 344 /****************************************************************************** 345 * 346 * FUNCTION: AbCompareAmlFiles 347 * 348 * DESCRIPTION: Compare two AML files 349 * 350 ******************************************************************************/ 351 352 int 353 AbCompareAmlFiles ( 354 char *File1Path, 355 char *File2Path) 356 { 357 UINT32 Actual1; 358 UINT32 Actual2; 359 UINT32 Offset; 360 UINT8 Char1; 361 UINT8 Char2; 362 UINT8 Mismatches = 0; 363 BOOLEAN HeaderMismatch = FALSE; 364 FILE *File1; 365 FILE *File2; 366 int Status = -1; 367 368 369 File1 = fopen (File1Path, "rb"); 370 if (!File1) 371 { 372 printf ("Could not open file %s\n", File1Path); 373 return (-1); 374 } 375 376 File2 = fopen (File2Path, "rb"); 377 if (!File2) 378 { 379 printf ("Could not open file %s\n", File2Path); 380 goto Exit1; 381 } 382 383 /* Read the ACPI header from each file */ 384 385 Actual1 = fread (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File1); 386 if (Actual1 != sizeof (ACPI_TABLE_HEADER)) 387 { 388 printf ("File %s does not contain an ACPI table header\n", File1Path); 389 goto Exit2; 390 } 391 392 Actual2 = fread (&Header2, 1, sizeof (ACPI_TABLE_HEADER), File2); 393 if (Actual2 != sizeof (ACPI_TABLE_HEADER)) 394 { 395 printf ("File %s does not contain an ACPI table header\n", File2Path); 396 goto Exit2; 397 } 398 399 if ((!AbValidateHeader (&Header1)) || 400 (!AbValidateHeader (&Header2))) 401 { 402 goto Exit2; 403 } 404 405 /* Table signatures must match */ 406 407 if (*((UINT32 *) Header1.Signature) != *((UINT32 *) Header2.Signature)) 408 { 409 printf ("Table signatures do not match\n"); 410 goto Exit2; 411 } 412 413 if (!Gbl_TerseMode) 414 { 415 /* Display header information */ 416 417 printf ("Comparing %s to %s\n", File1Path, File2Path); 418 AbPrintHeadersInfo (&Header1, &Header2); 419 } 420 421 if (memcmp (&Header1, &Header2, sizeof (ACPI_TABLE_HEADER))) 422 { 423 printf ("Headers do not match exactly\n"); 424 HeaderMismatch = TRUE; 425 } 426 427 /* Do the byte-by-byte compare */ 428 429 printf ("Compare offset: %u\n", AbGbl_CompareOffset); 430 if (AbGbl_CompareOffset) 431 { 432 fseek (File2, AbGbl_CompareOffset, SEEK_CUR); 433 } 434 435 Actual1 = fread (&Char1, 1, 1, File1); 436 Actual2 = fread (&Char2, 1, 1, File2); 437 Offset = sizeof (ACPI_TABLE_HEADER); 438 439 while ((Actual1 == 1) && (Actual2 == 1)) 440 { 441 if (Char1 != Char2) 442 { 443 printf ("Error - Byte mismatch at offset %8.4X: 0x%2.2X 0x%2.2X\n", 444 Offset, Char1, Char2); 445 Mismatches++; 446 if ((Mismatches > 100) && (!AbGbl_DisplayAllMiscompares)) 447 { 448 printf ("100 Mismatches: Too many mismatches\n"); 449 goto Exit2; 450 } 451 } 452 453 Offset++; 454 Actual1 = fread (&Char1, 1, 1, File1); 455 Actual2 = fread (&Char2, 1, 1, File2); 456 } 457 458 if (Actual1) 459 { 460 printf ("Error - file %s is longer than file %s\n", File1Path, File2Path); 461 Mismatches++; 462 } 463 else if (Actual2) 464 { 465 printf ("Error - file %s is shorter than file %s\n", File1Path, File2Path); 466 Mismatches++; 467 } 468 else if (!Mismatches) 469 { 470 if (HeaderMismatch) 471 { 472 printf ("Files compare exactly after header\n"); 473 } 474 else 475 { 476 printf ("Files compare exactly\n"); 477 } 478 } 479 480 printf ("%u Mismatches found\n", Mismatches); 481 if (Mismatches == 0) 482 { 483 Status = 0; 484 } 485 486 Exit2: 487 fclose (File2); 488 489 Exit1: 490 fclose (File1); 491 return (Status); 492 } 493 494 495 /****************************************************************************** 496 * 497 * FUNCTION: AbGetFile 498 * 499 * DESCRIPTION: Open a file and read it entirely into a new buffer 500 * 501 ******************************************************************************/ 502 503 static char * 504 AbGetFile ( 505 char *Filename, 506 UINT32 *FileSize) 507 { 508 FILE *File; 509 UINT32 Size; 510 char *Buffer = NULL; 511 size_t Actual; 512 513 514 /* Binary mode does not alter CR/LF pairs */ 515 516 File = fopen (Filename, "rb"); 517 if (!File) 518 { 519 printf ("Could not open file %s\n", Filename); 520 return (NULL); 521 } 522 523 /* Need file size to allocate a buffer */ 524 525 Size = CmGetFileSize (File); 526 if (Size == ACPI_UINT32_MAX) 527 { 528 printf ("Could not get file size (seek) for %s\n", Filename); 529 goto ErrorExit; 530 } 531 532 /* Allocate a buffer for the entire file */ 533 534 Buffer = calloc (Size, 1); 535 if (!Buffer) 536 { 537 printf ("Could not allocate buffer of size %u\n", Size); 538 goto ErrorExit; 539 } 540 541 /* Read the entire file */ 542 543 Actual = fread (Buffer, 1, Size, File); 544 if (Actual != Size) 545 { 546 printf ("Could not read the input file %s\n", Filename); 547 free (Buffer); 548 Buffer = NULL; 549 goto ErrorExit; 550 } 551 552 *FileSize = Size; 553 554 ErrorExit: 555 fclose (File); 556 return (Buffer); 557 } 558 559 560 /****************************************************************************** 561 * 562 * FUNCTION: AbDumpAmlFile 563 * 564 * DESCRIPTION: Dump a binary AML file to a text file 565 * 566 ******************************************************************************/ 567 568 int 569 AbDumpAmlFile ( 570 char *File1Path, 571 char *File2Path) 572 { 573 char *FileBuffer; 574 FILE *FileOutHandle; 575 UINT32 FileSize = 0; 576 int Status = -1; 577 578 579 /* Get the entire AML file, validate header */ 580 581 FileBuffer = AbGetFile (File1Path, &FileSize); 582 if (!FileBuffer) 583 { 584 return (-1); 585 } 586 587 printf ("Input file: %s contains %u (0x%X) bytes\n", 588 File1Path, FileSize, FileSize); 589 590 FileOutHandle = fopen (File2Path, "wb"); 591 if (!FileOutHandle) 592 { 593 printf ("Could not open file %s\n", File2Path); 594 goto Exit1; 595 } 596 597 if (!AbValidateHeader ((ACPI_TABLE_HEADER *) FileBuffer)) 598 { 599 goto Exit2; 600 } 601 602 /* Convert binary AML to text, using common dump buffer routine */ 603 604 AcpiGbl_DebugFile = FileOutHandle; 605 AcpiGbl_DbOutputFlags = ACPI_DB_REDIRECTABLE_OUTPUT; 606 607 AcpiOsPrintf ("%4.4s @ 0x%8.8X\n", 608 ((ACPI_TABLE_HEADER *) FileBuffer)->Signature, 0); 609 610 AcpiUtDumpBuffer ((UINT8 *) FileBuffer, FileSize, DB_BYTE_DISPLAY, 0); 611 612 /* Summary for the output file */ 613 614 FileSize = CmGetFileSize (FileOutHandle); 615 printf ("Output file: %s contains %u (0x%X) bytes\n\n", 616 File2Path, FileSize, FileSize); 617 618 Status = 0; 619 620 Exit2: 621 fclose (FileOutHandle); 622 623 Exit1: 624 free (FileBuffer); 625 return (Status); 626 } 627