/contrib/rombios/biossums.c

https://github.com/l4ka/afterburner · C · 504 lines · 370 code · 116 blank · 18 comment · 101 complexity · b91484820778c7f55fe39e0d26170542 MD5 · raw file

  1. /*
  2. * $Id: biossums.c,v 1.4 2007/05/28 08:09:13 vruppert Exp $
  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. /* biossums.c --- written by Eike W. for the Bochs BIOS */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. typedef unsigned char byte;
  23. void check( int value, char* message );
  24. #define LEN_BIOS_DATA 0x10000
  25. #define MAX_OFFSET (LEN_BIOS_DATA - 1)
  26. #define BIOS_OFFSET 0xFFFF
  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 );
  31. #define _32__LEN 9
  32. #define _32__CHKSUM 10
  33. #define _32__MINHDR 16
  34. long chksum__32__get_offset( byte* data, long offset );
  35. byte chksum__32__calc_value( byte* data, long offset );
  36. byte chksum__32__get_value( byte* data, long offset );
  37. void chksum__32__set_value( byte* data, long offset, byte value );
  38. #define _MP__LEN 8
  39. #define _MP__CHKSUM 10
  40. #define _MP__MINHDR 16
  41. long chksum__mp__get_offset( byte* data, long offset );
  42. byte chksum__mp__calc_value( byte* data, long offset );
  43. byte chksum__mp__get_value( byte* data, long offset );
  44. void chksum__mp__set_value( byte* data, long offset, byte value );
  45. #define PCMP_BASELEN 4
  46. #define PCMP_CHKSUM 7
  47. #define PCMP_EXT_LEN 40
  48. #define PCMP_EXT_CHKSUM 42
  49. #define PCMP_MINHDR 42
  50. long chksum_pcmp_get_offset( byte* data, long offset );
  51. byte chksum_pcmp_calc_value( byte* data, long offset );
  52. byte chksum_pcmp_get_value( byte* data, long offset );
  53. void chksum_pcmp_set_value( byte* data, long offset, byte value );
  54. #define _PIR_LEN 6
  55. #define _PIR_CHKSUM 31
  56. #define _PIR_MINHDR 32
  57. long chksum__pir_get_offset( byte *data, long offset );
  58. byte chksum__pir_calc_value( byte* data, long offset );
  59. byte chksum__pir_get_value( byte* data, long offset );
  60. void chksum__pir_set_value( byte* data, long offset, byte value );
  61. byte bios_data[LEN_BIOS_DATA];
  62. long bios_len;
  63. int main(int argc, char* argv[]) {
  64. FILE* stream;
  65. long offset, tmp_offset;
  66. byte cur_val = 0, new_val = 0;
  67. int arg = 1, hits, pad = 0;
  68. if ((argc == 3) && (!strcmp(argv[1], "-pad"))) {
  69. pad = 1;
  70. arg = 2;
  71. } else if (argc != 2) {
  72. printf("Error. Need a file-name as an argument.\n");
  73. exit(EXIT_FAILURE);
  74. }
  75. memset(bios_data, 0xff, LEN_BIOS_DATA);
  76. if ((stream = fopen(argv[arg], "rb")) == NULL) {
  77. printf("Error opening %s for reading.\n", argv[arg]);
  78. exit(EXIT_FAILURE);
  79. }
  80. bios_len = fread(bios_data, 1, LEN_BIOS_DATA, stream);
  81. if ((bios_len < LEN_BIOS_DATA) && (pad == 0)) {
  82. printf("Error reading 64KBytes from %s.\n", argv[arg]);
  83. fclose(stream);
  84. exit(EXIT_FAILURE);
  85. }
  86. fclose(stream);
  87. if (pad == 1) goto write_bios;
  88. hits = 0;
  89. offset = 0L;
  90. while( (tmp_offset = chksum__32__get_offset( bios_data, offset )) != -1L ) {
  91. offset = tmp_offset;
  92. cur_val = chksum__32__get_value( bios_data, offset );
  93. new_val = chksum__32__calc_value( bios_data, offset );
  94. printf( "\n\nPCI-Bios header at: 0x%4lX\n", offset );
  95. printf( "Current checksum: 0x%02X\n", cur_val );
  96. printf( "Calculated checksum: 0x%02X ", new_val );
  97. hits++;
  98. }
  99. if( hits == 1 && cur_val != new_val ) {
  100. printf( "Setting checksum." );
  101. chksum__32__set_value( bios_data, offset, new_val );
  102. }
  103. if( hits >= 2 ) {
  104. printf( "Multiple PCI headers! No checksum set." );
  105. }
  106. if( hits ) {
  107. printf( "\n" );
  108. }
  109. hits = 0;
  110. offset = 0L;
  111. while( (tmp_offset = chksum__mp__get_offset( bios_data, offset )) != -1L ) {
  112. offset = tmp_offset;
  113. cur_val = chksum__mp__get_value( bios_data, offset );
  114. new_val = chksum__mp__calc_value( bios_data, offset );
  115. printf( "\n\nMP header at: 0x%4lX\n", offset );
  116. printf( "Current checksum: 0x%02X\n", cur_val );
  117. printf( "Calculated checksum: 0x%02X ", new_val );
  118. hits++;
  119. }
  120. if( hits == 1 && cur_val != new_val ) {
  121. printf( "Setting checksum." );
  122. chksum__mp__set_value( bios_data, offset, new_val );
  123. }
  124. if( hits >= 2 ) {
  125. printf( "Warning! Multiple MP headers. No checksum set." );
  126. }
  127. if( hits ) {
  128. printf( "\n" );
  129. }
  130. hits = 0;
  131. offset = 0L;
  132. while( (tmp_offset = chksum_pcmp_get_offset( bios_data, offset )) != -1L ) {
  133. offset = tmp_offset;
  134. cur_val = chksum_pcmp_get_value( bios_data, offset );
  135. new_val = chksum_pcmp_calc_value( bios_data, offset );
  136. printf( "\n\nPCMP header at: 0x%4lX\n", offset );
  137. printf( "Current checksum: 0x%02X\n", cur_val );
  138. printf( "Calculated checksum: 0x%02X ", new_val );
  139. hits++;
  140. }
  141. if( hits == 1 && cur_val != new_val ) {
  142. printf( "Setting checksum." );
  143. chksum_pcmp_set_value( bios_data, offset, new_val );
  144. }
  145. if( hits >= 2 ) {
  146. printf( "Warning! Multiple PCMP headers. No checksum set." );
  147. }
  148. if( hits ) {
  149. printf( "\n" );
  150. }
  151. hits = 0;
  152. offset = 0L;
  153. while( (tmp_offset = chksum__pir_get_offset( bios_data, offset )) != -1L ) {
  154. offset = tmp_offset;
  155. cur_val = chksum__pir_get_value( bios_data, offset );
  156. new_val = chksum__pir_calc_value( bios_data, offset );
  157. printf( "\n\n$PIR header at: 0x%4lX\n", offset );
  158. printf( "Current checksum: 0x%02X\n", cur_val );
  159. printf( "Calculated checksum: 0x%02X\n ", new_val );
  160. hits++;
  161. }
  162. if( hits == 1 && cur_val != new_val ) {
  163. printf( "Setting checksum." );
  164. chksum__pir_set_value( bios_data, offset, new_val );
  165. }
  166. if( hits >= 2 ) {
  167. printf( "Warning! Multiple $PIR headers. No checksum set." );
  168. }
  169. if( hits ) {
  170. printf( "\n" );
  171. }
  172. offset = 0L;
  173. offset = chksum_bios_get_offset( bios_data, offset );
  174. cur_val = chksum_bios_get_value( bios_data, offset );
  175. new_val = chksum_bios_calc_value( bios_data, offset );
  176. printf( "\n\nBios checksum at: 0x%4lX\n", offset );
  177. printf( "Current checksum: 0x%02X\n", cur_val );
  178. printf( "Calculated checksum: 0x%02X ", new_val );
  179. if( cur_val != new_val ) {
  180. printf( "Setting checksum." );
  181. chksum_bios_set_value( bios_data, offset, new_val );
  182. }
  183. printf( "\n" );
  184. write_bios:
  185. if ((stream = fopen(argv[arg], "wb")) == NULL) {
  186. printf("Error opening %s for writing.\n", argv[arg]);
  187. exit(EXIT_FAILURE);
  188. }
  189. if (fwrite(bios_data, 1, LEN_BIOS_DATA, stream) < LEN_BIOS_DATA) {
  190. printf("Error writing 64KBytes to %s.\n", argv[arg]);
  191. fclose(stream);
  192. exit(EXIT_FAILURE);
  193. }
  194. fclose(stream);
  195. return(EXIT_SUCCESS);
  196. }
  197. void check(int okay, char* message) {
  198. if (!okay) {
  199. printf("\n\nError. %s.\n", message);
  200. exit(EXIT_FAILURE);
  201. }
  202. }
  203. long chksum_bios_get_offset( byte* data, long offset ) {
  204. return( BIOS_OFFSET );
  205. }
  206. byte chksum_bios_calc_value( byte* data, long offset ) {
  207. int i;
  208. byte sum;
  209. sum = 0;
  210. for( i = 0; i < MAX_OFFSET; i++ ) {
  211. sum = sum + *( data + i );
  212. }
  213. sum = -sum; /* iso ensures -s + s == 0 on unsigned types */
  214. return( sum );
  215. }
  216. byte chksum_bios_get_value( byte* data, long offset ) {
  217. return( *( data + BIOS_OFFSET ) );
  218. }
  219. void chksum_bios_set_value( byte* data, long offset, byte value ) {
  220. *( data + BIOS_OFFSET ) = value;
  221. }
  222. byte chksum__32__calc_value( byte* data, long offset ) {
  223. int i;
  224. int len;
  225. byte sum;
  226. check( offset + _32__MINHDR <= MAX_OFFSET, "_32_ header out of bounds" );
  227. len = *( data + offset + _32__LEN ) << 4;
  228. check( offset + len <= MAX_OFFSET, "_32_ header-length out of bounds" );
  229. sum = 0;
  230. for( i = 0; i < len; i++ ) {
  231. if( i != _32__CHKSUM ) {
  232. sum = sum + *( data + offset + i );
  233. }
  234. }
  235. sum = -sum;
  236. return( sum );
  237. }
  238. long chksum__32__get_offset( byte* data, long offset ) {
  239. long result = -1L;
  240. offset = offset + 0x0F;
  241. offset = offset & ~( 0x0F );
  242. while( offset + 16 < MAX_OFFSET ) {
  243. offset = offset + 16;
  244. if( *( data + offset + 0 ) == '_' && \
  245. *( data + offset + 1 ) == '3' && \
  246. *( data + offset + 2 ) == '2' && \
  247. *( data + offset + 3 ) == '_' ) {
  248. result = offset;
  249. break;
  250. }
  251. }
  252. return( result );
  253. }
  254. byte chksum__32__get_value( byte* data, long offset ) {
  255. check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
  256. return( *( data + offset + _32__CHKSUM ) );
  257. }
  258. void chksum__32__set_value( byte* data, long offset, byte value ) {
  259. check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
  260. *( data + offset + _32__CHKSUM ) = value;
  261. }
  262. byte chksum__mp__calc_value( byte* data, long offset ) {
  263. int i;
  264. int len;
  265. byte sum;
  266. check( offset + _MP__MINHDR <= MAX_OFFSET, "_MP_ header out of bounds" );
  267. len = *( data + offset + _MP__LEN ) << 4;
  268. check( offset + len <= MAX_OFFSET, "_MP_ header-length out of bounds" );
  269. sum = 0;
  270. for( i = 0; i < len; i++ ) {
  271. if( i != _MP__CHKSUM ) {
  272. sum = sum + *( data + offset + i );
  273. }
  274. }
  275. sum = -sum;
  276. return( sum );
  277. }
  278. long chksum__mp__get_offset( byte* data, long offset ) {
  279. long result = -1L;
  280. offset = offset + 0x0F;
  281. offset = offset & ~( 0x0F );
  282. while( offset + 16 < MAX_OFFSET ) {
  283. offset = offset + 16;
  284. if( *( data + offset + 0 ) == '_' && \
  285. *( data + offset + 1 ) == 'M' && \
  286. *( data + offset + 2 ) == 'P' && \
  287. *( data + offset + 3 ) == '_' ) {
  288. result = offset;
  289. break;
  290. }
  291. }
  292. return( result );
  293. }
  294. byte chksum__mp__get_value( byte* data, long offset ) {
  295. check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
  296. return( *( data + offset + _MP__CHKSUM ) );
  297. }
  298. void chksum__mp__set_value( byte* data, long offset, byte value ) {
  299. check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
  300. *( data + offset + _MP__CHKSUM ) = value;
  301. }
  302. byte chksum_pcmp_calc_value( byte* data, long offset ) {
  303. int i;
  304. int len;
  305. byte sum;
  306. check( offset + PCMP_MINHDR <= MAX_OFFSET, "PCMP header out of bounds" );
  307. len = *( data + offset + PCMP_BASELEN ) + \
  308. ( *( data + offset + PCMP_BASELEN + 1 ) << 8 );
  309. check( offset + len <= MAX_OFFSET, "PCMP header-length out of bounds" );
  310. if( *( data + offset + PCMP_EXT_LEN ) | \
  311. *( data + offset + PCMP_EXT_LEN + 1 ) | \
  312. *( data + offset + PCMP_EXT_CHKSUM ) ) {
  313. check( 0, "PCMP header indicates extended tables (unsupported)" );
  314. }
  315. sum = 0;
  316. for( i = 0; i < len; i++ ) {
  317. if( i != PCMP_CHKSUM ) {
  318. sum = sum + *( data + offset + i );
  319. }
  320. }
  321. sum = -sum;
  322. return( sum );
  323. }
  324. long chksum_pcmp_get_offset( byte* data, long offset ) {
  325. long result = -1L;
  326. offset = offset + 0x0F;
  327. offset = offset & ~( 0x0F );
  328. while( offset + 16 < MAX_OFFSET ) {
  329. offset = offset + 16;
  330. if( *( data + offset + 0 ) == 'P' && \
  331. *( data + offset + 1 ) == 'C' && \
  332. *( data + offset + 2 ) == 'M' && \
  333. *( data + offset + 3 ) == 'P' ) {
  334. result = offset;
  335. break;
  336. }
  337. }
  338. return( result );
  339. }
  340. byte chksum_pcmp_get_value( byte* data, long offset ) {
  341. check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
  342. return( *( data + offset + PCMP_CHKSUM ) );
  343. }
  344. void chksum_pcmp_set_value( byte* data, long offset, byte value ) {
  345. check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
  346. *( data + offset + PCMP_CHKSUM ) = value;
  347. }
  348. byte chksum__pir_calc_value( byte* data, long offset ) {
  349. int i;
  350. int len;
  351. byte sum;
  352. check( offset + _PIR_MINHDR <= MAX_OFFSET, "$PIR header out of bounds" );
  353. len = *( data + offset + _PIR_LEN ) + \
  354. ( *( data + offset + _PIR_LEN + 1 ) << 8 );
  355. check( offset + len <= MAX_OFFSET, "$PIR header-length out of bounds" );
  356. sum = 0;
  357. for( i = 0; i < len; i++ ) {
  358. if( i != _PIR_CHKSUM ) {
  359. sum = sum + *( data + offset + i );
  360. }
  361. }
  362. sum = -sum;
  363. return( sum );
  364. }
  365. long chksum__pir_get_offset( byte* data, long offset ) {
  366. long result = -1L;
  367. offset = offset + 0x0F;
  368. offset = offset & ~( 0x0F );
  369. while( offset + 16 < MAX_OFFSET ) {
  370. offset = offset + 16;
  371. if( *( data + offset + 0 ) == '$' && \
  372. *( data + offset + 1 ) == 'P' && \
  373. *( data + offset + 2 ) == 'I' && \
  374. *( data + offset + 3 ) == 'R' ) {
  375. result = offset;
  376. break;
  377. }
  378. }
  379. return( result );
  380. }
  381. byte chksum__pir_get_value( byte* data, long offset ) {
  382. check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
  383. return( *( data + offset + _PIR_CHKSUM ) );
  384. }
  385. void chksum__pir_set_value( byte* data, long offset, byte value ) {
  386. check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
  387. *( data + offset + _PIR_CHKSUM ) = value;
  388. }