VirtualBox

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

Last change on this file since 14047 was 14047, checked in by vboxsync, 17 years ago

biossums: fixed warning (64-bit MSC), return 1 not -1 on failure, delete output on failure, display the program name in the error message.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.5 KB
Line 
1/* $Id: biossums.c 14047 2008-11-10 22:42:14Z 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.215389.xyz. 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
28typedef unsigned char uint8_t;
29
30static uint8_t abBios[64*1024];
31static FILE *g_pIn = NULL;
32static FILE *g_pOut = NULL;
33static const char *g_pszOutFile = NULL;
34static const char *g_argv0;
35
36/**
37 * Find where the filename starts in the given path.
38 */
39static const char *name(const char *pszPath)
40{
41 const char *psz = strrchr(pszPath, '/');
42#if defined(_MSC_VER) || defined(__OS2__)
43 const char *psz2 = strrchr(pszPath, '\\');
44 if (!psz2)
45 psz2 = strrchr(pszPath, ':');
46 if (psz2 && (!psz || psz2 > psz))
47 psz = psz2;
48#endif
49 return psz ? psz + 1 : pszPath;
50}
51
52/**
53 * Report an error.
54 */
55static int fatal(const char *pszFormat, ...)
56{
57 va_list va;
58
59 fprintf(stderr, "%s: ", name(g_argv0));
60
61 va_start(va, pszFormat);
62 vfprintf(stderr, pszFormat, va);
63 va_end(va);
64
65 /* clean up */
66 if (g_pIn)
67 fclose(g_pIn);
68 if (g_pOut)
69 fclose(g_pOut);
70 if (g_pszOutFile)
71 unlink(g_pszOutFile);
72
73 return 1;
74}
75
76/**
77 * Calculate the checksum.
78 */
79static uint8_t calculateChecksum(uint8_t *pb, size_t cb, size_t iChecksum)
80{
81 uint8_t u8Sum = 0;
82 size_t i;
83
84 for (i = 0; i < cb; i++)
85 if (i != iChecksum)
86 u8Sum += pb[i];
87
88 return -u8Sum;
89}
90
91/**
92 * Find a header in the binary.
93 *
94 * @param pb Where to search for the signature
95 * @param cb Size of the search area
96 * @param pbHeader Pointer to the start of the signature
97 * @returns 0 if signature was not found, 1 if found or
98 * 2 if more than one signature was found */
99static int searchHeader(uint8_t *pb, size_t cb, const char *pszHeader, uint8_t **pbHeader)
100{
101 int fFound = 0;
102 unsigned int i;
103 size_t cbSignature = strlen(pszHeader);
104
105 for (i = 0; i < cb; i += 16)
106 if (!memcmp(pb + i, pszHeader, cbSignature))
107 {
108 if (fFound++)
109 return 2;
110 *pbHeader = pb + i;
111 }
112
113 return fFound;
114}
115
116int main(int argc, char **argv)
117{
118 FILE *pIn, *pOut;
119 size_t cbIn, cbOut;
120 int fAdapterBios = 0;
121
122 g_argv0 = argv[0];
123
124 if (argc != 3)
125 return fatal("Input file name and output file name required.\n");
126
127 pIn = g_pIn = fopen(argv[1], "rb");
128 if (!pIn)
129 return fatal("Error opening '%s' for reading (%s).\n", argv[1], strerror(errno));
130
131 pOut = g_pOut = fopen(argv[2], "wb");
132 if (!pOut)
133 return fatal("Error opening '%s' for writing (%s).\n", argv[2], strerror(errno));
134 g_pszOutFile = argv[2];
135
136 /* safety precaution (aka. complete paranoia :-) */
137 memset(abBios, 0, sizeof(abBios));
138
139 cbIn = fread(abBios, 1, sizeof(abBios), pIn);
140 if (ferror(pIn))
141 return fatal("Error reading from '%s' (%s).\n", argv[1], strerror(errno));
142 g_pIn = NULL;
143 fclose(pIn);
144
145 fAdapterBios = abBios[0] == 0x55 && abBios[1] == 0xaa;
146
147 /* align size to page size */
148 if ((cbIn % 4096) != 0)
149 cbIn = (cbIn + 4095) & ~4095;
150
151 if (!fAdapterBios && cbIn != 64*1024)
152 return fatal("Size of system BIOS is not 64KB!\n");
153
154 if (fAdapterBios)
155 {
156 /* adapter BIOS */
157
158 /* set the length indicator */
159 abBios[2] = (uint8_t)(cbIn / 512);
160 }
161 else
162 {
163 /* system BIOS */
164 size_t cbChecksum;
165 uint8_t u8Checksum;
166 uint8_t *pbHeader;
167
168 /* Set the BIOS32 header checksum. */
169 switch (searchHeader(abBios, cbIn, "_32_", &pbHeader))
170 {
171 case 0:
172 return fatal("No BIOS32 header not found!\n");
173 case 2:
174 return fatal("More than one BIOS32 header found!\n");
175 case 1:
176 cbChecksum = (size_t)pbHeader[9] * 16;
177 u8Checksum = calculateChecksum(pbHeader, cbChecksum, 10);
178 pbHeader[10] = u8Checksum;
179 break;
180 }
181
182 /* Set the PIR header checksum according to PCI IRQ Routing table
183 * specification version 1.0, Microsoft Corporation, 1996 */
184 switch (searchHeader(abBios, cbIn, "$PIR", &pbHeader))
185 {
186 case 0:
187 return fatal("No PCI IRQ routing table found!\n");
188 case 2:
189 return fatal("More than one PCI IRQ routing table found!\n");
190 case 1:
191 cbChecksum = (size_t)pbHeader[6] + (size_t)pbHeader[7] * 256;
192 u8Checksum = calculateChecksum(pbHeader, cbChecksum, 31);
193 pbHeader[31] = u8Checksum;
194 break;
195 }
196
197 /* Set the SMBIOS header checksum according to System Management BIOS
198 * Reference Specification Version 2.5, DSP0134. */
199 switch (searchHeader(abBios, cbIn, "_SM_", &pbHeader))
200 {
201 case 0:
202 return fatal("No SMBIOS header found!\n");
203 case 2:
204 return fatal("More than one SMBIOS header found!\n");
205 case 1:
206 /* at first fix the DMI header starting at SMBIOS header offset 16 */
207 u8Checksum = calculateChecksum(pbHeader+16, 15, 5);
208 pbHeader[21] = u8Checksum;
209
210 /* now fix the checksum of the whole SMBIOS header */
211 cbChecksum = (size_t)pbHeader[5];
212 u8Checksum = calculateChecksum(pbHeader, cbChecksum, 4);
213 pbHeader[4] = u8Checksum;
214 break;
215 }
216 }
217
218 /* set the BIOS checksum */
219 abBios[cbIn-1] = calculateChecksum(abBios, cbIn, cbIn - 1);
220
221 cbOut = fwrite(abBios, 1, cbIn, pOut);
222 if (ferror(pOut))
223 return fatal("Error writing to '%s' (%s).\n", g_pszOutFile, strerror(errno));
224 g_pOut = NULL;
225 if (fclose(pOut))
226 return fatal("Error closing '%s' (%s).\n", g_pszOutFile, strerror(errno));
227
228 return 0;
229}
230
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette