summaryrefslogtreecommitdiff
path: root/utils/sbtools
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2011-10-23 17:43:52 +0000
committerAmaury Pouly <pamaury@rockbox.org>2011-10-23 17:43:52 +0000
commitb93e15c404cda96397ba2b98e49359a81d34c957 (patch)
treec01fa91dad56a1b51b4f448835de4465ab1cc265 /utils/sbtools
parent94c573f3eca59347cd397d6b68159997bb674246 (diff)
downloadrockbox-b93e15c404cda96397ba2b98e49359a81d34c957.tar.gz
rockbox-b93e15c404cda96397ba2b98e49359a81d34c957.zip
sbtools: fix sbtoelf to support NOP, add alignment support to elftosb
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30832 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/sbtools')
-rw-r--r--utils/sbtools/elftosb.c84
-rw-r--r--utils/sbtools/sbtoelf.c20
2 files changed, 94 insertions, 10 deletions
diff --git a/utils/sbtools/elftosb.c b/utils/sbtools/elftosb.c
index f78c6cf64b..986376179a 100644
--- a/utils/sbtools/elftosb.c
+++ b/utils/sbtools/elftosb.c
@@ -203,6 +203,7 @@ struct sb_section_t
203 uint32_t identifier; 203 uint32_t identifier;
204 bool is_data; 204 bool is_data;
205 bool is_cleartext; 205 bool is_cleartext;
206 uint32_t alignment;
206 // data sections are handled as a single SB_INST_DATA virtual instruction 207 // data sections are handled as a single SB_INST_DATA virtual instruction
207 int nr_insts; 208 int nr_insts;
208 struct sb_inst_t *insts; 209 struct sb_inst_t *insts;
@@ -333,6 +334,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
333 /* options */ 334 /* options */
334 do 335 do
335 { 336 {
337 /* cleartext */
336 struct cmd_option_t *opt = db_find_option_by_id(csec->opt_list, "cleartext"); 338 struct cmd_option_t *opt = db_find_option_by_id(csec->opt_list, "cleartext");
337 if(opt != NULL) 339 if(opt != NULL)
338 { 340 {
@@ -342,6 +344,23 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
342 bug("Cleartext section attribute must be 0 or 1\n"); 344 bug("Cleartext section attribute must be 0 or 1\n");
343 sec->is_cleartext = opt->val; 345 sec->is_cleartext = opt->val;
344 } 346 }
347 /* alignment */
348 opt = db_find_option_by_id(csec->opt_list, "alignment");
349 if(opt != NULL)
350 {
351 if(opt->is_string)
352 bug("Cleartext section attribute must be an integer\n");
353 // n is a power of 2 iff n & (n - 1) = 0
354 // alignement cannot be lower than block size
355 if((opt->val & (opt->val - 1)) != 0)
356 bug("Cleartext section attribute must be a power of two\n");
357 if(opt->val < BLOCK_SIZE)
358 sec->alignment = BLOCK_SIZE;
359 else
360 sec->alignment = opt->val;
361 }
362 else
363 sec->alignment = BLOCK_SIZE;
345 }while(0); 364 }while(0);
346 365
347 if(csec->is_data) 366 if(csec->is_data)
@@ -469,6 +488,16 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
469 * SB file production 488 * SB file production
470 */ 489 */
471 490
491/* helper function to augment an array, free old array */
492void *augment_array(void *arr, size_t elem_sz, size_t cnt, void *aug, size_t aug_cnt)
493{
494 void *p = xmalloc(elem_sz * (cnt + aug_cnt));
495 memcpy(p, arr, elem_sz * cnt);
496 memcpy(p + elem_sz * cnt, aug, elem_sz * aug_cnt);
497 free(arr);
498 return p;
499}
500
472static void fill_gaps(struct sb_file_t *sb) 501static void fill_gaps(struct sb_file_t *sb)
473{ 502{
474 for(int i = 0; i < sb->nr_sections; i++) 503 for(int i = 0; i < sb->nr_sections; i++)
@@ -501,6 +530,11 @@ static void compute_sb_offsets(struct sb_file_t *sb)
501 { 530 {
502 /* each section has a preliminary TAG command */ 531 /* each section has a preliminary TAG command */
503 sb->image_size += sizeof(struct sb_instruction_tag_t) / BLOCK_SIZE; 532 sb->image_size += sizeof(struct sb_instruction_tag_t) / BLOCK_SIZE;
533 /* we might need to pad the section so compute next alignment */
534 uint32_t alignment = BLOCK_SIZE;
535 if((i + 1) < sb->nr_sections)
536 alignment = sb->sections[i + 1].alignment;
537 alignment /= BLOCK_SIZE; /* alignment in block sizes */
504 538
505 struct sb_section_t *sec = &sb->sections[i]; 539 struct sb_section_t *sec = &sb->sections[i];
506 540
@@ -561,6 +595,50 @@ static void compute_sb_offsets(struct sb_file_t *sb)
561 else 595 else
562 bug("die on inst %d\n", inst->inst); 596 bug("die on inst %d\n", inst->inst);
563 } 597 }
598 /* we need to make sure next section starts on the right alignment.
599 * Since each section starts with a boot tag, we thus need to ensure
600 * that this sections ends at adress X such that X+BLOCK_SIZE is
601 * a multiple of the alignment.
602 * For data sections, we just add random data, otherwise we add nops */
603 uint32_t missing_sz = alignment - ((sb->image_size + 1) % alignment);
604 if(missing_sz != alignment)
605 {
606 struct sb_inst_t *aug_insts;
607 int nr_aug_insts = 0;
608
609 if(sb->sections[i].is_data)
610 {
611 nr_aug_insts = 1;
612 aug_insts = malloc(sizeof(struct sb_inst_t));
613 memset(aug_insts, 0, sizeof(struct sb_inst_t));
614 aug_insts[0].inst = SB_INST_DATA;
615 aug_insts[0].size = missing_sz * BLOCK_SIZE;
616 aug_insts[0].data = xmalloc(missing_sz * BLOCK_SIZE);
617 generate_random_data(aug_insts[0].data, missing_sz * BLOCK_SIZE);
618 if(g_debug)
619 printf(" DATA | size=0x%08x\n", aug_insts[0].size);
620 }
621 else
622 {
623 nr_aug_insts = missing_sz;
624 aug_insts = malloc(sizeof(struct sb_inst_t) * nr_aug_insts);
625 memset(aug_insts, 0, sizeof(struct sb_inst_t) * nr_aug_insts);
626 for(int j = 0; j < nr_aug_insts; j++)
627 {
628 aug_insts[j].inst = SB_INST_NOP;
629 if(g_debug)
630 printf(" NOOP\n");
631 }
632 }
633
634 sb->sections[i].insts = augment_array(sb->sections[i].insts, sizeof(struct sb_inst_t),
635 sb->sections[i].nr_insts, aug_insts, nr_aug_insts);
636 sb->sections[i].nr_insts += nr_aug_insts;
637
638 /* augment image and section size */
639 sb->image_size += missing_sz;
640 sec->sec_size += missing_sz;
641 }
564 } 642 }
565 /* final signature */ 643 /* final signature */
566 sb->image_size += 2; 644 sb->image_size += 2;
@@ -679,6 +757,8 @@ void produce_sb_instruction(struct sb_inst_t *inst,
679 case SB_INST_MODE: 757 case SB_INST_MODE:
680 cmd->data = inst->addr; 758 cmd->data = inst->addr;
681 break; 759 break;
760 case SB_INST_NOP:
761 break;
682 default: 762 default:
683 bug("die\n"); 763 bug("die\n");
684 } 764 }
@@ -799,11 +879,11 @@ void usage(void)
799{ 879{
800 printf("Usage: elftosb [options | file]...\n"); 880 printf("Usage: elftosb [options | file]...\n");
801 printf("Options:\n"); 881 printf("Options:\n");
802 printf(" -?/--help:\t\tDisplay this message\n"); 882 printf(" -?/--help\tDisplay this message\n");
803 printf(" -o <file>\tSet output file\n"); 883 printf(" -o <file>\tSet output file\n");
804 printf(" -c <file>\tSet command file\n"); 884 printf(" -c <file>\tSet command file\n");
805 printf(" -d/--debug\tEnable debug output\n"); 885 printf(" -d/--debug\tEnable debug output\n");
806 printf(" -k <file>\t\tAdd key file\n"); 886 printf(" -k <file>\tAdd key file\n");
807 printf(" -z\t\tAdd zero key\n"); 887 printf(" -z\t\tAdd zero key\n");
808 exit(1); 888 exit(1);
809} 889}
diff --git a/utils/sbtools/sbtoelf.c b/utils/sbtools/sbtoelf.c
index 9a06eade79..4878c73faf 100644
--- a/utils/sbtools/sbtoelf.c
+++ b/utils/sbtools/sbtoelf.c
@@ -260,8 +260,6 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
260 &buf[pos + sizeof(struct sb_instruction_load_t)]); 260 &buf[pos + sizeof(struct sb_instruction_load_t)]);
261 261
262 pos += load->len + sizeof(struct sb_instruction_load_t); 262 pos += load->len + sizeof(struct sb_instruction_load_t);
263 // unsure about rounding
264 pos = ROUND_UP(pos, 16);
265 } 263 }
266 else if(hdr->opcode == SB_INST_FILL) 264 else if(hdr->opcode == SB_INST_FILL)
267 { 265 {
@@ -283,8 +281,6 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
283 elf_add_fill_section(&elf, fill->addr, fill->len, fill->pattern); 281 elf_add_fill_section(&elf, fill->addr, fill->len, fill->pattern);
284 282
285 pos += sizeof(struct sb_instruction_fill_t); 283 pos += sizeof(struct sb_instruction_fill_t);
286 // fixme: useless as pos is a multiple of 16 and fill struct is 4-bytes wide ?
287 pos = ROUND_UP(pos, 16);
288 } 284 }
289 else if(hdr->opcode == SB_INST_CALL || 285 else if(hdr->opcode == SB_INST_CALL ||
290 hdr->opcode == SB_INST_JUMP) 286 hdr->opcode == SB_INST_JUMP)
@@ -311,8 +307,6 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
311 elf_init(&elf); 307 elf_init(&elf);
312 308
313 pos += sizeof(struct sb_instruction_call_t); 309 pos += sizeof(struct sb_instruction_call_t);
314 // fixme: useless as pos is a multiple of 16 and call struct is 4-bytes wide ?
315 pos = ROUND_UP(pos, 16);
316 } 310 }
317 else if(hdr->opcode == SB_INST_MODE) 311 else if(hdr->opcode == SB_INST_MODE)
318 { 312 {
@@ -325,12 +319,20 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
325 color(OFF); 319 color(OFF);
326 pos += sizeof(struct sb_instruction_mode_t); 320 pos += sizeof(struct sb_instruction_mode_t);
327 } 321 }
322 else if(hdr->opcode == SB_INST_NOP)
323 {
324 color(RED);
325 printf("NOOP\n");
326 pos += sizeof(struct sb_instruction_mode_t);
327 }
328 else 328 else
329 { 329 {
330 color(RED); 330 color(RED);
331 printf("Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos); 331 printf("Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos);
332 break; 332 break;
333 } 333 }
334
335 pos = ROUND_UP(pos, BLOCK_SIZE);
334 } 336 }
335 337
336 if(!elf_is_empty(&elf)) 338 if(!elf_is_empty(&elf))
@@ -609,7 +611,7 @@ static void extract(unsigned long filesize)
609 const char *indent = " "; 611 const char *indent = " ";
610 while(true) 612 while(true)
611 { 613 {
612 byte cmd[16]; 614 byte cmd[BLOCK_SIZE];
613 if(sb_header->nr_keys > 0) 615 if(sb_header->nr_keys > 0)
614 cbc_mac(g_buf + offset, cmd, 1, real_key, iv, &iv, 0); 616 cbc_mac(g_buf + offset, cmd, 1, real_key, iv, &iv, 0);
615 else 617 else
@@ -620,7 +622,7 @@ static void extract(unsigned long filesize)
620 if(checksum != hdr->checksum) 622 if(checksum != hdr->checksum)
621 { 623 {
622 color(GREY); 624 color(GREY);
623 printf("[Bad checksum]"); 625 printf("[Bad checksum']");
624 } 626 }
625 627
626 if(hdr->opcode == SB_INST_NOP) 628 if(hdr->opcode == SB_INST_NOP)
@@ -628,6 +630,8 @@ static void extract(unsigned long filesize)
628 color(RED); 630 color(RED);
629 printf("NOOP\n"); 631 printf("NOOP\n");
630 offset += BLOCK_SIZE; 632 offset += BLOCK_SIZE;
633 /* restart with IV */
634 memcpy(iv, g_buf, 16);
631 } 635 }
632 else if(hdr->opcode == SB_INST_TAG) 636 else if(hdr->opcode == SB_INST_TAG)
633 { 637 {