diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2012-12-16 01:52:19 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2012-12-16 01:52:19 +0100 |
commit | 4fc3397c5b79811dff1205a5d42ac1e573f990ab (patch) | |
tree | 9ac6ea6c194787d603d62256dbced48948b71db0 /utils/imxtools | |
parent | 51604e84459be926ae1375cf940a832635fd12c2 (diff) | |
download | rockbox-4fc3397c5b79811dff1205a5d42ac1e573f990ab.tar.gz rockbox-4fc3397c5b79811dff1205a5d42ac1e573f990ab.zip |
imxtools/sbtools: implement sb1 write
Change-Id: Ic36d3a8fcf09350dff5988eb860d76eb11608cc2
Diffstat (limited to 'utils/imxtools')
-rw-r--r-- | utils/imxtools/sbtools/sb1.c | 188 | ||||
-rw-r--r-- | utils/imxtools/sbtools/sb1.h | 9 |
2 files changed, 181 insertions, 16 deletions
diff --git a/utils/imxtools/sbtools/sb1.c b/utils/imxtools/sbtools/sb1.c index 22854036c1..576196d5bd 100644 --- a/utils/imxtools/sbtools/sb1.c +++ b/utils/imxtools/sbtools/sb1.c | |||
@@ -59,7 +59,123 @@ static void fix_version(struct sb1_version_t *ver) | |||
59 | 59 | ||
60 | enum sb1_error_t sb1_write_file(struct sb1_file_t *sb, const char *filename) | 60 | enum sb1_error_t sb1_write_file(struct sb1_file_t *sb, const char *filename) |
61 | { | 61 | { |
62 | return SB1_ERROR; | 62 | /* compute image size (without userdata) */ |
63 | uint32_t image_size = 0; | ||
64 | image_size += sizeof(struct sb1_header_t); | ||
65 | for(int i = 0; i < sb->nr_insts; i++) | ||
66 | { | ||
67 | switch(sb->insts[i].cmd) | ||
68 | { | ||
69 | case SB1_INST_LOAD: | ||
70 | image_size += 8 + ROUND_UP(sb->insts[i].size, 4); | ||
71 | break; | ||
72 | case SB1_INST_FILL: | ||
73 | case SB1_INST_JUMP: | ||
74 | case SB1_INST_CALL: | ||
75 | image_size += 12; | ||
76 | break; | ||
77 | case SB1_INST_MODE: | ||
78 | case SB1_INST_SDRAM: | ||
79 | image_size += 8; | ||
80 | break; | ||
81 | default: | ||
82 | bugp("Unknown SB instruction: %#x\n", sb->insts[i].cmd); | ||
83 | } | ||
84 | } | ||
85 | // now take crypto marks and sector size into account: | ||
86 | // there is one crypto mark per sector, ie 4 bytes for 508 = 512 (sector) | ||
87 | image_size += 4 * ((image_size + SECTOR_SIZE - 5) / (SECTOR_SIZE - 4)); | ||
88 | image_size = ROUND_UP(image_size, SECTOR_SIZE); | ||
89 | |||
90 | /* allocate buffer and fill it (ignoring crypto for now) */ | ||
91 | void *buf = xmalloc(image_size); | ||
92 | struct sb1_header_t *header = buf; | ||
93 | memset(buf, 0, image_size); | ||
94 | header->rom_version = sb->rom_version; | ||
95 | header->image_size = image_size + sb->userdata_size; | ||
96 | header->header_size = sizeof(struct sb1_header_t); | ||
97 | header->userdata_offset = sb->userdata ? image_size : 0; | ||
98 | memcpy(&header->product_ver, &sb->product_ver, sizeof(sb->product_ver)); | ||
99 | memcpy(&header->component_ver, &sb->component_ver, sizeof(sb->component_ver)); | ||
100 | header->drive_tag = sb->drive_tag; | ||
101 | strncpy((void *)header->signature, "STMP", 4); | ||
102 | |||
103 | struct sb1_cmd_header_t *cmd = (void *)(header + 1); | ||
104 | for(int i = 0; i < sb->nr_insts; i++) | ||
105 | { | ||
106 | int bytes = 0; | ||
107 | switch(sb->insts[i].cmd) | ||
108 | { | ||
109 | case SB1_INST_LOAD: | ||
110 | bytes = sb->insts[i].size; | ||
111 | cmd->addr = sb->insts[i].addr; | ||
112 | memcpy(cmd + 1, sb->insts[i].data, sb->insts[i].size); | ||
113 | memset((void *)(cmd + 1) + sb->insts[i].size, 0, | ||
114 | bytes - sb->insts[i].size); | ||
115 | break; | ||
116 | case SB1_INST_FILL: | ||
117 | bytes = 4; | ||
118 | memcpy(cmd + 1, &sb->insts[i].pattern, 4); | ||
119 | cmd->addr = sb->insts[i].addr; | ||
120 | break; | ||
121 | case SB1_INST_JUMP: | ||
122 | case SB1_INST_CALL: | ||
123 | bytes = 4; | ||
124 | cmd->addr = sb->insts[i].addr; | ||
125 | memcpy(cmd + 1, &sb->insts[i].argument, 4); | ||
126 | break; | ||
127 | case SB1_INST_MODE: | ||
128 | bytes = 4; | ||
129 | cmd->addr = sb->insts[i].mode; | ||
130 | break; | ||
131 | case SB1_INST_SDRAM: | ||
132 | bytes = 0; | ||
133 | cmd->addr = SB1_MK_ADDR_SDRAM(sb->insts[i].sdram.chip_select, | ||
134 | sb->insts[i].sdram.size_index); | ||
135 | break; | ||
136 | default: | ||
137 | bugp("Unknown SB instruction: %#x\n", sb->insts[i].cmd); | ||
138 | } | ||
139 | |||
140 | cmd->cmd = SB1_MK_CMD(sb->insts[i].cmd, sb->insts[i].datatype, | ||
141 | bytes, sb->insts[i].critical, | ||
142 | ROUND_UP(bytes, 4) / 4 + 1); | ||
143 | |||
144 | cmd = (void *)cmd + 8 + ROUND_UP(bytes, 4); | ||
145 | } | ||
146 | |||
147 | /* move everything to prepare crypto marks (start at the end !) */ | ||
148 | for(int i = image_size / SECTOR_SIZE - 1; i >= 0; i--) | ||
149 | memmove(buf + i * SECTOR_SIZE, buf + i * (SECTOR_SIZE - 4), SECTOR_SIZE - 4); | ||
150 | |||
151 | union xorcrypt_key_t key[2]; | ||
152 | memcpy(key, sb->key, sizeof(sb->key)); | ||
153 | void *ptr = header + 1; | ||
154 | int offset = header->header_size; | ||
155 | for(unsigned i = 0; i < image_size / SECTOR_SIZE; i++) | ||
156 | { | ||
157 | int size = SECTOR_SIZE - 4 - offset; | ||
158 | uint32_t mark = xor_encrypt(key, ptr, size); | ||
159 | *(uint32_t *)(ptr + size) = mark; | ||
160 | |||
161 | ptr += size + 4; | ||
162 | offset = 0; | ||
163 | } | ||
164 | |||
165 | FILE *fd = fopen(filename, "wb"); | ||
166 | if(fd == NULL) | ||
167 | return SB1_OPEN_ERROR; | ||
168 | if(fwrite(buf, image_size, 1, fd) != 1) | ||
169 | { | ||
170 | free(buf); | ||
171 | return SB1_WRITE_ERROR; | ||
172 | } | ||
173 | free(buf); | ||
174 | if(sb->userdata) | ||
175 | fwrite(sb->userdata, sb->userdata_size, 1, fd); | ||
176 | fclose(fd); | ||
177 | |||
178 | return SB1_SUCCESS; | ||
63 | } | 179 | } |
64 | 180 | ||
65 | struct sb1_file_t *sb1_read_file(const char *filename, void *u, | 181 | struct sb1_file_t *sb1_read_file(const char *filename, void *u, |
@@ -237,6 +353,8 @@ struct sb1_file_t *sb1_read_memory(void *_buf, size_t filesize, void *u, | |||
237 | } | 353 | } |
238 | } | 354 | } |
239 | } | 355 | } |
356 | |||
357 | memcpy(file->key, key, sizeof(key)); | ||
240 | 358 | ||
241 | if(!valid_key) | 359 | if(!valid_key) |
242 | fatal(SB1_NO_VALID_KEY, "No valid key found\n"); | 360 | fatal(SB1_NO_VALID_KEY, "No valid key found\n"); |
@@ -279,18 +397,6 @@ struct sb1_file_t *sb1_read_memory(void *_buf, size_t filesize, void *u, | |||
279 | printf(YELLOW, " Boot:"); | 397 | printf(YELLOW, " Boot:"); |
280 | printf(RED, " %#x ", SB1_CMD_BOOT(cmd->cmd)); | 398 | printf(RED, " %#x ", SB1_CMD_BOOT(cmd->cmd)); |
281 | printf(GREEN, "(%s)\n", sb1_cmd_name(SB1_CMD_BOOT(cmd->cmd))); | 399 | printf(GREEN, "(%s)\n", sb1_cmd_name(SB1_CMD_BOOT(cmd->cmd))); |
282 | printf(YELLOW, " Addr:"); | ||
283 | printf(RED, " %#x", cmd->addr); | ||
284 | |||
285 | if(SB1_CMD_BOOT(cmd->cmd) == SB1_INST_SDRAM) | ||
286 | printf(GREEN, " (Chip Select=%d, Size=%d)", SB1_ADDR_SDRAM_CS(cmd->addr), | ||
287 | sb1_sdram_size_by_index(SB1_ADDR_SDRAM_SZ(cmd->addr))); | ||
288 | printf(OFF, "\n"); | ||
289 | if(SB1_CMD_BOOT(cmd->cmd) == SB1_INST_FILL) | ||
290 | { | ||
291 | printf(YELLOW, " Pattern:"); | ||
292 | printf(RED, " %#x\n", *(uint32_t *)(cmd + 1)); | ||
293 | } | ||
294 | 400 | ||
295 | /* copy command */ | 401 | /* copy command */ |
296 | struct sb1_inst_t inst; | 402 | struct sb1_inst_t inst; |
@@ -305,16 +411,42 @@ struct sb1_file_t *sb1_read_memory(void *_buf, size_t filesize, void *u, | |||
305 | case SB1_INST_SDRAM: | 411 | case SB1_INST_SDRAM: |
306 | inst.sdram.chip_select = SB1_ADDR_SDRAM_CS(cmd->addr); | 412 | inst.sdram.chip_select = SB1_ADDR_SDRAM_CS(cmd->addr); |
307 | inst.sdram.size_index = SB1_ADDR_SDRAM_SZ(cmd->addr); | 413 | inst.sdram.size_index = SB1_ADDR_SDRAM_SZ(cmd->addr); |
414 | printf(YELLOW, " Ram:"); | ||
415 | printf(RED, " %#x", inst.addr); | ||
416 | printf(GREEN, " (Chip Select=%d, Size=%d)\n", SB1_ADDR_SDRAM_CS(cmd->addr), | ||
417 | sb1_sdram_size_by_index(SB1_ADDR_SDRAM_SZ(cmd->addr))); | ||
308 | break; | 418 | break; |
309 | case SB1_INST_MODE: | 419 | case SB1_INST_MODE: |
310 | inst.mode = cmd->addr; | 420 | inst.mode = cmd->addr; |
421 | printf(YELLOW, " Mode:"); | ||
422 | printf(RED, " %#x\n", inst.mode); | ||
311 | break; | 423 | break; |
312 | case SB1_INST_LOAD: | 424 | case SB1_INST_LOAD: |
313 | inst.data = malloc(inst.size); | 425 | inst.data = malloc(inst.size); |
314 | memcpy(inst.data, cmd + 1, inst.size); | 426 | memcpy(inst.data, cmd + 1, inst.size); |
315 | /* fallthrough */ | ||
316 | default: | ||
317 | inst.addr = cmd->addr; | 427 | inst.addr = cmd->addr; |
428 | printf(YELLOW, " Addr:"); | ||
429 | printf(RED, " %#x\n", inst.addr); | ||
430 | break; | ||
431 | case SB1_INST_FILL: | ||
432 | inst.addr = cmd->addr; | ||
433 | inst.pattern = *(uint32_t *)(cmd + 1); | ||
434 | printf(YELLOW, " Addr:"); | ||
435 | printf(RED, " %#x\n", cmd->addr); | ||
436 | printf(YELLOW, " Pattern:"); | ||
437 | printf(RED, " %#x\n", inst.pattern); | ||
438 | break; | ||
439 | case SB1_INST_CALL: | ||
440 | case SB1_INST_JUMP: | ||
441 | inst.addr = cmd->addr; | ||
442 | inst.argument = *(uint32_t *)(cmd + 1); | ||
443 | printf(YELLOW, " Addr:"); | ||
444 | printf(RED, " %#x\n", cmd->addr); | ||
445 | printf(YELLOW, " Argument:"); | ||
446 | printf(RED, " %#x\n", inst.pattern); | ||
447 | break; | ||
448 | default: | ||
449 | printf(GREY, "WARNING: unknown SB command !\n"); | ||
318 | break; | 450 | break; |
319 | } | 451 | } |
320 | 452 | ||
@@ -447,4 +579,28 @@ void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf cprintf) | |||
447 | #undef printf | 579 | #undef printf |
448 | #undef print_hex | 580 | #undef print_hex |
449 | } | 581 | } |
450 | 582 | ||
583 | static struct crypto_key_t g_default_xor_key = | ||
584 | { | ||
585 | .method = CRYPTO_XOR_KEY, | ||
586 | .u.xor_key = | ||
587 | { | ||
588 | {.k = {0x67ECAEF6, 0xB31FB961, 0x118A9F4C, 0xA32A97DA, | ||
589 | 0x6CC39617, 0x5BC00314, 0x9D430685, 0x4D7DB502, | ||
590 | 0xA347685E, 0x3C87E86C, 0x8987AAA0, 0x24B78EF1, | ||
591 | 0x893B9605, 0x9BB8C2BE, 0x6D9544E2, 0x375B525C}}, | ||
592 | {.k = {0x3F424704, 0x53B5A331, 0x6AD345A5, 0x20DCEC51, | ||
593 | 0x743C8D3B, 0x444B3792, 0x0AF429569, 0xB7EE1111, | ||
594 | 0x583BF768, 0x9683BF9A, 0x0B032D799, 0xFE4E78ED, | ||
595 | 0xF20D08C2, 0xFA0BE4A2, 0x4D89C317, 0x887B2D6F}} | ||
596 | } | ||
597 | }; | ||
598 | |||
599 | void sb1_get_default_key(struct crypto_key_t *key) | ||
600 | { | ||
601 | memcpy(key, &g_default_xor_key, sizeof(g_default_xor_key)); | ||
602 | /* decrypt the xor key which is xor'ed */ | ||
603 | for(int i = 0; i < 2; i++) | ||
604 | for(int j = 0; j < 16; j++) | ||
605 | key->u.xor_key[i].k[j] ^= 0xaa55aa55; | ||
606 | } \ No newline at end of file | ||
diff --git a/utils/imxtools/sbtools/sb1.h b/utils/imxtools/sbtools/sb1.h index 8d8c2d2296..0a0c9fe69c 100644 --- a/utils/imxtools/sbtools/sb1.h +++ b/utils/imxtools/sbtools/sb1.h | |||
@@ -66,9 +66,14 @@ struct sb1_cmd_header_t | |||
66 | #define SB1_CMD_DATATYPE(cmd) (((cmd) >> 4) & 0x3) | 66 | #define SB1_CMD_DATATYPE(cmd) (((cmd) >> 4) & 0x3) |
67 | #define SB1_CMD_BOOT(cmd) ((cmd) & 0xf) | 67 | #define SB1_CMD_BOOT(cmd) ((cmd) & 0xf) |
68 | 68 | ||
69 | #define SB1_MK_CMD(boot,data,bytes,crit,size) \ | ||
70 | ((boot) | (data) << 4 | (bytes) << 6 | (crit) << 20 | (size) << 21) | ||
71 | |||
69 | #define SB1_ADDR_SDRAM_CS(addr) ((addr) & 0x3) | 72 | #define SB1_ADDR_SDRAM_CS(addr) ((addr) & 0x3) |
70 | #define SB1_ADDR_SDRAM_SZ(addr) ((addr) >> 16) | 73 | #define SB1_ADDR_SDRAM_SZ(addr) ((addr) >> 16) |
71 | 74 | ||
75 | #define SB1_MK_ADDR_SDRAM(cs,sz) ((cs) | (sz) << 16) | ||
76 | |||
72 | int sb1_sdram_size_by_index(int index); // returns - 1 on error | 77 | int sb1_sdram_size_by_index(int index); // returns - 1 on error |
73 | int sb1_sdram_index_by_size(int size); // returns -1 on error | 78 | int sb1_sdram_index_by_size(int size); // returns -1 on error |
74 | 79 | ||
@@ -105,6 +110,7 @@ struct sb1_inst_t | |||
105 | // <union> | 110 | // <union> |
106 | void *data; | 111 | void *data; |
107 | uint32_t pattern; | 112 | uint32_t pattern; |
113 | uint32_t argument; | ||
108 | // </union> | 114 | // </union> |
109 | }; | 115 | }; |
110 | 116 | ||
@@ -119,6 +125,7 @@ struct sb1_file_t | |||
119 | struct sb1_inst_t *insts; | 125 | struct sb1_inst_t *insts; |
120 | void *userdata; | 126 | void *userdata; |
121 | int userdata_size; | 127 | int userdata_size; |
128 | union xorcrypt_key_t key[2]; | ||
122 | }; | 129 | }; |
123 | 130 | ||
124 | enum sb1_error_t | 131 | enum sb1_error_t |
@@ -146,6 +153,8 @@ struct sb1_file_t *sb1_read_file_ex(const char *filename, size_t offset, size_t | |||
146 | struct sb1_file_t *sb1_read_memory(void *buffer, size_t size, void *u, | 153 | struct sb1_file_t *sb1_read_memory(void *buffer, size_t size, void *u, |
147 | sb1_color_printf printf, enum sb1_error_t *err); | 154 | sb1_color_printf printf, enum sb1_error_t *err); |
148 | 155 | ||
156 | void sb1_get_default_key(struct crypto_key_t *key); | ||
157 | |||
149 | void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf printf); | 158 | void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf printf); |
150 | void sb1_free(struct sb1_file_t *file); | 159 | void sb1_free(struct sb1_file_t *file); |
151 | 160 | ||