diff options
Diffstat (limited to 'utils/sbtools/sbtoelf.c')
-rw-r--r-- | utils/sbtools/sbtoelf.c | 232 |
1 files changed, 178 insertions, 54 deletions
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 | ||
316 | void 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 | |||
316 | static void extract(unsigned long filesize) | 328 | static 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]); |