1
0
Fork 0
forked from len0rd/rockbox

sbtools: add missing cariage return, implement boot mode command, add C++ style comments support

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30192 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Amaury Pouly 2011-07-22 15:45:08 +00:00
parent 146e2eb089
commit 56bc02c7a2
2 changed files with 114 additions and 43 deletions

View file

@ -38,7 +38,10 @@
#include "elf.h" #include "elf.h"
#include "sb.h" #include "sb.h"
#define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0) #define _STR(a) #a
#define STR(a) _STR(a)
#define bug(...) do { fprintf(stderr,"["__FILE__":"STR(__LINE__)"]ERROR: "__VA_ARGS__); exit(1); } while(0)
#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0) #define bugp(a) do { perror("ERROR: "a); exit(1); } while(0)
bool g_debug = false; bool g_debug = false;
@ -197,13 +200,14 @@ enum cmd_inst_type_t
CMD_LOAD_AT, /* load binary at */ CMD_LOAD_AT, /* load binary at */
CMD_CALL_AT, /* call at address */ CMD_CALL_AT, /* call at address */
CMD_JUMP_AT, /* jump at address */ CMD_JUMP_AT, /* jump at address */
CMD_MODE, /* change boot mode */
}; };
struct cmd_inst_t struct cmd_inst_t
{ {
enum cmd_inst_type_t type; enum cmd_inst_type_t type;
char *identifier; char *identifier;
uint32_t argument; // for jump, call uint32_t argument; // for jump, call, mode
uint32_t addr; // for 'at' uint32_t addr; // for 'at'
struct cmd_inst_t *next; struct cmd_inst_t *next;
}; };
@ -253,18 +257,18 @@ static void __parse_string(char **ptr, char *end, void *user, void (*emit_fn)(vo
{ {
(*ptr)++; (*ptr)++;
if(*ptr == end) if(*ptr == end)
bug("Unfinished string"); bug("Unfinished string\n");
if(**ptr == '\\') emit_fn(user, '\\'); if(**ptr == '\\') emit_fn(user, '\\');
else if(**ptr == '\'') emit_fn(user, '\''); else if(**ptr == '\'') emit_fn(user, '\'');
else if(**ptr == '\"') emit_fn(user, '\"'); else if(**ptr == '\"') emit_fn(user, '\"');
else bug("Unknown escape sequence \\%c", **ptr); else bug("Unknown escape sequence \\%c\n", **ptr);
(*ptr)++; (*ptr)++;
} }
else else
emit_fn(user, *(*ptr)++); emit_fn(user, *(*ptr)++);
} }
if(*ptr == end || **ptr != '"') if(*ptr == end || **ptr != '"')
bug("unfinished string"); bug("unfinished string\n");
(*ptr)++; (*ptr)++;
} }
@ -315,9 +319,9 @@ static void parse_ascii_number(char **ptr, char *end, struct lexem_t *lexem)
break; break;
} }
if(*ptr == end || **ptr != '\'') if(*ptr == end || **ptr != '\'')
bug("Unterminated ascii number literal"); bug("Unterminated ascii number literal\n");
if(len != 1 && len != 2 && len != 4) if(len != 1 && len != 2 && len != 4)
bug("Invalid ascii number literal length: only 1, 2 or 4 are valid"); bug("Invalid ascii number literal length: only 1, 2 or 4 are valid\n");
/* skip ' */ /* skip ' */
(*ptr)++; (*ptr)++;
lexem->type = LEX_NUMBER; lexem->type = LEX_NUMBER;
@ -371,13 +375,30 @@ static void next_lexem(char **ptr, char *end, struct lexem_t *lexem)
(*ptr)++; (*ptr)++;
continue; continue;
} }
/* skip comments */ /* skip C++ style comments */
if(**ptr == '/' && (*ptr) + 1 != end && (*ptr)[1] == '/') if(**ptr == '/' && (*ptr) + 1 != end && (*ptr)[1] == '/')
{ {
while(*ptr != end && **ptr != '\n') while(*ptr != end && **ptr != '\n')
(*ptr)++; (*ptr)++;
continue; continue;
} }
/* skip C-style comments */
if(**ptr == '/' && (*ptr) + 1 != end && (*ptr)[1] == '*')
{
(*ptr) += 2;
if(*ptr == end)
bug("invalid command file: unterminated comment");
while(true)
{
if(**ptr == '*' && (*ptr) + 1 != end && (*ptr)[1] == '/')
{
(*ptr) += 2;
break;
}
(*ptr)++;
}
continue;
}
break; break;
} }
if(*ptr == end) ret_simple(LEX_EOF, 0); if(*ptr == end) ret_simple(LEX_EOF, 0);
@ -455,10 +476,10 @@ static struct cmd_file_t *read_command_file(const char *file)
/* sources */ /* sources */
next(); next();
if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "sources") != 0) if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "sources") != 0)
bug("invalid command file: 'sources' expected"); bug("invalid command file: 'sources' expected\n");
next(); next();
if(lexem.type != LEX_LBRACE) if(lexem.type != LEX_LBRACE)
bug("invalid command file: '{' expected after 'sources'"); bug("invalid command file: '{' expected after 'sources'\n");
while(true) while(true)
{ {
@ -469,20 +490,20 @@ static struct cmd_file_t *read_command_file(const char *file)
memset(src, 0, sizeof(struct cmd_source_t)); memset(src, 0, sizeof(struct cmd_source_t));
src->next = cmd_file->source_list; src->next = cmd_file->source_list;
if(lexem.type != LEX_IDENTIFIER) if(lexem.type != LEX_IDENTIFIER)
bug("invalid command file: identifier expected in sources"); bug("invalid command file: identifier expected in sources\n");
src->identifier = lexem.str; src->identifier = lexem.str;
next(); next();
if(lexem.type != LEX_EQUAL) if(lexem.type != LEX_EQUAL)
bug("invalid command file: '=' expected after identifier"); bug("invalid command file: '=' expected after identifier\n");
next(); next();
if(lexem.type != LEX_STRING) if(lexem.type != LEX_STRING)
bug("invalid command file: string expected after '='"); bug("invalid command file: string expected after '='\n");
src->filename = lexem.str; src->filename = lexem.str;
next(); next();
if(lexem.type != LEX_SEMICOLON) if(lexem.type != LEX_SEMICOLON)
bug("invalid command file: ';' expected after string"); bug("invalid command file: ';' expected after string\n");
if(find_source_by_id(cmd_file, src->identifier) != NULL) if(find_source_by_id(cmd_file, src->identifier) != NULL)
bug("invalid command file: duplicated source identifier"); bug("invalid command file: duplicated source identifier\n");
/* type filled later */ /* type filled later */
src->type = CMD_SRC_UNK; src->type = CMD_SRC_UNK;
cmd_file->source_list = src; cmd_file->source_list = src;
@ -499,10 +520,10 @@ static struct cmd_file_t *read_command_file(const char *file)
if(lexem.type == LEX_EOF) if(lexem.type == LEX_EOF)
break; break;
if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "section") != 0) if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "section") != 0)
bug("invalid command file: 'section' expected"); bug("invalid command file: 'section' expected\n");
next(); next();
if(lexem.type != LEX_LPAREN) if(lexem.type != LEX_LPAREN)
bug("invalid command file: '(' expected after 'section'"); bug("invalid command file: '(' expected after 'section'\n");
next(); next();
/* can be a number or a 4 character long string */ /* can be a number or a 4 character long string */
if(lexem.type == LEX_NUMBER) if(lexem.type == LEX_NUMBER)
@ -510,14 +531,14 @@ static struct cmd_file_t *read_command_file(const char *file)
sec->identifier = lexem.num; sec->identifier = lexem.num;
} }
else else
bug("invalid command file: number expected as section identifier"); bug("invalid command file: number expected as section identifier\n");
next(); next();
if(lexem.type != LEX_RPAREN) if(lexem.type != LEX_RPAREN)
bug("invalid command file: ')' expected after section identifier"); bug("invalid command file: ')' expected after section identifier\n");
next(); next();
if(lexem.type != LEX_LBRACE) if(lexem.type != LEX_LBRACE)
bug("invalid command file: '{' expected after section directive"); bug("invalid command file: '{' expected after section directive\n");
/* commands */ /* commands */
while(true) while(true)
{ {
@ -527,24 +548,26 @@ static struct cmd_file_t *read_command_file(const char *file)
if(lexem.type == LEX_RBRACE) if(lexem.type == LEX_RBRACE)
break; break;
if(lexem.type != LEX_IDENTIFIER) if(lexem.type != LEX_IDENTIFIER)
bug("invalid command file: instruction expected in section"); bug("invalid command file: instruction expected in section\n");
if(strcmp(lexem.str, "load") == 0) if(strcmp(lexem.str, "load") == 0)
inst->type = CMD_LOAD; inst->type = CMD_LOAD;
else if(strcmp(lexem.str, "call") == 0) else if(strcmp(lexem.str, "call") == 0)
inst->type = CMD_CALL; inst->type = CMD_CALL;
else if(strcmp(lexem.str, "jump") == 0) else if(strcmp(lexem.str, "jump") == 0)
inst->type = CMD_JUMP; inst->type = CMD_JUMP;
else if(strcmp(lexem.str, "mode") == 0)
inst->type = CMD_MODE;
else else
bug("invalid command file: instruction expected in section"); bug("invalid command file: instruction expected in section\n");
next(); next();
if(inst->type == CMD_LOAD) if(inst->type == CMD_LOAD)
{ {
if(lexem.type != LEX_IDENTIFIER) if(lexem.type != LEX_IDENTIFIER)
bug("invalid command file: identifier expected after instruction"); bug("invalid command file: identifier expected after instruction\n");
inst->identifier = lexem.str; inst->identifier = lexem.str;
if(find_source_by_id(cmd_file, inst->identifier) == NULL) if(find_source_by_id(cmd_file, inst->identifier) == NULL)
bug("invalid command file: undefined reference to source '%s'", inst->identifier); bug("invalid command file: undefined reference to source '%s'\n", inst->identifier);
next(); next();
if(lexem.type == LEX_RANGLE) if(lexem.type == LEX_RANGLE)
{ {
@ -552,12 +575,12 @@ static struct cmd_file_t *read_command_file(const char *file)
inst->type = CMD_LOAD_AT; inst->type = CMD_LOAD_AT;
next(); next();
if(lexem.type != LEX_NUMBER) if(lexem.type != LEX_NUMBER)
bug("invalid command file: number expected for loading address"); bug("invalid command file: number expected for loading address\n");
inst->addr = lexem.num; inst->addr = lexem.num;
next(); next();
} }
if(lexem.type != LEX_SEMICOLON) if(lexem.type != LEX_SEMICOLON)
bug("invalid command file: expected ';' after command"); bug("invalid command file: expected ';' after command\n");
} }
else if(inst->type == CMD_CALL || inst->type == CMD_JUMP) else if(inst->type == CMD_CALL || inst->type == CMD_JUMP)
{ {
@ -565,7 +588,7 @@ static struct cmd_file_t *read_command_file(const char *file)
{ {
inst->identifier = lexem.str; inst->identifier = lexem.str;
if(find_source_by_id(cmd_file, inst->identifier) == NULL) if(find_source_by_id(cmd_file, inst->identifier) == NULL)
bug("invalid command file: undefined reference to source '%s'", inst->identifier); bug("invalid command file: undefined reference to source '%s'\n", inst->identifier);
next(); next();
} }
else if(lexem.type == LEX_NUMBER) else if(lexem.type == LEX_NUMBER)
@ -575,24 +598,33 @@ static struct cmd_file_t *read_command_file(const char *file)
next(); next();
} }
else else
bug("invalid command file: identifier or number expected after jump/load"); bug("invalid command file: identifier or number expected after jump/load\n");
if(lexem.type == LEX_LPAREN) if(lexem.type == LEX_LPAREN)
{ {
next(); next();
if(lexem.type != LEX_NUMBER) if(lexem.type != LEX_NUMBER)
bug("invalid command file: expected numeral expression after ("); bug("invalid command file: expected numeral expression after (\n");
inst->argument = lexem.num; inst->argument = lexem.num;
next(); next();
if(lexem.type != LEX_RPAREN) if(lexem.type != LEX_RPAREN)
bug("invalid command file: expected closing brace"); bug("invalid command file: expected closing brace\n");
next(); next();
} }
if(lexem.type != LEX_SEMICOLON) if(lexem.type != LEX_SEMICOLON)
bug("invalid command file: expected ';' after command"); bug("invalid command file: expected ';' after command\n");
}
else if(inst->type == CMD_MODE)
{
if(lexem.type != LEX_NUMBER)
bug("invalid command file: number expected after 'mode'\n");
inst->argument = lexem.num;
next();
if(lexem.type != LEX_SEMICOLON)
bug("invalid command file: expected ';' after command\n");
} }
else else
bug("die"); bug("die\n");
if(end_list == NULL) if(end_list == NULL)
{ {
sec->inst_list = inst; sec->inst_list = inst;
@ -685,7 +717,7 @@ static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id)
if(src->type == CMD_SRC_ELF && src->loaded) if(src->type == CMD_SRC_ELF && src->loaded)
return; return;
if(src->type != CMD_SRC_UNK) if(src->type != CMD_SRC_UNK)
bug("source '%s' seen both as elf and binary file", id); bug("source '%s' seen both as elf and binary file\n", id);
src->type = CMD_SRC_ELF; src->type = CMD_SRC_ELF;
int fd = open(src->filename, O_RDONLY); int fd = open(src->filename, O_RDONLY);
if(fd < 0) if(fd < 0)
@ -708,7 +740,7 @@ static void load_bin_by_id(struct cmd_file_t *cmd_file, const char *id)
if(src->type == CMD_SRC_BIN && src->loaded) if(src->type == CMD_SRC_BIN && src->loaded)
return; return;
if(src->type != CMD_SRC_UNK) if(src->type != CMD_SRC_UNK)
bug("source '%s' seen both as elf and binary file", id); bug("source '%s' seen both as elf and binary file\n", id);
src->type = CMD_SRC_BIN; src->type = CMD_SRC_BIN;
int fd = open(src->filename, O_RDONLY); int fd = open(src->filename, O_RDONLY);
if(fd < 0) if(fd < 0)
@ -773,8 +805,12 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
load_bin_by_id(cmd_file, cinst->identifier); load_bin_by_id(cmd_file, cinst->identifier);
sec->nr_insts++; sec->nr_insts++;
} }
else if(cinst->type == CMD_MODE)
{
sec->nr_insts++;
}
else else
bug("die"); bug("die\n");
cinst = cinst->next; cinst = cinst->next;
} }
@ -830,8 +866,13 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
sec->insts[idx].data = bin->data; sec->insts[idx].data = bin->data;
sec->insts[idx++].size = bin->size; sec->insts[idx++].size = bin->size;
} }
else if(cinst->type == CMD_MODE)
{
sec->insts[idx].inst = SB_INST_MODE;
sec->insts[idx++].addr = cinst->argument;
}
else else
bug("die"); bug("die\n");
cinst = cinst->next; cinst = cinst->next;
} }
@ -909,6 +950,15 @@ static void compute_sb_offsets(struct sb_file_t *sb)
sb->image_size += (inst->size + inst->padding_size) / BLOCK_SIZE; sb->image_size += (inst->size + inst->padding_size) / BLOCK_SIZE;
sec->sec_size += (inst->size + inst->padding_size) / BLOCK_SIZE; sec->sec_size += (inst->size + inst->padding_size) / BLOCK_SIZE;
} }
else if(inst->inst == SB_INST_MODE)
{
if(g_debug)
printf("MODE | mod=0x%08x", inst->addr);
sb->image_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE;
sec->sec_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE;
}
else
bug("die on inst %d\n", inst->inst);
} }
} }
/* final signature */ /* final signature */
@ -999,26 +1049,31 @@ static void produce_section_tag_cmd(struct sb_section_t *sec,
void produce_sb_instruction(struct sb_inst_t *inst, void produce_sb_instruction(struct sb_inst_t *inst,
struct sb_instruction_common_t *cmd) struct sb_instruction_common_t *cmd)
{ {
cmd->hdr.flags = 0; memset(cmd, 0, sizeof(struct sb_instruction_common_t));
cmd->hdr.opcode = inst->inst; cmd->hdr.opcode = inst->inst;
cmd->addr = inst->addr;
cmd->len = inst->size;
switch(inst->inst) switch(inst->inst)
{ {
case SB_INST_CALL: case SB_INST_CALL:
case SB_INST_JUMP: case SB_INST_JUMP:
cmd->len = 0; cmd->addr = inst->addr;
cmd->data = inst->argument; cmd->data = inst->argument;
break; break;
case SB_INST_FILL: case SB_INST_FILL:
cmd->addr = inst->addr;
cmd->len = inst->size;
cmd->data = inst->pattern; cmd->data = inst->pattern;
break; break;
case SB_INST_LOAD: case SB_INST_LOAD:
cmd->addr = inst->addr;
cmd->len = inst->size;
cmd->data = crc_continue(crc(inst->data, inst->size), cmd->data = crc_continue(crc(inst->data, inst->size),
inst->padding, inst->padding_size); inst->padding, inst->padding_size);
break; break;
default: case SB_INST_MODE:
cmd->data = inst->addr;
break; break;
default:
bug("die\n");
} }
cmd->hdr.checksum = instruction_checksum(&cmd->hdr); cmd->hdr.checksum = instruction_checksum(&cmd->hdr);
} }

View file

@ -224,7 +224,15 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
color(GREY); color(GREY);
printf("[Bad checksum]"); printf("[Bad checksum]");
} }
if(hdr->flags != 0)
{
color(GREY);
printf("[");
color(BLUE);
printf("f=%x", hdr->flags);
color(GREY);
printf("] ");
}
if(hdr->opcode == SB_INST_LOAD) if(hdr->opcode == SB_INST_LOAD)
{ {
struct sb_instruction_load_t *load = (struct sb_instruction_load_t *)&buf[pos]; struct sb_instruction_load_t *load = (struct sb_instruction_load_t *)&buf[pos];
@ -612,8 +620,16 @@ static void extract(unsigned long filesize)
printf("cnt=0x%08x", tag->len); printf("cnt=0x%08x", tag->len);
color(OFF);printf(" | "); color(OFF);printf(" | ");
color(YELLOW); color(YELLOW);
printf("flg=0x%08x\n", tag->flags); printf("flg=0x%08x", tag->flags);
color(OFF); color(OFF);
if(tag->hdr.flags & SB_INST_LAST_TAG)
{
printf(" | ");
color(RED);
printf(" Last section");
color(OFF);
}
printf("\n");
offset += sizeof(struct sb_instruction_tag_t); offset += sizeof(struct sb_instruction_tag_t);
char name[5]; char name[5];