1 | /* biossums.c --- written by Eike W. for the Bochs BIOS */
|
---|
2 | /* adapted for the LGPL'd VGABIOS by vruppert */
|
---|
3 |
|
---|
4 | #include <stdlib.h>
|
---|
5 | #include <stdio.h>
|
---|
6 |
|
---|
7 | typedef unsigned char byte;
|
---|
8 |
|
---|
9 | void check( int value, char* message );
|
---|
10 |
|
---|
11 | #define LEN_BIOS_DATA 0x8000
|
---|
12 | #define MAX_OFFSET (LEN_BIOS_DATA - 1)
|
---|
13 |
|
---|
14 |
|
---|
15 | #define BIOS_OFFSET 0x7FFF
|
---|
16 |
|
---|
17 | long chksum_bios_get_offset( byte* data, long offset );
|
---|
18 | byte chksum_bios_calc_value( byte* data, long offset );
|
---|
19 | byte chksum_bios_get_value( byte* data, long offset );
|
---|
20 | void chksum_bios_set_value( byte* data, long offset, byte value );
|
---|
21 |
|
---|
22 |
|
---|
23 | #define PMID_LEN 20
|
---|
24 | #define PMID_CHKSUM 19
|
---|
25 |
|
---|
26 | long chksum_pmid_get_offset( byte* data, long offset );
|
---|
27 | byte chksum_pmid_calc_value( byte* data, long offset );
|
---|
28 | byte chksum_pmid_get_value( byte* data, long offset );
|
---|
29 | void chksum_pmid_set_value( byte* data, long offset, byte value );
|
---|
30 |
|
---|
31 |
|
---|
32 | byte bios_data[LEN_BIOS_DATA];
|
---|
33 |
|
---|
34 |
|
---|
35 | int main( int argc, char* argv[] ) {
|
---|
36 |
|
---|
37 | FILE* stream;
|
---|
38 | long offset, tmp_offset;
|
---|
39 | byte cur_val = 0, new_val = 0;
|
---|
40 | int hits;
|
---|
41 |
|
---|
42 |
|
---|
43 | if( argc != 2 ) {
|
---|
44 | printf( "Error. Need a file-name as an argument.\n" );
|
---|
45 | exit( EXIT_FAILURE );
|
---|
46 | }
|
---|
47 |
|
---|
48 | if(( stream = fopen( argv[1], "rb" )) == NULL ) {
|
---|
49 | printf( "Error opening %s for reading.\n", argv[1] );
|
---|
50 | exit( EXIT_FAILURE );
|
---|
51 | }
|
---|
52 | if( fread( bios_data, 1, LEN_BIOS_DATA, stream ) >= LEN_BIOS_DATA ) {
|
---|
53 | printf( "Error reading max. 32767 Bytes from %s.\n", argv[1] );
|
---|
54 | fclose( stream );
|
---|
55 | exit( EXIT_FAILURE );
|
---|
56 | }
|
---|
57 | fclose( stream );
|
---|
58 |
|
---|
59 | hits = 0;
|
---|
60 | offset = 0L;
|
---|
61 | while( (tmp_offset = chksum_pmid_get_offset( bios_data, offset )) != -1L ) {
|
---|
62 | offset = tmp_offset;
|
---|
63 | cur_val = chksum_pmid_get_value( bios_data, offset );
|
---|
64 | new_val = chksum_pmid_calc_value( bios_data, offset );
|
---|
65 | printf( "\nPMID entry at: 0x%4lX\n", offset );
|
---|
66 | printf( "Current checksum: 0x%02X\n", cur_val );
|
---|
67 | printf( "Calculated checksum: 0x%02X ", new_val );
|
---|
68 | hits++;
|
---|
69 | }
|
---|
70 | if( hits == 1 && cur_val != new_val ) {
|
---|
71 | printf( "Setting checksum." );
|
---|
72 | chksum_pmid_set_value( bios_data, offset, new_val );
|
---|
73 | }
|
---|
74 | if( hits >= 2 ) {
|
---|
75 | printf( "Multiple PMID entries! No checksum set." );
|
---|
76 | }
|
---|
77 | if( hits ) {
|
---|
78 | printf( "\n" );
|
---|
79 | }
|
---|
80 |
|
---|
81 |
|
---|
82 | offset = 0L;
|
---|
83 | offset = chksum_bios_get_offset( bios_data, offset );
|
---|
84 | cur_val = chksum_bios_get_value( bios_data, offset );
|
---|
85 | new_val = chksum_bios_calc_value( bios_data, offset );
|
---|
86 | printf( "\nBios checksum at: 0x%4lX\n", offset );
|
---|
87 | printf( "Current checksum: 0x%02X\n", cur_val );
|
---|
88 | printf( "Calculated checksum: 0x%02X ", new_val );
|
---|
89 | if( cur_val != new_val ) {
|
---|
90 | printf( "Setting checksum." );
|
---|
91 | chksum_bios_set_value( bios_data, offset, new_val );
|
---|
92 | }
|
---|
93 | printf( "\n\n" );
|
---|
94 |
|
---|
95 |
|
---|
96 | if(( stream = fopen( argv[1], "wb" )) == NULL ) {
|
---|
97 | printf( "Error opening %s for writing.\n", argv[1] );
|
---|
98 | exit( EXIT_FAILURE );
|
---|
99 | }
|
---|
100 | if( fwrite( bios_data, 1, LEN_BIOS_DATA, stream ) < LEN_BIOS_DATA ) {
|
---|
101 | printf( "Error writing 32KBytes to %s.\n", argv[1] );
|
---|
102 | fclose( stream );
|
---|
103 | exit( EXIT_FAILURE );
|
---|
104 | }
|
---|
105 | fclose( stream );
|
---|
106 |
|
---|
107 | return( EXIT_SUCCESS );
|
---|
108 | }
|
---|
109 |
|
---|
110 |
|
---|
111 | void check( int okay, char* message ) {
|
---|
112 |
|
---|
113 | if( !okay ) {
|
---|
114 | printf( "\n\nError. %s.\n", message );
|
---|
115 | exit( EXIT_FAILURE );
|
---|
116 | }
|
---|
117 | }
|
---|
118 |
|
---|
119 |
|
---|
120 | long chksum_bios_get_offset( byte* data, long offset ) {
|
---|
121 |
|
---|
122 | return( BIOS_OFFSET );
|
---|
123 | }
|
---|
124 |
|
---|
125 |
|
---|
126 | byte chksum_bios_calc_value( byte* data, long offset ) {
|
---|
127 |
|
---|
128 | int i;
|
---|
129 | byte sum;
|
---|
130 |
|
---|
131 | sum = 0;
|
---|
132 | for( i = 0; i < MAX_OFFSET; i++ ) {
|
---|
133 | sum = sum + *( data + i );
|
---|
134 | }
|
---|
135 | sum = -sum; /* iso ensures -s + s == 0 on unsigned types */
|
---|
136 | return( sum );
|
---|
137 | }
|
---|
138 |
|
---|
139 |
|
---|
140 | byte chksum_bios_get_value( byte* data, long offset ) {
|
---|
141 |
|
---|
142 | return( *( data + BIOS_OFFSET ) );
|
---|
143 | }
|
---|
144 |
|
---|
145 |
|
---|
146 | void chksum_bios_set_value( byte* data, long offset, byte value ) {
|
---|
147 |
|
---|
148 | *( data + BIOS_OFFSET ) = value;
|
---|
149 | }
|
---|
150 |
|
---|
151 |
|
---|
152 | byte chksum_pmid_calc_value( byte* data, long offset ) {
|
---|
153 |
|
---|
154 | int i;
|
---|
155 | int len;
|
---|
156 | byte sum;
|
---|
157 |
|
---|
158 | len = PMID_LEN;
|
---|
159 | check( offset + len <= MAX_OFFSET, "PMID entry length out of bounds" );
|
---|
160 | sum = 0;
|
---|
161 | for( i = 0; i < len; i++ ) {
|
---|
162 | if( i != PMID_CHKSUM ) {
|
---|
163 | sum = sum + *( data + offset + i );
|
---|
164 | }
|
---|
165 | }
|
---|
166 | sum = -sum;
|
---|
167 | return( sum );
|
---|
168 | }
|
---|
169 |
|
---|
170 |
|
---|
171 | long chksum_pmid_get_offset( byte* data, long offset ) {
|
---|
172 |
|
---|
173 | long result = -1L;
|
---|
174 |
|
---|
175 | while( offset + PMID_LEN < MAX_OFFSET ) {
|
---|
176 | offset = offset + 1;
|
---|
177 | if( *( data + offset + 0 ) == 'P' && \
|
---|
178 | *( data + offset + 1 ) == 'M' && \
|
---|
179 | *( data + offset + 2 ) == 'I' && \
|
---|
180 | *( data + offset + 3 ) == 'D' ) {
|
---|
181 | result = offset;
|
---|
182 | break;
|
---|
183 | }
|
---|
184 | }
|
---|
185 | return( result );
|
---|
186 | }
|
---|
187 |
|
---|
188 |
|
---|
189 | byte chksum_pmid_get_value( byte* data, long offset ) {
|
---|
190 |
|
---|
191 | check( offset + PMID_CHKSUM <= MAX_OFFSET, "PMID checksum out of bounds" );
|
---|
192 | return( *( data + offset + PMID_CHKSUM ) );
|
---|
193 | }
|
---|
194 |
|
---|
195 |
|
---|
196 | void chksum_pmid_set_value( byte* data, long offset, byte value ) {
|
---|
197 |
|
---|
198 | check( offset + PMID_CHKSUM <= MAX_OFFSET, "PMID checksum out of bounds" );
|
---|
199 | *( data + offset + PMID_CHKSUM ) = value;
|
---|
200 | }
|
---|