VirtualBox

source: vbox/trunk/src/bldprogs/biossums.c@ 16560

Last change on this file since 16560 was 14076, checked in by vboxsync, 16 years ago

warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.6 KB
Line 
1/* $Id: biossums.c 14076 2008-11-11 07:24:05Z vboxsync $ */
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
31typedef unsigned char uint8_t;
32
33static uint8_t abBios[64*1024];
34static FILE *g_pIn = NULL;
35static FILE *g_pOut = NULL;
36static const char *g_pszOutFile = NULL;
37static const char *g_argv0;
38
39/**
40 * Find where the filename starts in the given path.
41 */
42static 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 */
58static 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 */
82static 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 */
102static 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
119int 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 repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use