summaryrefslogtreecommitdiff
path: root/utils/rk27utils/rkboottool
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rk27utils/rkboottool')
-rw-r--r--utils/rk27utils/rkboottool/Makefile7
-rw-r--r--utils/rk27utils/rkboottool/rkboottool.c360
2 files changed, 367 insertions, 0 deletions
diff --git a/utils/rk27utils/rkboottool/Makefile b/utils/rk27utils/rkboottool/Makefile
new file mode 100644
index 0000000000..895dfc87cc
--- /dev/null
+++ b/utils/rk27utils/rkboottool/Makefile
@@ -0,0 +1,7 @@
1all: rkboottool
2
3rkboottool: rkboottool.c
4 gcc -g -std=c99 -o $@ -W -Wall $^
5
6clean:
7 rm -fr rkboottool
diff --git a/utils/rk27utils/rkboottool/rkboottool.c b/utils/rk27utils/rkboottool/rkboottool.c
new file mode 100644
index 0000000000..ad08b0b5f6
--- /dev/null
+++ b/utils/rk27utils/rkboottool/rkboottool.c
@@ -0,0 +1,360 @@
1#include <stdio.h>
2#include <stdint.h>
3#include <stdbool.h>
4#include <stdlib.h>
5#include <string.h>
6
7#define VERSION "v0.3"
8
9/* time field stucture */
10struct rktime_t
11{
12 uint16_t year;
13 uint16_t month;
14 uint16_t day;
15 uint16_t hour;
16 uint16_t minute;
17 uint16_t second;
18};
19
20/* Rock27Boot.bin header structure */
21struct rkboot_info_t
22{
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;
37};
38
39/* actions */
40enum {
41 NONE = 0,
42 INFO = 1,
43 EXTRACT = 2,
44 SCRAMBLE = 4
45};
46
47/* scramble mode */
48enum {
49 CONTINOUS_ENC, /* scramble whole block at once */
50 PAGE_ENC /* nand bootloader is scrambled in 0x200 chunks */
51};
52
53/* scrambling/descrambling reverse engineered by AleMaxx */
54static void encode_page(uint8_t *inpg, uint8_t *outpg, const int size)
55{
56
57uint8_t key[] = {
58 0x7C, 0x4E, 0x03, 0x04,
59 0x55, 0x05, 0x09, 0x07,
60 0x2D, 0x2C, 0x7B, 0x38,
61 0x17, 0x0D, 0x17, 0x11
62};
63 int i, i3, x, val, idx;
64
65 uint8_t key1[0x100];
66 uint8_t key2[0x100];
67
68 for (i=0; i<0x100; i++) {
69 key1[i] = i;
70 key2[i] = key[i&0xf];
71 }
72
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;
81 }
82
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];
93 }
94}
95
96static void *binary_extract(FILE *fp, uint32_t offset, uint32_t len, int descramble, int encode_mode)
97{
98 void *buff, *buff_ptr;
99 uint32_t ret;
100
101 if ((fp == NULL) || len == 0)
102 return NULL;
103
104 /* allocate buff */
105 if ((buff = malloc(len)) == NULL)
106 return NULL;
107
108 /* seek to the begining of the data */
109 fseek(fp, offset, SEEK_SET);
110
111 /* read into the buffer */
112 ret = fread(buff, 1, len, fp);
113
114 if (ret != len)
115 {
116 free(buff);
117 return NULL;
118 }
119
120 /* descramble */
121 if ( descramble )
122 {
123 buff_ptr = buff;
124 if (encode_mode == PAGE_ENC)
125 {
126 while (len >= 0x200)
127 {
128 encode_page((uint8_t *)buff_ptr,
129 (uint8_t *)buff_ptr,
130 0x200);
131
132 buff_ptr += 0x200;
133 len -= 0x200;
134 }
135 }
136 encode_page((uint8_t *)buff_ptr, (uint8_t *)buff_ptr, len);
137 }
138
139 return buff;
140}
141
142static void usage(void)
143{
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");
152}
153
154int main (int argc, char **argv)
155{
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;
162
163 if ( argc < 2 )
164 {
165 usage();
166 return -1;
167 }
168
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");
174
175 /* arguments handling */
176 while (i < argc)
177 {
178 if ((strcmp(argv[i],"-i")==0) || (strcmp(argv[i],"--info")==0))
179 {
180 action |= INFO;
181 }
182 else if ((strcmp(argv[i],"-e")==0) || (strcmp(argv[i],"--extract")==0))
183 {
184 action |= EXTRACT;
185 }
186 else if ((strcmp(argv[i],"-d")==0) || (strcmp(argv[i],"--descramble")==0))
187 {
188 action |= SCRAMBLE;
189 }
190 else if ((strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"--help")==0))
191 {
192 usage();
193 return 0;
194 }
195 else if ( argv[i][0] != '-' )
196 {
197 /* file argument */
198 in_filename = argv[i];
199 }
200 i++;
201 }
202
203 if ( (fp_in = fopen(in_filename, "rb")) == NULL )
204 {
205 fprintf(stderr, "error: can't open %s file for reading\n", in_filename);
206 return -1;
207 }
208
209 ret = fread(&rkboot_info, 1, sizeof(rkboot_info), fp_in);
210
211 if (ret != sizeof(rkboot_info))
212 {
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;
217 }
218
219 if (action & INFO)
220 {
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]);
226
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);
245 }
246
247 if (action & EXTRACT)
248 {
249 /* first stage */
250 buff = binary_extract(fp_in, rkboot_info.s1_offset,
251 rkboot_info.s1_len,
252 action & SCRAMBLE,
253 CONTINOUS_ENC);
254
255 if ( buff == NULL )
256 {
257 fclose(fp_in);
258 fprintf(stderr, "error: can't extract image\n");
259 return -2;
260 }
261
262 /* output */
263 if ((fp_out = fopen("rkboot_s1.bin", "wb")) == NULL)
264 {
265 free(buff);
266 fclose(fp_in);
267 fprintf(stderr, "[error]: can't open rkboot_s1.bin for writing\n");
268 return -3;
269 }
270
271 fwrite(buff, 1, rkboot_info.s1_len, fp_out);
272
273 fprintf(stderr, "[info]: extracted rkboot_s1.bin file\n");
274 free(buff);
275 fclose(fp_out);
276
277 /* second stage */
278 buff = binary_extract(fp_in, rkboot_info.s2_offset,
279 rkboot_info.s2_len,
280 action & SCRAMBLE,
281 CONTINOUS_ENC);
282
283 if ( buff == NULL )
284 {
285 fclose(fp_in);
286 fprintf(stderr, "error: can't extract image\n");
287 return -2;
288 }
289
290 if ((fp_out = fopen("rkboot_s2.bin", "wb")) == NULL)
291 {
292 free(buff);
293 fclose(fp_in);
294 fprintf(stderr, "[error]: can't open rkboot_s2.bin for writing\n");
295 return -4;
296 }
297
298 fwrite(buff, 1, rkboot_info.s2_len, fp_out);
299
300 fprintf(stderr, "[info]: extracted rkboot_s2.bin file\n");
301 free(buff);
302 fclose(fp_out);
303
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 )
310 {
311 fclose(fp_in);
312 fprintf(stderr, "[error]: can't extract image.\n");
313 return -2;
314 }
315
316 if ((fp_out = fopen("rkboot_s3.bin", "wb")) == NULL)
317 {
318 free(buff);
319 fclose(fp_in);
320 fprintf(stderr, "[error]: can't open rkboot_s3.bin for writing\n");
321 return -4;
322 }
323
324 fwrite(buff, 1, rkboot_info.s3_len, fp_out);
325
326 fprintf(stderr, "[info]: extracted rkboot_s3.bin file\n");
327 free(buff);
328 fclose(fp_out);
329
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 )
336 {
337 fclose(fp_in);
338 fprintf(stderr, "[error]: can't extract image\n");
339 return -2;
340 }
341
342 if ((fp_out = fopen("rkboot_s4.bin", "wb")) == NULL)
343 {
344 free(buff);
345 fclose(fp_in);
346 fprintf(stderr, "[error]: can't open rkboot_s4.bin for writing\n");
347 return -4;
348 }
349
350 fwrite(buff, 1, rkboot_info.s4_len, fp_out);
351
352 fprintf(stderr, "[info]: extracted rkboot_s4.bin file\n");
353 free(buff);
354 fclose(fp_out);
355 }
356
357 fclose(fp_in);
358 return 0;
359}
360