summaryrefslogtreecommitdiff
path: root/utils/sbtools
diff options
context:
space:
mode:
Diffstat (limited to 'utils/sbtools')
-rw-r--r--utils/sbtools/sb.h20
-rw-r--r--utils/sbtools/sbtoelf.c232
2 files changed, 196 insertions, 56 deletions
diff --git a/utils/sbtools/sb.h b/utils/sbtools/sb.h
index be25b4bf88..01ee0e642f 100644
--- a/utils/sbtools/sb.h
+++ b/utils/sbtools/sb.h
@@ -52,7 +52,7 @@ struct sb_header_t
52 uint64_t timestamp; /* In microseconds since 2000/1/1 00:00:00 */ 52 uint64_t timestamp; /* In microseconds since 2000/1/1 00:00:00 */
53 struct sb_version_t product_ver; 53 struct sb_version_t product_ver;
54 struct sb_version_t component_ver; 54 struct sb_version_t component_ver;
55 uint16_t drive_tag; /* Unknown meaning */ 55 uint16_t drive_tag; /* first tag to boot ? */
56 uint8_t rand_pad1[6]; /* Random padding */ 56 uint8_t rand_pad1[6]; /* Random padding */
57} __attribute__((packed)); 57} __attribute__((packed));
58 58
@@ -84,11 +84,19 @@ struct sb_key_dictionary_entry_t
84#define SB_INST_CALL 0x5 84#define SB_INST_CALL 0x5
85#define SB_INST_MODE 0x6 85#define SB_INST_MODE 0x6
86 86
87/* flags */
88#define SB_INST_LAST_TAG 1 /* for TAG */
89#define SB_INST_LOAD_DCD 1 /* for LOAD */
90#define SB_INST_FILL_BYTE 0 /* for FILL */
91#define SB_INST_FILL_HWORD 1 /* for FILL */
92#define SB_INST_FILL_WORD 2 /* for FILL */
93#define SB_INST_HAB_EXEC 1 /* for JUMP/CALL */
94
87struct sb_instruction_header_t 95struct sb_instruction_header_t
88{ 96{
89 uint8_t checksum; 97 uint8_t checksum;
90 uint8_t opcode; 98 uint8_t opcode;
91 uint16_t zero_except_for_tag; 99 uint16_t flags;
92} __attribute__((packed)); 100} __attribute__((packed));
93 101
94struct sb_instruction_load_t 102struct sb_instruction_load_t
@@ -114,3 +122,11 @@ struct sb_instruction_call_t
114 uint32_t zero; 122 uint32_t zero;
115 uint32_t arg; 123 uint32_t arg;
116} __attribute__((packed)); 124} __attribute__((packed));
125
126struct sb_instruction_tag_t
127{
128 struct sb_instruction_header_t hdr;
129 uint32_t identifier; /* section identifier */
130 uint32_t len; /* length of the section */
131 uint32_t flags; /* section flags */
132} __attribute__((packed));
diff --git a/utils/sbtools/sbtoelf.c b/utils/sbtools/sbtoelf.c
index 3a3d9a7bb7..b430e07eb7 100644
--- a/utils/sbtools/sbtoelf.c
+++ b/utils/sbtools/sbtoelf.c
@@ -313,6 +313,18 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
313 elf_release(&elf); 313 elf_release(&elf);
314} 314}
315 315
316void fill_section_name(char name[5], uint32_t identifier)
317{
318 name[0] = (identifier >> 24) & 0xff;
319 name[1] = (identifier >> 16) & 0xff;
320 name[2] = (identifier >> 8) & 0xff;
321 name[3] = identifier & 0xff;
322 for(int i = 0; i < 4; i++)
323 if(!isprint(name[i]))
324 name[i] = '_';
325 name[4] = 0;
326}
327
316static void extract(unsigned long filesize) 328static void extract(unsigned long filesize)
317{ 329{
318 struct sha_1_params_t sha_1_params; 330 struct sha_1_params_t sha_1_params;
@@ -404,6 +416,11 @@ static void extract(unsigned long filesize)
404 color(YELLOW); 416 color(YELLOW);
405 printf("%X.%X.%X\n", sb_header->component_ver.major, 417 printf("%X.%X.%X\n", sb_header->component_ver.major,
406 sb_header->component_ver.minor, sb_header->component_ver.revision); 418 sb_header->component_ver.minor, sb_header->component_ver.revision);
419
420 color(GREEN);
421 printf(" Drive tag = ");
422 color(YELLOW);
423 printf("%x\n", sb_header->drive_tag);
407 424
408 /* encryption cbc-mac */ 425 /* encryption cbc-mac */
409 key_array_t keys = NULL; /* array of 16-bytes keys */ 426 key_array_t keys = NULL; /* array of 16-bytes keys */
@@ -472,62 +489,165 @@ static void extract(unsigned long filesize)
472 } 489 }
473 490
474 /* sections */ 491 /* sections */
475 color(BLUE); 492 char *raw_cmd_env = getenv("SB_RAW_CMD");
476 printf("Sections\n"); 493 if(raw_cmd_env == NULL || strcmp(raw_cmd_env, "YES") != 0)
477
478 for(int i = 0; i < sb_header->nr_sections; i++)
479 { 494 {
480 uint32_t ofs = sb_header->header_size * BLOCK_SIZE + i * sizeof(struct sb_section_header_t); 495 color(BLUE);
481 struct sb_section_header_t *sec_hdr = (struct sb_section_header_t *)&g_buf[ofs]; 496 printf("Sections\n");
482 497 for(int i = 0; i < sb_header->nr_sections; i++)
483 char name[5]; 498 {
484 name[0] = (sec_hdr->identifier >> 24) & 0xff; 499 uint32_t ofs = sb_header->header_size * BLOCK_SIZE + i * sizeof(struct sb_section_header_t);
485 name[1] = (sec_hdr->identifier >> 16) & 0xff; 500 struct sb_section_header_t *sec_hdr = (struct sb_section_header_t *)&g_buf[ofs];
486 name[2] = (sec_hdr->identifier >> 8) & 0xff;
487 name[3] = sec_hdr->identifier & 0xff;
488 for(int i = 0; i < 4; i++)
489 if(!isprint(name[i]))
490 name[i] = '_';
491 name[4] = 0;
492 int pos = sec_hdr->offset * BLOCK_SIZE;
493 int size = sec_hdr->size * BLOCK_SIZE;
494 int data_sec = !(sec_hdr->flags & SECTION_BOOTABLE);
495 int encrypted = !(sec_hdr->flags & SECTION_CLEARTEXT);
496
497 color(GREEN);
498 printf(" Section ");
499 color(YELLOW);
500 printf("'%s'\n", name);
501 color(GREEN);
502 printf(" pos = ");
503 color(YELLOW);
504 printf("%8x - %8x\n", pos, pos+size);
505 color(GREEN);
506 printf(" len = ");
507 color(YELLOW);
508 printf("%8x\n", size);
509 color(GREEN);
510 printf(" flags = ");
511 color(YELLOW);
512 printf("%8x", sec_hdr->flags);
513 color(RED);
514 if(data_sec)
515 printf(" Data Section");
516 else
517 printf(" Boot Section");
518 if(encrypted)
519 printf(" (Encrypted)");
520 printf("\n");
521 501
522 /* save it */ 502 char name[5];
523 byte *sec = xmalloc(size); 503 fill_section_name(name, sec_hdr->identifier);
524 if(encrypted) 504 int pos = sec_hdr->offset * BLOCK_SIZE;
525 cbc_mac(g_buf + pos, sec, size / BLOCK_SIZE, real_key, g_buf, NULL, 0); 505 int size = sec_hdr->size * BLOCK_SIZE;
526 else 506 int data_sec = !(sec_hdr->flags & SECTION_BOOTABLE);
527 memcpy(sec, g_buf + pos, size); 507 int encrypted = !(sec_hdr->flags & SECTION_CLEARTEXT);
528 508
529 extract_section(data_sec, name, sec, size, " "); 509 color(GREEN);
530 free(sec); 510 printf(" Section ");
511 color(YELLOW);
512 printf("'%s'\n", name);
513 color(GREEN);
514 printf(" pos = ");
515 color(YELLOW);
516 printf("%8x - %8x\n", pos, pos+size);
517 color(GREEN);
518 printf(" len = ");
519 color(YELLOW);
520 printf("%8x\n", size);
521 color(GREEN);
522 printf(" flags = ");
523 color(YELLOW);
524 printf("%8x", sec_hdr->flags);
525 color(RED);
526 if(data_sec)
527 printf(" Data Section");
528 else
529 printf(" Boot Section");
530 if(encrypted)
531 printf(" (Encrypted)");
532 printf("\n");
533
534 /* save it */
535 byte *sec = xmalloc(size);
536 if(encrypted)
537 cbc_mac(g_buf + pos, sec, size / BLOCK_SIZE, real_key, g_buf, NULL, 0);
538 else
539 memcpy(sec, g_buf + pos, size);
540
541 extract_section(data_sec, name, sec, size, " ");
542 free(sec);
543 }
544 }
545 else
546 {
547 /* advanced raw mode */
548 color(BLUE);
549 printf("Commands\n");
550 uint32_t offset = sizeof(struct sb_header_t)
551 + sizeof(struct sb_section_header_t) * sb_header->nr_sections
552 + sizeof(struct sb_key_dictionary_entry_t) * sb_header->nr_keys;
553 byte iv[16];
554 memcpy(iv, g_buf, 16);
555 const char *indent = " ";
556 while(true)
557 {
558 byte cmd[16];
559 if(sb_header->nr_keys > 0)
560 cbc_mac(g_buf + offset, cmd, 1, real_key, iv, &iv, 0);
561 else
562 memcpy(cmd, g_buf + offset, BLOCK_SIZE);
563 struct sb_instruction_header_t *hdr = (struct sb_instruction_header_t *)cmd;
564 printf("%s", indent);
565 uint8_t checksum = instruction_checksum(hdr);
566 if(checksum != hdr->checksum)
567 {
568 color(GREY);
569 printf("[Bad checksum]");
570 }
571
572 if(hdr->opcode == SB_INST_NOP)
573 {
574 color(RED);
575 printf("NOOP\n");
576 offset += BLOCK_SIZE;
577 }
578 else if(hdr->opcode == SB_INST_TAG)
579 {
580 struct sb_instruction_tag_t *tag = (struct sb_instruction_tag_t *)hdr;
581 color(RED);
582 printf("BTAG");
583 color(OFF);printf(" | ");
584 color(BLUE);
585 printf("sec=0x%08x", tag->identifier);
586 color(OFF);printf(" | ");
587 color(GREEN);
588 printf("cnt=0x%08x", tag->len);
589 color(OFF);printf(" | ");
590 color(YELLOW);
591 printf("flg=0x%08x\n", tag->flags);
592 color(OFF);
593 offset += sizeof(struct sb_instruction_tag_t);
594
595 char name[5];
596 fill_section_name(name, tag->identifier);
597 int pos = offset;
598 int size = (tag->len - 1) * BLOCK_SIZE; /* command include itself */
599 int data_sec = !(tag->flags & SECTION_BOOTABLE);
600 int encrypted = !(tag->flags & SECTION_CLEARTEXT);
601
602 color(GREEN);
603 printf("%sSection ", indent);
604 color(YELLOW);
605 printf("'%s'\n", name);
606 color(GREEN);
607 printf("%s pos = ", indent);
608 color(YELLOW);
609 printf("%8x - %8x\n", pos, pos+size);
610 color(GREEN);
611 printf("%s len = ", indent);
612 color(YELLOW);
613 printf("%8x\n", size);
614 color(GREEN);
615 printf("%s flags = ", indent);
616 color(YELLOW);
617 printf("%8x", tag->flags);
618 color(RED);
619 if(data_sec)
620 printf(" Data Section");
621 else
622 printf(" Boot Section");
623 if(encrypted)
624 printf(" (Encrypted)");
625 printf("\n");
626
627 /* save it */
628 byte *sec = xmalloc(size);
629 if(encrypted)
630 cbc_mac(g_buf + pos, sec, size / BLOCK_SIZE, real_key, g_buf, NULL, 0);
631 else
632 memcpy(sec, g_buf + pos, size);
633
634 extract_section(data_sec, name, sec, size, " ");
635 free(sec);
636
637 /* last one ? */
638 if(tag->hdr.flags & SB_INST_LAST_TAG)
639 break;
640 offset += size;
641 /* restart with IV */
642 memcpy(iv, g_buf, 16);
643 }
644 else
645 {
646 color(RED);
647 printf("Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset);
648 break;
649 }
650 }
531 } 651 }
532 652
533 /* final signature */ 653 /* final signature */
@@ -565,7 +685,11 @@ int main(int argc, const char **argv)
565 int fd; 685 int fd;
566 struct stat st; 686 struct stat st;
567 if(argc != 3 && argc != 4) 687 if(argc != 3 && argc != 4)
568 bug("Usage: %s <firmware> <key file> [<out prefix>]\n",*argv); 688 {
689 printf("Usage: %s <firmware> <key file> [<out prefix>]\n",*argv);
690 printf("To use raw command mode, set environment variable SB_RAW_CMD to YES\n");
691 return 1;
692 }
569 693
570 if(argc == 4) 694 if(argc == 4)
571 snprintf(out_prefix, PREFIX_SIZE, "%s", argv[3]); 695 snprintf(out_prefix, PREFIX_SIZE, "%s", argv[3]);