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 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 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 251 long chksum_bios_get_offset( byte* data, long offset ) { 252 253 return( BIOS_OFFSET ); 254 } 255 256 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 271 byte chksum_bios_get_value( byte* data, long offset ) { 272 273 return( *( data + BIOS_OFFSET ) ); 274 } 275 276 277 void chksum_bios_set_value( byte* data, long offset, byte value ) { 278 279 *( data + BIOS_OFFSET ) = value; 280 } 281 282 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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