bcmalgo.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #include <stdlib.h>
  2. #include <sys/types.h>
  3. #include <stdio.h>
  4. #include <inttypes.h>
  5. #include <string.h>
  6. #include <getopt.h>
  7. #include <unistd.h>
  8. #include <sys/time.h>
  9. #include <sys/stat.h>
  10. #include "bcmalgo.h"
  11. #define UTIL_VERSION "0.1"
  12. #define ENDIAN_REVERSE_NEEDED
  13. uint32_t reverse_endian32 ( uint32_t data )
  14. {
  15. #ifdef ENDIAN_REVERSE_NEEDED
  16. return 0 | ( data & 0x000000ff ) << 24
  17. | ( data & 0x0000ff00 ) << 8
  18. | ( data & 0x00ff0000 ) >> 8
  19. | ( data & 0xff000000 ) >> 24;
  20. #else
  21. return data;
  22. #endif
  23. }
  24. uint16_t reverse_endian16 ( uint16_t data )
  25. {
  26. #ifdef ENDIAN_REVERSE_NEEDED
  27. return 0 | ( data & 0x00ff ) << 8
  28. | ( data & 0xff00 ) >> 8;
  29. #else
  30. return data;
  31. #endif
  32. }
  33. uint32_t get_buffer_crc ( char* filebuffer,size_t size )
  34. {
  35. long crc=0xffffffffL;
  36. long crcxor = 0xffffffffL;
  37. long num4 = 0xffffffffL;
  38. long num5 = size;
  39. long num6 = 0x4c11db7L;
  40. long num7 = 0x80000000L;
  41. int i;
  42. long j;
  43. for ( i = 0; i < ( num5 ); i++ )
  44. {
  45. long num2 = filebuffer[i];
  46. for ( j = 0x80L; j != 0L; j = j >> 1 )
  47. {
  48. long num3 = crc & num7;
  49. crc = crc << 1;
  50. if ( ( num2 & j ) != 0L )
  51. {
  52. num3 ^= num7;
  53. }
  54. if ( num3 != 0L )
  55. {
  56. crc ^= num6;
  57. }
  58. }
  59. }
  60. crc ^= crcxor;
  61. crc &= num4;
  62. uint8_t b1 = ( uint8_t ) ( ( crc & -16777216L ) >> 0x18 );
  63. uint8_t b2 = ( uint8_t ) ( ( crc & 0xff0000L ) >> 0x10 );
  64. uint8_t b3 = ( uint8_t ) ( ( crc & 0xff00L ) >> 8 );
  65. uint8_t b4 = ( uint8_t ) ( crc & 0xffL );
  66. int32_t crc_result = ( b1 | b2 << 8| b3 << 16| b4 <<24 );
  67. return reverse_endian32 ( crc_result );
  68. }
  69. //Thnx to Vector for the algo.
  70. uint32_t get_file_crc ( char* filename )
  71. {
  72. struct stat buf;
  73. stat ( filename,&buf );
  74. char* filebuffer = malloc ( buf.st_size+10 );
  75. FILE* fd = fopen ( filename,"r" );
  76. fread ( filebuffer, 1, buf.st_size,fd );
  77. fclose ( fd );
  78. uint32_t crc = get_buffer_crc ( filebuffer,buf.st_size );
  79. free ( filebuffer );
  80. return crc;
  81. }
  82. uint16_t get_hcs ( ldr_header_t* hd )
  83. {
  84. uint8_t* head = ( uint8_t* ) hd;
  85. uint8_t hcs_minor;
  86. uint8_t hcs_major;
  87. uint16_t n = 0xffff;
  88. uint16_t m = 0;
  89. int state = 0;
  90. int i,j;
  91. for ( i = 0; i < 0x54; i++ )
  92. {
  93. uint16_t m = head[i];
  94. m = m << 8;
  95. for ( j = 0; j < 8; j++ )
  96. {
  97. if ( ( ( n ^ m ) & 0x8000 ) == 0 )
  98. {
  99. state = 0;
  100. }
  101. else
  102. {
  103. state = 1;
  104. }
  105. n = n << 1;
  106. if ( state )
  107. {
  108. n ^= 0x1021;
  109. }
  110. m = m << 1;
  111. }
  112. n &= 0xffff;
  113. }
  114. n ^= 0xffff;
  115. hcs_major = ( uint8_t ) ( ( n & 0xff00 ) >> 8 );
  116. hcs_minor = ( uint8_t ) ( n & 0xff );
  117. uint16_t hcs = hcs_major <<8 | hcs_minor;
  118. return hcs;
  119. }
  120. ldr_header_t* construct_header ( uint32_t magic, uint16_t rev_maj,uint16_t rev_min, uint32_t build_date, uint32_t filelen, uint32_t ldaddress, const char* filename, uint32_t crc_data )
  121. {
  122. ldr_header_t* hd = malloc ( sizeof ( ldr_header_t ) );
  123. hd->magic=reverse_endian16 ( magic );
  124. hd->control=0; //FixMe: Make use of it once compression is around
  125. hd->rev_min = reverse_endian16 ( rev_min );
  126. hd->rev_maj = reverse_endian16 ( rev_maj );
  127. hd->build_date = reverse_endian32 ( build_date );
  128. hd->filelen = reverse_endian32 ( filelen );
  129. hd->ldaddress = reverse_endian32 ( ldaddress );
  130. printf ( "Creating header for %s...\n", filename );
  131. if ( strlen ( filename ) >63 )
  132. {
  133. printf ( "[!] Filename too long - stripping it to 63 bytes.\n" );
  134. strncpy ( ( char* ) &hd->filename, filename, 63 );
  135. hd->filename[63]=0x00;
  136. }
  137. else
  138. {
  139. strcpy ( ( char* ) &hd->filename, filename );
  140. }
  141. hd->crc=reverse_endian32 ( crc_data );
  142. hd->hcs = reverse_endian16 ( get_hcs ( hd ) );
  143. return hd;
  144. }
  145. static char control_unc[] = "Uncompressed";
  146. static char control_lz[] = "LZRW1/KH";
  147. static char control_mlzo[] = "mini-LZO";
  148. static char control_nrv[] = "NRV2D99 [Bootloader?]";
  149. static char control_nstdlzma[] = "(non-standard) LZMA";
  150. static char control_unk[] = "Unknown";
  151. char* get_control_info ( uint16_t control )
  152. {
  153. control = reverse_endian16 ( control );
  154. switch ( control )
  155. {
  156. case 0:
  157. return control_unc;
  158. break;
  159. case 1:
  160. return control_lz;
  161. break;
  162. case 2:
  163. return control_mlzo;
  164. break;
  165. case 3:
  166. return control_unc;
  167. break;
  168. case 4:
  169. return control_nrv;
  170. break;
  171. case 5:
  172. return control_nstdlzma;
  173. break;
  174. case 6:
  175. return control_unc;
  176. break;
  177. case 7:
  178. return control_unc;
  179. break;
  180. default:
  181. return control_unk;
  182. break;
  183. }
  184. }
  185. int dump_header ( ldr_header_t* hd )
  186. {
  187. printf ( "=== Header Information ===\n" );
  188. printf ( "Header magic:\t0x%04X\n",reverse_endian16 ( hd->magic ) );
  189. printf ( "Control:\t0x%04X (%s)\n",reverse_endian16 ( hd->control ), get_control_info ( hd->control ) );
  190. printf ( "Major rev. :\t0x%04X\n",reverse_endian16 ( hd->rev_maj ) );
  191. printf ( "Minor rev. :\t0x%04X\n",reverse_endian16 ( hd->rev_min ) );
  192. printf ( "File name :\t%s\n", ( char* ) &hd->filename );
  193. printf ( "File length:\t%d bytes\n", reverse_endian32 ( hd->filelen ) );
  194. printf ( "Build time:\t0x%08X //FixMe: print in human-readable form\n", reverse_endian32 ( hd->build_date ) ); //FixMe:
  195. printf ( "HCS:\t\t0x%04X ",reverse_endian16 ( hd->hcs ) );
  196. uint16_t hcs = get_hcs ( hd );
  197. int ret=0;
  198. if ( hcs ==reverse_endian16 ( hd->hcs ) )
  199. {
  200. printf ( "(OK!)\n" );
  201. }
  202. else
  203. {
  204. printf ( "(ERROR! expected 0x%04X)\n",hcs );
  205. ret=1;
  206. }
  207. //printf("HCS:\t0x%02X",reverse_endian32(hd->hcs));
  208. printf ( "Load address:\t0x%08X\n", reverse_endian32 ( hd->ldaddress ) ); //FixMe:
  209. printf ( "HNW:\t\t0x%04X\n",reverse_endian16 ( hd->her_znaet_chto ) ); //Hell knows what
  210. printf ( "CRC:\t\t0x%08X\n",reverse_endian32 ( hd->crc ) );
  211. printf ( "=== Binary Header Dump===\n" );
  212. int i,j;
  213. uint8_t* head = ( uint8_t* ) hd;
  214. for ( i=0;i<=sizeof ( ldr_header_t );i++ )
  215. {
  216. if ( i % 8==0 )
  217. printf ( "\n" );
  218. printf ( "0x%02x ",head[i] );
  219. }
  220. printf ( "\n\n== End Of Header dump ==\n" );
  221. return ret;
  222. }
  223. void print_copyright()
  224. {
  225. printf ( "Part of bcm-utils package ver. " UTIL_VERSION " \n" );
  226. printf ( "Copyright (C) 2009 Andrew 'Necromant' Andrianov\n"
  227. "This is free software, and you are welcome to redistribute it\n"
  228. "under certain conditions. See COPYING for details\n" );
  229. }