summaryrefslogtreecommitdiff
path: root/utils/rknanoutils/rkboottool/rkboottool.c
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-06-19 15:39:43 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2012-06-19 15:42:16 +0200
commitd6bbe39dc6ea7b8460c2fd0d5cf83ec076b035f2 (patch)
treed292f855539ce085c6fae73b8ac77177941ad55f /utils/rknanoutils/rkboottool/rkboottool.c
parente5d6e42e0b29170a596e03942a46ed4ad1fefd23 (diff)
downloadrockbox-d6bbe39dc6ea7b8460c2fd0d5cf83ec076b035f2.tar.gz
rockbox-d6bbe39dc6ea7b8460c2fd0d5cf83ec076b035f2.zip
rknanoutils: more reverse engineering of the BOOT format.
I found out that the file has a number of "entries", in 3 categories. The third category seem to contain bootable files. In the RKnano firmware file I have, these entries are named "NandBoot1" and "NandBoot2". They seem to use the same format as the stage3 of the RKnanoFW format but we do not understand this format precisely for now anyway. Change-Id: I72d77e609cdeeb802af793c010d6788bf36cd7e2
Diffstat (limited to 'utils/rknanoutils/rkboottool/rkboottool.c')
-rw-r--r--utils/rknanoutils/rkboottool/rkboottool.c229
1 files changed, 201 insertions, 28 deletions
diff --git a/utils/rknanoutils/rkboottool/rkboottool.c b/utils/rknanoutils/rkboottool/rkboottool.c
index f1e0e97f69..f913b12377 100644
--- a/utils/rknanoutils/rkboottool/rkboottool.c
+++ b/utils/rknanoutils/rkboottool/rkboottool.c
@@ -137,8 +137,15 @@ static uint16_t crc(uint8_t *buf, int size)
137 return result; 137 return result;
138} 138}
139 139
140/* scramble mode */
141enum {
142 NO_ENC,
143 CONTINOUS_ENC, /* scramble whole block at once */
144 PAGE_ENC /* nand bootloader is scrambled in 0x200 chunks */
145};
146
140static void save_blob(const struct rknano_blob_t *b, void *buf, uint32_t size, 147static void save_blob(const struct rknano_blob_t *b, void *buf, uint32_t size,
141 char *name, int suffix, bool descramble) 148 char *name, int suffix, int enc_mode)
142{ 149{
143 if(g_out_prefix == NULL || b->size == 0 || b->offset + b->size > size) 150 if(g_out_prefix == NULL || b->size == 0 || b->offset + b->size > size)
144 return; 151 return;
@@ -146,10 +153,23 @@ static void save_blob(const struct rknano_blob_t *b, void *buf, uint32_t size,
146 sprintf(path, "%s%s%d.bin", g_out_prefix, name, suffix); 153 sprintf(path, "%s%s%d.bin", g_out_prefix, name, suffix);
147 FILE *f = fopen(path, "wb"); 154 FILE *f = fopen(path, "wb");
148 uint8_t *ptr = buf + b->offset; 155 uint8_t *ptr = buf + b->offset;
149 if(descramble) 156 if(enc_mode != NO_ENC)
150 { 157 {
151 ptr = malloc(b->size); 158 ptr = malloc(b->size);
152 encode_page(buf + b->offset, ptr, b->size); 159 int len = b->size;
160 uint8_t *buff_ptr = buf + b->offset;
161 uint8_t *out_ptr = ptr;
162 if(enc_mode == PAGE_ENC)
163 {
164 while(len >= 0x200)
165 {
166 encode_page(buff_ptr, out_ptr, 0x200);
167 buff_ptr += 0x200;
168 out_ptr += 0x200;
169 len -= 0x200;
170 }
171 }
172 encode_page(buff_ptr, out_ptr, len);
153 } 173 }
154 174
155 if(f) 175 if(f)
@@ -158,7 +178,7 @@ static void save_blob(const struct rknano_blob_t *b, void *buf, uint32_t size,
158 fclose(f); 178 fclose(f);
159 } 179 }
160 180
161 if(descramble) 181 if(enc_mode != NO_ENC)
162 free(ptr); 182 free(ptr);
163} 183}
164 184
@@ -196,7 +216,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
196 cprintf(GREEN, " %i: ", i); 216 cprintf(GREEN, " %i: ", i);
197 print_blob_interval(&hdr->stage[i]); 217 print_blob_interval(&hdr->stage[i]);
198 cprintf(OFF, "\n"); 218 cprintf(OFF, "\n");
199 save_blob(&hdr->stage[i], buf, size, "stage", i, false); 219 save_blob(&hdr->stage[i], buf, size, "stage", i, NO_ENC);
200 } 220 }
201 cprintf(BLUE, "Fonts\n"); 221 cprintf(BLUE, "Fonts\n");
202 for(unsigned i = 0; i < hdr->nr_fonts; i++) 222 for(unsigned i = 0; i < hdr->nr_fonts; i++)
@@ -204,7 +224,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
204 cprintf(GREEN, " %i: ", i); 224 cprintf(GREEN, " %i: ", i);
205 print_blob_interval(&hdr->font[i]); 225 print_blob_interval(&hdr->font[i]);
206 cprintf(OFF, "\n"); 226 cprintf(OFF, "\n");
207 save_blob(&hdr->font[i], buf, size, "font", i, false); 227 save_blob(&hdr->font[i], buf, size, "font", i, NO_ENC);
208 } 228 }
209 cprintf(BLUE, "GBK\n"); 229 cprintf(BLUE, "GBK\n");
210 for(unsigned i = 0; i < hdr->nr_gbk; i++) 230 for(unsigned i = 0; i < hdr->nr_gbk; i++)
@@ -212,7 +232,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
212 cprintf(GREEN, " %i: ", i); 232 cprintf(GREEN, " %i: ", i);
213 print_blob_interval(&hdr->gbk[i]); 233 print_blob_interval(&hdr->gbk[i]);
214 cprintf(OFF, "\n"); 234 cprintf(OFF, "\n");
215 save_blob(&hdr->gbk[i], buf, size, "gbk", i, false); 235 save_blob(&hdr->gbk[i], buf, size, "gbk", i, NO_ENC);
216 } 236 }
217 cprintf(BLUE, "String Tables\n"); 237 cprintf(BLUE, "String Tables\n");
218 for(unsigned i = 0; i < hdr->nr_strtbl; i++) 238 for(unsigned i = 0; i < hdr->nr_strtbl; i++)
@@ -220,7 +240,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
220 cprintf(GREEN, " %i: ", i); 240 cprintf(GREEN, " %i: ", i);
221 print_blob_interval(&hdr->strtbl[i]); 241 print_blob_interval(&hdr->strtbl[i]);
222 cprintf(OFF, "\n"); 242 cprintf(OFF, "\n");
223 save_blob(&hdr->strtbl[i], buf, size, "strtbl", i, false); 243 save_blob(&hdr->strtbl[i], buf, size, "strtbl", i, NO_ENC);
224 } 244 }
225 cprintf(BLUE, "Image Resources\n"); 245 cprintf(BLUE, "Image Resources\n");
226 for(unsigned i = 0; i < hdr->nr_imageres; i++) 246 for(unsigned i = 0; i < hdr->nr_imageres; i++)
@@ -228,7 +248,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
228 cprintf(GREEN, " %i: ", i); 248 cprintf(GREEN, " %i: ", i);
229 print_blob_interval(&hdr->imageres[i]); 249 print_blob_interval(&hdr->imageres[i]);
230 cprintf(OFF, "\n"); 250 cprintf(OFF, "\n");
231 save_blob(&hdr->imageres[i], buf, size, "imgres", i, false); 251 save_blob(&hdr->imageres[i], buf, size, "imgres", i, NO_ENC);
232 } 252 }
233 cprintf(BLUE, "Unknown\n"); 253 cprintf(BLUE, "Unknown\n");
234 for(unsigned i = 0; i < hdr->nr_unk; i++) 254 for(unsigned i = 0; i < hdr->nr_unk; i++)
@@ -236,7 +256,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
236 cprintf(GREEN, " %i: ", i); 256 cprintf(GREEN, " %i: ", i);
237 print_blob_interval(&hdr->unk[i]); 257 print_blob_interval(&hdr->unk[i]);
238 cprintf(OFF, "\n"); 258 cprintf(OFF, "\n");
239 save_blob(&hdr->unk[i], buf, size, "unk", i, false); 259 save_blob(&hdr->unk[i], buf, size, "unk", i, NO_ENC);
240 } 260 }
241 cprintf(BLUE, "Other\n"); 261 cprintf(BLUE, "Other\n");
242 cprintf(GREEN, " Size: "); 262 cprintf(GREEN, " Size: ");
@@ -313,6 +333,13 @@ static int do_nanostage_image(uint8_t *buf, unsigned long size)
313#define MAGIC_BOOT "BOOT" 333#define MAGIC_BOOT "BOOT"
314#define MAGIC_BOOT_SIZE 4 334#define MAGIC_BOOT_SIZE 4
315 335
336struct rknano_boot_desc_t
337{
338 uint8_t count;
339 uint32_t offset;
340 uint8_t stride;
341} __attribute__((packed));
342
316struct rknano_boot_header_t 343struct rknano_boot_header_t
317{ 344{
318 char magic[MAGIC_BOOT_SIZE]; 345 char magic[MAGIC_BOOT_SIZE];
@@ -322,16 +349,151 @@ struct rknano_boot_header_t
322 uint16_t field_E; 349 uint16_t field_E;
323 uint8_t field_10[5]; 350 uint8_t field_10[5];
324 uint32_t field_15; 351 uint32_t field_15;
325 uint8_t field_19; 352 struct rknano_boot_desc_t desc_1;
326 uint32_t field_1A; 353 struct rknano_boot_desc_t desc_2;
327 uint8_t field_1E[2]; 354 struct rknano_boot_desc_t desc_4;
328 uint32_t field_20; 355 uint8_t field_2B[9];
329 uint8_t field_24[2];
330 uint32_t field_26;
331 uint8_t field_2A[10];
332 uint32_t field_34; 356 uint32_t field_34;
333} __attribute__((packed)); 357} __attribute__((packed));
334 358
359struct rknano_boot_entry_t
360{
361 uint8_t entry_size; // unsure
362 uint32_t unk;
363 uint16_t name[20];
364 uint32_t offset;
365 uint32_t size;
366 uint32_t sthg2;
367} __attribute__((packed));
368
369uint32_t boot_crc_table[256] =
370{
371 0x00000000, 0x04C10DB7, 0x09821B6E, 0x0D4316D9,
372 0x130436DC, 0x17C53B6B, 0x1A862DB2, 0x1E472005,
373 0x26086DB8, 0x22C9600F, 0x2F8A76D6, 0x2B4B7B61,
374 0x350C5B64, 0x31CD56D3, 0x3C8E400A, 0x384F4DBD,
375 0x4C10DB70, 0x48D1D6C7, 0x4592C01E, 0x4153CDA9,
376 0x5F14EDAC, 0x5BD5E01B, 0x5696F6C2, 0x5257FB75,
377 0x6A18B6C8, 0x6ED9BB7F, 0x639AADA6, 0x675BA011,
378 0x791C8014, 0x7DDD8DA3, 0x709E9B7A, 0x745F96CD,
379 0x9821B6E0, 0x9CE0BB57, 0x91A3AD8E, 0x9562A039,
380 0x8B25803C, 0x8FE48D8B, 0x82A79B52, 0x866696E5,
381 0xBE29DB58, 0xBAE8D6EF, 0xB7ABC036, 0xB36ACD81,
382 0xAD2DED84, 0xA9ECE033, 0xA4AFF6EA, 0xA06EFB5D,
383 0xD4316D90, 0xD0F06027, 0xDDB376FE, 0xD9727B49,
384 0xC7355B4C, 0xC3F456FB, 0xCEB74022, 0xCA764D95,
385 0xF2390028, 0xF6F80D9F, 0xFBBB1B46, 0xFF7A16F1,
386 0xE13D36F4, 0xE5FC3B43, 0xE8BF2D9A, 0xEC7E202D,
387 0x34826077, 0x30436DC0, 0x3D007B19, 0x39C176AE,
388 0x278656AB, 0x23475B1C, 0x2E044DC5, 0x2AC54072,
389 0x128A0DCF, 0x164B0078, 0x1B0816A1, 0x1FC91B16,
390 0x018E3B13, 0x054F36A4, 0x080C207D, 0x0CCD2DCA,
391 0x7892BB07, 0x7C53B6B0, 0x7110A069, 0x75D1ADDE,
392 0x6B968DDB, 0x6F57806C, 0x621496B5, 0x66D59B02,
393 0x5E9AD6BF, 0x5A5BDB08, 0x5718CDD1, 0x53D9C066,
394 0x4D9EE063, 0x495FEDD4, 0x441CFB0D, 0x40DDF6BA,
395 0xACA3D697, 0xA862DB20, 0xA521CDF9, 0xA1E0C04E,
396 0xBFA7E04B, 0xBB66EDFC, 0xB625FB25, 0xB2E4F692,
397 0x8AABBB2F, 0x8E6AB698, 0x8329A041, 0x87E8ADF6,
398 0x99AF8DF3, 0x9D6E8044, 0x902D969D, 0x94EC9B2A,
399 0xE0B30DE7, 0xE4720050, 0xE9311689, 0xEDF01B3E,
400 0xF3B73B3B, 0xF776368C, 0xFA352055, 0xFEF42DE2,
401 0xC6BB605F, 0xC27A6DE8, 0xCF397B31, 0xCBF87686,
402 0xD5BF5683, 0xD17E5B34, 0xDC3D4DED, 0xD8FC405A,
403 0x6904C0EE, 0x6DC5CD59, 0x6086DB80, 0x6447D637,
404 0x7A00F632, 0x7EC1FB85, 0x7382ED5C, 0x7743E0EB,
405 0x4F0CAD56, 0x4BCDA0E1, 0x468EB638, 0x424FBB8F,
406 0x5C089B8A, 0x58C9963D, 0x558A80E4, 0x514B8D53,
407 0x25141B9E, 0x21D51629, 0x2C9600F0, 0x28570D47,
408 0x36102D42, 0x32D120F5, 0x3F92362C, 0x3B533B9B,
409 0x031C7626, 0x07DD7B91, 0x0A9E6D48, 0x0E5F60FF,
410 0x101840FA, 0x14D94D4D, 0x199A5B94, 0x1D5B5623,
411 0xF125760E, 0xF5E47BB9, 0xF8A76D60, 0xFC6660D7,
412 0xE22140D2, 0xE6E04D65, 0xEBA35BBC, 0xEF62560B,
413 0xD72D1BB6, 0xD3EC1601, 0xDEAF00D8, 0xDA6E0D6F,
414 0xC4292D6A, 0xC0E820DD, 0xCDAB3604, 0xC96A3BB3,
415 0xBD35AD7E, 0xB9F4A0C9, 0xB4B7B610, 0xB076BBA7,
416 0xAE319BA2, 0xAAF09615, 0xA7B380CC, 0xA3728D7B,
417 0x9B3DC0C6, 0x9FFCCD71, 0x92BFDBA8, 0x967ED61F,
418 0x8839F61A, 0x8CF8FBAD, 0x81BBED74, 0x857AE0C3,
419 0x5D86A099, 0x5947AD2E, 0x5404BBF7, 0x50C5B640,
420 0x4E829645, 0x4A439BF2, 0x47008D2B, 0x43C1809C,
421 0x7B8ECD21, 0x7F4FC096, 0x720CD64F, 0x76CDDBF8,
422 0x688AFBFD, 0x6C4BF64A, 0x6108E093, 0x65C9ED24,
423 0x11967BE9, 0x1557765E, 0x18146087, 0x1CD56D30,
424 0x02924D35, 0x06534082, 0x0B10565B, 0x0FD15BEC,
425 0x379E1651, 0x335F1BE6, 0x3E1C0D3F, 0x3ADD0088,
426 0x249A208D, 0x205B2D3A, 0x2D183BE3, 0x29D93654,
427 0xC5A71679, 0xC1661BCE, 0xCC250D17, 0xC8E400A0,
428 0xD6A320A5, 0xD2622D12, 0xDF213BCB, 0xDBE0367C,
429 0xE3AF7BC1, 0xE76E7676, 0xEA2D60AF, 0xEEEC6D18,
430 0xF0AB4D1D, 0xF46A40AA, 0xF9295673, 0xFDE85BC4,
431 0x89B7CD09, 0x8D76C0BE, 0x8035D667, 0x84F4DBD0,
432 0x9AB3FBD5, 0x9E72F662, 0x9331E0BB, 0x97F0ED0C,
433 0xAFBFA0B1, 0xAB7EAD06, 0xA63DBBDF, 0xA2FCB668,
434 0xBCBB966D, 0xB87A9BDA, 0xB5398D03, 0xB1F880B4,
435};
436
437static uint32_t boot_crc(uint8_t *buf, int size)
438{
439 uint32_t crc = 0;
440 for(int i = 0; i < size; i++)
441 crc = boot_crc_table[buf[i] ^ (crc >> 24)] ^ (crc << 8);
442 return crc;
443}
444
445wchar_t *from_uni16(uint16_t *str)
446{
447 static wchar_t buffer[64];
448 int i = 0;
449 while(str[i])
450 {
451 buffer[i] = str[i];
452 i++;
453 }
454 return buffer;
455}
456
457static int do_boot_desc(uint8_t *buf, unsigned long size,
458 struct rknano_boot_desc_t *desc, int desc_idx)
459{
460 (void) buf;
461 (void) size;
462 cprintf(BLUE, "Desc %d\n", desc_idx);
463 cprintf(GREEN, " Count: "); cprintf(YELLOW, "%d\n", desc->count);
464 cprintf(GREEN, " Offset: "); cprintf(YELLOW, "%#x\n", desc->offset);
465 cprintf(GREEN, " Stride: "); cprintf(YELLOW, "%#x ", desc->stride);
466 if(desc->stride < sizeof(struct rknano_boot_entry_t))
467 cprintf(RED, "(too small <%#lx)\n", sizeof(struct rknano_boot_entry_t));
468 else
469 cprintf(RED, "(OK >=%#lx)\n", sizeof(struct rknano_boot_entry_t));
470
471 for(int i = 0; i < desc->count; i++)
472 {
473 struct rknano_boot_entry_t *entry = (void *)(buf + desc->offset + i * desc->stride);
474 cprintf(BLUE, " Entry %d\n", i);
475 cprintf(GREEN, " Entry size: "); cprintf(YELLOW, "%#x ", entry->entry_size);
476 if(desc->stride < sizeof(struct rknano_boot_entry_t))
477 cprintf(RED, "(too small <%#lx)\n", sizeof(struct rknano_boot_entry_t));
478 else
479 cprintf(RED, "(OK >=%#lx)\n", sizeof(struct rknano_boot_entry_t));
480 cprintf(GREEN, " Unk: "); cprintf(YELLOW, "%#x\n", entry->unk);
481 cprintf(GREEN, " Name: "); cprintf(YELLOW, "%S\n", from_uni16(entry->name));
482 cprintf(GREEN, " Offset: "); cprintf(YELLOW, "%#x\n", entry->offset);
483 cprintf(GREEN, " Size: "); cprintf(YELLOW, "%#x\n", entry->size);
484 cprintf(GREEN, " Sthg 2: "); cprintf(YELLOW, "%#x\n", entry->sthg2);
485
486 struct rknano_blob_t blob;
487 blob.offset = entry->offset;
488 blob.size = entry->size;
489 char name[128];
490 sprintf(name, "desc_%d_ent_%S_", desc_idx, from_uni16(entry->name));
491 save_blob(&blob, buf, size, name, i, PAGE_ENC);
492 }
493
494 return 0;
495}
496
335static int do_boot_image(uint8_t *buf, unsigned long size) 497static int do_boot_image(uint8_t *buf, unsigned long size)
336{ 498{
337 if(sizeof(struct rknano_boot_header_t) != 0x38) 499 if(sizeof(struct rknano_boot_header_t) != 0x38)
@@ -359,17 +521,28 @@ static int do_boot_image(uint8_t *buf, unsigned long size)
359 print("field_E", field_E); 521 print("field_E", field_E);
360 print_arr("field_10", field_10, 5); 522 print_arr("field_10", field_10, 5);
361 print("field_15", field_15); 523 print("field_15", field_15);
362 print("field_19", field_19); 524 print_arr("field_2A", field_2B, 9);
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); 525 print("field_34", field_34);
370 cprintf(GREEN, "Value: ");
371 cprintf(YELLOW, "%#x\n", *(unsigned long *)((uint8_t *)hdr + hdr->field_34 - 10));
372 526
527 do_boot_desc(buf, size, &hdr->desc_1, 1);
528 do_boot_desc(buf, size, &hdr->desc_2, 2);
529 do_boot_desc(buf, size, &hdr->desc_4, 4);
530
531 cprintf(BLUE, "Variable Header:\n");
532 cprintf(GREEN, " Value: ");
533 cprintf(YELLOW, "%#lx\n", *(unsigned long *)((uint8_t *)hdr + hdr->field_34 - 10));
534
535 /* The last 4 bytes are a 32-bit CRC */
536 cprintf(BLUE, "Post Header:\n");
537 cprintf(GREEN, " CRC: ");
538 uint32_t crc = *(uint32_t *)(buf + size - 4);
539 uint32_t ccrc = boot_crc(buf, size - 4);
540 cprintf(YELLOW, "%08x ", crc);
541 if(crc == ccrc)
542 cprintf(RED, "OK\n");
543 else
544 cprintf(RED, "Mismatch\n");
545
373 return 0; 546 return 0;
374} 547}
375 548
@@ -414,12 +587,12 @@ static int do_rkfw_image(uint8_t *buf, unsigned long size)
414 cprintf(GREEN, " Loader: "); 587 cprintf(GREEN, " Loader: ");
415 print_blob_interval(&hdr->loader); 588 print_blob_interval(&hdr->loader);
416 cprintf(OFF, "\n"); 589 cprintf(OFF, "\n");
417 save_blob(&hdr->loader, buf, size, "loader", 0, false); 590 save_blob(&hdr->loader, buf, size, "loader", 0, NO_ENC);
418 591
419 cprintf(GREEN, " Update: "); 592 cprintf(GREEN, " Update: ");
420 print_blob_interval(&hdr->update); 593 print_blob_interval(&hdr->update);
421 cprintf(OFF, "\n"); 594 cprintf(OFF, "\n");
422 save_blob(&hdr->update, buf, size, "update", 0, false); 595 save_blob(&hdr->update, buf, size, "update", 0, NO_ENC);
423 596
424 print("hdr_size", hdr_size); 597 print("hdr_size", hdr_size);
425 print("field_6", field_6); 598 print("field_6", field_6);