Fix FS#12824 : Malfunctioning FFT plugin in Sansa Clip Zip
[maemo-rb.git] / utils / rk27utils / rkboottool / rkboottool.c
blobad08b0b5f699a240b5bb153f7f42f2e4e7ddf944
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <stdbool.h>
4 #include <stdlib.h>
5 #include <string.h>
7 #define VERSION "v0.3"
9 /* time field stucture */
10 struct rktime_t
12 uint16_t year;
13 uint16_t month;
14 uint16_t day;
15 uint16_t hour;
16 uint16_t minute;
17 uint16_t second;
20 /* Rock27Boot.bin header structure */
21 struct rkboot_info_t
23 char sign[32];
24 uint8_t check_values[16];
25 struct rktime_t time;
26 uint32_t ui_master_version;
27 uint32_t ui_slave_version;
28 uint32_t s1_offset;
29 int32_t s1_len;
30 uint32_t s2_offset;
31 int32_t s2_len;
32 uint32_t s3_offset;
33 int32_t s3_len;
34 uint32_t s4_offset;
35 int32_t s4_len;
36 uint32_t version_flag;
39 /* actions */
40 enum {
41 NONE = 0,
42 INFO = 1,
43 EXTRACT = 2,
44 SCRAMBLE = 4
47 /* scramble mode */
48 enum {
49 CONTINOUS_ENC, /* scramble whole block at once */
50 PAGE_ENC /* nand bootloader is scrambled in 0x200 chunks */
53 /* scrambling/descrambling reverse engineered by AleMaxx */
54 static void encode_page(uint8_t *inpg, uint8_t *outpg, const int size)
57 uint8_t key[] = {
58 0x7C, 0x4E, 0x03, 0x04,
59 0x55, 0x05, 0x09, 0x07,
60 0x2D, 0x2C, 0x7B, 0x38,
61 0x17, 0x0D, 0x17, 0x11
63 int i, i3, x, val, idx;
65 uint8_t key1[0x100];
66 uint8_t key2[0x100];
68 for (i=0; i<0x100; i++) {
69 key1[i] = i;
70 key2[i] = key[i&0xf];
73 i3 = 0;
74 for (i=0; i<0x100; i++) {
75 x = key1[i];
76 i3 = key1[i] + i3;
77 i3 += key2[i];
78 i3 &= 0xff;
79 key1[i] = key1[i3];
80 key1[i3] = x;
83 idx = 0;
84 for (i=0; i<size; i++) {
85 x = key1[(i+1) & 0xff];
86 val = x;
87 idx = (x + idx) & 0xff;
88 key1[(i+1) & 0xff] = key1[idx];
89 key1[idx] = (x & 0xff);
90 val = (key1[(i+1)&0xff] + x) & 0xff;
91 val = key1[val];
92 outpg[i] = val ^ inpg[i];
96 static void *binary_extract(FILE *fp, uint32_t offset, uint32_t len, int descramble, int encode_mode)
98 void *buff, *buff_ptr;
99 uint32_t ret;
101 if ((fp == NULL) || len == 0)
102 return NULL;
104 /* allocate buff */
105 if ((buff = malloc(len)) == NULL)
106 return NULL;
108 /* seek to the begining of the data */
109 fseek(fp, offset, SEEK_SET);
111 /* read into the buffer */
112 ret = fread(buff, 1, len, fp);
114 if (ret != len)
116 free(buff);
117 return NULL;
120 /* descramble */
121 if ( descramble )
123 buff_ptr = buff;
124 if (encode_mode == PAGE_ENC)
126 while (len >= 0x200)
128 encode_page((uint8_t *)buff_ptr,
129 (uint8_t *)buff_ptr,
130 0x200);
132 buff_ptr += 0x200;
133 len -= 0x200;
136 encode_page((uint8_t *)buff_ptr, (uint8_t *)buff_ptr, len);
139 return buff;
142 static void usage(void)
144 printf("Usage: rkboottool [options] Rock27Boot.bin\n");
145 printf("-h|--help This help message\n");
146 printf("-e|--extract Extract binary images from Rock27Boot.bin file\n");
147 printf("-d|--descramble Descramble extracted binary images\n");
148 printf("-i|--info Print info about Rock27Boot.bin file\n");
149 printf("\n");
150 printf("Usually you would like to use -d -e together to obtain raw binary\n");
151 printf("(out files rkboot_s1.bin, rkboot_s2.bin, rkboot_s3.bin, rkboot_s4.bin)\n");
154 int main (int argc, char **argv)
156 struct rkboot_info_t rkboot_info;
157 FILE *fp_in, *fp_out;
158 int32_t i = 0, action = NONE;
159 int32_t ret;
160 void *buff;
161 char *in_filename = NULL;
163 if ( argc < 2 )
165 usage();
166 return -1;
169 /* print banner */
170 fprintf(stderr,"rkboottool " VERSION "\n");
171 fprintf(stderr,"(C) Marcin Bukat 2011\n");
172 fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n");
173 fprintf(stderr,"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
175 /* arguments handling */
176 while (i < argc)
178 if ((strcmp(argv[i],"-i")==0) || (strcmp(argv[i],"--info")==0))
180 action |= INFO;
182 else if ((strcmp(argv[i],"-e")==0) || (strcmp(argv[i],"--extract")==0))
184 action |= EXTRACT;
186 else if ((strcmp(argv[i],"-d")==0) || (strcmp(argv[i],"--descramble")==0))
188 action |= SCRAMBLE;
190 else if ((strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"--help")==0))
192 usage();
193 return 0;
195 else if ( argv[i][0] != '-' )
197 /* file argument */
198 in_filename = argv[i];
200 i++;
203 if ( (fp_in = fopen(in_filename, "rb")) == NULL )
205 fprintf(stderr, "error: can't open %s file for reading\n", in_filename);
206 return -1;
209 ret = fread(&rkboot_info, 1, sizeof(rkboot_info), fp_in);
211 if (ret != sizeof(rkboot_info))
213 fclose(fp_in);
214 fprintf(stderr, "error: can't read %s file header\n", in_filename);
215 fprintf(stderr, "read %d, expected %d\n", ret, sizeof(rkboot_info));
216 return -2;
219 if (action & INFO)
221 printf("file: %s\n", in_filename);
222 printf("signature: %s\n", rkboot_info.sign);
223 printf("check bytes: ");
224 for (i = 0; i < 16; i++)
225 printf("0x%0x ", rkboot_info.check_values[i]);
227 printf("\n");
228 printf("timestamp %d.%d.%d %d:%d:%d\n", rkboot_info.time.day,
229 rkboot_info.time.month,
230 rkboot_info.time.year,
231 rkboot_info.time.hour,
232 rkboot_info.time.minute,
233 rkboot_info.time.second);
234 printf("UI master version: 0x%0x\n", rkboot_info.ui_master_version);
235 printf("UI slave version: 0x%0x\n", rkboot_info.ui_slave_version);
236 printf("s1 data offset: 0x%0x\n", rkboot_info.s1_offset);
237 printf("s1 data len: 0x%0x\n", rkboot_info.s1_len);
238 printf("s2 offset: 0x%0x\n", rkboot_info.s2_offset);
239 printf("s2 len: 0x%0x\n", rkboot_info.s2_len);
240 printf("s3 offset: 0x%0x\n", rkboot_info.s3_offset);
241 printf("s3 len: 0x%0x\n", rkboot_info.s3_len);
242 printf("s4 offset: 0x%0x\n", rkboot_info.s4_offset);
243 printf("s4 len: 0x%0x\n", rkboot_info.s4_len);
244 printf("UI version flag: 0x%0x\n", rkboot_info.version_flag);
247 if (action & EXTRACT)
249 /* first stage */
250 buff = binary_extract(fp_in, rkboot_info.s1_offset,
251 rkboot_info.s1_len,
252 action & SCRAMBLE,
253 CONTINOUS_ENC);
255 if ( buff == NULL )
257 fclose(fp_in);
258 fprintf(stderr, "error: can't extract image\n");
259 return -2;
262 /* output */
263 if ((fp_out = fopen("rkboot_s1.bin", "wb")) == NULL)
265 free(buff);
266 fclose(fp_in);
267 fprintf(stderr, "[error]: can't open rkboot_s1.bin for writing\n");
268 return -3;
271 fwrite(buff, 1, rkboot_info.s1_len, fp_out);
273 fprintf(stderr, "[info]: extracted rkboot_s1.bin file\n");
274 free(buff);
275 fclose(fp_out);
277 /* second stage */
278 buff = binary_extract(fp_in, rkboot_info.s2_offset,
279 rkboot_info.s2_len,
280 action & SCRAMBLE,
281 CONTINOUS_ENC);
283 if ( buff == NULL )
285 fclose(fp_in);
286 fprintf(stderr, "error: can't extract image\n");
287 return -2;
290 if ((fp_out = fopen("rkboot_s2.bin", "wb")) == NULL)
292 free(buff);
293 fclose(fp_in);
294 fprintf(stderr, "[error]: can't open rkboot_s2.bin for writing\n");
295 return -4;
298 fwrite(buff, 1, rkboot_info.s2_len, fp_out);
300 fprintf(stderr, "[info]: extracted rkboot_s2.bin file\n");
301 free(buff);
302 fclose(fp_out);
304 /* third stage */
305 buff = binary_extract(fp_in, rkboot_info.s3_offset,
306 rkboot_info.s3_len,
307 action & SCRAMBLE,
308 PAGE_ENC);
309 if ( buff == NULL )
311 fclose(fp_in);
312 fprintf(stderr, "[error]: can't extract image.\n");
313 return -2;
316 if ((fp_out = fopen("rkboot_s3.bin", "wb")) == NULL)
318 free(buff);
319 fclose(fp_in);
320 fprintf(stderr, "[error]: can't open rkboot_s3.bin for writing\n");
321 return -4;
324 fwrite(buff, 1, rkboot_info.s3_len, fp_out);
326 fprintf(stderr, "[info]: extracted rkboot_s3.bin file\n");
327 free(buff);
328 fclose(fp_out);
330 /* forth stage */
331 buff = binary_extract(fp_in, rkboot_info.s4_offset,
332 rkboot_info.s4_len,
333 action & SCRAMBLE,
334 CONTINOUS_ENC);
335 if ( buff == NULL )
337 fclose(fp_in);
338 fprintf(stderr, "[error]: can't extract image\n");
339 return -2;
342 if ((fp_out = fopen("rkboot_s4.bin", "wb")) == NULL)
344 free(buff);
345 fclose(fp_in);
346 fprintf(stderr, "[error]: can't open rkboot_s4.bin for writing\n");
347 return -4;
350 fwrite(buff, 1, rkboot_info.s4_len, fp_out);
352 fprintf(stderr, "[info]: extracted rkboot_s4.bin file\n");
353 free(buff);
354 fclose(fp_out);
357 fclose(fp_in);
358 return 0;