summaryrefslogtreecommitdiff
path: root/utils/sbtools/elftosb.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/sbtools/elftosb.c')
-rw-r--r--utils/sbtools/elftosb.c387
1 files changed, 274 insertions, 113 deletions
diff --git a/utils/sbtools/elftosb.c b/utils/sbtools/elftosb.c
index 0b659eaf26..f78c6cf64b 100644
--- a/utils/sbtools/elftosb.c
+++ b/utils/sbtools/elftosb.c
@@ -33,6 +33,7 @@
33#include <time.h> 33#include <time.h>
34#include <stdarg.h> 34#include <stdarg.h>
35#include <strings.h> 35#include <strings.h>
36#include <getopt.h>
36 37
37#include "crypto.h" 38#include "crypto.h"
38#include "elf.h" 39#include "elf.h"
@@ -46,6 +47,8 @@
46#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0) 47#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0)
47 48
48bool g_debug = false; 49bool g_debug = false;
50char **g_extern;
51int g_extern_count;
49 52
50#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round)) 53#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
51 54
@@ -107,6 +110,16 @@ typedef byte (*key_array_t)[16];
107int g_nr_keys; 110int g_nr_keys;
108key_array_t g_key_array; 111key_array_t g_key_array;
109 112
113static void add_keys(key_array_t ka, int kac)
114{
115 key_array_t new_ka = xmalloc((g_nr_keys + kac) * 16);
116 memcpy(new_ka, g_key_array, g_nr_keys * 16);
117 memcpy(new_ka + g_nr_keys, ka, kac * 16);
118 free(g_key_array);
119 g_key_array = new_ka;
120 g_nr_keys += kac;
121}
122
110static key_array_t read_keys(const char *key_file, int *num_keys) 123static key_array_t read_keys(const char *key_file, int *num_keys)
111{ 124{
112 int size; 125 int size;
@@ -168,6 +181,8 @@ static key_array_t read_keys(const char *key_file, int *num_keys)
168 * command file to sb conversion 181 * command file to sb conversion
169 */ 182 */
170 183
184#define SB_INST_DATA 0xff
185
171struct sb_inst_t 186struct sb_inst_t
172{ 187{
173 uint8_t inst; /* SB_INST_* */ 188 uint8_t inst; /* SB_INST_* */
@@ -186,6 +201,9 @@ struct sb_inst_t
186struct sb_section_t 201struct sb_section_t
187{ 202{
188 uint32_t identifier; 203 uint32_t identifier;
204 bool is_data;
205 bool is_cleartext;
206 // data sections are handled as a single SB_INST_DATA virtual instruction
189 int nr_insts; 207 int nr_insts;
190 struct sb_inst_t *insts; 208 struct sb_inst_t *insts;
191 /* for production use */ 209 /* for production use */
@@ -221,6 +239,16 @@ static void elf_printf(void *user, bool error, const char *fmt, ...)
221 va_end(args); 239 va_end(args);
222} 240}
223 241
242static void resolve_extern(struct cmd_source_t *src)
243{
244 if(!src->is_extern)
245 return;
246 src->is_extern = false;
247 if(src->extern_nr < 0 || src->extern_nr >= g_extern_count)
248 bug("There aren't enough file on command file to resolve extern(%d)\n", src->extern_nr);
249 src->filename = g_extern[src->extern_nr];
250}
251
224static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id) 252static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id)
225{ 253{
226 struct cmd_source_t *src = db_find_source_by_id(cmd_file, id); 254 struct cmd_source_t *src = db_find_source_by_id(cmd_file, id);
@@ -231,6 +259,9 @@ static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id)
231 return; 259 return;
232 if(src->type != CMD_SRC_UNK) 260 if(src->type != CMD_SRC_UNK)
233 bug("source '%s' seen both as elf and binary file\n", id); 261 bug("source '%s' seen both as elf and binary file\n", id);
262 /* resolve potential extern file */
263 resolve_extern(src);
264 /* load it */
234 src->type = CMD_SRC_ELF; 265 src->type = CMD_SRC_ELF;
235 int fd = open(src->filename, O_RDONLY); 266 int fd = open(src->filename, O_RDONLY);
236 if(fd < 0) 267 if(fd < 0)
@@ -255,6 +286,9 @@ static void load_bin_by_id(struct cmd_file_t *cmd_file, const char *id)
255 return; 286 return;
256 if(src->type != CMD_SRC_UNK) 287 if(src->type != CMD_SRC_UNK)
257 bug("source '%s' seen both as elf and binary file\n", id); 288 bug("source '%s' seen both as elf and binary file\n", id);
289 /* resolve potential extern file */
290 resolve_extern(src);
291 /* load it */
258 src->type = CMD_SRC_BIN; 292 src->type = CMD_SRC_BIN;
259 int fd = open(src->filename, O_RDONLY); 293 int fd = open(src->filename, O_RDONLY);
260 if(fd < 0) 294 if(fd < 0)
@@ -274,8 +308,8 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
274 struct sb_file_t *sb = xmalloc(sizeof(struct sb_file_t)); 308 struct sb_file_t *sb = xmalloc(sizeof(struct sb_file_t));
275 memset(sb, 0, sizeof(struct sb_file_t)); 309 memset(sb, 0, sizeof(struct sb_file_t));
276 310
277 sb->product_ver = cmd_file->product_ver; 311 db_generate_default_sb_version(&sb->product_ver);
278 sb->component_ver = cmd_file->component_ver; 312 db_generate_default_sb_version(&sb->component_ver);
279 313
280 if(g_debug) 314 if(g_debug)
281 printf("Applying command file...\n"); 315 printf("Applying command file...\n");
@@ -295,103 +329,136 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
295 { 329 {
296 struct sb_section_t *sec = &sb->sections[i]; 330 struct sb_section_t *sec = &sb->sections[i];
297 sec->identifier = csec->identifier; 331 sec->identifier = csec->identifier;
298 /* count instructions */ 332
299 struct cmd_inst_t *cinst = csec->inst_list; 333 /* options */
300 while(cinst) 334 do
301 { 335 {
302 if(cinst->type == CMD_LOAD) 336 struct cmd_option_t *opt = db_find_option_by_id(csec->opt_list, "cleartext");
303 { 337 if(opt != NULL)
304 load_elf_by_id(cmd_file, cinst->identifier);
305 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf;
306 sec->nr_insts += elf_get_nr_sections(elf);
307 }
308 else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL)
309 { 338 {
310 load_elf_by_id(cmd_file, cinst->identifier); 339 if(opt->is_string)
311 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf; 340 bug("Cleartext section attribute must be an integer\n");
312 if(!elf_get_start_addr(elf, NULL)) 341 if(opt->val != 0 && opt->val != 1)
313 bug("cannot jump/call '%s' because it has no starting point !\n", cinst->identifier); 342 bug("Cleartext section attribute must be 0 or 1\n");
314 sec->nr_insts++; 343 sec->is_cleartext = opt->val;
315 } 344 }
316 else if(cinst->type == CMD_CALL_AT || cinst->type == CMD_JUMP_AT) 345 }while(0);
317 { 346
318 sec->nr_insts++; 347 if(csec->is_data)
319 } 348 {
320 else if(cinst->type == CMD_LOAD_AT) 349 sec->is_data = true;
321 { 350 sec->nr_insts = 1;
322 load_bin_by_id(cmd_file, cinst->identifier); 351 sec->insts = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t));
323 sec->nr_insts++; 352 memset(sec->insts, 0, sec->nr_insts * sizeof(struct sb_inst_t));
324 } 353
325 else if(cinst->type == CMD_MODE) 354 load_bin_by_id(cmd_file, csec->source_id);
355 struct bin_param_t *bin = &db_find_source_by_id(cmd_file, csec->source_id)->bin;
356
357 sec->insts[0].inst = SB_INST_DATA;
358 sec->insts[0].size = bin->size;
359 sec->insts[0].data = bin->data;
360 }
361 else
362 {
363 sec->is_data = false;
364 /* count instructions and loads things */
365 struct cmd_inst_t *cinst = csec->inst_list;
366 while(cinst)
326 { 367 {
327 sec->nr_insts++; 368 if(cinst->type == CMD_LOAD)
369 {
370 load_elf_by_id(cmd_file, cinst->identifier);
371 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf;
372 sec->nr_insts += elf_get_nr_sections(elf);
373 }
374 else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL)
375 {
376 load_elf_by_id(cmd_file, cinst->identifier);
377 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf;
378 if(!elf_get_start_addr(elf, NULL))
379 bug("cannot jump/call '%s' because it has no starting point !\n", cinst->identifier);
380 sec->nr_insts++;
381 }
382 else if(cinst->type == CMD_CALL_AT || cinst->type == CMD_JUMP_AT)
383 {
384 sec->nr_insts++;
385 }
386 else if(cinst->type == CMD_LOAD_AT)
387 {
388 load_bin_by_id(cmd_file, cinst->identifier);
389 sec->nr_insts++;
390 }
391 else if(cinst->type == CMD_MODE)
392 {
393 sec->nr_insts++;
394 }
395 else
396 bug("die\n");
397
398 cinst = cinst->next;
328 } 399 }
329 else
330 bug("die\n");
331
332 cinst = cinst->next;
333 }
334 400
335 sec->insts = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t)); 401 sec->insts = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t));
336 memset(sec->insts, 0, sec->nr_insts * sizeof(struct sb_inst_t)); 402 memset(sec->insts, 0, sec->nr_insts * sizeof(struct sb_inst_t));
337 /* flatten */ 403 /* flatten */
338 int idx = 0; 404 int idx = 0;
339 cinst = csec->inst_list; 405 cinst = csec->inst_list;
340 while(cinst) 406 while(cinst)
341 {
342 if(cinst->type == CMD_LOAD)
343 { 407 {
344 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf; 408 if(cinst->type == CMD_LOAD)
345 struct elf_section_t *esec = elf->first_section;
346 while(esec)
347 { 409 {
348 if(esec->type == EST_LOAD) 410 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf;
349 { 411 struct elf_section_t *esec = elf->first_section;
350 sec->insts[idx].inst = SB_INST_LOAD; 412 while(esec)
351 sec->insts[idx].addr = esec->addr;
352 sec->insts[idx].size = esec->size;
353 sec->insts[idx++].data = esec->section;
354 }
355 else if(esec->type == EST_FILL)
356 { 413 {
357 sec->insts[idx].inst = SB_INST_FILL; 414 if(esec->type == EST_LOAD)
358 sec->insts[idx].addr = esec->addr; 415 {
359 sec->insts[idx].size = esec->size; 416 sec->insts[idx].inst = SB_INST_LOAD;
360 sec->insts[idx++].pattern = esec->pattern; 417 sec->insts[idx].addr = esec->addr;
418 sec->insts[idx].size = esec->size;
419 sec->insts[idx++].data = esec->section;
420 }
421 else if(esec->type == EST_FILL)
422 {
423 sec->insts[idx].inst = SB_INST_FILL;
424 sec->insts[idx].addr = esec->addr;
425 sec->insts[idx].size = esec->size;
426 sec->insts[idx++].pattern = esec->pattern;
427 }
428 esec = esec->next;
361 } 429 }
362 esec = esec->next;
363 } 430 }
431 else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL)
432 {
433 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf;
434 sec->insts[idx].argument = cinst->argument;
435 sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL;
436 sec->insts[idx++].addr = elf->start_addr;
437 }
438 else if(cinst->type == CMD_JUMP_AT || cinst->type == CMD_CALL_AT)
439 {
440 sec->insts[idx].argument = cinst->argument;
441 sec->insts[idx].inst = (cinst->type == CMD_JUMP_AT) ? SB_INST_JUMP : SB_INST_CALL;
442 sec->insts[idx++].addr = cinst->addr;
443 }
444 else if(cinst->type == CMD_LOAD_AT)
445 {
446 struct bin_param_t *bin = &db_find_source_by_id(cmd_file, cinst->identifier)->bin;
447 sec->insts[idx].inst = SB_INST_LOAD;
448 sec->insts[idx].addr = cinst->addr;
449 sec->insts[idx].data = bin->data;
450 sec->insts[idx++].size = bin->size;
451 }
452 else if(cinst->type == CMD_MODE)
453 {
454 sec->insts[idx].inst = SB_INST_MODE;
455 sec->insts[idx++].addr = cinst->argument;
456 }
457 else
458 bug("die\n");
459
460 cinst = cinst->next;
364 } 461 }
365 else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL)
366 {
367 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf;
368 sec->insts[idx].argument = cinst->argument;
369 sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL;
370 sec->insts[idx++].addr = elf->start_addr;
371 }
372 else if(cinst->type == CMD_JUMP_AT || cinst->type == CMD_CALL_AT)
373 {
374 sec->insts[idx].argument = cinst->argument;
375 sec->insts[idx].inst = (cinst->type == CMD_JUMP_AT) ? SB_INST_JUMP : SB_INST_CALL;
376 sec->insts[idx++].addr = cinst->addr;
377 }
378 else if(cinst->type == CMD_LOAD_AT)
379 {
380 struct bin_param_t *bin = &db_find_source_by_id(cmd_file, cinst->identifier)->bin;
381 sec->insts[idx].inst = SB_INST_LOAD;
382 sec->insts[idx].addr = cinst->addr;
383 sec->insts[idx].data = bin->data;
384 sec->insts[idx++].size = bin->size;
385 }
386 else if(cinst->type == CMD_MODE)
387 {
388 sec->insts[idx].inst = SB_INST_MODE;
389 sec->insts[idx++].addr = cinst->argument;
390 }
391 else
392 bug("die\n");
393
394 cinst = cinst->next;
395 } 462 }
396 } 463 }
397 464
@@ -399,7 +466,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
399} 466}
400 467
401/** 468/**
402 * Sb file production 469 * SB file production
403 */ 470 */
404 471
405static void fill_gaps(struct sb_file_t *sb) 472static void fill_gaps(struct sb_file_t *sb)
@@ -436,6 +503,16 @@ static void compute_sb_offsets(struct sb_file_t *sb)
436 sb->image_size += sizeof(struct sb_instruction_tag_t) / BLOCK_SIZE; 503 sb->image_size += sizeof(struct sb_instruction_tag_t) / BLOCK_SIZE;
437 504
438 struct sb_section_t *sec = &sb->sections[i]; 505 struct sb_section_t *sec = &sb->sections[i];
506
507 if(g_debug)
508 {
509 printf("%s section 0x%08x", sec->is_data ? "Data" : "Boot",
510 sec->identifier);
511 if(sec->is_cleartext)
512 printf(" (cleartext)");
513 printf("\n");
514 }
515
439 sec->file_offset = sb->image_size; 516 sec->file_offset = sb->image_size;
440 for(int j = 0; j < sec->nr_insts; j++) 517 for(int j = 0; j < sec->nr_insts; j++)
441 { 518 {
@@ -443,7 +520,7 @@ static void compute_sb_offsets(struct sb_file_t *sb)
443 if(inst->inst == SB_INST_CALL || inst->inst == SB_INST_JUMP) 520 if(inst->inst == SB_INST_CALL || inst->inst == SB_INST_JUMP)
444 { 521 {
445 if(g_debug) 522 if(g_debug)
446 printf("%s | addr=0x%08x | arg=0x%08x\n", 523 printf(" %s | addr=0x%08x | arg=0x%08x\n",
447 inst->inst == SB_INST_CALL ? "CALL" : "JUMP", inst->addr, inst->argument); 524 inst->inst == SB_INST_CALL ? "CALL" : "JUMP", inst->addr, inst->argument);
448 sb->image_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE; 525 sb->image_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE;
449 sec->sec_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE; 526 sec->sec_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE;
@@ -451,7 +528,7 @@ static void compute_sb_offsets(struct sb_file_t *sb)
451 else if(inst->inst == SB_INST_FILL) 528 else if(inst->inst == SB_INST_FILL)
452 { 529 {
453 if(g_debug) 530 if(g_debug)
454 printf("FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n", 531 printf(" FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n",
455 inst->addr, inst->size, inst->pattern); 532 inst->addr, inst->size, inst->pattern);
456 sb->image_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE; 533 sb->image_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE;
457 sec->sec_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE; 534 sec->sec_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE;
@@ -459,7 +536,7 @@ static void compute_sb_offsets(struct sb_file_t *sb)
459 else if(inst->inst == SB_INST_LOAD) 536 else if(inst->inst == SB_INST_LOAD)
460 { 537 {
461 if(g_debug) 538 if(g_debug)
462 printf("LOAD | addr=0x%08x | len=0x%08x\n", inst->addr, inst->size); 539 printf(" LOAD | addr=0x%08x | len=0x%08x\n", inst->addr, inst->size);
463 /* load header */ 540 /* load header */
464 sb->image_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE; 541 sb->image_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE;
465 sec->sec_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE; 542 sec->sec_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE;
@@ -470,10 +547,17 @@ static void compute_sb_offsets(struct sb_file_t *sb)
470 else if(inst->inst == SB_INST_MODE) 547 else if(inst->inst == SB_INST_MODE)
471 { 548 {
472 if(g_debug) 549 if(g_debug)
473 printf("MODE | mod=0x%08x", inst->addr); 550 printf(" MODE | mod=0x%08x", inst->addr);
474 sb->image_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE; 551 sb->image_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE;
475 sec->sec_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE; 552 sec->sec_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE;
476 } 553 }
554 else if(inst->inst == SB_INST_DATA)
555 {
556 if(g_debug)
557 printf(" DATA | size=0x%08x\n", inst->size);
558 sb->image_size += ROUND_UP(inst->size, BLOCK_SIZE) / BLOCK_SIZE;
559 sec->sec_size += ROUND_UP(inst->size, BLOCK_SIZE) / BLOCK_SIZE;
560 }
477 else 561 else
478 bug("die on inst %d\n", inst->inst); 562 bug("die on inst %d\n", inst->inst);
479 } 563 }
@@ -544,7 +628,8 @@ static void produce_sb_section_header(struct sb_section_t *sec,
544 sec_hdr->identifier = sec->identifier; 628 sec_hdr->identifier = sec->identifier;
545 sec_hdr->offset = sec->file_offset; 629 sec_hdr->offset = sec->file_offset;
546 sec_hdr->size = sec->sec_size; 630 sec_hdr->size = sec->sec_size;
547 sec_hdr->flags = SECTION_BOOTABLE; 631 sec_hdr->flags = (sec->is_data ? 0 : SECTION_BOOTABLE)
632 | (sec->is_cleartext ? SECTION_CLEARTEXT : 0);
548} 633}
549 634
550static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr) 635static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr)
@@ -563,7 +648,8 @@ static void produce_section_tag_cmd(struct sb_section_t *sec,
563 tag->hdr.flags = is_last ? SB_INST_LAST_TAG : 0; 648 tag->hdr.flags = is_last ? SB_INST_LAST_TAG : 0;
564 tag->identifier = sec->identifier; 649 tag->identifier = sec->identifier;
565 tag->len = sec->sec_size; 650 tag->len = sec->sec_size;
566 tag->flags = SECTION_BOOTABLE; 651 tag->flags = (sec->is_data ? 0 : SECTION_BOOTABLE)
652 | (sec->is_cleartext ? SECTION_CLEARTEXT : 0);
567 tag->hdr.checksum = instruction_checksum(&tag->hdr); 653 tag->hdr.checksum = instruction_checksum(&tag->hdr);
568} 654}
569 655
@@ -671,21 +757,24 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename)
671 { 757 {
672 struct sb_inst_t *inst = &sb->sections[i].insts[j]; 758 struct sb_inst_t *inst = &sb->sections[i].insts[j];
673 /* command */ 759 /* command */
674 struct sb_instruction_common_t cmd; 760 if(inst->inst != SB_INST_DATA)
675 produce_sb_instruction(inst, &cmd); 761 {
676 if(g_nr_keys > 0) 762 struct sb_instruction_common_t cmd;
677 cbc_mac((byte *)&cmd, (byte *)&cmd, sizeof(cmd) / BLOCK_SIZE, 763 produce_sb_instruction(inst, &cmd);
678 real_key, cur_cbc_mac, &cur_cbc_mac, 1); 764 if(g_nr_keys > 0 && !sb->sections[i].is_cleartext)
679 sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd)); 765 cbc_mac((byte *)&cmd, (byte *)&cmd, sizeof(cmd) / BLOCK_SIZE,
680 write(fd, &cmd, sizeof(cmd)); 766 real_key, cur_cbc_mac, &cur_cbc_mac, 1);
767 sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd));
768 write(fd, &cmd, sizeof(cmd));
769 }
681 /* data */ 770 /* data */
682 if(inst->inst == SB_INST_LOAD) 771 if(inst->inst == SB_INST_LOAD || inst->inst == SB_INST_DATA)
683 { 772 {
684 uint32_t sz = inst->size + inst->padding_size; 773 uint32_t sz = inst->size + inst->padding_size;
685 byte *data = xmalloc(sz); 774 byte *data = xmalloc(sz);
686 memcpy(data, inst->data, inst->size); 775 memcpy(data, inst->data, inst->size);
687 memcpy(data + inst->size, inst->padding, inst->padding_size); 776 memcpy(data + inst->size, inst->padding, inst->padding_size);
688 if(g_nr_keys > 0) 777 if(g_nr_keys > 0 && !sb->sections[i].is_cleartext)
689 cbc_mac(data, data, sz / BLOCK_SIZE, 778 cbc_mac(data, data, sz / BLOCK_SIZE,
690 real_key, cur_cbc_mac, &cur_cbc_mac, 1); 779 real_key, cur_cbc_mac, &cur_cbc_mac, 1);
691 sha_1_update(&file_sha1, data, sz); 780 sha_1_update(&file_sha1, data, sz);
@@ -706,22 +795,94 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename)
706 close(fd); 795 close(fd);
707} 796}
708 797
709int main(int argc, const char **argv) 798void usage(void)
799{
800 printf("Usage: elftosb [options | file]...\n");
801 printf("Options:\n");
802 printf(" -?/--help:\t\tDisplay this message\n");
803 printf(" -o <file>\tSet output file\n");
804 printf(" -c <file>\tSet command file\n");
805 printf(" -d/--debug\tEnable debug output\n");
806 printf(" -k <file>\t\tAdd key file\n");
807 printf(" -z\t\tAdd zero key\n");
808 exit(1);
809}
810
811static byte g_zero_key[16] = {0};
812
813int main(int argc, char **argv)
710{ 814{
711 if(argc != 4) 815 char *cmd_filename = NULL;
816 char *output_filename = NULL;
817
818 while(1)
712 { 819 {
713 printf("Usage: %s <cmd file> <key file> <out file>\n",*argv); 820 static struct option long_options[] =
714 printf("To enable debug mode, set environement variable SB_DEBUG to YES\n"); 821 {
715 return 1; 822 {"help", no_argument, 0, '?'},
823 {"debug", no_argument, 0, 'd'},
824 {0, 0, 0, 0}
825 };
826
827 int c = getopt_long(argc, argv, "?do:c:k:z", long_options, NULL);
828 if(c == -1)
829 break;
830 switch(c)
831 {
832 case 'd':
833 g_debug = true;
834 break;
835 case '?':
836 usage();
837 break;
838 case 'o':
839 output_filename = optarg;
840 break;
841 case 'c':
842 cmd_filename = optarg;
843 break;
844 case 'k':
845 {
846 int kac;
847 key_array_t ka = read_keys(optarg, &kac);
848 add_keys(ka, kac);
849 break;
850 }
851 case 'z':
852 {
853 add_keys(&g_zero_key, 1);
854 break;
855 }
856 default:
857 abort();
858 }
716 } 859 }
717 860
718 if(strcasecmp(s_getenv("SB_DEBUG"), "YES") == 0) 861 if(!cmd_filename)
719 g_debug = true; 862 bug("You must specify a command file\n");
863 if(!output_filename)
864 bug("You must specify an output file\n");
865
866 g_extern = &argv[optind];
867 g_extern_count = argc - optind;
868
869 if(g_debug)
870 {
871 printf("key: %d\n", g_nr_keys);
872 for(int i = 0; i < g_nr_keys; i++)
873 {
874 for(int j = 0; j < 16; j++)
875 printf(" %02x", g_key_array[i][j]);
876 printf("\n");
877 }
878
879 for(int i = 0; i < g_extern_count; i++)
880 printf("extern(%d)=%s\n", i, g_extern[i]);
881 }
720 882
721 g_key_array = read_keys(argv[2], &g_nr_keys); 883 struct cmd_file_t *cmd_file = db_parse_file(cmd_filename);
722 struct cmd_file_t *cmd_file = db_parse_file(argv[1]);
723 struct sb_file_t *sb_file = apply_cmd_file(cmd_file); 884 struct sb_file_t *sb_file = apply_cmd_file(cmd_file);
724 produce_sb_file(sb_file, argv[3]); 885 produce_sb_file(sb_file, output_filename);
725 886
726 return 0; 887 return 0;
727} 888}