- pcibios fixes by lukewarm (SF patch #1114826)
[gplbios.git] / biossums.c
blob91530c0904157af5cdeded8dbbc81d9a60fae214
1 /* biossums.c --- written by Eike W. */
3 #include <stdlib.h>
4 #include <stdio.h>
6 typedef unsigned char byte;
8 void check( int value, char* message );
10 #define LEN_BIOS_DATA 0x10000
11 #define MAX_OFFSET (LEN_BIOS_DATA - 1)
14 #define BIOS_OFFSET 0xFFFF
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 );
22 #define _32__LEN 9
23 #define _32__CHKSUM 10
25 #define _32__MINHDR 16
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 );
33 #define _MP__LEN 8
34 #define _MP__CHKSUM 10
36 #define _MP__MINHDR 16
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 );
44 #define PCMP_BASELEN 4
45 #define PCMP_CHKSUM 7
46 #define PCMP_EXT_LEN 40
47 #define PCMP_EXT_CHKSUM 42
49 #define PCMP_MINHDR 42
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 );
57 #define _PIR_LEN 6
58 #define _PIR_CHKSUM 31
60 #define _PIR_MINHDR 32
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 );
68 byte bios_data[LEN_BIOS_DATA];
71 int main( int argc, char* argv[] ) {
73 FILE* stream;
74 long offset, tmp_offset;
75 byte cur_val = 0, new_val = 0;
76 int hits;
79 if( argc != 2 ) {
80 printf( "Error. Need a file-name as an argument.\n" );
81 exit( EXIT_FAILURE );
84 if(( stream = fopen( argv[1], "rb" )) == NULL ) {
85 printf( "Error opening %s for reading.\n", argv[1] );
86 exit( EXIT_FAILURE );
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 );
93 fclose( stream );
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++;
106 if( hits == 1 && cur_val != new_val ) {
107 printf( "Setting checksum." );
108 chksum__32__set_value( bios_data, offset, new_val );
110 if( hits >= 2 ) {
111 printf( "Multiple PCI headers! No checksum set." );
113 if( hits ) {
114 printf( "\n" );
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++;
129 if( hits == 1 && cur_val != new_val ) {
130 printf( "Setting checksum." );
131 chksum__mp__set_value( bios_data, offset, new_val );
133 if( hits >= 2 ) {
134 printf( "Warning! Multiple MP headers. No checksum set." );
136 if( hits ) {
137 printf( "\n" );
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++;
152 if( hits == 1 && cur_val != new_val ) {
153 printf( "Setting checksum." );
154 chksum_pcmp_set_value( bios_data, offset, new_val );
156 if( hits >= 2 ) {
157 printf( "Warning! Multiple PCMP headers. No checksum set." );
159 if( hits ) {
160 printf( "\n" );
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++;
175 if( hits == 1 && cur_val != new_val ) {
176 printf( "Setting checksum." );
177 chksum__pir_set_value( bios_data, offset, new_val );
179 if( hits >= 2 ) {
180 printf( "Warning! Multiple $PIR headers. No checksum set." );
182 if( hits ) {
183 printf( "\n" );
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 );
198 printf( "\n" );
201 if(( stream = fopen( argv[1], "wb" )) == NULL ) {
202 printf( "Error opening %s for writing.\n", argv[1] );
203 exit( EXIT_FAILURE );
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 );
210 fclose( stream );
212 return( EXIT_SUCCESS );
216 void check( int okay, char* message ) {
218 if( !okay ) {
219 printf( "\n\nError. %s.\n", message );
220 exit( EXIT_FAILURE );
225 long chksum_bios_get_offset( byte* data, long offset ) {
227 return( BIOS_OFFSET );
231 byte chksum_bios_calc_value( byte* data, long offset ) {
233 int i;
234 byte sum;
236 sum = 0;
237 for( i = 0; i < MAX_OFFSET; i++ ) {
238 sum = sum + *( data + i );
240 sum = -sum; /* iso ensures -s + s == 0 on unsigned types */
241 return( sum );
245 byte chksum_bios_get_value( byte* data, long offset ) {
247 return( *( data + BIOS_OFFSET ) );
251 void chksum_bios_set_value( byte* data, long offset, byte value ) {
253 *( data + BIOS_OFFSET ) = value;
257 byte chksum__32__calc_value( byte* data, long offset ) {
259 int i;
260 int len;
261 byte sum;
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 );
272 sum = -sum;
273 return( sum );
277 long chksum__32__get_offset( byte* data, long offset ) {
279 long result = -1L;
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;
293 return( result );
297 byte chksum__32__get_value( byte* data, long offset ) {
299 check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
300 return( *( data + offset + _32__CHKSUM ) );
304 void chksum__32__set_value( byte* data, long offset, byte value ) {
306 check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
307 *( data + offset + _32__CHKSUM ) = value;
311 byte chksum__mp__calc_value( byte* data, long offset ) {
313 int i;
314 int len;
315 byte sum;
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 );
326 sum = -sum;
327 return( sum );
331 long chksum__mp__get_offset( byte* data, long offset ) {
333 long result = -1L;
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;
347 return( result );
351 byte chksum__mp__get_value( byte* data, long offset ) {
353 check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
354 return( *( data + offset + _MP__CHKSUM ) );
358 void chksum__mp__set_value( byte* data, long offset, byte value ) {
360 check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
361 *( data + offset + _MP__CHKSUM ) = value;
365 byte chksum_pcmp_calc_value( byte* data, long offset ) {
367 int i;
368 int len;
369 byte sum;
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)" );
380 sum = 0;
381 for( i = 0; i < len; i++ ) {
382 if( i != PCMP_CHKSUM ) {
383 sum = sum + *( data + offset + i );
386 sum = -sum;
387 return( sum );
391 long chksum_pcmp_get_offset( byte* data, long offset ) {
393 long result = -1L;
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;
407 return( result );
411 byte chksum_pcmp_get_value( byte* data, long offset ) {
413 check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
414 return( *( data + offset + PCMP_CHKSUM ) );
418 void chksum_pcmp_set_value( byte* data, long offset, byte value ) {
420 check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
421 *( data + offset + PCMP_CHKSUM ) = value;
425 byte chksum__pir_calc_value( byte* data, long offset ) {
427 int i;
428 int len;
429 byte sum;
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 );
441 sum = -sum;
442 return( sum );
446 long chksum__pir_get_offset( byte* data, long offset ) {
448 long result = -1L;
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;
462 return( result );
466 byte chksum__pir_get_value( byte* data, long offset ) {
468 check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
469 return( *( data + offset + _PIR_CHKSUM ) );
473 void chksum__pir_set_value( byte* data, long offset, byte value ) {
475 check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
476 *( data + offset + _PIR_CHKSUM ) = value;