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