2 * $Id: biossums.c,v 1.4 2007/05/28 08:09:13 vruppert Exp $
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 */
25 typedef unsigned char byte
;
27 void check( int value
, char* message
);
29 #define LEN_BIOS_DATA 0x10000
30 #define MAX_OFFSET (LEN_BIOS_DATA - 1)
33 #define BIOS_OFFSET 0xFFFF
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
);
42 #define _32__CHKSUM 10
44 #define _32__MINHDR 16
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
);
53 #define _MP__CHKSUM 10
55 #define _MP__MINHDR 16
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
);
63 #define PCMP_BASELEN 4
65 #define PCMP_EXT_LEN 40
66 #define PCMP_EXT_CHKSUM 42
68 #define PCMP_MINHDR 42
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
);
77 #define _PIR_CHKSUM 31
79 #define _PIR_MINHDR 32
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
);
87 byte bios_data
[LEN_BIOS_DATA
];
91 int main(int argc
, char* argv
[]) {
94 long offset
, tmp_offset
;
95 byte cur_val
= 0, new_val
= 0;
96 int arg
= 1, hits
, pad
= 0;
99 if ((argc
== 3) && (!strcmp(argv
[1], "-pad"))) {
102 } else if (argc
!= 2) {
103 printf("Error. Need a file-name as an argument.\n");
106 memset(bios_data
, 0xff, LEN_BIOS_DATA
);
108 if ((stream
= fopen(argv
[arg
], "rb")) == NULL
) {
109 printf("Error opening %s for reading.\n", argv
[arg
]);
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
]);
119 if (pad
== 1) goto write_bios
;
123 while( (tmp_offset
= chksum__32__get_offset( bios_data
, offset
)) != -1L ) {
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
);
132 if( hits
== 1 && cur_val
!= new_val
) {
133 printf( "Setting checksum." );
134 chksum__32__set_value( bios_data
, offset
, new_val
);
137 printf( "Multiple PCI headers! No checksum set." );
146 while( (tmp_offset
= chksum__mp__get_offset( bios_data
, offset
)) != -1L ) {
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
);
155 if( hits
== 1 && cur_val
!= new_val
) {
156 printf( "Setting checksum." );
157 chksum__mp__set_value( bios_data
, offset
, new_val
);
160 printf( "Warning! Multiple MP headers. No checksum set." );
169 while( (tmp_offset
= chksum_pcmp_get_offset( bios_data
, offset
)) != -1L ) {
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
);
178 if( hits
== 1 && cur_val
!= new_val
) {
179 printf( "Setting checksum." );
180 chksum_pcmp_set_value( bios_data
, offset
, new_val
);
183 printf( "Warning! Multiple PCMP headers. No checksum set." );
192 while( (tmp_offset
= chksum__pir_get_offset( bios_data
, offset
)) != -1L ) {
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
);
201 if( hits
== 1 && cur_val
!= new_val
) {
202 printf( "Setting checksum." );
203 chksum__pir_set_value( bios_data
, offset
, new_val
);
206 printf( "Warning! Multiple $PIR headers. No checksum set." );
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
);
227 if ((stream
= fopen(argv
[arg
], "wb")) == NULL
) {
228 printf("Error opening %s for writing.\n", argv
[arg
]);
231 if (fwrite(bios_data
, 1, LEN_BIOS_DATA
, stream
) < LEN_BIOS_DATA
) {
232 printf("Error writing 64KBytes to %s.\n", argv
[arg
]);
238 return(EXIT_SUCCESS
);
242 void check(int okay
, char* message
) {
245 printf("\n\nError. %s.\n", message
);
251 long chksum_bios_get_offset( byte
* data
, long offset
) {
253 return( BIOS_OFFSET
);
257 byte
chksum_bios_calc_value( byte
* data
, long offset
) {
263 for( i
= 0; i
< MAX_OFFSET
; i
++ ) {
264 sum
= sum
+ *( data
+ i
);
266 sum
= -sum
; /* iso ensures -s + s == 0 on unsigned types */
271 byte
chksum_bios_get_value( byte
* data
, long offset
) {
273 return( *( data
+ BIOS_OFFSET
) );
277 void chksum_bios_set_value( byte
* data
, long offset
, byte value
) {
279 *( data
+ BIOS_OFFSET
) = value
;
283 byte
chksum__32__calc_value( byte
* data
, long offset
) {
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" );
293 for( i
= 0; i
< len
; i
++ ) {
294 if( i
!= _32__CHKSUM
) {
295 sum
= sum
+ *( data
+ offset
+ i
);
303 long chksum__32__get_offset( byte
* data
, long offset
) {
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 ) == '_' ) {
323 byte
chksum__32__get_value( byte
* data
, long offset
) {
325 check( offset
+ _32__CHKSUM
<= MAX_OFFSET
, "PCI-Bios checksum out of bounds" );
326 return( *( data
+ offset
+ _32__CHKSUM
) );
330 void chksum__32__set_value( byte
* data
, long offset
, byte value
) {
332 check( offset
+ _32__CHKSUM
<= MAX_OFFSET
, "PCI-Bios checksum out of bounds" );
333 *( data
+ offset
+ _32__CHKSUM
) = value
;
337 byte
chksum__mp__calc_value( byte
* data
, long offset
) {
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" );
347 for( i
= 0; i
< len
; i
++ ) {
348 if( i
!= _MP__CHKSUM
) {
349 sum
= sum
+ *( data
+ offset
+ i
);
357 long chksum__mp__get_offset( byte
* data
, long offset
) {
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 ) == '_' ) {
377 byte
chksum__mp__get_value( byte
* data
, long offset
) {
379 check( offset
+ _MP__CHKSUM
<= MAX_OFFSET
, "MP checksum out of bounds" );
380 return( *( data
+ offset
+ _MP__CHKSUM
) );
384 void chksum__mp__set_value( byte
* data
, long offset
, byte value
) {
386 check( offset
+ _MP__CHKSUM
<= MAX_OFFSET
, "MP checksum out of bounds" );
387 *( data
+ offset
+ _MP__CHKSUM
) = value
;
391 byte
chksum_pcmp_calc_value( byte
* data
, long offset
) {
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)" );
407 for( i
= 0; i
< len
; i
++ ) {
408 if( i
!= PCMP_CHKSUM
) {
409 sum
= sum
+ *( data
+ offset
+ i
);
417 long chksum_pcmp_get_offset( byte
* data
, long offset
) {
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' ) {
437 byte
chksum_pcmp_get_value( byte
* data
, long offset
) {
439 check( offset
+ PCMP_CHKSUM
<= MAX_OFFSET
, "PCMP checksum out of bounds" );
440 return( *( data
+ offset
+ PCMP_CHKSUM
) );
444 void chksum_pcmp_set_value( byte
* data
, long offset
, byte value
) {
446 check( offset
+ PCMP_CHKSUM
<= MAX_OFFSET
, "PCMP checksum out of bounds" );
447 *( data
+ offset
+ PCMP_CHKSUM
) = value
;
451 byte
chksum__pir_calc_value( byte
* data
, long offset
) {
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" );
462 for( i
= 0; i
< len
; i
++ ) {
463 if( i
!= _PIR_CHKSUM
) {
464 sum
= sum
+ *( data
+ offset
+ i
);
472 long chksum__pir_get_offset( byte
* data
, long offset
) {
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' ) {
492 byte
chksum__pir_get_value( byte
* data
, long offset
) {
494 check( offset
+ _PIR_CHKSUM
<= MAX_OFFSET
, "$PIR checksum out of bounds" );
495 return( *( data
+ offset
+ _PIR_CHKSUM
) );
499 void chksum__pir_set_value( byte
* data
, long offset
, byte value
) {
501 check( offset
+ _PIR_CHKSUM
<= MAX_OFFSET
, "$PIR checksum out of bounds" );
502 *( data
+ offset
+ _PIR_CHKSUM
) = value
;