11 #define cprintf(col, ...) do {color(col); printf(__VA_ARGS__); }while(0)
15 typedef uint8_t packed_bcd_uint8_t
;
16 typedef uint16_t packed_bcd_uint16_t
;
20 packed_bcd_uint16_t year
;
21 packed_bcd_uint8_t mday
;
22 packed_bcd_uint8_t month
;
25 struct rknano_version_t
27 packed_bcd_uint16_t major
;
28 packed_bcd_uint16_t minor
;
29 packed_bcd_uint16_t rev
;
45 #define VENDOR_NAME_SIZE 32
46 #define MODEL_NAME_SIZE 32
47 #define MAX_NR_STAGES 4
48 #define MAX_NR_FONTS 10
50 #define MAX_NR_STRTBL 10
51 #define MAX_NR_IMAGERES 10
53 #define MAGIC_RKNANOFW "RKnanoFW"
54 #define MAGIC_RKNANOFW_SIZE 8
56 struct rknano_header_t
58 struct rknano_date_t date
;
59 struct rknano_version_t version
;
61 char vendor
[VENDOR_NAME_SIZE
];
62 char model
[MODEL_NAME_SIZE
];
64 struct rknano_blob_t stage
[MAX_NR_STAGES
];
66 struct rknano_blob_t font
[MAX_NR_FONTS
];
68 struct rknano_blob_t gbk
[MAX_NR_GBK
];
70 struct rknano_blob_t strtbl
[MAX_NR_STRTBL
];
72 struct rknano_blob_t imageres
[MAX_NR_IMAGERES
];
74 struct rknano_blob_t unk
[MAX_NR_UNK
];
77 char magic
[MAGIC_RKNANOFW_SIZE
];
80 char *g_out_prefix
= NULL
;
82 static void encode_page(uint8_t *inpg
, uint8_t *outpg
, const int size
)
86 0x7C, 0x4E, 0x03, 0x04,
87 0x55, 0x05, 0x09, 0x07,
88 0x2D, 0x2C, 0x7B, 0x38,
89 0x17, 0x0D, 0x17, 0x11
91 int i
, i3
, x
, val
, idx
;
96 for (i
=0; i
<0x100; i
++) {
102 for (i
=0; i
<0x100; i
++) {
112 for (i
=0; i
<size
; i
++) {
113 x
= key1
[(i
+1) & 0xff];
115 idx
= (x
+ idx
) & 0xff;
116 key1
[(i
+1) & 0xff] = key1
[idx
];
117 key1
[idx
] = (x
& 0xff);
118 val
= (key1
[(i
+1)&0xff] + x
) & 0xff;
120 outpg
[i
] = val
^ inpg
[i
];
124 static uint16_t crc(uint8_t *buf
, int size
)
126 uint16_t result
= 65535;
127 for(; size
; buf
++, size
--)
129 for(int bit
= 128; bit
; bit
>>= 1)
132 result
= (2 * result
) ^ 0x1021;
145 CONTINOUS_ENC
, /* scramble whole block at once */
146 PAGE_ENC
/* nand bootloader is scrambled in 0x200 chunks */
149 static void save_blob(const struct rknano_blob_t
*b
, void *buf
, uint32_t size
,
150 char *name
, int suffix
, int enc_mode
)
152 if(g_out_prefix
== NULL
|| b
->size
== 0 || b
->offset
+ b
->size
> size
)
154 char *path
= malloc(strlen(g_out_prefix
) + strlen(name
) + 32);
156 sprintf(path
, "%s%s%d.bin", g_out_prefix
, name
, suffix
);
158 sprintf(path
, "%s%s.bin", g_out_prefix
, name
);
159 FILE *f
= fopen(path
, "wb");
160 uint8_t *ptr
= buf
+ b
->offset
;
161 if(enc_mode
!= NO_ENC
)
163 ptr
= malloc(b
->size
);
165 uint8_t *buff_ptr
= buf
+ b
->offset
;
166 uint8_t *out_ptr
= ptr
;
167 if(enc_mode
== PAGE_ENC
)
171 encode_page(buff_ptr
, out_ptr
, 0x200);
177 encode_page(buff_ptr
, out_ptr
, len
);
182 fwrite(ptr
, b
->size
, 1, f
);
186 if(enc_mode
!= NO_ENC
)
190 static void print_blob_interval(const struct rknano_blob_t
*b
)
192 cprintf(YELLOW
, "%#x -> %#x", b
->offset
, b
->offset
+ b
->size
);
195 static int do_nanofw_image(uint8_t *buf
, unsigned long size
)
197 if(size
< sizeof(struct rknano_header_t
))
199 struct rknano_header_t
*hdr
= (void *)buf
;
202 if(strncmp(hdr
->magic
, MAGIC_RKNANOFW
, MAGIC_RKNANOFW_SIZE
))
205 cprintf(BLUE
, "Header\n");
206 cprintf(GREEN
, " Date: ");
207 cprintf(YELLOW
, "%x/%x/%x\n", hdr
->date
.mday
, hdr
->date
.month
, hdr
->date
.year
);
208 cprintf(GREEN
, " Version: ");
209 cprintf(YELLOW
, "%x.%x.%x\n", hdr
->version
.major
, hdr
->version
.minor
, hdr
->version
.rev
);
210 cprintf(GREEN
, " Vendor: ");
211 cprintf(YELLOW
, "%s\n", hdr
->vendor
);
212 cprintf(GREEN
, " Model: ");
213 cprintf(YELLOW
, "%s\n", hdr
->model
);
214 cprintf(GREEN
, " Pad: ");
215 for(int i
= 0; i
< 6; i
++)
216 cprintf(YELLOW
, " %02x", hdr
->unk6
[i
]);
217 cprintf(YELLOW
, "\n");
218 cprintf(BLUE
, "Stages\n");
219 for(unsigned i
= 0; i
< hdr
->nr_stages
; i
++)
221 cprintf(GREEN
, " %i: ", i
);
222 print_blob_interval(&hdr
->stage
[i
]);
224 save_blob(&hdr
->stage
[i
], buf
, size
, "stage", i
, NO_ENC
);
226 cprintf(BLUE
, "Fonts\n");
227 for(unsigned i
= 0; i
< hdr
->nr_fonts
; i
++)
229 cprintf(GREEN
, " %i: ", i
);
230 print_blob_interval(&hdr
->font
[i
]);
232 save_blob(&hdr
->font
[i
], buf
, size
, "font", i
, NO_ENC
);
234 cprintf(BLUE
, "GBK\n");
235 for(unsigned i
= 0; i
< hdr
->nr_gbk
; i
++)
237 cprintf(GREEN
, " %i: ", i
);
238 print_blob_interval(&hdr
->gbk
[i
]);
240 save_blob(&hdr
->gbk
[i
], buf
, size
, "gbk", i
, NO_ENC
);
242 cprintf(BLUE
, "String Tables\n");
243 for(unsigned i
= 0; i
< hdr
->nr_strtbl
; i
++)
245 cprintf(GREEN
, " %i: ", i
);
246 print_blob_interval(&hdr
->strtbl
[i
]);
248 save_blob(&hdr
->strtbl
[i
], buf
, size
, "strtbl", i
, NO_ENC
);
250 cprintf(BLUE
, "Image Resources\n");
251 for(unsigned i
= 0; i
< hdr
->nr_imageres
; i
++)
253 cprintf(GREEN
, " %i: ", i
);
254 print_blob_interval(&hdr
->imageres
[i
]);
256 save_blob(&hdr
->imageres
[i
], buf
, size
, "imgres", i
, NO_ENC
);
258 cprintf(BLUE
, "Unknown\n");
259 for(unsigned i
= 0; i
< hdr
->nr_unk
; i
++)
261 cprintf(GREEN
, " %i: ", i
);
262 print_blob_interval(&hdr
->unk
[i
]);
264 save_blob(&hdr
->unk
[i
], buf
, size
, "unk", i
, NO_ENC
);
266 cprintf(BLUE
, "Other\n");
267 cprintf(GREEN
, " Size: ");
268 cprintf(YELLOW
, "%#x\n", hdr
->size
);
269 cprintf(GREEN
, " Magic: ");
270 cprintf(YELLOW
, "%." STR(MAGIC_RKNANOFW_SIZE
) "s ", hdr
->magic
);
271 if(strncmp(hdr
->magic
, MAGIC_RKNANOFW
, MAGIC_RKNANOFW_SIZE
) == 0)
272 cprintf(RED
, "OK\n");
274 cprintf(RED
, "Mismatch\n");
279 struct rknano_stage_header_t
283 } __attribute__((packed
));
286 * The [code_pa,code_pa+code_sz[ and [data_pa,data_pa+data_sz[ ranges
287 * are consistent: they never overlap and have no gaps and fill the
288 * entire space. Furthermore they match the code sequences so it's
289 * reasonable to assume these fields are correct.
290 * The other fields are still quite unsure. */
292 struct rknano_stage_section_t
302 } __attribute__((packed
));
304 static void elf_printf(void *user
, bool error
, const char *fmt
, ...)
306 if(!g_debug
&& !error
)
315 static void elf_write(void *user
, uint32_t addr
, const void *buf
, size_t count
)
318 fseek(f
, addr
, SEEK_SET
);
319 fwrite(buf
, count
, 1, f
);
322 static void extract_elf_section(struct elf_params_t
*elf
, int count
)
324 if(g_out_prefix
== NULL
)
326 char *filename
= xmalloc(strlen(g_out_prefix
) + 32);
327 sprintf(filename
, "%s%d.elf", g_out_prefix
, count
);
329 printf("Write entry %d to %s\n", count
, filename
);
331 FILE *fd
= fopen(filename
, "wb");
336 elf_write_file(elf
, elf_write
, elf_printf
, fd
);
340 static int do_nanostage_image(uint8_t *buf
, unsigned long size
)
342 if(size
< sizeof(struct rknano_stage_section_t
))
344 struct rknano_stage_header_t
*hdr
= (void *)buf
;
346 cprintf(BLUE
, "Header\n");
347 cprintf(GREEN
, " Base Address: ");
348 cprintf(YELLOW
, "%#08x\n", hdr
->addr
);
349 cprintf(GREEN
, " Load count: ");
350 cprintf(YELLOW
, "%d\n", hdr
->count
);
352 struct rknano_stage_section_t
*sec
= (void *)(hdr
+ 1);
354 for(unsigned i
= 0; i
< hdr
->count
; i
++, sec
++)
356 cprintf(BLUE
, "Section %d\n", i
);
357 cprintf(GREEN
, " Code: ");
358 cprintf(YELLOW
, "0x%08x", sec
->code_pa
);
359 cprintf(RED
, "-(txt)-");
360 cprintf(YELLOW
, "0x%08x", sec
->code_pa
+ sec
->code_sz
);
361 cprintf(BLUE
, " |--> ");
362 cprintf(YELLOW
, "0x%08x", sec
->code_va
);
363 cprintf(RED
, "-(txt)-");
364 cprintf(YELLOW
, "0x%08x\n", sec
->code_va
+ sec
->code_sz
);
366 cprintf(GREEN
, " Data: ");
367 cprintf(YELLOW
, "0x%08x", sec
->data_pa
);
368 cprintf(RED
, "-(dat)-");
369 cprintf(YELLOW
, "0x%08x", sec
->data_pa
+ sec
->data_sz
);
370 cprintf(BLUE
, " |--> ");
371 cprintf(YELLOW
, "0x%08x", sec
->data_va
);
372 cprintf(RED
, "-(dat)-");
373 cprintf(YELLOW
, "0x%08x\n", sec
->data_va
+ sec
->data_sz
);
375 cprintf(GREEN
, " Data: ");
377 cprintf(BLUE
, " |--> ");
378 cprintf(YELLOW
, "0x%08x", sec
->bss_va
);
379 cprintf(RED
, "-(bss)-");
380 cprintf(YELLOW
, "0x%08x\n", sec
->bss_va
+ sec
->bss_sz
);
383 struct rknano_blob_t blob
;
384 blob
.offset
= sec
->code_pa
- hdr
->addr
;
385 blob
.size
= sec
->code_sz
;
386 save_blob(&blob
, buf
, size
, "entry.", i
, NO_ENC
);
388 struct elf_params_t elf
;
390 elf_add_load_section(&elf
, sec
->code_va
, sec
->code_sz
, buf
+ sec
->code_pa
- hdr
->addr
);
391 elf_add_load_section(&elf
, sec
->data_va
, sec
->data_sz
, buf
+ sec
->data_pa
- hdr
->addr
);
392 elf_add_fill_section(&elf
, sec
->bss_va
, sec
->bss_sz
, 0);
393 extract_elf_section(&elf
, i
);
401 #define MAGIC_BOOT "BOOT"
402 #define MAGIC_BOOT_SIZE 4
404 struct rknano_boot_desc_t
409 } __attribute__((packed
));
411 struct rknano_boot_header_t
413 char magic
[MAGIC_BOOT_SIZE
];
424 struct rknano_boot_desc_t desc_1
;
425 struct rknano_boot_desc_t desc_2
;
426 struct rknano_boot_desc_t desc_4
;
429 } __attribute__((packed
));
431 struct rknano_boot_entry_t
433 uint8_t entry_size
; // unsure
439 } __attribute__((packed
));
441 uint32_t boot_crc_table
[256] =
443 0x00000000, 0x04C10DB7, 0x09821B6E, 0x0D4316D9,
444 0x130436DC, 0x17C53B6B, 0x1A862DB2, 0x1E472005,
445 0x26086DB8, 0x22C9600F, 0x2F8A76D6, 0x2B4B7B61,
446 0x350C5B64, 0x31CD56D3, 0x3C8E400A, 0x384F4DBD,
447 0x4C10DB70, 0x48D1D6C7, 0x4592C01E, 0x4153CDA9,
448 0x5F14EDAC, 0x5BD5E01B, 0x5696F6C2, 0x5257FB75,
449 0x6A18B6C8, 0x6ED9BB7F, 0x639AADA6, 0x675BA011,
450 0x791C8014, 0x7DDD8DA3, 0x709E9B7A, 0x745F96CD,
451 0x9821B6E0, 0x9CE0BB57, 0x91A3AD8E, 0x9562A039,
452 0x8B25803C, 0x8FE48D8B, 0x82A79B52, 0x866696E5,
453 0xBE29DB58, 0xBAE8D6EF, 0xB7ABC036, 0xB36ACD81,
454 0xAD2DED84, 0xA9ECE033, 0xA4AFF6EA, 0xA06EFB5D,
455 0xD4316D90, 0xD0F06027, 0xDDB376FE, 0xD9727B49,
456 0xC7355B4C, 0xC3F456FB, 0xCEB74022, 0xCA764D95,
457 0xF2390028, 0xF6F80D9F, 0xFBBB1B46, 0xFF7A16F1,
458 0xE13D36F4, 0xE5FC3B43, 0xE8BF2D9A, 0xEC7E202D,
459 0x34826077, 0x30436DC0, 0x3D007B19, 0x39C176AE,
460 0x278656AB, 0x23475B1C, 0x2E044DC5, 0x2AC54072,
461 0x128A0DCF, 0x164B0078, 0x1B0816A1, 0x1FC91B16,
462 0x018E3B13, 0x054F36A4, 0x080C207D, 0x0CCD2DCA,
463 0x7892BB07, 0x7C53B6B0, 0x7110A069, 0x75D1ADDE,
464 0x6B968DDB, 0x6F57806C, 0x621496B5, 0x66D59B02,
465 0x5E9AD6BF, 0x5A5BDB08, 0x5718CDD1, 0x53D9C066,
466 0x4D9EE063, 0x495FEDD4, 0x441CFB0D, 0x40DDF6BA,
467 0xACA3D697, 0xA862DB20, 0xA521CDF9, 0xA1E0C04E,
468 0xBFA7E04B, 0xBB66EDFC, 0xB625FB25, 0xB2E4F692,
469 0x8AABBB2F, 0x8E6AB698, 0x8329A041, 0x87E8ADF6,
470 0x99AF8DF3, 0x9D6E8044, 0x902D969D, 0x94EC9B2A,
471 0xE0B30DE7, 0xE4720050, 0xE9311689, 0xEDF01B3E,
472 0xF3B73B3B, 0xF776368C, 0xFA352055, 0xFEF42DE2,
473 0xC6BB605F, 0xC27A6DE8, 0xCF397B31, 0xCBF87686,
474 0xD5BF5683, 0xD17E5B34, 0xDC3D4DED, 0xD8FC405A,
475 0x6904C0EE, 0x6DC5CD59, 0x6086DB80, 0x6447D637,
476 0x7A00F632, 0x7EC1FB85, 0x7382ED5C, 0x7743E0EB,
477 0x4F0CAD56, 0x4BCDA0E1, 0x468EB638, 0x424FBB8F,
478 0x5C089B8A, 0x58C9963D, 0x558A80E4, 0x514B8D53,
479 0x25141B9E, 0x21D51629, 0x2C9600F0, 0x28570D47,
480 0x36102D42, 0x32D120F5, 0x3F92362C, 0x3B533B9B,
481 0x031C7626, 0x07DD7B91, 0x0A9E6D48, 0x0E5F60FF,
482 0x101840FA, 0x14D94D4D, 0x199A5B94, 0x1D5B5623,
483 0xF125760E, 0xF5E47BB9, 0xF8A76D60, 0xFC6660D7,
484 0xE22140D2, 0xE6E04D65, 0xEBA35BBC, 0xEF62560B,
485 0xD72D1BB6, 0xD3EC1601, 0xDEAF00D8, 0xDA6E0D6F,
486 0xC4292D6A, 0xC0E820DD, 0xCDAB3604, 0xC96A3BB3,
487 0xBD35AD7E, 0xB9F4A0C9, 0xB4B7B610, 0xB076BBA7,
488 0xAE319BA2, 0xAAF09615, 0xA7B380CC, 0xA3728D7B,
489 0x9B3DC0C6, 0x9FFCCD71, 0x92BFDBA8, 0x967ED61F,
490 0x8839F61A, 0x8CF8FBAD, 0x81BBED74, 0x857AE0C3,
491 0x5D86A099, 0x5947AD2E, 0x5404BBF7, 0x50C5B640,
492 0x4E829645, 0x4A439BF2, 0x47008D2B, 0x43C1809C,
493 0x7B8ECD21, 0x7F4FC096, 0x720CD64F, 0x76CDDBF8,
494 0x688AFBFD, 0x6C4BF64A, 0x6108E093, 0x65C9ED24,
495 0x11967BE9, 0x1557765E, 0x18146087, 0x1CD56D30,
496 0x02924D35, 0x06534082, 0x0B10565B, 0x0FD15BEC,
497 0x379E1651, 0x335F1BE6, 0x3E1C0D3F, 0x3ADD0088,
498 0x249A208D, 0x205B2D3A, 0x2D183BE3, 0x29D93654,
499 0xC5A71679, 0xC1661BCE, 0xCC250D17, 0xC8E400A0,
500 0xD6A320A5, 0xD2622D12, 0xDF213BCB, 0xDBE0367C,
501 0xE3AF7BC1, 0xE76E7676, 0xEA2D60AF, 0xEEEC6D18,
502 0xF0AB4D1D, 0xF46A40AA, 0xF9295673, 0xFDE85BC4,
503 0x89B7CD09, 0x8D76C0BE, 0x8035D667, 0x84F4DBD0,
504 0x9AB3FBD5, 0x9E72F662, 0x9331E0BB, 0x97F0ED0C,
505 0xAFBFA0B1, 0xAB7EAD06, 0xA63DBBDF, 0xA2FCB668,
506 0xBCBB966D, 0xB87A9BDA, 0xB5398D03, 0xB1F880B4,
509 static uint32_t boot_crc(uint8_t *buf
, int size
)
512 for(int i
= 0; i
< size
; i
++)
513 crc
= boot_crc_table
[buf
[i
] ^ (crc
>> 24)] ^ (crc
<< 8);
517 wchar_t *from_uni16(uint16_t *str
)
519 static wchar_t buffer
[64];
529 static int do_boot_desc(uint8_t *buf
, unsigned long size
,
530 struct rknano_boot_desc_t
*desc
, int desc_idx
)
534 cprintf(BLUE
, "Desc %d\n", desc_idx
);
535 cprintf(GREEN
, " Count: "); cprintf(YELLOW
, "%d\n", desc
->count
);
536 cprintf(GREEN
, " Offset: "); cprintf(YELLOW
, "%#x\n", desc
->offset
);
537 cprintf(GREEN
, " Stride: "); cprintf(YELLOW
, "%#x ", desc
->stride
);
538 if(desc
->stride
< sizeof(struct rknano_boot_entry_t
))
539 cprintf(RED
, "(too small <%#lx)\n", sizeof(struct rknano_boot_entry_t
));
541 cprintf(RED
, "(OK >=%#lx)\n", sizeof(struct rknano_boot_entry_t
));
543 for(int i
= 0; i
< desc
->count
; i
++)
545 struct rknano_boot_entry_t
*entry
= (void *)(buf
+ desc
->offset
+ i
* desc
->stride
);
546 cprintf(BLUE
, " Entry %d\n", i
);
547 cprintf(GREEN
, " Entry size: "); cprintf(YELLOW
, "%#x ", entry
->entry_size
);
548 if(desc
->stride
< sizeof(struct rknano_boot_entry_t
))
549 cprintf(RED
, "(too small <%#lx)\n", sizeof(struct rknano_boot_entry_t
));
551 cprintf(RED
, "(OK >=%#lx)\n", sizeof(struct rknano_boot_entry_t
));
552 cprintf(GREEN
, " Unk: "); cprintf(YELLOW
, "%#x\n", entry
->unk
);
553 cprintf(GREEN
, " Name: "); cprintf(YELLOW
, "%S\n", from_uni16(entry
->name
));
554 cprintf(GREEN
, " Offset: "); cprintf(YELLOW
, "%#x\n", entry
->offset
);
555 cprintf(GREEN
, " Size: "); cprintf(YELLOW
, "%#x\n", entry
->size
);
556 cprintf(GREEN
, " Sthg 2: "); cprintf(YELLOW
, "%#x\n", entry
->sthg2
);
558 struct rknano_blob_t blob
;
559 blob
.offset
= entry
->offset
;
560 blob
.size
= entry
->size
;
562 sprintf(name
, "%d.%S", desc_idx
, from_uni16(entry
->name
));
563 save_blob(&blob
, buf
, size
, name
, -1, PAGE_ENC
);
569 static int do_boot_image(uint8_t *buf
, unsigned long size
)
571 if(size
< sizeof(struct rknano_boot_header_t
))
573 struct rknano_boot_header_t
*hdr
= (void *)buf
;
574 if(strncmp(hdr
->magic
, MAGIC_BOOT
, MAGIC_BOOT_SIZE
))
577 cprintf(BLUE
, "Header\n");
578 cprintf(GREEN
, " Magic: ");
579 cprintf(YELLOW
, "%." STR(MAGIC_BOOT_SIZE
) "s ", hdr
->magic
);
580 if(strncmp(hdr
->magic
, MAGIC_BOOT
, MAGIC_BOOT_SIZE
) == 0)
581 cprintf(RED
, "OK\n");
583 cprintf(RED
, "Mismatch\n");
585 cprintf(GREEN
, " Header Size: ");
586 cprintf(YELLOW
, "%#x ", hdr
->hdr_size
);
587 if(hdr
->hdr_size
>= sizeof(struct rknano_boot_header_t
))
588 cprintf(RED
, "OK\n");
590 cprintf(RED
, "Mismatch\n");
592 #define print(str, name) cprintf(GREEN, " "str": ");cprintf(YELLOW, "%#x\n", (unsigned)hdr->name)
593 #define print_arr(str, name, sz) \
594 cprintf(GREEN, " "str":");for(int i = 0; i < sz; i++)cprintf(YELLOW, " %#x", (unsigned)hdr->name[i]);printf("\n")
596 cprintf(GREEN
, " Version: ");
597 cprintf(YELLOW
, "%x.%x.%x\n", (hdr
->version
>> 24) & 0xff,
598 (hdr
->version
>> 16) & 0xff, hdr
->version
& 0xffff);
600 cprintf(GREEN
, " Date: ");
601 cprintf(YELLOW
, "%d/%d/%d %02d:%02d:%02d\n", hdr
->day
, hdr
->month
, hdr
->year
,
602 hdr
->hour
, hdr
->minute
, hdr
->second
);
604 cprintf(GREEN
, " Chip: ");
605 cprintf(YELLOW
, "%#x\n", hdr
->chip
);
607 print_arr("field_2A", field_2B
, 9);
608 print("field_34", field_34
);
610 do_boot_desc(buf
, size
, &hdr
->desc_1
, 1);
611 do_boot_desc(buf
, size
, &hdr
->desc_2
, 2);
612 do_boot_desc(buf
, size
, &hdr
->desc_4
, 4);
614 cprintf(BLUE
, "Variable Header:\n");
615 cprintf(GREEN
, " Value: ");
616 cprintf(YELLOW
, "%#lx\n", *(unsigned long *)((uint8_t *)hdr
+ hdr
->field_34
- 10));
618 /* The last 4 bytes are a 32-bit CRC */
619 cprintf(BLUE
, "Post Header:\n");
620 cprintf(GREEN
, " CRC: ");
621 uint32_t crc
= *(uint32_t *)(buf
+ size
- 4);
622 uint32_t ccrc
= boot_crc(buf
, size
- 4);
623 cprintf(YELLOW
, "%08x ", crc
);
625 cprintf(RED
, "OK\n");
627 cprintf(RED
, "Mismatch\n");
632 typedef struct rknano_blob_t rkfw_blob_t
;
634 #define MAGIC_RKFW "RKFW"
635 #define MAGIC_RKFW_SIZE 4
639 char magic
[MAGIC_RKFW_SIZE
];
640 uint16_t hdr_size
; // UNSURE
653 } __attribute__((packed
));
655 static int do_rkfw_image(uint8_t *buf
, unsigned long size
)
657 if(size
< sizeof(struct rkfw_header_t
))
659 struct rkfw_header_t
*hdr
= (void *)buf
;
660 if(strncmp(hdr
->magic
, MAGIC_RKFW
, MAGIC_RKFW_SIZE
))
663 cprintf(BLUE
, "Header\n");
664 cprintf(GREEN
, " Magic: ");
665 cprintf(YELLOW
, "%." STR(MAGIC_RKFW_SIZE
) "s ", hdr
->magic
);
666 if(strncmp(hdr
->magic
, MAGIC_RKFW
, MAGIC_RKFW_SIZE
) == 0)
667 cprintf(RED
, "OK\n");
669 cprintf(RED
, "Mismatch\n");
671 cprintf(GREEN
, " Header size: ");
672 cprintf(YELLOW
, " %#x ", hdr
->hdr_size
);
673 if(hdr
->hdr_size
== sizeof(struct rkfw_header_t
))
674 cprintf(RED
, "OK\n");
676 cprintf(RED
, "Mismatch\n");
677 cprintf(GREEN
, " Version: ");
678 cprintf(YELLOW
, "%x.%x.%x\n", (hdr
->version
>> 24) & 0xff,
679 (hdr
->version
>> 16) & 0xff, hdr
->version
& 0xffff);
681 cprintf(GREEN
, " Code: ");
682 cprintf(YELLOW
, "%#x\n", hdr
->code
);
684 cprintf(GREEN
, " Date: ");
685 cprintf(YELLOW
, "%d/%d/%d %02d:%02d:%02d\n", hdr
->day
, hdr
->month
, hdr
->year
,
686 hdr
->hour
, hdr
->minute
, hdr
->second
);
688 cprintf(GREEN
, " Chip: ");
689 cprintf(YELLOW
, "%#x\n", hdr
->chip
);
691 cprintf(GREEN
, " Loader: ");
692 print_blob_interval(&hdr
->loader
);
694 save_blob(&hdr
->loader
, buf
, size
, "loader", 0, NO_ENC
);
696 cprintf(GREEN
, " Update: ");
697 print_blob_interval(&hdr
->update
);
699 save_blob(&hdr
->update
, buf
, size
, "update", 0, NO_ENC
);
701 print_arr("pad", pad
, 61);
706 static int do_rkencode_image(uint8_t *buf
, unsigned long size
)
708 void *ptr
= malloc(size
);
710 uint8_t *buff_ptr
= buf
;
711 uint8_t *out_ptr
= ptr
;
712 int enc_mode
= PAGE_ENC
;
713 if(enc_mode
== PAGE_ENC
)
717 encode_page(buff_ptr
, out_ptr
, 0x200);
723 encode_page(buff_ptr
, out_ptr
, len
);
727 FILE *f
= fopen(g_out_prefix
, "wb");
730 fwrite(buff_ptr
, 1, size
, f
);
734 printf("Cannot open output file: %m\n");
741 static void usage(void)
743 printf("Usage: rkboottool [options] rknanoboot.bin\n");
744 printf("Options:\n");
745 printf(" --rkfw\tUnpack a rkfw file\n");
746 printf(" --rknanofw\tUnpack a regular RknanoFW file\n");
747 printf(" --rkboot\tUnpack a BOOT file\n");
748 printf(" --rknanostage\tUnpack a RknanoFW stage file\n");
749 printf(" --rkencode\tEncode a raw file\n");
750 printf(" -o <prefix>\tSet output prefix\n");
751 printf("The default is to try to guess the format.\n");
752 printf("If several formats are specified, all are tried.\n");
756 int main(int argc
, char **argv
)
758 bool try_nanofw
= false;
759 bool try_rkfw
= false;
760 bool try_boot
= false;
761 bool try_nanostage
= false;
762 bool try_rkencode
= false;
766 static struct option long_options
[] =
768 {"help", no_argument
, 0, '?'},
769 {"debug", no_argument
, 0, 'd'},
770 {"rkfw", no_argument
, 0, '9'},
771 {"rknanofw", no_argument
, 0, 'n'},
772 {"rknanostage", no_argument
, 0, 's'},
773 {"rkencode", no_argument
, 0, 'e'},
774 {"rkboot", no_argument
, 0, 'b'},
775 {"no-color", no_argument
, 0, 'c'},
779 int c
= getopt_long(argc
, argv
, "?d9nscbeo:", long_options
, NULL
);
802 g_out_prefix
= optarg
;
808 try_nanostage
= true;
814 printf("Invalid argument '%c'\n", c
);
819 if(argc
- optind
!= 1)
825 if(!try_nanostage
&& !try_rkfw
&& !try_nanofw
&& !try_boot
&& !try_rkencode
)
826 try_nanostage
= try_rkfw
= try_nanofw
= try_boot
= true;
828 FILE *fin
= fopen(argv
[optind
], "r");
831 perror("Cannot open boot file");
834 fseek(fin
, 0, SEEK_END
);
835 long size
= ftell(fin
);
836 fseek(fin
, 0, SEEK_SET
);
838 void *buf
= malloc(size
);
841 perror("Cannot allocate memory");
845 if(fread(buf
, size
, 1, fin
) != 1)
847 perror("Cannot read file");
853 if(try_nanofw
&& !do_nanofw_image(buf
, size
))
855 if(try_rkfw
&& !do_rkfw_image(buf
, size
))
857 if(try_boot
&& !do_boot_image(buf
, size
))
859 if(try_nanostage
&& !do_nanostage_image(buf
, size
))
861 if(try_rkencode
&& !do_rkencode_image(buf
, size
))
863 cprintf(GREY
, "No valid format found!\n");