VirtualBox

root/trunk/src/bldprogs/biossums.c

Revision 14076, 6.6 kB (checked in by vboxsync, 2 months ago)

warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* $Id$ */
2 /** @file
3  * Tool for modifying a BIOS image to write the BIOS checksum.
4  */
5
6 /*
7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8  *
9  * This file is part of VirtualBox Open Source Edition (OSE), as
10  * available from http://www.virtualbox.org. This file is free software;
11  * you can redistribute it and/or modify it under the terms of the GNU
12  * General Public License (GPL) as published by the Free Software
13  * Foundation, in version 2 as it comes in the "COPYING" file of the
14  * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16  *
17  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18  * Clara, CA 95054 USA or visit http://www.sun.com if you need
19  * additional information or have any questions.
20  */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <errno.h>
27 #ifndef RT_OS_WINDOWS
28 # include <unistd.h> /* unlink */
29 #endif
30
31 typedef unsigned char uint8_t;
32
33 static uint8_t abBios[64*1024];
34 static FILE *g_pIn = NULL;
35 static FILE *g_pOut = NULL;
36 static const char *g_pszOutFile = NULL;
37 static const char *g_argv0;
38
39 /**
40  * Find where the filename starts in the given path.
41  */
42 static const char *name(const char *pszPath)
43 {
44     const char *psz = strrchr(pszPath, '/');
45 #if defined(_MSC_VER) || defined(__OS2__)
46     const char *psz2 = strrchr(pszPath, '\\');
47     if (!psz2)
48         psz2 = strrchr(pszPath, ':');
49     if (psz2 && (!psz || psz2 > psz))
50         psz = psz2;
51 #endif
52     return psz ? psz + 1 : pszPath;
53 }
54
55 /**
56  * Report an error.
57  */
58 static int fatal(const char *pszFormat, ...)
59 {
60     va_list va;
61
62     fprintf(stderr, "%s: ", name(g_argv0));
63
64     va_start(va, pszFormat);
65     vfprintf(stderr, pszFormat, va);
66     va_end(va);
67
68     /* clean up */
69     if (g_pIn)
70         fclose(g_pIn);
71     if (g_pOut)
72         fclose(g_pOut);
73     if (g_pszOutFile)
74         unlink(g_pszOutFile);
75
76     return 1;
77 }
78
79 /**
80  * Calculate the checksum.
81  */
82 static uint8_t calculateChecksum(uint8_t *pb, size_t cb, size_t iChecksum)
83 {
84     uint8_t u8Sum = 0;
85     size_t  i;
86
87     for (i = 0; i < cb; i++)
88         if (i != iChecksum)
89             u8Sum += pb[i];
90
91     return -u8Sum;
92 }
93
94 /**
95  * Find a header in the binary.
96  *
97  * @param   pb        Where to search for the signature
98  * @param   cb        Size of the search area
99  * @param   pbHeader  Pointer to the start of the signature
100  * @returns           0 if signature was not found, 1 if found or
101  *                    2 if more than one signature was found */
102 static int searchHeader(uint8_t *pb, size_t cb, const char *pszHeader, uint8_t **pbHeader)
103 {
104     int          fFound = 0;
105     unsigned int i;
106     size_t       cbSignature = strlen(pszHeader);
107
108     for (i = 0; i < cb; i += 16)
109         if (!memcmp(pb + i, pszHeader, cbSignature))
110         {
111             if (fFound++)
112                 return 2;
113             *pbHeader = pb + i;
114         }
115
116     return fFound;
117 }
118
119 int main(int argc, char **argv)
120 {
121     FILE    *pIn, *pOut;
122     size_t  cbIn, cbOut;
123     int     fAdapterBios = 0;
124
125     g_argv0 = argv[0];
126
127     if (argc != 3)
128         return fatal("Input file name and output file name required.\n");
129
130     pIn = g_pIn = fopen(argv[1], "rb");
131     if (!pIn)
132         return fatal("Error opening '%s' for reading (%s).\n", argv[1], strerror(errno));
133
134     pOut = g_pOut = fopen(argv[2], "wb");
135     if (!pOut)
136         return fatal("Error opening '%s' for writing (%s).\n", argv[2], strerror(errno));
137     g_pszOutFile = argv[2];
138
139     /* safety precaution (aka. complete paranoia :-) */
140     memset(abBios, 0, sizeof(abBios));
141
142     cbIn = fread(abBios, 1, sizeof(abBios), pIn);
143     if (ferror(pIn))
144         return fatal("Error reading from '%s' (%s).\n", argv[1], strerror(errno));
145     g_pIn = NULL;
146     fclose(pIn);
147
148     fAdapterBios = abBios[0] == 0x55 && abBios[1] == 0xaa;
149
150     /* align size to page size */
151     if ((cbIn % 4096) != 0)
152         cbIn = (cbIn + 4095) & ~4095;
153
154     if (!fAdapterBios && cbIn != 64*1024)
155         return fatal("Size of system BIOS is not 64KB!\n");
156
157     if (fAdapterBios)
158     {
159         /* adapter BIOS */
160
161         /* set the length indicator */
162         abBios[2] = (uint8_t)(cbIn / 512);
163     }
164     else
165     {
166         /* system BIOS */
167         size_t  cbChecksum;
168         uint8_t u8Checksum;
169         uint8_t *pbHeader;
170
171         /* Set the BIOS32 header checksum. */
172         switch (searchHeader(abBios, cbIn, "_32_", &pbHeader))
173         {
174             case 0:
175                 return fatal("No BIOS32 header not found!\n");
176             case 2:
177                 return fatal("More than one BIOS32 header found!\n");
178             case 1:
179                 cbChecksum = (size_t)pbHeader[9] * 16;
180                 u8Checksum = calculateChecksum(pbHeader, cbChecksum, 10);
181                 pbHeader[10] = u8Checksum;
182                 break;
183         }
184
185         /* Set the PIR header checksum according to PCI IRQ Routing table
186          * specification version 1.0, Microsoft Corporation, 1996 */
187         switch (searchHeader(abBios, cbIn, "$PIR", &pbHeader))
188         {
189             case 0:
190                 return fatal("No PCI IRQ routing table found!\n");
191             case 2:
192                 return fatal("More than one PCI IRQ routing table found!\n");
193             case 1:
194                 cbChecksum = (size_t)pbHeader[6] + (size_t)pbHeader[7] * 256;
195                 u8Checksum = calculateChecksum(pbHeader, cbChecksum, 31);
196                 pbHeader[31] = u8Checksum;
197                 break;
198         }
199
200         /* Set the SMBIOS header checksum according to System Management BIOS
201          * Reference Specification Version 2.5, DSP0134. */
202         switch (searchHeader(abBios, cbIn, "_SM_", &pbHeader))
203         {
204             case 0:
205                 return fatal("No SMBIOS header found!\n");
206             case 2:
207                 return fatal("More than one SMBIOS header found!\n");
208             case 1:
209                 /* at first fix the DMI header starting at SMBIOS header offset 16 */
210                 u8Checksum = calculateChecksum(pbHeader+16, 15, 5);
211                 pbHeader[21] = u8Checksum;
212
213                 /* now fix the checksum of the whole SMBIOS header */
214                 cbChecksum = (size_t)pbHeader[5];
215                 u8Checksum = calculateChecksum(pbHeader, cbChecksum, 4);
216                 pbHeader[4] = u8Checksum;
217                 break;
218         }
219     }
220
221     /* set the BIOS checksum */
222     abBios[cbIn-1] = calculateChecksum(abBios, cbIn, cbIn - 1);
223
224     cbOut = fwrite(abBios, 1, cbIn, pOut);
225     if (ferror(pOut))
226         return fatal("Error writing to '%s' (%s).\n", g_pszOutFile, strerror(errno));
227     g_pOut = NULL;
228     if (fclose(pOut))
229         return fatal("Error closing '%s' (%s).\n", g_pszOutFile, strerror(errno));
230
231     return 0;
232 }
233
Note: See TracBrowser for help on using the browser.

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy