1/****************************************************************************** 2 * 3 * Module Name: abcompare - compare AML files 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 47ACPI_TABLE_HEADER Header1; 48ACPI_TABLE_HEADER Header2; 49 50#define BUFFER_SIZE 256 51char Buffer[BUFFER_SIZE]; 52 53 54/* Local prototypes */ 55 56static BOOLEAN 57AbValidateHeader ( 58 ACPI_TABLE_HEADER *Header); 59 60static UINT8 61AcpiTbSumTable ( 62 void *Buffer, 63 UINT32 Length); 64 65static char * 66AbGetFile ( 67 char *Filename, 68 UINT32 *FileSize); 69 70static void 71AbPrintHeaderInfo ( 72 ACPI_TABLE_HEADER *Header); 73 74static void 75AbPrintHeadersInfo ( 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 88static BOOLEAN 89AbValidateHeader ( 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 116static UINT8 117AcpiTbSumTable ( 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 154static void 155AbPrintHeaderInfo ( 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 173static void 174AbPrintHeadersInfo ( 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 202void 203AbDisplayHeader ( 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 243void 244AbComputeChecksum ( 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 332Exit2: 333 AcpiOsFree (Table); 334 335Exit1: 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 352int 353AbCompareAmlFiles ( 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 if (fseek (File2, AbGbl_CompareOffset, SEEK_CUR)) 433 { 434 printf ("Seek error on file %s\n", File2Path); 435 goto Exit2; 436 } 437 } 438 439 Actual1 = fread (&Char1, 1, 1, File1); 440 Actual2 = fread (&Char2, 1, 1, File2); 441 Offset = sizeof (ACPI_TABLE_HEADER); 442 443 while ((Actual1 == 1) && (Actual2 == 1)) 444 { 445 if (Char1 != Char2) 446 { 447 printf ("Error - Byte mismatch at offset %8.4X: 0x%2.2X 0x%2.2X\n", 448 Offset, Char1, Char2); 449 Mismatches++; 450 if ((Mismatches > 100) && (!AbGbl_DisplayAllMiscompares)) 451 { 452 printf ("100 Mismatches: Too many mismatches\n"); 453 goto Exit2; 454 } 455 } 456 457 Offset++; 458 Actual1 = fread (&Char1, 1, 1, File1); 459 Actual2 = fread (&Char2, 1, 1, File2); 460 } 461 462 if (Actual1) 463 { 464 printf ("Error - file %s is longer than file %s\n", File1Path, File2Path); 465 Mismatches++; 466 } 467 else if (Actual2) 468 { 469 printf ("Error - file %s is shorter than file %s\n", File1Path, File2Path); 470 Mismatches++; 471 } 472 else if (!Mismatches) 473 { 474 if (HeaderMismatch) 475 { 476 printf ("Files compare exactly after header\n"); 477 } 478 else 479 { 480 printf ("Files compare exactly\n"); 481 } 482 } 483 484 printf ("%u Mismatches found\n", Mismatches); 485 if (Mismatches == 0) 486 { 487 Status = 0; 488 } 489 490Exit2: 491 fclose (File2); 492 493Exit1: 494 fclose (File1); 495 return (Status); 496} 497 498 499/****************************************************************************** 500 * 501 * FUNCTION: AbGetFile 502 * 503 * DESCRIPTION: Open a file and read it entirely into a new buffer 504 * 505 ******************************************************************************/ 506 507static char * 508AbGetFile ( 509 char *Filename, 510 UINT32 *FileSize) 511{ 512 FILE *File; 513 UINT32 Size; 514 char *DataBuffer = NULL; 515 size_t Actual; 516 517 518 /* Binary mode does not alter CR/LF pairs */ 519 520 File = fopen (Filename, "rb"); 521 if (!File) 522 { 523 printf ("Could not open file %s\n", Filename); 524 return (NULL); 525 } 526 527 /* Need file size to allocate a buffer */ 528 529 Size = CmGetFileSize (File); 530 if (Size == ACPI_UINT32_MAX) 531 { 532 printf ("Could not get file size (seek) for %s\n", Filename); 533 goto ErrorExit; 534 } 535 536 /* Allocate a buffer for the entire file */ 537 538 DataBuffer = calloc (Size, 1); 539 if (!DataBuffer) 540 { 541 printf ("Could not allocate buffer of size %u\n", Size); 542 goto ErrorExit; 543 } 544 545 /* Read the entire file */ 546 547 Actual = fread (DataBuffer, 1, Size, File); 548 if (Actual != Size) 549 { 550 printf ("Could not read the input file %s\n", Filename); 551 free (DataBuffer); 552 DataBuffer = NULL; 553 goto ErrorExit; 554 } 555 556 *FileSize = Size; 557 558ErrorExit: 559 fclose (File); 560 return (DataBuffer); 561} 562 563 564/****************************************************************************** 565 * 566 * FUNCTION: AbDumpAmlFile 567 * 568 * DESCRIPTION: Dump a binary AML file to a text file 569 * 570 ******************************************************************************/ 571 572int 573AbDumpAmlFile ( 574 char *File1Path, 575 char *File2Path) 576{ 577 char *FileBuffer; 578 FILE *FileOutHandle; 579 UINT32 FileSize = 0; 580 int Status = -1; 581 582 583 /* Get the entire AML file, validate header */ 584 585 FileBuffer = AbGetFile (File1Path, &FileSize); 586 if (!FileBuffer) 587 { 588 return (-1); 589 } 590 591 printf ("Input file: %s contains %u (0x%X) bytes\n", 592 File1Path, FileSize, FileSize); 593 594 FileOutHandle = fopen (File2Path, "wb"); 595 if (!FileOutHandle) 596 { 597 printf ("Could not open file %s\n", File2Path); 598 goto Exit1; 599 } 600 601 if (!AbValidateHeader ((ACPI_TABLE_HEADER *) FileBuffer)) 602 { 603 goto Exit2; 604 } 605 606 /* Convert binary AML to text, using common dump buffer routine */ 607 608 AcpiGbl_DebugFile = FileOutHandle; 609 AcpiGbl_DbOutputFlags = ACPI_DB_REDIRECTABLE_OUTPUT; 610 611 AcpiOsPrintf ("%4.4s @ 0x%8.8X\n", 612 ((ACPI_TABLE_HEADER *) FileBuffer)->Signature, 0); 613 614 AcpiUtDumpBuffer ((UINT8 *) FileBuffer, FileSize, DB_BYTE_DISPLAY, 0); 615 616 /* Summary for the output file */ 617 618 FileSize = CmGetFileSize (FileOutHandle); 619 printf ("Output file: %s contains %u (0x%X) bytes\n\n", 620 File2Path, FileSize, FileSize); 621 622 Status = 0; 623 624Exit2: 625 fclose (FileOutHandle); 626 627Exit1: 628 free (FileBuffer); 629 return (Status); 630} 631