summaryrefslogtreecommitdiff
path: root/utils/rknanoutils/rkboottool
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rknanoutils/rkboottool')
-rw-r--r--utils/rknanoutils/rkboottool/rkboottool.c295
1 files changed, 280 insertions, 15 deletions
diff --git a/utils/rknanoutils/rkboottool/rkboottool.c b/utils/rknanoutils/rkboottool/rkboottool.c
index e41224065d..f1e0e97f69 100644
--- a/utils/rknanoutils/rkboottool/rkboottool.c
+++ b/utils/rknanoutils/rkboottool/rkboottool.c
@@ -3,9 +3,12 @@
3#include <stdbool.h> 3#include <stdbool.h>
4#include <stdlib.h> 4#include <stdlib.h>
5#include <string.h> 5#include <string.h>
6#include <getopt.h>
6#include "misc.h" 7#include "misc.h"
7 8
8#define cprintf(col, ...) do {printf("%s", col); printf(__VA_ARGS__); }while(0) 9#define cprintf(col, ...) do {color(col); printf(__VA_ARGS__); }while(0)
10
11bool g_debug = false;
9 12
10typedef uint8_t packed_bcd_uint8_t; 13typedef uint8_t packed_bcd_uint8_t;
11typedef uint16_t packed_bcd_uint16_t; 14typedef uint16_t packed_bcd_uint16_t;
@@ -72,7 +75,7 @@ struct rknano_header_t
72 char magic[MAGIC_RKNANOFW_SIZE]; 75 char magic[MAGIC_RKNANOFW_SIZE];
73}; 76};
74 77
75char *prefix = NULL; 78char *g_out_prefix = NULL;
76 79
77static void encode_page(uint8_t *inpg, uint8_t *outpg, const int size) 80static void encode_page(uint8_t *inpg, uint8_t *outpg, const int size)
78{ 81{
@@ -137,10 +140,10 @@ static uint16_t crc(uint8_t *buf, int size)
137static void save_blob(const struct rknano_blob_t *b, void *buf, uint32_t size, 140static void save_blob(const struct rknano_blob_t *b, void *buf, uint32_t size,
138 char *name, int suffix, bool descramble) 141 char *name, int suffix, bool descramble)
139{ 142{
140 if(prefix == NULL || b->size == 0 || b->offset + b->size > size) 143 if(g_out_prefix == NULL || b->size == 0 || b->offset + b->size > size)
141 return; 144 return;
142 char *path = malloc(strlen(prefix) + strlen(name) + 32); 145 char *path = malloc(strlen(g_out_prefix) + strlen(name) + 32);
143 sprintf(path, "%s%s%d.bin", prefix, name, suffix); 146 sprintf(path, "%s%s%d.bin", g_out_prefix, name, suffix);
144 FILE *f = fopen(path, "wb"); 147 FILE *f = fopen(path, "wb");
145 uint8_t *ptr = buf + b->offset; 148 uint8_t *ptr = buf + b->offset;
146 if(descramble) 149 if(descramble)
@@ -164,16 +167,15 @@ static void print_blob_interval(const struct rknano_blob_t *b)
164 cprintf(YELLOW, "%#x -> %#x", b->offset, b->offset + b->size); 167 cprintf(YELLOW, "%#x -> %#x", b->offset, b->offset + b->size);
165} 168}
166 169
167static int do_image(int argc, char **argv, uint8_t *buf, unsigned long size) 170static int do_nanofw_image(uint8_t *buf, unsigned long size)
168{ 171{
169 (void) argc;
170 (void) argv;
171
172 if(size < sizeof(struct rknano_header_t)) 172 if(size < sizeof(struct rknano_header_t))
173 return 1; 173 return 1;
174 struct rknano_header_t *hdr = (void *)buf; 174 struct rknano_header_t *hdr = (void *)buf;
175 if(size < hdr->size) 175 if(size < hdr->size)
176 return 1; 176 return 1;
177 if(strncmp(hdr->magic, MAGIC_RKNANOFW, MAGIC_RKNANOFW_SIZE))
178 return 1;
177 179
178 cprintf(BLUE, "Header\n"); 180 cprintf(BLUE, "Header\n");
179 cprintf(GREEN, " Date: "); 181 cprintf(GREEN, " Date: ");
@@ -249,18 +251,269 @@ static int do_image(int argc, char **argv, uint8_t *buf, unsigned long size)
249 return 0; 251 return 0;
250} 252}
251 253
254struct rknano_stage_header_t
255{
256 uint32_t addr;
257} __attribute__((packed));
258
259struct rknano_stage_section_t
260{
261 uint32_t a;
262 uint32_t code_pa;
263 uint32_t code_va;
264 uint32_t code_sz;
265 uint32_t data_pa;
266 uint32_t data_va;
267 uint32_t data_sz;
268 uint32_t bss_end_va;
269} __attribute__((packed));
270
271static int do_nanostage_image(uint8_t *buf, unsigned long size)
272{
273 if(size < sizeof(struct rknano_stage_section_t))
274 return 1;
275 struct rknano_stage_header_t *hdr = (void *)buf;
276
277 cprintf(BLUE, "Header\n");
278 cprintf(GREEN, " Base Address: ");
279 cprintf(YELLOW, "%#x\n", hdr->addr);
280
281 struct rknano_stage_section_t *sec = (void *)(hdr + 1);
282 void *end = buf + size;
283
284 int i = 0;
285 while((void *)sec < end && (sec->code_sz || sec->bss_end_va))
286 {
287 cprintf(BLUE, "Section %d\n", i);
288 cprintf(GREEN, " Something: ");
289 cprintf(YELLOW, "%#x\n", sec->a);
290 cprintf(GREEN, " Code: ");
291 cprintf(YELLOW, "%#x", sec->code_pa);
292 cprintf(BLUE, " |--> ");
293 cprintf(YELLOW, "%#x", sec->code_va);
294 cprintf(RED, "-(code)-");
295 cprintf(YELLOW, "%#x\n", sec->code_va + sec->code_sz);
296
297 cprintf(GREEN, " Data: ");
298 cprintf(YELLOW, "%#x", sec->data_pa);
299 cprintf(BLUE, " |--> ");
300 cprintf(YELLOW, "%#x", sec->data_va);
301 cprintf(RED, "-(data)-");
302 cprintf(YELLOW, "%#x", sec->data_va + sec->data_sz);
303 cprintf(RED, "-(bss)-");
304 cprintf(YELLOW, "%#x\n", sec->bss_end_va);
305
306 sec++;
307 i++;
308 }
309
310 return 0;
311}
312
313#define MAGIC_BOOT "BOOT"
314#define MAGIC_BOOT_SIZE 4
315
316struct rknano_boot_header_t
317{
318 char magic[MAGIC_BOOT_SIZE];
319 uint16_t field_4;
320 uint32_t field_6;
321 uint32_t field_A;
322 uint16_t field_E;
323 uint8_t field_10[5];
324 uint32_t field_15;
325 uint8_t field_19;
326 uint32_t field_1A;
327 uint8_t field_1E[2];
328 uint32_t field_20;
329 uint8_t field_24[2];
330 uint32_t field_26;
331 uint8_t field_2A[10];
332 uint32_t field_34;
333} __attribute__((packed));
334
335static int do_boot_image(uint8_t *buf, unsigned long size)
336{
337 if(sizeof(struct rknano_boot_header_t) != 0x38)
338 printf("aie");
339 if(size < sizeof(struct rknano_boot_header_t))
340 return 1;
341 struct rknano_boot_header_t *hdr = (void *)buf;
342 if(strncmp(hdr->magic, MAGIC_BOOT, MAGIC_BOOT_SIZE))
343 return 1;
344
345 cprintf(BLUE, "Header\n");
346 cprintf(GREEN, " Magic: ");
347 cprintf(YELLOW, "%." STR(MAGIC_BOOT_SIZE) "s ", hdr->magic);
348 if(strncmp(hdr->magic, MAGIC_BOOT, MAGIC_BOOT_SIZE) == 0)
349 cprintf(RED, "OK\n");
350 else
351 cprintf(RED, "Mismatch\n");
352#define print(str, name) cprintf(GREEN, " "str": ");cprintf(YELLOW, "%#x\n", (unsigned)hdr->name)
353#define print_arr(str, name, sz) \
354 cprintf(GREEN, " "str":");for(int i = 0; i < sz; i++)cprintf(YELLOW, " %#x", (unsigned)hdr->name[i]);printf("\n")
355
356 print("field_4", field_4);
357 print("field_6", field_6);
358 print("field_A", field_A);
359 print("field_E", field_E);
360 print_arr("field_10", field_10, 5);
361 print("field_15", field_15);
362 print("field_19", field_19);
363 print("field_1A", field_1A);
364 print_arr("field_1E", field_1E, 2);
365 print("field_20", field_20);
366 print_arr("field_24", field_24, 2);
367 print("field_26", field_26);
368 print_arr("field_2A", field_2A, 10);
369 print("field_34", field_34);
370 cprintf(GREEN, "Value: ");
371 cprintf(YELLOW, "%#x\n", *(unsigned long *)((uint8_t *)hdr + hdr->field_34 - 10));
372
373 return 0;
374}
375
376typedef struct rknano_blob_t rkfw_blob_t;
377
378#define MAGIC_RKFW "RKFW"
379#define MAGIC_RKFW_SIZE 4
380
381struct rkfw_header_t
382{
383 char magic[MAGIC_RKFW_SIZE];
384 uint16_t hdr_size; // UNSURE
385 uint32_t field_6;
386 uint32_t field_A;
387 uint16_t field_E;
388 uint8_t field_10[5];
389 uint32_t field_15;
390 rkfw_blob_t loader;
391 rkfw_blob_t update;
392 uint8_t pad[60];
393 uint8_t field_65;
394} __attribute__((packed));
395
396static int do_rkfw_image(uint8_t *buf, unsigned long size)
397{
398 if(sizeof(struct rkfw_header_t) != 0x66)
399 printf("aie");
400 if(size < sizeof(struct rkfw_header_t))
401 return 1;
402 struct rkfw_header_t *hdr = (void *)buf;
403 if(strncmp(hdr->magic, MAGIC_RKFW, MAGIC_RKFW_SIZE))
404 return 1;
405
406 cprintf(BLUE, "Header\n");
407 cprintf(GREEN, " Magic: ");
408 cprintf(YELLOW, "%." STR(MAGIC_RKFW_SIZE) "s ", hdr->magic);
409 if(strncmp(hdr->magic, MAGIC_RKFW, MAGIC_RKFW_SIZE) == 0)
410 cprintf(RED, "OK\n");
411 else
412 cprintf(RED, "Mismatch\n");
413
414 cprintf(GREEN, " Loader: ");
415 print_blob_interval(&hdr->loader);
416 cprintf(OFF, "\n");
417 save_blob(&hdr->loader, buf, size, "loader", 0, false);
418
419 cprintf(GREEN, " Update: ");
420 print_blob_interval(&hdr->update);
421 cprintf(OFF, "\n");
422 save_blob(&hdr->update, buf, size, "update", 0, false);
423
424 print("hdr_size", hdr_size);
425 print("field_6", field_6);
426 print("field_A", field_A);
427 print("field_E", field_E);
428 print_arr("field_10", field_10, 5);
429 print("field_15", field_15);
430 print_arr("pad", pad, 60);
431 print("field_65", field_65);
432
433 return 0;
434}
435
252static void usage(void) 436static void usage(void)
253{ 437{
254 printf("Usage: rkboottool [options] rknanoboot.bin out_prefix\n"); 438 printf("Usage: rkboottool [options] rknanoboot.bin\n");
439 printf("Options:\n");
440 printf(" --rkfw\tUnpack a rkfw file\n");
441 printf(" --rknanofw\tUnpack a regular RknanoFW file\n");
442 printf(" --rkboot\tUnpack a BOOT file\n");
443 printf(" --rknanostage\tUnpack a RknanoFW stage file\n");
444 printf(" -o <prefix>\tSet output prefix\n");
445 printf("The default is to try to guess the format.\n");
446 printf("If several formats are specified, all are tried.\n");
255 exit(1); 447 exit(1);
256} 448}
257 449
258int main(int argc, char **argv) 450int main(int argc, char **argv)
259{ 451{
260 if(argc < 3) 452 bool try_nanofw = false;
453 bool try_rkfw = false;
454 bool try_boot = false;
455 bool try_nanostage = false;
456
457 while(1)
458 {
459 static struct option long_options[] =
460 {
461 {"help", no_argument, 0, '?'},
462 {"debug", no_argument, 0, 'd'},
463 {"rkfw", no_argument, 0, '9'},
464 {"rknanofw", no_argument, 0, 'n'},
465 {"rknanostage", no_argument, 0, 's'},
466 {"rkboot", no_argument, 0, 'b'},
467 {"no-color", no_argument, 0, 'c'},
468 {0, 0, 0, 0}
469 };
470
471 int c = getopt_long(argc, argv, "?d9nscbo:", long_options, NULL);
472 if(c == -1)
473 break;
474 switch(c)
475 {
476 case -1:
477 break;
478 case 'c':
479 enable_color(false);
480 break;
481 case 'b':
482 try_boot = true;
483 break;
484 case 'n':
485 try_nanofw = true;
486 break;
487 case 'd':
488 g_debug = true;
489 break;
490 case '?':
491 usage();
492 break;
493 case 'o':
494 g_out_prefix = optarg;
495 break;
496 case '9':
497 try_rkfw = true;
498 break;
499 case 's':
500 try_nanostage = true;
501 break;
502 default:
503 abort();
504 }
505 }
506
507 if(argc - optind != 1)
508 {
261 usage(); 509 usage();
262 prefix = argv[argc - 1]; 510 return 1;
263 FILE *fin = fopen(argv[argc - 2], "r"); 511 }
512
513 if(!try_nanostage && !try_rkfw && !try_nanofw && !try_boot)
514 try_nanostage = try_rkfw = try_nanofw = try_boot = true;
515
516 FILE *fin = fopen(argv[optind], "r");
264 if(fin == NULL) 517 if(fin == NULL)
265 { 518 {
266 perror("Cannot open boot file"); 519 perror("Cannot open boot file");
@@ -284,7 +537,19 @@ int main(int argc, char **argv)
284 } 537 }
285 538
286 fclose(fin); 539 fclose(fin);
287 540
288 return do_image(argc - 1, argv, buf, size); 541 if(try_nanofw && !do_nanofw_image(buf, size))
542 goto Lsuccess;
543 if(try_rkfw && !do_rkfw_image(buf, size))
544 goto Lsuccess;
545 if(try_boot && !do_boot_image(buf, size))
546 goto Lsuccess;
547 if(try_nanostage && !do_nanostage_image(buf, size))
548 goto Lsuccess;
549 cprintf(GREY, "No valid format found!\n");
550 Lsuccess:
551 free(buf);
552
553 return 0;
289} 554}
290 555