1 /* biossums.c --- written by Eike W. */
2
3 #include <stdlib.h>
4 #include <stdio.h>
5
6 typedef unsigned char byte;
7
8 void check( int value, char* message );
9
10 #define LEN_BIOS_DATA 0x10000
11 #define MAX_OFFSET (LEN_BIOS_DATA - 1)
12
13
14 #define BIOS_OFFSET 0xFFFF
15
16 long chksum_bios_get_offset( byte* data, long offset );
17 byte chksum_bios_calc_value( byte* data, long offset );
18 byte chksum_bios_get_value( byte* data, long offset );
19 void chksum_bios_set_value( byte* data, long offset, byte value );
20
21
22 #define _32__LEN 9
23 #define _32__CHKSUM 10
24
25 #define _32__MINHDR 16
26
27 long chksum__32__get_offset( byte* data, long offset );
28 byte chksum__32__calc_value( byte* data, long offset );
29 byte chksum__32__get_value( byte* data, long offset );
30 void chksum__32__set_value( byte* data, long offset, byte value );
31
32
33 #define _MP__LEN 8
34 #define _MP__CHKSUM 10
35
36 #define _MP__MINHDR 16
37
38 long chksum__mp__get_offset( byte* data, long offset );
39 byte chksum__mp__calc_value( byte* data, long offset );
40 byte chksum__mp__get_value( byte* data, long offset );
41 void chksum__mp__set_value( byte* data, long offset, byte value );
42
43
44 #define PCMP_BASELEN 4
45 #define PCMP_CHKSUM 7
46 #define PCMP_EXT_LEN 40
47 #define PCMP_EXT_CHKSUM 42
48
49 #define PCMP_MINHDR 42
50
51 long chksum_pcmp_get_offset( byte* data, long offset );
52 byte chksum_pcmp_calc_value( byte* data, long offset );
53 byte chksum_pcmp_get_value( byte* data, long offset );
54 void chksum_pcmp_set_value( byte* data, long offset, byte value );
55
56
57 #define _PIR_LEN 6
58 #define _PIR_CHKSUM 31
59
60 #define _PIR_MINHDR 32
61
62 long chksum__pir_get_offset( byte *data, long offset );
63 byte chksum__pir_calc_value( byte* data, long offset );
64 byte chksum__pir_get_value( byte* data, long offset );
65 void chksum__pir_set_value( byte* data, long offset, byte value );
66
67
68 byte bios_data[LEN_BIOS_DATA];
69
70
main(int argc,char * argv[])71 int main( int argc, char* argv[] ) {
72
73 FILE* stream;
74 long offset, tmp_offset;
75 byte cur_val = 0, new_val = 0;
76 int hits;
77
78
79 if( argc != 2 ) {
80 printf( "Error. Need a file-name as an argument.\n" );
81 exit( EXIT_FAILURE );
82 }
83
84 if(( stream = fopen( argv[1], "rb" )) == NULL ) {
85 printf( "Error opening %s for reading.\n", argv[1] );
86 exit( EXIT_FAILURE );
87 }
88 if( fread( bios_data, 1, LEN_BIOS_DATA, stream ) < LEN_BIOS_DATA ) {
89 printf( "Error reading 64KBytes from %s.\n", argv[1] );
90 fclose( stream );
91 exit( EXIT_FAILURE );
92 }
93 fclose( stream );
94
95 hits = 0;
96 offset = 0L;
97 while( (tmp_offset = chksum__32__get_offset( bios_data, offset )) != -1L ) {
98 offset = tmp_offset;
99 cur_val = chksum__32__get_value( bios_data, offset );
100 new_val = chksum__32__calc_value( bios_data, offset );
101 printf( "\n\nPCI-Bios header at: 0x%4lX\n", offset );
102 printf( "Current checksum: 0x%02X\n", cur_val );
103 printf( "Calculated checksum: 0x%02X ", new_val );
104 hits++;
105 }
106 if( hits == 1 && cur_val != new_val ) {
107 printf( "Setting checksum." );
108 chksum__32__set_value( bios_data, offset, new_val );
109 }
110 if( hits >= 2 ) {
111 printf( "Multiple PCI headers! No checksum set." );
112 }
113 if( hits ) {
114 printf( "\n" );
115 }
116
117
118 hits = 0;
119 offset = 0L;
120 while( (tmp_offset = chksum__mp__get_offset( bios_data, offset )) != -1L ) {
121 offset = tmp_offset;
122 cur_val = chksum__mp__get_value( bios_data, offset );
123 new_val = chksum__mp__calc_value( bios_data, offset );
124 printf( "\n\nMP header at: 0x%4lX\n", offset );
125 printf( "Current checksum: 0x%02X\n", cur_val );
126 printf( "Calculated checksum: 0x%02X ", new_val );
127 hits++;
128 }
129 if( hits == 1 && cur_val != new_val ) {
130 printf( "Setting checksum." );
131 chksum__mp__set_value( bios_data, offset, new_val );
132 }
133 if( hits >= 2 ) {
134 printf( "Warning! Multiple MP headers. No checksum set." );
135 }
136 if( hits ) {
137 printf( "\n" );
138 }
139
140
141 hits = 0;
142 offset = 0L;
143 while( (tmp_offset = chksum_pcmp_get_offset( bios_data, offset )) != -1L ) {
144 offset = tmp_offset;
145 cur_val = chksum_pcmp_get_value( bios_data, offset );
146 new_val = chksum_pcmp_calc_value( bios_data, offset );
147 printf( "\n\nPCMP header at: 0x%4lX\n", offset );
148 printf( "Current checksum: 0x%02X\n", cur_val );
149 printf( "Calculated checksum: 0x%02X ", new_val );
150 hits++;
151 }
152 if( hits == 1 && cur_val != new_val ) {
153 printf( "Setting checksum." );
154 chksum_pcmp_set_value( bios_data, offset, new_val );
155 }
156 if( hits >= 2 ) {
157 printf( "Warning! Multiple PCMP headers. No checksum set." );
158 }
159 if( hits ) {
160 printf( "\n" );
161 }
162
163
164 hits = 0;
165 offset = 0L;
166 while( (tmp_offset = chksum__pir_get_offset( bios_data, offset )) != -1L ) {
167 offset = tmp_offset;
168 cur_val = chksum__pir_get_value( bios_data, offset );
169 new_val = chksum__pir_calc_value( bios_data, offset );
170 printf( "\n\n$PIR header at: 0x%4lX\n", offset );
171 printf( "Current checksum: 0x%02X\n", cur_val );
172 printf( "Calculated checksum: 0x%02X\n ", new_val );
173 hits++;
174 }
175 if( hits == 1 && cur_val != new_val ) {
176 printf( "Setting checksum." );
177 chksum__pir_set_value( bios_data, offset, new_val );
178 }
179 if( hits >= 2 ) {
180 printf( "Warning! Multiple $PIR headers. No checksum set." );
181 }
182 if( hits ) {
183 printf( "\n" );
184 }
185
186
187 offset = 0L;
188 offset = chksum_bios_get_offset( bios_data, offset );
189 cur_val = chksum_bios_get_value( bios_data, offset );
190 new_val = chksum_bios_calc_value( bios_data, offset );
191 printf( "\n\nBios checksum at: 0x%4lX\n", offset );
192 printf( "Current checksum: 0x%02X\n", cur_val );
193 printf( "Calculated checksum: 0x%02X ", new_val );
194 if( cur_val != new_val ) {
195 printf( "Setting checksum." );
196 chksum_bios_set_value( bios_data, offset, new_val );
197 }
198 printf( "\n" );
199
200
201 if(( stream = fopen( argv[1], "wb" )) == NULL ) {
202 printf( "Error opening %s for writing.\n", argv[1] );
203 exit( EXIT_FAILURE );
204 }
205 if( fwrite( bios_data, 1, LEN_BIOS_DATA, stream ) < LEN_BIOS_DATA ) {
206 printf( "Error writing 64KBytes to %s.\n", argv[1] );
207 fclose( stream );
208 exit( EXIT_FAILURE );
209 }
210 fclose( stream );
211
212 return( EXIT_SUCCESS );
213 }
214
215
check(int okay,char * message)216 void check( int okay, char* message ) {
217
218 if( !okay ) {
219 printf( "\n\nError. %s.\n", message );
220 exit( EXIT_FAILURE );
221 }
222 }
223
224
chksum_bios_get_offset(byte * data,long offset)225 long chksum_bios_get_offset( byte* data, long offset ) {
226
227 return( BIOS_OFFSET );
228 }
229
230
chksum_bios_calc_value(byte * data,long offset)231 byte chksum_bios_calc_value( byte* data, long offset ) {
232
233 int i;
234 byte sum;
235
236 sum = 0;
237 for( i = 0; i < MAX_OFFSET; i++ ) {
238 sum = sum + *( data + i );
239 }
240 sum = -sum; /* iso ensures -s + s == 0 on unsigned types */
241 return( sum );
242 }
243
244
chksum_bios_get_value(byte * data,long offset)245 byte chksum_bios_get_value( byte* data, long offset ) {
246
247 return( *( data + BIOS_OFFSET ) );
248 }
249
250
chksum_bios_set_value(byte * data,long offset,byte value)251 void chksum_bios_set_value( byte* data, long offset, byte value ) {
252
253 *( data + BIOS_OFFSET ) = value;
254 }
255
256
chksum__32__calc_value(byte * data,long offset)257 byte chksum__32__calc_value( byte* data, long offset ) {
258
259 int i;
260 int len;
261 byte sum;
262
263 check( offset + _32__MINHDR <= MAX_OFFSET, "_32_ header out of bounds" );
264 len = *( data + offset + _32__LEN ) << 4;
265 check( offset + len <= MAX_OFFSET, "_32_ header-length out of bounds" );
266 sum = 0;
267 for( i = 0; i < len; i++ ) {
268 if( i != _32__CHKSUM ) {
269 sum = sum + *( data + offset + i );
270 }
271 }
272 sum = -sum;
273 return( sum );
274 }
275
276
chksum__32__get_offset(byte * data,long offset)277 long chksum__32__get_offset( byte* data, long offset ) {
278
279 long result = -1L;
280
281 offset = offset + 0x0F;
282 offset = offset & ~( 0x0F );
283 while( offset + 16 < MAX_OFFSET ) {
284 offset = offset + 16;
285 if( *( data + offset + 0 ) == '_' && \
286 *( data + offset + 1 ) == '3' && \
287 *( data + offset + 2 ) == '2' && \
288 *( data + offset + 3 ) == '_' ) {
289 result = offset;
290 break;
291 }
292 }
293 return( result );
294 }
295
296
chksum__32__get_value(byte * data,long offset)297 byte chksum__32__get_value( byte* data, long offset ) {
298
299 check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
300 return( *( data + offset + _32__CHKSUM ) );
301 }
302
303
chksum__32__set_value(byte * data,long offset,byte value)304 void chksum__32__set_value( byte* data, long offset, byte value ) {
305
306 check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
307 *( data + offset + _32__CHKSUM ) = value;
308 }
309
310
chksum__mp__calc_value(byte * data,long offset)311 byte chksum__mp__calc_value( byte* data, long offset ) {
312
313 int i;
314 int len;
315 byte sum;
316
317 check( offset + _MP__MINHDR <= MAX_OFFSET, "_MP_ header out of bounds" );
318 len = *( data + offset + _MP__LEN ) << 4;
319 check( offset + len <= MAX_OFFSET, "_MP_ header-length out of bounds" );
320 sum = 0;
321 for( i = 0; i < len; i++ ) {
322 if( i != _MP__CHKSUM ) {
323 sum = sum + *( data + offset + i );
324 }
325 }
326 sum = -sum;
327 return( sum );
328 }
329
330
chksum__mp__get_offset(byte * data,long offset)331 long chksum__mp__get_offset( byte* data, long offset ) {
332
333 long result = -1L;
334
335 offset = offset + 0x0F;
336 offset = offset & ~( 0x0F );
337 while( offset + 16 < MAX_OFFSET ) {
338 offset = offset + 16;
339 if( *( data + offset + 0 ) == '_' && \
340 *( data + offset + 1 ) == 'M' && \
341 *( data + offset + 2 ) == 'P' && \
342 *( data + offset + 3 ) == '_' ) {
343 result = offset;
344 break;
345 }
346 }
347 return( result );
348 }
349
350
chksum__mp__get_value(byte * data,long offset)351 byte chksum__mp__get_value( byte* data, long offset ) {
352
353 check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
354 return( *( data + offset + _MP__CHKSUM ) );
355 }
356
357
chksum__mp__set_value(byte * data,long offset,byte value)358 void chksum__mp__set_value( byte* data, long offset, byte value ) {
359
360 check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
361 *( data + offset + _MP__CHKSUM ) = value;
362 }
363
364
chksum_pcmp_calc_value(byte * data,long offset)365 byte chksum_pcmp_calc_value( byte* data, long offset ) {
366
367 int i;
368 int len;
369 byte sum;
370
371 check( offset + PCMP_MINHDR <= MAX_OFFSET, "PCMP header out of bounds" );
372 len = *( data + offset + PCMP_BASELEN ) + \
373 ( *( data + offset + PCMP_BASELEN + 1 ) << 8 );
374 check( offset + len <= MAX_OFFSET, "PCMP header-length out of bounds" );
375 if( *( data + offset + PCMP_EXT_LEN ) | \
376 *( data + offset + PCMP_EXT_LEN + 1 ) | \
377 *( data + offset + PCMP_EXT_CHKSUM ) ) {
378 check( 0, "PCMP header indicates extended tables (unsupported)" );
379 }
380 sum = 0;
381 for( i = 0; i < len; i++ ) {
382 if( i != PCMP_CHKSUM ) {
383 sum = sum + *( data + offset + i );
384 }
385 }
386 sum = -sum;
387 return( sum );
388 }
389
390
chksum_pcmp_get_offset(byte * data,long offset)391 long chksum_pcmp_get_offset( byte* data, long offset ) {
392
393 long result = -1L;
394
395 offset = offset + 0x0F;
396 offset = offset & ~( 0x0F );
397 while( offset + 16 < MAX_OFFSET ) {
398 offset = offset + 16;
399 if( *( data + offset + 0 ) == 'P' && \
400 *( data + offset + 1 ) == 'C' && \
401 *( data + offset + 2 ) == 'M' && \
402 *( data + offset + 3 ) == 'P' ) {
403 result = offset;
404 break;
405 }
406 }
407 return( result );
408 }
409
410
chksum_pcmp_get_value(byte * data,long offset)411 byte chksum_pcmp_get_value( byte* data, long offset ) {
412
413 check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
414 return( *( data + offset + PCMP_CHKSUM ) );
415 }
416
417
chksum_pcmp_set_value(byte * data,long offset,byte value)418 void chksum_pcmp_set_value( byte* data, long offset, byte value ) {
419
420 check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
421 *( data + offset + PCMP_CHKSUM ) = value;
422 }
423
424
chksum__pir_calc_value(byte * data,long offset)425 byte chksum__pir_calc_value( byte* data, long offset ) {
426
427 int i;
428 int len;
429 byte sum;
430
431 check( offset + _PIR_MINHDR <= MAX_OFFSET, "$PIR header out of bounds" );
432 len = *( data + offset + _PIR_LEN ) + \
433 ( *( data + offset + _PIR_LEN + 1 ) << 8 );
434 check( offset + len <= MAX_OFFSET, "$PIR header-length out of bounds" );
435 sum = 0;
436 for( i = 0; i < len; i++ ) {
437 if( i != _PIR_CHKSUM ) {
438 sum = sum + *( data + offset + i );
439 }
440 }
441 sum = -sum;
442 return( sum );
443 }
444
445
chksum__pir_get_offset(byte * data,long offset)446 long chksum__pir_get_offset( byte* data, long offset ) {
447
448 long result = -1L;
449
450 offset = offset + 0x0F;
451 offset = offset & ~( 0x0F );
452 while( offset + 16 < MAX_OFFSET ) {
453 offset = offset + 16;
454 if( *( data + offset + 0 ) == '$' && \
455 *( data + offset + 1 ) == 'P' && \
456 *( data + offset + 2 ) == 'I' && \
457 *( data + offset + 3 ) == 'R' ) {
458 result = offset;
459 break;
460 }
461 }
462 return( result );
463 }
464
465
chksum__pir_get_value(byte * data,long offset)466 byte chksum__pir_get_value( byte* data, long offset ) {
467
468 check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
469 return( *( data + offset + _PIR_CHKSUM ) );
470 }
471
472
chksum__pir_set_value(byte * data,long offset,byte value)473 void chksum__pir_set_value( byte* data, long offset, byte value ) {
474
475 check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
476 *( data + offset + _PIR_CHKSUM ) = value;
477 }
478
479