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