- added stub for real mode PCIBIOS function 'find class code'
[gplbios.git] / biossums.c
blobfb1f96990a99a8b89e82e8a2109135265e3a8bb4
1 /*
2 * $Id$
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.
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.
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
19 /* biossums.c --- written by Eike W. for the Bochs BIOS */
21 #include <stdlib.h>
22 #include <stdio.h>
24 typedef unsigned char byte;
26 void check( int value, char* message );
28 #define LEN_BIOS_DATA 0x10000
29 #define MAX_OFFSET (LEN_BIOS_DATA - 1)
32 #define BIOS_OFFSET 0xFFFF
34 long chksum_bios_get_offset( byte* data, long offset );
35 byte chksum_bios_calc_value( byte* data, long offset );
36 byte chksum_bios_get_value( byte* data, long offset );
37 void chksum_bios_set_value( byte* data, long offset, byte value );
40 #define _32__LEN 9
41 #define _32__CHKSUM 10
43 #define _32__MINHDR 16
45 long chksum__32__get_offset( byte* data, long offset );
46 byte chksum__32__calc_value( byte* data, long offset );
47 byte chksum__32__get_value( byte* data, long offset );
48 void chksum__32__set_value( byte* data, long offset, byte value );
51 #define _MP__LEN 8
52 #define _MP__CHKSUM 10
54 #define _MP__MINHDR 16
56 long chksum__mp__get_offset( byte* data, long offset );
57 byte chksum__mp__calc_value( byte* data, long offset );
58 byte chksum__mp__get_value( byte* data, long offset );
59 void chksum__mp__set_value( byte* data, long offset, byte value );
62 #define PCMP_BASELEN 4
63 #define PCMP_CHKSUM 7
64 #define PCMP_EXT_LEN 40
65 #define PCMP_EXT_CHKSUM 42
67 #define PCMP_MINHDR 42
69 long chksum_pcmp_get_offset( byte* data, long offset );
70 byte chksum_pcmp_calc_value( byte* data, long offset );
71 byte chksum_pcmp_get_value( byte* data, long offset );
72 void chksum_pcmp_set_value( byte* data, long offset, byte value );
75 #define _PIR_LEN 6
76 #define _PIR_CHKSUM 31
78 #define _PIR_MINHDR 32
80 long chksum__pir_get_offset( byte *data, long offset );
81 byte chksum__pir_calc_value( byte* data, long offset );
82 byte chksum__pir_get_value( byte* data, long offset );
83 void chksum__pir_set_value( byte* data, long offset, byte value );
86 byte bios_data[LEN_BIOS_DATA];
87 long bios_len;
90 int main(int argc, char* argv[]) {
92 FILE* stream;
93 long offset, tmp_offset;
94 byte cur_val = 0, new_val = 0;
95 int arg = 1, hits, pad = 0;
98 if ((argc == 3) && (!strcmp(argv[1], "-pad"))) {
99 pad = 1;
100 arg = 2;
101 } else if (argc != 2) {
102 printf("Error. Need a file-name as an argument.\n");
103 exit(EXIT_FAILURE);
105 memset(bios_data, 0xff, LEN_BIOS_DATA);
107 if ((stream = fopen(argv[arg], "rb")) == NULL) {
108 printf("Error opening %s for reading.\n", argv[arg]);
109 exit(EXIT_FAILURE);
111 bios_len = fread(bios_data, 1, LEN_BIOS_DATA, stream);
112 if ((bios_len < LEN_BIOS_DATA) && (pad == 0)) {
113 printf("Error reading 64KBytes from %s.\n", argv[arg]);
114 fclose(stream);
115 exit(EXIT_FAILURE);
117 fclose(stream);
118 if (pad == 1) goto write_bios;
120 hits = 0;
121 offset = 0L;
122 while( (tmp_offset = chksum__32__get_offset( bios_data, offset )) != -1L ) {
123 offset = tmp_offset;
124 cur_val = chksum__32__get_value( bios_data, offset );
125 new_val = chksum__32__calc_value( bios_data, offset );
126 printf( "\n\nPCI-Bios header at: 0x%4lX\n", offset );
127 printf( "Current checksum: 0x%02X\n", cur_val );
128 printf( "Calculated checksum: 0x%02X ", new_val );
129 hits++;
131 if( hits == 1 && cur_val != new_val ) {
132 printf( "Setting checksum." );
133 chksum__32__set_value( bios_data, offset, new_val );
135 if( hits >= 2 ) {
136 printf( "Multiple PCI headers! No checksum set." );
138 if( hits ) {
139 printf( "\n" );
143 hits = 0;
144 offset = 0L;
145 while( (tmp_offset = chksum__mp__get_offset( bios_data, offset )) != -1L ) {
146 offset = tmp_offset;
147 cur_val = chksum__mp__get_value( bios_data, offset );
148 new_val = chksum__mp__calc_value( bios_data, offset );
149 printf( "\n\nMP header at: 0x%4lX\n", offset );
150 printf( "Current checksum: 0x%02X\n", cur_val );
151 printf( "Calculated checksum: 0x%02X ", new_val );
152 hits++;
154 if( hits == 1 && cur_val != new_val ) {
155 printf( "Setting checksum." );
156 chksum__mp__set_value( bios_data, offset, new_val );
158 if( hits >= 2 ) {
159 printf( "Warning! Multiple MP headers. No checksum set." );
161 if( hits ) {
162 printf( "\n" );
166 hits = 0;
167 offset = 0L;
168 while( (tmp_offset = chksum_pcmp_get_offset( bios_data, offset )) != -1L ) {
169 offset = tmp_offset;
170 cur_val = chksum_pcmp_get_value( bios_data, offset );
171 new_val = chksum_pcmp_calc_value( bios_data, offset );
172 printf( "\n\nPCMP header at: 0x%4lX\n", offset );
173 printf( "Current checksum: 0x%02X\n", cur_val );
174 printf( "Calculated checksum: 0x%02X ", new_val );
175 hits++;
177 if( hits == 1 && cur_val != new_val ) {
178 printf( "Setting checksum." );
179 chksum_pcmp_set_value( bios_data, offset, new_val );
181 if( hits >= 2 ) {
182 printf( "Warning! Multiple PCMP headers. No checksum set." );
184 if( hits ) {
185 printf( "\n" );
189 hits = 0;
190 offset = 0L;
191 while( (tmp_offset = chksum__pir_get_offset( bios_data, offset )) != -1L ) {
192 offset = tmp_offset;
193 cur_val = chksum__pir_get_value( bios_data, offset );
194 new_val = chksum__pir_calc_value( bios_data, offset );
195 printf( "\n\n$PIR header at: 0x%4lX\n", offset );
196 printf( "Current checksum: 0x%02X\n", cur_val );
197 printf( "Calculated checksum: 0x%02X\n ", new_val );
198 hits++;
200 if( hits == 1 && cur_val != new_val ) {
201 printf( "Setting checksum." );
202 chksum__pir_set_value( bios_data, offset, new_val );
204 if( hits >= 2 ) {
205 printf( "Warning! Multiple $PIR headers. No checksum set." );
207 if( hits ) {
208 printf( "\n" );
212 offset = 0L;
213 offset = chksum_bios_get_offset( bios_data, offset );
214 cur_val = chksum_bios_get_value( bios_data, offset );
215 new_val = chksum_bios_calc_value( bios_data, offset );
216 printf( "\n\nBios checksum at: 0x%4lX\n", offset );
217 printf( "Current checksum: 0x%02X\n", cur_val );
218 printf( "Calculated checksum: 0x%02X ", new_val );
219 if( cur_val != new_val ) {
220 printf( "Setting checksum." );
221 chksum_bios_set_value( bios_data, offset, new_val );
223 printf( "\n" );
225 write_bios:
226 if ((stream = fopen(argv[arg], "wb")) == NULL) {
227 printf("Error opening %s for writing.\n", argv[arg]);
228 exit(EXIT_FAILURE);
230 if (fwrite(bios_data, 1, LEN_BIOS_DATA, stream) < LEN_BIOS_DATA) {
231 printf("Error writing 64KBytes to %s.\n", argv[arg]);
232 fclose(stream);
233 exit(EXIT_FAILURE);
235 fclose(stream);
237 return(EXIT_SUCCESS);
241 void check(int okay, char* message) {
243 if (!okay) {
244 printf("\n\nError. %s.\n", message);
245 exit(EXIT_FAILURE);
250 long chksum_bios_get_offset( byte* data, long offset ) {
252 return( BIOS_OFFSET );
256 byte chksum_bios_calc_value( byte* data, long offset ) {
258 int i;
259 byte sum;
261 sum = 0;
262 for( i = 0; i < MAX_OFFSET; i++ ) {
263 sum = sum + *( data + i );
265 sum = -sum; /* iso ensures -s + s == 0 on unsigned types */
266 return( sum );
270 byte chksum_bios_get_value( byte* data, long offset ) {
272 return( *( data + BIOS_OFFSET ) );
276 void chksum_bios_set_value( byte* data, long offset, byte value ) {
278 *( data + BIOS_OFFSET ) = value;
282 byte chksum__32__calc_value( byte* data, long offset ) {
284 int i;
285 int len;
286 byte sum;
288 check( offset + _32__MINHDR <= MAX_OFFSET, "_32_ header out of bounds" );
289 len = *( data + offset + _32__LEN ) << 4;
290 check( offset + len <= MAX_OFFSET, "_32_ header-length out of bounds" );
291 sum = 0;
292 for( i = 0; i < len; i++ ) {
293 if( i != _32__CHKSUM ) {
294 sum = sum + *( data + offset + i );
297 sum = -sum;
298 return( sum );
302 long chksum__32__get_offset( byte* data, long offset ) {
304 long result = -1L;
306 offset = offset + 0x0F;
307 offset = offset & ~( 0x0F );
308 while( offset + 16 < MAX_OFFSET ) {
309 offset = offset + 16;
310 if( *( data + offset + 0 ) == '_' && \
311 *( data + offset + 1 ) == '3' && \
312 *( data + offset + 2 ) == '2' && \
313 *( data + offset + 3 ) == '_' ) {
314 result = offset;
315 break;
318 return( result );
322 byte chksum__32__get_value( byte* data, long offset ) {
324 check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
325 return( *( data + offset + _32__CHKSUM ) );
329 void chksum__32__set_value( byte* data, long offset, byte value ) {
331 check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
332 *( data + offset + _32__CHKSUM ) = value;
336 byte chksum__mp__calc_value( byte* data, long offset ) {
338 int i;
339 int len;
340 byte sum;
342 check( offset + _MP__MINHDR <= MAX_OFFSET, "_MP_ header out of bounds" );
343 len = *( data + offset + _MP__LEN ) << 4;
344 check( offset + len <= MAX_OFFSET, "_MP_ header-length out of bounds" );
345 sum = 0;
346 for( i = 0; i < len; i++ ) {
347 if( i != _MP__CHKSUM ) {
348 sum = sum + *( data + offset + i );
351 sum = -sum;
352 return( sum );
356 long chksum__mp__get_offset( byte* data, long offset ) {
358 long result = -1L;
360 offset = offset + 0x0F;
361 offset = offset & ~( 0x0F );
362 while( offset + 16 < MAX_OFFSET ) {
363 offset = offset + 16;
364 if( *( data + offset + 0 ) == '_' && \
365 *( data + offset + 1 ) == 'M' && \
366 *( data + offset + 2 ) == 'P' && \
367 *( data + offset + 3 ) == '_' ) {
368 result = offset;
369 break;
372 return( result );
376 byte chksum__mp__get_value( byte* data, long offset ) {
378 check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
379 return( *( data + offset + _MP__CHKSUM ) );
383 void chksum__mp__set_value( byte* data, long offset, byte value ) {
385 check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
386 *( data + offset + _MP__CHKSUM ) = value;
390 byte chksum_pcmp_calc_value( byte* data, long offset ) {
392 int i;
393 int len;
394 byte sum;
396 check( offset + PCMP_MINHDR <= MAX_OFFSET, "PCMP header out of bounds" );
397 len = *( data + offset + PCMP_BASELEN ) + \
398 ( *( data + offset + PCMP_BASELEN + 1 ) << 8 );
399 check( offset + len <= MAX_OFFSET, "PCMP header-length out of bounds" );
400 if( *( data + offset + PCMP_EXT_LEN ) | \
401 *( data + offset + PCMP_EXT_LEN + 1 ) | \
402 *( data + offset + PCMP_EXT_CHKSUM ) ) {
403 check( 0, "PCMP header indicates extended tables (unsupported)" );
405 sum = 0;
406 for( i = 0; i < len; i++ ) {
407 if( i != PCMP_CHKSUM ) {
408 sum = sum + *( data + offset + i );
411 sum = -sum;
412 return( sum );
416 long chksum_pcmp_get_offset( byte* data, long offset ) {
418 long result = -1L;
420 offset = offset + 0x0F;
421 offset = offset & ~( 0x0F );
422 while( offset + 16 < MAX_OFFSET ) {
423 offset = offset + 16;
424 if( *( data + offset + 0 ) == 'P' && \
425 *( data + offset + 1 ) == 'C' && \
426 *( data + offset + 2 ) == 'M' && \
427 *( data + offset + 3 ) == 'P' ) {
428 result = offset;
429 break;
432 return( result );
436 byte chksum_pcmp_get_value( byte* data, long offset ) {
438 check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
439 return( *( data + offset + PCMP_CHKSUM ) );
443 void chksum_pcmp_set_value( byte* data, long offset, byte value ) {
445 check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
446 *( data + offset + PCMP_CHKSUM ) = value;
450 byte chksum__pir_calc_value( byte* data, long offset ) {
452 int i;
453 int len;
454 byte sum;
456 check( offset + _PIR_MINHDR <= MAX_OFFSET, "$PIR header out of bounds" );
457 len = *( data + offset + _PIR_LEN ) + \
458 ( *( data + offset + _PIR_LEN + 1 ) << 8 );
459 check( offset + len <= MAX_OFFSET, "$PIR header-length out of bounds" );
460 sum = 0;
461 for( i = 0; i < len; i++ ) {
462 if( i != _PIR_CHKSUM ) {
463 sum = sum + *( data + offset + i );
466 sum = -sum;
467 return( sum );
471 long chksum__pir_get_offset( byte* data, long offset ) {
473 long result = -1L;
475 offset = offset + 0x0F;
476 offset = offset & ~( 0x0F );
477 while( offset + 16 < MAX_OFFSET ) {
478 offset = offset + 16;
479 if( *( data + offset + 0 ) == '$' && \
480 *( data + offset + 1 ) == 'P' && \
481 *( data + offset + 2 ) == 'I' && \
482 *( data + offset + 3 ) == 'R' ) {
483 result = offset;
484 break;
487 return( result );
491 byte chksum__pir_get_value( byte* data, long offset ) {
493 check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
494 return( *( data + offset + _PIR_CHKSUM ) );
498 void chksum__pir_set_value( byte* data, long offset, byte value ) {
500 check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
501 *( data + offset + _PIR_CHKSUM ) = value;