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