1
0
Fork 0
forked from len0rd/rockbox

sbtoelf: include a raw command mode to see hidden command used by the bootrom (tag and nop)

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29739 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Amaury Pouly 2011-04-17 18:37:23 +00:00
parent c4cb4cca47
commit 8a8d77b8e5
2 changed files with 196 additions and 56 deletions

View file

@ -52,7 +52,7 @@ struct sb_header_t
uint64_t timestamp; /* In microseconds since 2000/1/1 00:00:00 */
struct sb_version_t product_ver;
struct sb_version_t component_ver;
uint16_t drive_tag; /* Unknown meaning */
uint16_t drive_tag; /* first tag to boot ? */
uint8_t rand_pad1[6]; /* Random padding */
} __attribute__((packed));
@ -84,11 +84,19 @@ struct sb_key_dictionary_entry_t
#define SB_INST_CALL 0x5
#define SB_INST_MODE 0x6
/* flags */
#define SB_INST_LAST_TAG 1 /* for TAG */
#define SB_INST_LOAD_DCD 1 /* for LOAD */
#define SB_INST_FILL_BYTE 0 /* for FILL */
#define SB_INST_FILL_HWORD 1 /* for FILL */
#define SB_INST_FILL_WORD 2 /* for FILL */
#define SB_INST_HAB_EXEC 1 /* for JUMP/CALL */
struct sb_instruction_header_t
{
uint8_t checksum;
uint8_t opcode;
uint16_t zero_except_for_tag;
uint16_t flags;
} __attribute__((packed));
struct sb_instruction_load_t
@ -114,3 +122,11 @@ struct sb_instruction_call_t
uint32_t zero;
uint32_t arg;
} __attribute__((packed));
struct sb_instruction_tag_t
{
struct sb_instruction_header_t hdr;
uint32_t identifier; /* section identifier */
uint32_t len; /* length of the section */
uint32_t flags; /* section flags */
} __attribute__((packed));

View file

