summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-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 f1e0e97..f913b12 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)
return result;
}
+/* scramble mode */
+enum {
+ NO_ENC,
+ CONTINOUS_ENC, /* scramble whole block at once */
+ PAGE_ENC /* nand bootloader is scrambled in 0x200 chunks */
+};
+
static void save_blob(const struct rknano_blob_t *b, void *buf, uint32_t size,
- char *name, int suffix, bool descramble)
+ char *name, int suffix, int enc_mode)
{
if(g_out_prefix == NULL || b->size == 0 || b->offset + b->size > size)
return;
@@ -146,10 +153,23 @@ static void save_blob(const struct rknano_blob_t *b, void *buf, uint32_t size,
sprintf(path, "%s%s%d.bin", g_out_prefix, name, suffix);
FILE *f = fopen(path, "wb");
uint8_t *ptr = buf + b->offset;
- if(descramble)
+ if(enc_mode != NO_ENC)
{
ptr = malloc(b->size);
- encode_page(buf + b->offset, ptr, b->size);
+ int len = b->size;
+ uint8_t *buff_ptr = buf + b->offset;
+ uint8_t *out_ptr = ptr;
+ if(enc_mode == PAGE_ENC)
+ {
+ while(len >= 0x200)
+ {
+ encode_page(buff_ptr, out_ptr, 0x200);
+ buff_ptr += 0x200;
+ out_ptr += 0x200;
+ len -= 0x200;
+ }
+ }
+ encode_page(buff_ptr, out_ptr, len);
}
if(f)
@@ -158,7 +178,7 @@ static void save_blob(const struct rknano_blob_t *b, void *buf, uint32_t size,
fclose(f);
}
- if(descramble)
+ if(enc_mode != NO_ENC)
free(ptr);
}
@@ -196,7 +216,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
cprintf(GREEN, " %i: ", i);
print_blob_interval(&hdr->stage[i]);
cprintf(OFF, "\n");
- save_blob(&hdr->stage[i], buf, size, "stage", i, false);
+ save_blob(&hdr->stage[i], buf, size, "stage", i, NO_ENC);
}
cprintf(BLUE, "Fonts\n");
for(unsigned i = 0; i < hdr->nr_fonts; i++)
@@ -204,7 +224,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
cprintf(GREEN, " %i: ", i);
print_blob_interval(&hdr->font[i]);
cprintf(OFF, "\n");
- save_blob(&hdr->font[i], buf, size, "font", i, false);
+ save_blob(&hdr->font[i], buf, size, "font", i, NO_ENC);
}
cprintf(BLUE, "GBK\n");
for(unsigned i = 0; i < hdr->nr_gbk; i++)
@@ -212,7 +232,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
cprintf(GREEN, " %i: ", i);
print_blob_interval(&hdr->gbk[i]);
cprintf(OFF, "\n");
- save_blob(&hdr->gbk[i], buf, size, "gbk", i, false);
+ save_blob(&hdr->gbk[i], buf, size, "gbk", i, NO_ENC);
}
cprintf(BLUE, "String Tables\n");
for(unsigned i = 0; i < hdr->nr_strtbl; i++)
@@ -220,7 +240,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
cprintf(GREEN, " %i: ", i);
print_blob_interval(&hdr->strtbl[i]);
cprintf(OFF, "\n");
- save_blob(&hdr->strtbl[i], buf, size, "strtbl", i, false);
+ save_blob(&hdr->strtbl[i], buf, size, "strtbl", i, NO_ENC);
}
cprintf(BLUE, "Image Resources\n");
for(unsigned i = 0; i < hdr->nr_imageres; i++)
@@ -228,7 +248,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
cprintf(GREEN, " %i: ", i);
print_blob_interval(&hdr->imageres[i]);
cprintf(OFF, "\n");
- save_blob(&hdr->imageres[i], buf, size, "imgres", i, false);
+ save_blob(&hdr->imageres[i], buf, size, "imgres", i, NO_ENC);
}
cprintf(BLUE, "Unknown\n");
for(unsigned i = 0; i < hdr->nr_unk; i++)
@@ -236,7 +256,7 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
cprintf(GREEN, " %i: ", i);
print_blob_interval(&hdr->unk[i]);
cprintf(OFF, "\n");
- save_blob(&hdr->unk[i], buf, size, "unk", i, false);
+ save_blob(&hdr->unk[i], buf, size, "unk", i, NO_ENC);
}
cprintf(BLUE, "Other\n");
cprintf(GREEN, " Size: ");
@@ -313,6 +333,13 @@ static int do_nanostage_image(uint8_t *buf, unsigned long size)
#define MAGIC_BOOT "BOOT"
#define MAGIC_BOOT_SIZE 4
+struct rknano_boot_desc_t
+{
+ uint8_t count;
+ uint32_t offset;
+ uint8_t stride;
+} __attribute__((packed));
+
struct rknano_boot_header_t
{
char magic[MAGIC_BOOT_SIZE];
@@ -322,16 +349,151 @@ struct rknano_boot_header_t
uint16_t field_E;
uint8_t field_10[5];
uint32_t field_15;
- uint8_t field_19;
- uint32_t field_1A;
- uint8_t field_1E[2];
- uint32_t field_20;
- uint8_t field_24[2];
- uint32_t field_26;
- uint8_t field_2A[10];
+ struct rknano_boot_desc_t desc_1;
+ struct rknano_boot_desc_t desc_2;
+ struct rknano_boot_desc_t desc_4;
+ uint8_t field_2B[9];
uint32_t field_34;
} __attribute__((packed));
+struct rknano_boot_entry_t
+{
+ uint8_t entry_size; // unsure
+ uint32_t unk;
+ uint16_t name[20];
+ uint32_t offset;
+ uint32_t size;
+ uint32_t sthg2;
+} __attribute__((packed));
+
+uint32_t boot_crc_table[256] =
+{
+ 0x00000000, 0x04C10DB7, 0x09821B6E, 0x0D4316D9,
+ 0x130436DC, 0x17C53B6B, 0x1A862DB2, 0x1E472005,
+ 0x26086DB8, 0x22C9600F, 0x2F8A76D6, 0x2B4B7B61,
+ 0x350C5B64, 0x31CD56D3, 0x3C8E400A, 0x384F4DBD,
+ 0x4C10DB70, 0x48D1D6C7, 0x4592C01E, 0x4153CDA9,
+ 0x5F14EDAC, 0x5BD5E01B, 0x5696F6C2, 0x5257FB75,
+ 0x6A18B6C8, 0x6ED9BB7F, 0x639AADA6, 0x675BA011,
+ 0x791C8014, 0x7DDD8DA3, 0x709E9B7A, 0x745F96CD,
+ 0x9821B6E0, 0x9CE0BB57, 0x91A3AD8E, 0x9562A039,
+ 0x8B25803C, 0x8FE48D8B, 0x82A79B52, 0x866696E5,
+ 0xBE29DB58, 0xBAE8D6EF, 0xB7ABC036, 0xB36ACD81,
+ 0xAD2DED84, 0xA9ECE033, 0xA4AFF6EA, 0xA06EFB5D,
+ 0xD4316D90, 0xD0F06027, 0xDDB376FE, 0xD9727B49,
+ 0xC7355B4C, 0xC3F456FB, 0xCEB74022, 0xCA764D95,
+ 0xF2390028, 0xF6F80D9F, 0xFBBB1B46, 0xFF7A16F1,
+ 0xE13D36F4, 0xE5FC3B43, 0xE8BF2D9A, 0xEC7E202D,
+ 0x34826077, 0x30436DC0, 0x3D007B19, 0x39C176AE,
+ 0x278656AB, 0x23475B1C, 0x2E044DC5, 0x2AC54072,
+ 0x128A0DCF, 0x164B0078, 0x1B0816A1, 0x1FC91B16,
+ 0x018E3B13, 0x054F36A4, 0x080C207D, 0x0CCD2DCA,
+ 0x7892BB07, 0x7C53B6B0, 0x7110A069, 0x75D1ADDE,
+ 0x6B968DDB, 0x6F57806C, 0x621496B5, 0x66D59B02,
+ 0x5E9AD6BF, 0x5A5BDB08, 0x5718CDD1, 0x53D9C066,
+ 0x4D9EE063, 0x495FEDD4, 0x441CFB0D, 0x40DDF6BA,
+ 0xACA3D697, 0xA862DB20, 0xA521CDF9, 0xA1E0C04E,
+ 0xBFA7E04B, 0xBB66EDFC, 0xB625FB25, 0xB2E4F692,
+ 0x8AABBB2F, 0x8E6AB698, 0x8329A041, 0x87E8ADF6,
+ 0x99AF8DF3, 0x9D6E8044, 0x902D969D, 0x94EC9B2A,
+ 0xE0B30DE7, 0xE4720050, 0xE9311689, 0xEDF01B3E,
+ 0xF3B73B3B, 0xF776368C, 0xFA352055, 0xFEF42DE2,
+ 0xC6BB605F, 0xC27A6DE8, 0xCF397B31, 0xCBF87686,
+ 0xD5BF5683, 0xD17E5B34, 0xDC3D4DED, 0xD8FC405A,
+ 0x6904C0EE, 0x6DC5CD59, 0x6086DB80, 0x6447D637,
+ 0x7A00F632, 0x7EC1FB85, 0x7382ED5C, 0x7743E0EB,
+ 0x4F0CAD56, 0x4BCDA0E1, 0x468EB638, 0x424FBB8F,
+ 0x5C089B8A, 0x58C9963D, 0x558A80E4, 0x514B8D53,
+ 0x25141B9E, 0x21D51629, 0x2C9600F0, 0x28570D47,
+ 0x36102D42, 0x32D120F5, 0x3F92362C, 0x3B533B9B,
+ 0x031C7626, 0x07DD7B91, 0x0A9E6D48, 0x0E5F60FF,
+ 0x101840FA, 0x14D94D4D, 0x199A5B94, 0x1D5B5623,
+ 0xF125760E, 0xF5E47BB9, 0xF8A76D60, 0xFC6660D7,
+ 0xE22140D2, 0xE6E04D65, 0xEBA35BBC, 0xEF62560B,
+ 0xD72D1BB6, 0xD3EC1601, 0xDEAF00D8, 0xDA6E0D6F,
+ 0xC4292D6A, 0xC0E820DD, 0xCDAB3604, 0xC96A3BB3,
+ 0xBD35AD7E, 0xB9F4A0C9, 0xB4B7B610, 0xB076BBA7,
+ 0xAE319BA2, 0xAAF09615, 0xA7B380CC, 0xA3728D7B,
+ 0x9B3DC0C6, 0x9FFCCD71, 0x92BFDBA8, 0x967ED61F,
+ 0x8839F61A, 0x8CF8FBAD, 0x81BBED74, 0x857AE0C3,
+ 0x5D86A099, 0x5947AD2E, 0x5404BBF7, 0x50C5B640,
+ 0x4E829645, 0x4A439BF2, 0x47008D2B, 0x43C1809C,
+ 0x7B8ECD21, 0x7F4FC096, 0x720CD64F, 0x76CDDBF8,
+ 0x688AFBFD, 0x6C4BF64A, 0x6108E093, 0x65C9ED24,
+ 0x11967BE9, 0x1557765E, 0x18146087, 0x1CD56D30,
+ 0x02924D35, 0x06534082, 0x0B10565B, 0x0FD15BEC,
+ 0x379E1651, 0x335F1BE6, 0x3E1C0D3F, 0x3ADD0088,
+ 0x249A208D, 0x205B2D3A, 0x2D183BE3, 0x29D93654,
+ 0xC5A71679, 0xC1661BCE, 0xCC250D17, 0xC8E400A0,
+ 0xD6A320A5, 0xD2622D12, 0xDF213BCB, 0xDBE0367C,
+ 0xE3AF7BC1, 0xE76E7676, 0xEA2D60AF, 0xEEEC6D18,
+ 0xF0AB4D1D, 0xF46A40AA, 0xF9295673, 0xFDE85BC4,
+ 0x89B7CD09, 0x8D76C0BE, 0x8035D667, 0x84F4DBD0,
+ 0x9AB3FBD5, 0x9E72F662, 0x9331E0BB, 0x97F0ED0C,
+ 0xAFBFA0B1, 0xAB7EAD06, 0xA63DBBDF, 0xA2FCB668,
+ 0xBCBB966D, 0xB87A9BDA, 0xB5398D03, 0xB1F880B4,
+};
+
+static uint32_t boot_crc(uint8_t *buf, int size)
+{
+ uint32_t crc = 0;
+ for(int i = 0; i < size; i++)
+ crc = boot_crc_table[buf[i] ^ (crc >> 24)] ^ (crc << 8);
+ return crc;
+}
+
+wchar_t *from_uni16(uint16_t *str)
+{
+ static wchar_t buffer[64];
+ int i = 0;
+ while(str[i])
+ {
+ buffer[i] = str[i];
+ i++;
+ }
+ return buffer;
+}
+
+static int do_boot_desc(uint8_t *buf, unsigned long size,
+ struct rknano_boot_desc_t *desc, int desc_idx)
+{
+ (void) buf;
+ (void) size;
+ cprintf(BLUE, "Desc %d\n", desc_idx);
+ cprintf(GREEN, " Count: "); cprintf(YELLOW, "%d\n", desc->count);
+ cprintf(GREEN, " Offset: "); cprintf(YELLOW, "%#x\n", desc->offset);
+ cprintf(GREEN, " Stride: "); cprintf(YELLOW, "%#x ", desc->stride);
+ if(desc->stride < sizeof(struct rknano_boot_entry_t))
+ cprintf(RED, "(too small <%#lx)\n", sizeof(struct rknano_boot_entry_t));
+ else
+ cprintf(RED, "(OK >=%#lx)\n", sizeof(struct rknano_boot_entry_t));
+
+ for(int i = 0; i < desc->count; i++)
+ {
+ struct rknano_boot_entry_t *entry = (void *)(buf + desc->offset + i * desc->stride);
+ cprintf(BLUE, " Entry %d\n", i);
+ cprintf(GREEN, " Entry size: "); cprintf(YELLOW, "%#x ", entry->entry_size);
+ if(desc->stride < sizeof(struct rknano_boot_entry_t))
+ cprintf(RED, "(too small <%#lx)\n", sizeof(struct rknano_boot_entry_t));
+ else
+ cprintf(RED, "(OK >=%#lx)\n", sizeof(struct rknano_boot_entry_t));
+ cprintf(GREEN, " Unk: "); cprintf(YELLOW, "%#x\n", entry->unk);
+ cprintf(GREEN, " Name: "); cprintf(YELLOW, "%S\n", from_uni16(entry->name));
+ cprintf(GREEN, " Offset: "); cprintf(YELLOW, "%#x\n", entry->offset);
+ cprintf(GREEN, " Size: "); cprintf(YELLOW, "%#x\n", entry->size);
+ cprintf(GREEN, " Sthg 2: "); cprintf(YELLOW, "%#x\n", entry->sthg2);
+
+ struct rknano_blob_t blob;
+ blob.offset = entry->offset;
+ blob.size = entry->size;
+ char name[128];
+ sprintf(name, "desc_%d_ent_%S_", desc_idx, from_uni16(entry->name));
+ save_blob(&blob, buf, size, name, i, PAGE_ENC);
+ }
+
+ return 0;
+}
+
static int do_boot_image(uint8_t *buf, unsigned long size)
{
if(sizeof(struct rknano_boot_header_t) != 0x38)
@@ -359,17 +521,28 @@ static int do_boot_image(uint8_t *buf, unsigned long size)
print("field_E", field_E);
print_arr("field_10", field_10, 5);
print("field_15", field_15);
- print("field_19", field_19);
- print("field_1A", field_1A);
- print_arr("field_1E", field_1E, 2);
- print("field_20", field_20);
- print_arr("field_24", field_24, 2);
- print("field_26", field_26);
- print_arr("field_2A", field_2A, 10);
+ print_arr("field_2A", field_2B, 9);
print("field_34", field_34);
- cprintf(GREEN, "Value: ");
- cprintf(YELLOW, "%#x\n", *(unsigned long *)((uint8_t *)hdr + hdr->field_34 - 10));
+ do_boot_desc(buf, size, &hdr->desc_1, 1);
+ do_boot_desc(buf, size, &hdr->desc_2, 2);
+ do_boot_desc(buf, size, &hdr->desc_4, 4);
+
+ cprintf(BLUE, "Variable Header:\n");
+ cprintf(GREEN, " Value: ");
+ cprintf(YELLOW, "%#lx\n", *(unsigned long *)((uint8_t *)hdr + hdr->field_34 - 10));
+
+ /* The last 4 bytes are a 32-bit CRC */
+ cprintf(BLUE, "Post Header:\n");
+ cprintf(GREEN, " CRC: ");
+ uint32_t crc = *(uint32_t *)(buf + size - 4);
+ uint32_t ccrc = boot_crc(buf, size - 4);
+ cprintf(YELLOW, "%08x ", crc);
+ if(crc == ccrc)
+ cprintf(RED, "OK\n");
+ else
+ cprintf(RED, "Mismatch\n");
+
return 0;
}
@@ -414,12 +587,12 @@ static int do_rkfw_image(uint8_t *buf, unsigned long size)
cprintf(GREEN, " Loader: ");
print_blob_interval(&hdr->loader);
cprintf(OFF, "\n");
- save_blob(&hdr->loader, buf, size, "loader", 0, false);
+ save_blob(&hdr->loader, buf, size, "loader", 0, NO_ENC);
cprintf(GREEN, " Update: ");
print_blob_interval(&hdr->update);
cprintf(OFF, "\n");
- save_blob(&hdr->update, buf, size, "update", 0, false);
+ save_blob(&hdr->update, buf, size, "update", 0, NO_ENC);
print("hdr_size", hdr_size);
print("field_6", field_6);