VirtualBox

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

Last change on this file since 94130 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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

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