@ -313,6 +313,18 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
elf_release(&elf);
}
void fill_section_name(char name[5], uint32_t identifier)
{
name[0] = (identifier >> 24) & 0xff;
name[1] = (identifier >> 16) & 0xff;
name[2] = (identifier >> 8) & 0xff;
name[3] = identifier & 0xff;
for(int i = 0; i < 4; i++)
if(!isprint(name[i]))
name[i] = '_';
name[4] = 0;
}
static void extract(unsigned long filesize)
{
struct sha_1_params_t sha_1_params;
@ -404,6 +416,11 @@ static void extract(unsigned long filesize)
color(YELLOW);
printf("%X.%X.%X\n", sb_header->component_ver.major,
sb_header->component_ver.minor, sb_header->component_ver.revision);
color(GREEN);
printf(" Drive tag = ");
color(YELLOW);
printf("%x\n", sb_header->drive_tag);
/* encryption cbc-mac */
key_array_t keys = NULL; /* array of 16-bytes keys */
@ -472,62 +489,165 @@ static void extract(unsigned long filesize)
}
/* sections */
color(BLUE);
printf("Sections\n");
for(int i = 0; i < sb_header->nr_sections; i++)
char *raw_cmd_env = getenv("SB_RAW_CMD");
if(raw_cmd_env == NULL || strcmp(raw_cmd_env, "YES") != 0)
{
uint32_t ofs = sb_header->header_size * BLOCK_SIZE + i * sizeof(struct sb_section_header_t);
struct sb_section_header_t *sec_hdr = (struct sb_section_header_t *)&g_buf[ofs];
char name[5];
name[0] = (sec_hdr->identifier >> 24) & 0xff;
name[1] = (sec_hdr->identifier >> 16) & 0xff;
name[2] = (sec_hdr->identifier >> 8) & 0xff;
name[3] = sec_hdr->identifier & 0xff;
for(int i = 0; i < 4; i++)
if(!isprint(name[i]))
name[i] = '_';
name[4] = 0;
int pos = sec_hdr->offset * BLOCK_SIZE;
int size = sec_hdr->size * BLOCK_SIZE;
int data_sec = !(sec_hdr->flags & SECTION_BOOTABLE);
int encrypted = !(sec_hdr->flags & SECTION_CLEARTEXT);
color(GREEN);
printf(" Section ");
color(YELLOW);
printf("'%s'\n", name);
color(GREEN);
printf(" pos = ");
color(YELLOW);
printf("%8x - %8x\n", pos, pos+size);
color(GREEN);
printf(" len = ");
color(YELLOW);
printf("%8x\n", size);
color(GREEN);
printf(" flags = ");
color(YELLOW);
printf("%8x", sec_hdr->flags);
color(RED);
if(data_sec)
printf(" Data Section");
else
printf(" Boot Section");
if(encrypted)
printf(" (Encrypted)");
printf("\n");
color(BLUE);
printf("Sections\n");
for(int i = 0; i < sb_header->nr_sections; i++)
{
uint32_t ofs = sb_header->header_size * BLOCK_SIZE + i * sizeof(struct sb_section_header_t);
struct sb_section_header_t *sec_hdr = (struct sb_section_header_t *)&g_buf[ofs];
/* save it */
byte *sec = xmalloc(size);
if(encrypted)
cbc_mac(g_buf + pos, sec, size / BLOCK_SIZE, real_key, g_buf, NULL, 0);
else
memcpy(sec, g_buf + pos, size);
char name[5];
fill_section_name(name, sec_hdr->identifier);
int pos = sec_hdr->offset * BLOCK_SIZE;
int size = sec_hdr->size * BLOCK_SIZE;
int data_sec = !(sec_hdr->flags & SECTION_BOOTABLE);
int encrypted = !(sec_hdr->flags & SECTION_CLEARTEXT);
extract_section(data_sec, name, sec, size, " ");
free(sec);
color(GREEN);
printf(" Section ");
color(YELLOW);
printf("'%s'\n", name);
color(GREEN);
printf(" pos = ");
color(YELLOW);
printf("%8x - %8x\n", pos, pos+size);
color(GREEN);
printf(" len = ");
color(YELLOW);
printf("%8x\n", size);
color(GREEN);
printf(" flags = ");
color(YELLOW);
printf("%8x", sec_hdr->flags);
color(RED);
if(data_sec)
printf(" Data Section");
else
printf(" Boot Section");
if(encrypted)
printf(" (Encrypted)");
printf("\n");
/* save it */
byte *sec = xmalloc(size);
if(encrypted)
cbc_mac(g_buf + pos, sec, size / BLOCK_SIZE, real_key, g_buf, NULL, 0);
else
memcpy(sec, g_buf + pos, size);
extract_section(data_sec, name, sec, size, " ");
free(sec);
}
}
else
{
/* advanced raw mode */
color(BLUE);
printf("Commands\n");
uint32_t offset = sizeof(struct sb_header_t)
+ sizeof(struct sb_section_header_t) * sb_header->nr_sections
+ sizeof(struct sb_key_dictionary_entry_t) * sb_header->nr_keys;
byte iv[16];
memcpy(iv, g_buf, 16);
const char *indent = " ";
while(true)
{
byte cmd[16];
if(sb_header->nr_keys > 0)
cbc_mac(g_buf + offset, cmd, 1, real_key, iv, &iv, 0);
else
memcpy(cmd, g_buf + offset, BLOCK_SIZE);
struct sb_instruction_header_t *hdr = (struct sb_instruction_header_t *)cmd;
printf("%s", indent);
uint8_t checksum = instruction_checksum(hdr);
if(checksum != hdr->checksum)
{
color(GREY);
printf("[Bad checksum]");
}
if(hdr->opcode == SB_INST_NOP)
{
color(RED);
printf("NOOP\n");
offset += BLOCK_SIZE;
}
else if(hdr->opcode == SB_INST_TAG)
{
struct sb_instruction_tag_t *tag = (struct sb_instruction_tag_t *)hdr;
color(RED);
printf("BTAG");
color(OFF);printf(" | ");
color(BLUE);
printf("sec=0x%08x", tag->identifier);
color(OFF);printf(" | ");
color(GREEN);
printf("cnt=0x%08x", tag->len);
color(OFF);printf(" | ");
color(YELLOW);
printf("flg=0x%08x\n", tag->flags);
color(OFF);
offset += sizeof(struct sb_instruction_tag_t);
char name[5];
fill_section_name(name, tag->identifier);
int pos = offset;
int size = (tag->len - 1) * BLOCK_SIZE; /* command include itself */
int data_sec = !(tag->flags & SECTION_BOOTABLE);
int encrypted = !(tag->flags & SECTION_CLEARTEXT);
color(GREEN);
printf("%sSection ", indent);
color(YELLOW);
printf("'%s'\n", name);
color(GREEN);
printf("%s pos = ", indent);
color(YELLOW);
printf("%8x - %8x\n", pos, pos+size);
color(GREEN);
printf("%s len = ", indent);
color(YELLOW);
printf("%8x\n", size);
color(GREEN);
printf("%s flags = ", indent);
color(YELLOW);
printf("%8x", tag->flags);
color(RED);
if(data_sec)
printf(" Data Section");
else
printf(" Boot Section");
if(encrypted)
printf(" (Encrypted)");
printf("\n");
/* save it */
byte *sec = xmalloc(size);
if(encrypted)
cbc_mac(g_buf + pos, sec, size / BLOCK_SIZE, real_key, g_buf, NULL, 0);
else
memcpy(sec, g_buf + pos, size);
extract_section(data_sec, name, sec, size, " ");
free(sec);
/* last one ? */
if(tag->hdr.flags & SB_INST_LAST_TAG)
break;
offset += size;
/* restart with IV */
memcpy(iv, g_buf, 16);
}
else
{
color(RED);
printf("Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset);
break;
}
}
}
/* final signature */
@ -565,7 +685,11 @@ int main(int argc, const char **argv)
int fd;
struct stat st;
if(argc != 3 && argc != 4)
bug("Usage: %s <firmware> <key file> [<out prefix>]\n",*argv);
{
printf("Usage: %s <firmware> <key file> [<out prefix>]\n",*argv);
printf("To use raw command mode, set environment variable SB_RAW_CMD to YES\n");
return 1;
}
if(argc == 4)
snprintf(out_prefix, PREFIX_SIZE, "%s", argv[3]);