kvm: qemu: deassign device from guest
[kvm-userspace.git] / bios / biossums.c
blob032ac23c3d0ec1fe954909cdad61e6f598fc354c
1 /*
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 */
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
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 );
41 #define _32__LEN 9
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 );
52 #define _MP__LEN 8
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
64 #define PCMP_CHKSUM 7
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 );
76 #define _PIR_LEN 6
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];
88 long bios_len;
91 int main(int argc, char* argv[]) {
93 FILE* stream;
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"))) {
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);
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]);
110 exit(EXIT_FAILURE);
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);
118 fclose(stream);
119 if (pad == 1) goto write_bios;
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++;
132 if( hits == 1 && cur_val != new_val ) {
133 printf( "Setting checksum." );
134 chksum__32__set_value( bios_data, offset, new_val );
136 if( hits >= 2 ) {
137 printf( "Multiple PCI headers! No checksum set." );
139 if( hits ) {
140 printf( "\n" );
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++;
155 if( hits == 1 && cur_val != new_val ) {
156 printf( "Setting checksum." );
157 chksum__mp__set_value( bios_data, offset, new_val );
159 if( hits >= 2 ) {
160 printf( "Warning! Multiple MP headers. No checksum set." );
162 if( hits ) {
163 printf( "\n" );
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++;
178 if( hits == 1 && cur_val != new_val ) {
179 printf( "Setting checksum." );
180 chksum_pcmp_set_value( bios_data, offset, new_val );
182 if( hits >= 2 ) {
183 printf( "Warning! Multiple PCMP headers. No checksum set." );
185 if( hits ) {
186 printf( "\n" );
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++;
201 if( hits == 1 && cur_val != new_val ) {
202 printf( "Setting checksum." );
203 chksum__pir_set_value( bios_data, offset, new_val );
205 if( hits >= 2 ) {
206 printf( "Warning! Multiple $PIR headers. No checksum set." );
208 if( hits ) {
209 printf( "\n" );
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 );
224 printf( "\n" );
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);
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);
236 fclose(stream);
238 return(EXIT_SUCCESS);
242 void check(int okay, char* message) {
244 if (!okay) {
245 printf("\n\nError. %s.\n", message);
246 exit(EXIT_FAILURE);
251 long chksum_bios_get_offset( byte* data, long offset ) {
253 return( BIOS_OFFSET );
257 byte chksum_bios_calc_value( byte* data, long offset ) {
259 int i;
260 byte sum;
262 sum = 0;
263 for( i = 0; i < MAX_OFFSET; i++ ) {
264 sum = sum + *( data + i );
266 sum = -sum; /* iso ensures -s + s == 0 on unsigned types */
267 return( sum );
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 ) {
285 int i;
286 int len;
287 byte sum;
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 );
298 sum = -sum;
299 return( sum );
303 long chksum__32__get_offset( byte* data, long offset ) {
305 long result = -1L;
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;
319 return( result );
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 ) {
339 int i;
340 int len;
341 byte sum;
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 );
352 sum = -sum;
353 return( sum );
357 long chksum__mp__get_offset( byte* data, long offset ) {
359 long result = -1L;
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;
373 return( result );
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 ) {
393 int i;
394 int len;
395 byte sum;
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)" );
406 sum = 0;
407 for( i = 0; i < len; i++ ) {
408 if( i != PCMP_CHKSUM ) {
409 sum = sum + *( data + offset + i );
412 sum = -sum;
413 return( sum );
417 long chksum_pcmp_get_offset( byte* data, long offset ) {
419 long result = -1L;
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;
433 return( result );
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 ) {
453 int i;
454 int len;
455 byte sum;
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 );
467 sum = -sum;
468 return( sum );
472 long chksum__pir_get_offset( byte* data, long offset ) {
474 long result = -1L;
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;
488 return( result );
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;