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 */
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
);
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
);
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
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
);
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
];
90 int main(int argc
, char* argv
[]) {
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"))) {
101 } else if (argc
!= 2) {
102 printf("Error. Need a file-name as an argument.\n");
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
]);
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
]);
118 if (pad
== 1) goto write_bios
;
122 while( (tmp_offset
= chksum__32__get_offset( bios_data
, offset
)) != -1L ) {
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
);
131 if( hits
== 1 && cur_val
!= new_val
) {
132 printf( "Setting checksum." );
133 chksum__32__set_value( bios_data
, offset
, new_val
);
136 printf( "Multiple PCI headers! No checksum set." );
145 while( (tmp_offset
= chksum__mp__get_offset( bios_data
, offset
)) != -1L ) {
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
);
154 if( hits
== 1 && cur_val
!= new_val
) {
155 printf( "Setting checksum." );
156 chksum__mp__set_value( bios_data
, offset
, new_val
);
159 printf( "Warning! Multiple MP headers. No checksum set." );
168 while( (tmp_offset
= chksum_pcmp_get_offset( bios_data
, offset
)) != -1L ) {
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
);
177 if( hits
== 1 && cur_val
!= new_val
) {
178 printf( "Setting checksum." );
179 chksum_pcmp_set_value( bios_data
, offset
, new_val
);
182 printf( "Warning! Multiple PCMP headers. No checksum set." );
191 while( (tmp_offset
= chksum__pir_get_offset( bios_data
, offset
)) != -1L ) {
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
);
200 if( hits
== 1 && cur_val
!= new_val
) {
201 printf( "Setting checksum." );
202 chksum__pir_set_value( bios_data
, offset
, new_val
);
205 printf( "Warning! Multiple $PIR headers. No checksum set." );
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
);
226 if ((stream
= fopen(argv
[arg
], "wb")) == NULL
) {
227 printf("Error opening %s for writing.\n", argv
[arg
]);
230 if (fwrite(bios_data
, 1, LEN_BIOS_DATA
, stream
) < LEN_BIOS_DATA
) {
231 printf("Error writing 64KBytes to %s.\n", argv
[arg
]);
237 return(EXIT_SUCCESS
);
241 void check(int okay
, char* message
) {
244 printf("\n\nError. %s.\n", message
);
250 long chksum_bios_get_offset( byte
* data
, long offset
) {
252 return( BIOS_OFFSET
);
256 byte
chksum_bios_calc_value( byte
* data
, long offset
) {
262 for( i
= 0; i
< MAX_OFFSET
; i
++ ) {
263 sum
= sum
+ *( data
+ i
);
265 sum
= -sum
; /* iso ensures -s + s == 0 on unsigned types */
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
) {
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" );
292 for( i
= 0; i
< len
; i
++ ) {
293 if( i
!= _32__CHKSUM
) {
294 sum
= sum
+ *( data
+ offset
+ i
);
302 long chksum__32__get_offset( byte
* data
, long offset
) {
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 ) == '_' ) {
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
) {
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" );
346 for( i
= 0; i
< len
; i
++ ) {
347 if( i
!= _MP__CHKSUM
) {
348 sum
= sum
+ *( data
+ offset
+ i
);
356 long chksum__mp__get_offset( byte
* data
, long offset
) {
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 ) == '_' ) {
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
) {
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)" );
406 for( i
= 0; i
< len
; i
++ ) {
407 if( i
!= PCMP_CHKSUM
) {
408 sum
= sum
+ *( data
+ offset
+ i
);
416 long chksum_pcmp_get_offset( byte
* data
, long offset
) {
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' ) {
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
) {
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" );
461 for( i
= 0; i
< len
; i
++ ) {
462 if( i
!= _PIR_CHKSUM
) {
463 sum
= sum
+ *( data
+ offset
+ i
);
471 long chksum__pir_get_offset( byte
* data
, long offset
) {
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' ) {
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
;