- biossums utility now supports VGABIOS sizes up to 64 kBytes
[vgabios.git] / biossums.c
blob2a356da08fd3c79223b9bfd05062b349c4198ae4
1 /* biossums.c --- written by Eike W. for the Bochs BIOS */
2 /* adapted for the LGPL'd VGABIOS by vruppert */
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
18 #include <stdlib.h>
19 #include <stdio.h>
21 typedef unsigned char byte;
23 void check( int value, char* message );
25 #define MAX_BIOS_DATA 0x10000
27 long chksum_bios_get_offset( byte* data, long offset );
28 byte chksum_bios_calc_value( byte* data, long offset );
29 byte chksum_bios_get_value( byte* data, long offset );
30 void chksum_bios_set_value( byte* data, long offset, byte value );
33 #define PMID_LEN 20
34 #define PMID_CHKSUM 19
36 long chksum_pmid_get_offset( byte* data, long offset );
37 byte chksum_pmid_calc_value( byte* data, long offset );
38 byte chksum_pmid_get_value( byte* data, long offset );
39 void chksum_pmid_set_value( byte* data, long offset, byte value );
42 byte bios_data[MAX_BIOS_DATA];
43 long bios_len;
46 int main( int argc, char* argv[] ) {
48 FILE* stream;
49 long offset, tmp_offset;
50 byte cur_val = 0, new_val = 0;
51 int hits;
54 if (argc != 2) {
55 printf( "Error. Need a file-name as an argument.\n" );
56 exit( EXIT_FAILURE );
59 if ((stream = fopen(argv[1], "rb")) == NULL) {
60 printf("Error opening %s for reading.\n", argv[1]);
61 exit(EXIT_FAILURE);
63 memset(bios_data, 0, MAX_BIOS_DATA);
64 bios_len = fread(bios_data, 1, MAX_BIOS_DATA, stream);
65 if (bios_len >= MAX_BIOS_DATA) {
66 printf("Error reading max. 65535 Bytes from %s.\n", argv[1]);
67 fclose(stream);
68 exit(EXIT_FAILURE);
70 fclose(stream);
71 if (bios_len < 0x7FFF) {
72 bios_len = 0x8000;
73 } else {
74 bios_len = (bios_len + 0x201) & ~0x1FF;
76 bios_data[2] = (byte)(bios_len / 512);
78 hits = 0;
79 offset = 0L;
80 while( (tmp_offset = chksum_pmid_get_offset( bios_data, offset )) != -1L ) {
81 offset = tmp_offset;
82 cur_val = chksum_pmid_get_value( bios_data, offset );
83 new_val = chksum_pmid_calc_value( bios_data, offset );
84 printf( "\nPMID entry at: 0x%4lX\n", offset );
85 printf( "Current checksum: 0x%02X\n", cur_val );
86 printf( "Calculated checksum: 0x%02X ", new_val );
87 hits++;
89 if( hits == 1 && cur_val != new_val ) {
90 printf( "Setting checksum." );
91 chksum_pmid_set_value( bios_data, offset, new_val );
93 if( hits >= 2 ) {
94 printf( "Multiple PMID entries! No checksum set." );
96 if( hits ) {
97 printf( "\n" );
101 offset = 0L;
102 offset = chksum_bios_get_offset( bios_data, offset );
103 cur_val = chksum_bios_get_value( bios_data, offset );
104 new_val = chksum_bios_calc_value( bios_data, offset );
105 printf( "\nBios checksum at: 0x%4lX\n", offset );
106 printf( "Current checksum: 0x%02X\n", cur_val );
107 printf( "Calculated checksum: 0x%02X ", new_val );
108 if( cur_val != new_val ) {
109 printf( "Setting checksum." );
110 chksum_bios_set_value( bios_data, offset, new_val );
112 printf( "\n" );
115 if(( stream = fopen( argv[1], "wb" )) == NULL ) {
116 printf( "Error opening %s for writing.\n", argv[1] );
117 exit( EXIT_FAILURE );
119 if( fwrite( bios_data, 1, bios_len, stream ) < bios_len ) {
120 printf( "Error writing %d KBytes to %s.\n", bios_len / 1024, argv[1] );
121 fclose( stream );
122 exit( EXIT_FAILURE );
124 fclose( stream );
126 return( EXIT_SUCCESS );
130 void check( int okay, char* message ) {
132 if( !okay ) {
133 printf( "\n\nError. %s.\n", message );
134 exit( EXIT_FAILURE );
139 long chksum_bios_get_offset( byte* data, long offset ) {
141 return (bios_len - 1);
145 byte chksum_bios_calc_value( byte* data, long offset ) {
147 int i;
148 byte sum;
150 sum = 0;
151 for( i = 0; i < offset; i++ ) {
152 sum = sum + *( data + i );
154 sum = -sum; /* iso ensures -s + s == 0 on unsigned types */
155 return( sum );
159 byte chksum_bios_get_value( byte* data, long offset ) {
161 return( *( data + offset ) );
165 void chksum_bios_set_value( byte* data, long offset, byte value ) {
167 *( data + offset ) = value;
171 byte chksum_pmid_calc_value( byte* data, long offset ) {
173 int i;
174 int len;
175 byte sum;
177 len = PMID_LEN;
178 check((offset + len) <= (bios_len - 1), "PMID entry length out of bounds" );
179 sum = 0;
180 for( i = 0; i < len; i++ ) {
181 if( i != PMID_CHKSUM ) {
182 sum = sum + *( data + offset + i );
185 sum = -sum;
186 return( sum );
190 long chksum_pmid_get_offset( byte* data, long offset ) {
192 long result = -1L;
194 while ((offset + PMID_LEN) < (bios_len - 1)) {
195 offset = offset + 1;
196 if( *( data + offset + 0 ) == 'P' && \
197 *( data + offset + 1 ) == 'M' && \
198 *( data + offset + 2 ) == 'I' && \
199 *( data + offset + 3 ) == 'D' ) {
200 result = offset;
201 break;
204 return( result );
208 byte chksum_pmid_get_value( byte* data, long offset ) {
210 check((offset + PMID_CHKSUM) <= (bios_len - 1), "PMID checksum out of bounds" );
211 return( *( data + offset + PMID_CHKSUM ) );
215 void chksum_pmid_set_value( byte* data, long offset, byte value ) {
217 check((offset + PMID_CHKSUM) <= (bios_len - 1), "PMID checksum out of bounds" );
218 *( data + offset + PMID_CHKSUM ) = value;