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