summaryrefslogtreecommitdiff
path: root/utils/sbtools
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2011-04-17 18:37:30 +0000
committerAmaury Pouly <pamaury@rockbox.org>2011-04-17 18:37:30 +0000
commite3fe3956f6c9c244ccbc57d1ddce7b2202b373f4 (patch)
treed7ce4f48d839157888f6f1ce7084e39473e60117 /utils/sbtools
parent8bff25945bfceaeace132998aa98f6d1022aa3e9 (diff)
elftosb: more code toward sb production
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29741 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/sbtools')
-rw-r--r--utils/sbtools/elftosb.c110
1 files changed, 95 insertions, 15 deletions
diff --git a/utils/sbtools/elftosb.c b/utils/sbtools/elftosb.c
index c4887ab47a..275f21724d 100644
--- a/utils/sbtools/elftosb.c
+++ b/utils/sbtools/elftosb.c
@@ -80,6 +80,9 @@ static int convxdigit(char digit, byte *val)
typedef byte (*key_array_t)[16];
+int g_nr_keys;
+key_array_t g_key_array;
+
static key_array_t read_keys(const char *key_file, int *num_keys)
{
int size;
@@ -499,12 +502,16 @@ struct sb_section_t
uint32_t identifier;
int nr_insts;
struct sb_inst_t *insts;
+ /* for production use */
+ uint32_t file_offset; /* in blocks */
};
struct sb_file_t
{
int nr_sections;
struct sb_section_t *sections;
+ /* for production use */
+ uint32_t image_size; /* in blocks */
};
static bool elf_read(void *user, uint32_t addr, void *buf, size_t count)
@@ -572,7 +579,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
if(cinst->type == CMD_LOAD)
sec->nr_insts += elf_get_nr_sections(elf);
- else if(cinst->type == CMD_JUMP || cinst->type == CMD_LOAD)
+ else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL)
{
if(!elf_get_start_addr(elf, NULL))
bug("cannot jump/call '%s' because it has no starting point !", cinst->identifier);
@@ -602,9 +609,6 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
sec->insts[idx].addr = esec->addr;
sec->insts[idx].size = esec->size;
sec->insts[idx++].data = esec->section;
- if(g_debug)
- printf("LOAD | addr=0x%08x | len=0x%08x | crc=0x%08x\n",
- esec->addr, esec->size, 0);
}
else if(esec->type == EST_FILL)
{
@@ -612,21 +616,14 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
sec->insts[idx].addr = esec->addr;
sec->insts[idx].size = esec->size;
sec->insts[idx++].pattern = esec->pattern;
- if(g_debug)
- printf("FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n",
- esec->addr, esec->size, esec->pattern);
}
esec = esec->next;
}
}
- else if(cinst->type == CMD_JUMP || cinst->type == CMD_LOAD)
+ else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL)
{
sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL;
sec->insts[idx++].addr = elf->start_addr;
- if(g_debug)
- printf("%s | addr=0x%08x | arg=0x%08x\n",
- (cinst->type == CMD_JUMP) ? "JUMP" : "CALL",
- elf->start_addr, 0);
}
cinst = cinst->next;
@@ -640,6 +637,82 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
* Sb file production
*/
+static void compute_sb_offsets(struct sb_file_t *sb)
+{
+ sb->image_size = 0;
+ /* sb header */
+ sb->image_size += sizeof(struct sb_header_t) / BLOCK_SIZE;
+ /* sections headers */
+ sb->image_size += sb->nr_sections * sizeof(struct sb_section_header_t) / BLOCK_SIZE;
+ /* key dictionary */
+ sb->image_size += g_nr_keys * sizeof(struct sb_key_dictionary_entry_t) / BLOCK_SIZE;
+ /* sections */
+ for(int i = 0; i < sb->nr_sections; i++)
+ {
+ /* each section has a preliminary TAG command */
+ sb->image_size += sizeof(struct sb_instruction_tag_t) / BLOCK_SIZE;
+
+ struct sb_section_t *sec = &sb->sections[i];
+ sec->file_offset = sb->image_size;
+ for(int j = 0; j < sec->nr_insts; j++)
+ {
+ struct sb_inst_t *inst = &sec->insts[j];
+ if(inst->inst == SB_INST_CALL || inst->inst == SB_INST_JUMP)
+ {
+ if(g_debug)
+ printf("%s | addr=0x%08x | arg=0x%08x\n",
+ inst->inst == SB_INST_CALL ? "CALL" : "JUMP", inst->addr, 0);
+ sb->image_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE;
+ }
+ else if(inst->inst == SB_INST_FILL)
+ {
+ if(g_debug)
+ printf("FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n",
+ inst->addr, inst->size, inst->pattern);
+ sb->image_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE;
+ }
+ else if(inst->inst == SB_INST_LOAD)
+ {
+ if(g_debug)
+ printf("LOAD | addr=0x%08x | len=0x%08x\n", inst->addr, inst->size);
+ /* load header */
+ sb->image_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE;
+ /* data + alignment */
+ sb->image_size += (inst->size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ }
+ }
+ }
+ /* final signature */
+ sb->image_size += 2;
+}
+
+static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr)
+{
+ sb_hdr->signature[0] = 'S';
+ sb_hdr->signature[1] = 'T';
+ sb_hdr->signature[2] = 'M';
+ sb_hdr->signature[3] = 'P';
+ sb_hdr->major_ver = IMAGE_MAJOR_VERSION;
+ sb_hdr->minor_ver = IMAGE_MINOR_VERSION;
+ sb_hdr->flags = 0;
+ sb_hdr->image_size = sb->image_size;
+}
+
+static void produce_sb_file(struct sb_file_t *sb, const char *filename)
+{
+ int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if(fd < 0)
+ bugp("cannot open output file");
+
+ compute_sb_offsets(sb);
+
+ struct sb_header_t sb_hdr;
+ produce_sb_header(sb, &sb_hdr);
+
+ close(fd);
+}
+
#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr)
@@ -654,12 +727,19 @@ static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr)
int main(int argc, const char **argv)
{
if(argc != 4)
- bug("Usage: %s <cmd file> <key file> <out file>\n",*argv);
+ {
+ printf("Usage: %s <cmd file> <key file> <out file>\n",*argv);
+ printf("To enable debug mode, set environement variable SB_DEBUG to YES\n");
+ return 1;
+ }
+
+ if(getenv("SB_DEBUG") != NULL && strcmp(getenv("SB_DEBUG"), "YES") == 0)
+ g_debug = true;
- int nr_keys;
- key_array_t key_array = read_keys(argv[2], &nr_keys);
+ g_key_array = read_keys(argv[2], &g_nr_keys);
struct cmd_file_t *cmd_file = read_command_file(argv[1]);
struct sb_file_t *sb_file = apply_cmd_file(cmd_file);
+ produce_sb_file(sb_file, argv[3]);
return 0;
}