diff options
author | Amaury Pouly <pamaury@rockbox.org> | 2011-11-06 01:49:13 +0000 |
---|---|---|
committer | Amaury Pouly <pamaury@rockbox.org> | 2011-11-06 01:49:13 +0000 |
commit | 5827937270bac874ae9e04679b3130fef9e306c4 (patch) | |
tree | 51bc262dedecdb7620300b46f23005c4b0eed311 | |
parent | 33d6bd61b51178b42a07a97118a689d849666331 (diff) | |
download | rockbox-5827937270bac874ae9e04679b3130fef9e306c4.tar.gz rockbox-5827937270bac874ae9e04679b3130fef9e306c4.zip |
sbtools: rename to imxtools, move imx_hid_recovery to imxtools/sbloader, fix tools to correctly handle/free memory, properly return error codes
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30907 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | utils/imx_hid_recovery/Makefile | 15 | ||||
-rw-r--r-- | utils/imxtools/Makefile (renamed from utils/sbtools/Makefile) | 8 | ||||
-rw-r--r-- | utils/imxtools/README (renamed from utils/sbtools/README) | 0 | ||||
-rw-r--r-- | utils/imxtools/aes128.c (renamed from utils/sbtools/aes128.c) | 0 | ||||
-rw-r--r-- | utils/imxtools/crc.c (renamed from utils/sbtools/crc.c) | 0 | ||||
-rw-r--r-- | utils/imxtools/crypto.c (renamed from utils/sbtools/crypto.c) | 0 | ||||
-rw-r--r-- | utils/imxtools/crypto.h (renamed from utils/sbtools/crypto.h) | 1 | ||||
-rw-r--r-- | utils/imxtools/dbparser.c (renamed from utils/sbtools/dbparser.c) | 164 | ||||
-rw-r--r-- | utils/imxtools/dbparser.h (renamed from utils/sbtools/dbparser.h) | 4 | ||||
-rw-r--r-- | utils/imxtools/elf.c (renamed from utils/sbtools/elf.c) | 21 | ||||
-rw-r--r-- | utils/imxtools/elf.h (renamed from utils/sbtools/elf.h) | 0 | ||||
-rw-r--r-- | utils/imxtools/elftosb.c (renamed from utils/sbtools/elftosb.c) | 24 | ||||
-rw-r--r-- | utils/imxtools/fuze+_key_file.txt (renamed from utils/sbtools/fuze+_key_file.txt) | 0 | ||||
-rw-r--r-- | utils/imxtools/misc.c (renamed from utils/sbtools/misc.c) | 14 | ||||
-rw-r--r-- | utils/imxtools/misc.h (renamed from utils/sbtools/misc.h) | 2 | ||||
-rw-r--r-- | utils/imxtools/sb.c (renamed from utils/sbtools/sb.c) | 285 | ||||
-rw-r--r-- | utils/imxtools/sb.h (renamed from utils/sbtools/sb.h) | 26 | ||||
-rw-r--r-- | utils/imxtools/sbloader.c (renamed from utils/imx_hid_recovery/imx_hid_recovery.c) | 0 | ||||
-rw-r--r-- | utils/imxtools/sbtoelf.c (renamed from utils/sbtools/sbtoelf.c) | 18 | ||||
-rw-r--r-- | utils/imxtools/sha1.c (renamed from utils/sbtools/sha1.c) | 0 |
20 files changed, 388 insertions, 194 deletions
diff --git a/utils/imx_hid_recovery/Makefile b/utils/imx_hid_recovery/Makefile deleted file mode 100644 index 24d0b8e3d3..0000000000 --- a/utils/imx_hid_recovery/Makefile +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | CC=gcc | ||
2 | LD=gcc | ||
3 | |||
4 | all: imx_hid_recovery | ||
5 | |||
6 | imx_hid_recovery.o: imx_hid_recovery.c | ||
7 | $(CC) -c -Wall -O2 -std=c99 `pkg-config --cflags libusb-1.0` -o $@ $< | ||
8 | |||
9 | imx_hid_recovery: imx_hid_recovery.o | ||
10 | $(LD) -o $@ $< `pkg-config --libs libusb-1.0` | ||
11 | |||
12 | clean: | ||
13 | rm -rf imx_hid_recovery.o | ||
14 | |||
15 | |||
diff --git a/utils/sbtools/Makefile b/utils/imxtools/Makefile index 69e63c9ac2..7a09d86d24 100644 --- a/utils/sbtools/Makefile +++ b/utils/imxtools/Makefile | |||
@@ -3,8 +3,9 @@ CC=gcc | |||
3 | LD=gcc | 3 | LD=gcc |
4 | CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES) | 4 | CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES) |
5 | LDFLAGS=`pkg-config --libs libusb-1.0` | 5 | LDFLAGS=`pkg-config --libs libusb-1.0` |
6 | BINS=elftosb sbtoelf sbloader | ||
6 | 7 | ||
7 | all: elftosb sbtoelf | 8 | all: $(BINS) |
8 | 9 | ||
9 | %.o: %.c | 10 | %.o: %.c |
10 | $(CC) $(CFLAGS) -c -o $@ $< | 11 | $(CC) $(CFLAGS) -c -o $@ $< |
@@ -15,8 +16,11 @@ sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o elf.o misc.o sb.o | |||
15 | elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o | 16 | elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o |
16 | $(LD) -o $@ $^ $(LDFLAGS) | 17 | $(LD) -o $@ $^ $(LDFLAGS) |
17 | 18 | ||
19 | sbloader: sbloader.o | ||
20 | $(LD) -o $@ $^ $(LDFLAGS) | ||
21 | |||
18 | clean: | 22 | clean: |
19 | rm -fr *.o | 23 | rm -fr *.o |
20 | 24 | ||
21 | veryclean: | 25 | veryclean: |
22 | rm -rf sbtoelf elftosb | 26 | rm -rf $(BINS) |
diff --git a/utils/sbtools/README b/utils/imxtools/README index 8bf6fd5f8e..8bf6fd5f8e 100644 --- a/utils/sbtools/README +++ b/utils/imxtools/README | |||
diff --git a/utils/sbtools/aes128.c b/utils/imxtools/aes128.c index 5870813db8..5870813db8 100644 --- a/utils/sbtools/aes128.c +++ b/utils/imxtools/aes128.c | |||
diff --git a/utils/sbtools/crc.c b/utils/imxtools/crc.c index eaf257ddfe..eaf257ddfe 100644 --- a/utils/sbtools/crc.c +++ b/utils/imxtools/crc.c | |||
diff --git a/utils/sbtools/crypto.c b/utils/imxtools/crypto.c index d4afc6c816..d4afc6c816 100644 --- a/utils/sbtools/crypto.c +++ b/utils/imxtools/crypto.c | |||
diff --git a/utils/sbtools/crypto.h b/utils/imxtools/crypto.h index 51f44406db..452db6a28d 100644 --- a/utils/sbtools/crypto.h +++ b/utils/imxtools/crypto.h | |||
@@ -63,6 +63,7 @@ void crypto_setup(enum crypto_method_t method, void *param); | |||
63 | #define CRYPTO_ERROR_DEVREJECT -5 /* device rejected cypto operation */ | 63 | #define CRYPTO_ERROR_DEVREJECT -5 /* device rejected cypto operation */ |
64 | #define CRYPTO_ERROR_DEVSILENT -6 /* device did not notify completion */ | 64 | #define CRYPTO_ERROR_DEVSILENT -6 /* device did not notify completion */ |
65 | #define CRYPTO_ERROR_DEVERR -7 /* device did something wrong (like return too small buffer) */ | 65 | #define CRYPTO_ERROR_DEVERR -7 /* device did something wrong (like return too small buffer) */ |
66 | #define CRYPTO_NUM_ERRORS 8 | ||
66 | /* return 0 on success, <0 on error */ | 67 | /* return 0 on success, <0 on error */ |
67 | int crypto_apply( | 68 | int crypto_apply( |
68 | byte *in_data, /* Input data */ | 69 | byte *in_data, /* Input data */ |
diff --git a/utils/sbtools/dbparser.c b/utils/imxtools/dbparser.c index 3cd0652d49..b2027e5ad7 100644 --- a/utils/sbtools/dbparser.c +++ b/utils/imxtools/dbparser.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #define _POSIX_C_SOURCE 200809L /* for strdup */ | ||
22 | #include <stdio.h> | 23 | #include <stdio.h> |
23 | #include <ctype.h> | 24 | #include <ctype.h> |
24 | #include <stdint.h> | 25 | #include <stdint.h> |
@@ -48,6 +49,7 @@ enum lexem_type_t | |||
48 | struct lexem_t | 49 | struct lexem_t |
49 | { | 50 | { |
50 | enum lexem_type_t type; | 51 | enum lexem_type_t type; |
52 | /* if str is not NULL, it must be a malloc'd pointer */ | ||
51 | char *str; | 53 | char *str; |
52 | uint32_t num; | 54 | uint32_t num; |
53 | int line; | 55 | int line; |
@@ -390,8 +392,15 @@ struct lex_ctx_t | |||
390 | struct lexem_t lexem; | 392 | struct lexem_t lexem; |
391 | }; | 393 | }; |
392 | 394 | ||
393 | static inline void next(struct lex_ctx_t *ctx) | 395 | /* When lexems hold strings (like identifier), it might be useful to steal |
396 | * the pointer and don't clean the lexem but in other case, one don't want | ||
397 | * to keep the pointer to the string and just want to release the memory. | ||
398 | * Thus clean_lexem should be true except when one keeps a pointer */ | ||
399 | static inline void next(struct lex_ctx_t *ctx, bool clean_lexem) | ||
394 | { | 400 | { |
401 | if(clean_lexem) | ||
402 | free(ctx->lexem.str); | ||
403 | memset(&ctx->lexem, 0, sizeof(struct lexem_t)); | ||
395 | next_lexem(&ctx->ctx, &ctx->lexem); | 404 | next_lexem(&ctx->ctx, &ctx->lexem); |
396 | } | 405 | } |
397 | 406 | ||
@@ -411,7 +420,7 @@ static uint32_t parse_term_expr(struct lex_ctx_t *ctx, struct cmd_option_t *cons | |||
411 | } | 420 | } |
412 | else | 421 | else |
413 | parse_error(ctx->lexem, "Number or constant identifier expected\n"); | 422 | parse_error(ctx->lexem, "Number or constant identifier expected\n"); |
414 | next(ctx); | 423 | next(ctx, true); |
415 | return ret; | 424 | return ret; |
416 | } | 425 | } |
417 | 426 | ||
@@ -420,7 +429,7 @@ static uint32_t parse_shift_expr(struct lex_ctx_t *ctx, struct cmd_option_t *con | |||
420 | uint32_t v = parse_term_expr(ctx, const_list); | 429 | uint32_t v = parse_term_expr(ctx, const_list); |
421 | while(ctx->lexem.type == LEX_LSHIFT) | 430 | while(ctx->lexem.type == LEX_LSHIFT) |
422 | { | 431 | { |
423 | next(ctx); | 432 | next(ctx, true); |
424 | v <<= parse_term_expr(ctx, const_list); | 433 | v <<= parse_term_expr(ctx, const_list); |
425 | } | 434 | } |
426 | return v; | 435 | return v; |
@@ -431,7 +440,7 @@ static uint32_t parse_or_expr(struct lex_ctx_t *ctx, struct cmd_option_t *const_ | |||
431 | uint32_t v = parse_shift_expr(ctx, const_list); | 440 | uint32_t v = parse_shift_expr(ctx, const_list); |
432 | while(ctx->lexem.type == LEX_OR) | 441 | while(ctx->lexem.type == LEX_OR) |
433 | { | 442 | { |
434 | next(ctx); | 443 | next(ctx, true); |
435 | v |= parse_shift_expr(ctx, const_list); | 444 | v |= parse_shift_expr(ctx, const_list); |
436 | } | 445 | } |
437 | return v; | 446 | return v; |
@@ -470,7 +479,7 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
470 | { | 479 | { |
471 | struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); | 480 | struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); |
472 | memset(opt, 0, sizeof(struct cmd_option_t)); | 481 | memset(opt, 0, sizeof(struct cmd_option_t)); |
473 | opt->name = init_const_name[i]; | 482 | opt->name = strdup(init_const_name[i]); |
474 | opt->is_string = false; | 483 | opt->is_string = false; |
475 | opt->val = init_const_value[i]; | 484 | opt->val = init_const_value[i]; |
476 | opt->next = cmd_file->constant_list; | 485 | opt->next = cmd_file->constant_list; |
@@ -483,14 +492,14 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
483 | lctx.ctx.begin = buf; | 492 | lctx.ctx.begin = buf; |
484 | lctx.ctx.ptr = buf; | 493 | lctx.ctx.ptr = buf; |
485 | lctx.ctx.end = buf + size; | 494 | lctx.ctx.end = buf + size; |
486 | #define next() next(&lctx) | 495 | #define next(clean_lexem) next(&lctx, clean_lexem) |
487 | #define lexem lctx.lexem | 496 | #define lexem lctx.lexem |
488 | /* init lexer */ | 497 | /* init lexer */ |
489 | next(); | 498 | next(false); /* don't clean init lexem because it doesn't exist */ |
490 | /* constants ? */ | 499 | /* constants ? */ |
491 | if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "constants")) | 500 | if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "constants")) |
492 | { | 501 | { |
493 | next(); | 502 | next(true); |
494 | if(lexem.type != LEX_LBRACE) | 503 | if(lexem.type != LEX_LBRACE) |
495 | parse_error(lexem, "'{' expected after 'constants'\n"); | 504 | parse_error(lexem, "'{' expected after 'constants'\n"); |
496 | 505 | ||
@@ -498,16 +507,16 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
498 | { | 507 | { |
499 | struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); | 508 | struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); |
500 | memset(opt, 0, sizeof(struct cmd_option_t)); | 509 | memset(opt, 0, sizeof(struct cmd_option_t)); |
501 | next(); | 510 | next(true); |
502 | if(lexem.type == LEX_RBRACE) | 511 | if(lexem.type == LEX_RBRACE) |
503 | break; | 512 | break; |
504 | if(lexem.type != LEX_IDENTIFIER) | 513 | if(lexem.type != LEX_IDENTIFIER) |
505 | parse_error(lexem, "Identifier expected in constants\n"); | 514 | parse_error(lexem, "Identifier expected in constants\n"); |
506 | opt->name = lexem.str; | 515 | opt->name = lexem.str; |
507 | next(); | 516 | next(false); /* lexem string is kept as option name */ |
508 | if(lexem.type != LEX_EQUAL) | 517 | if(lexem.type != LEX_EQUAL) |
509 | parse_error(lexem, "'=' expected after identifier\n"); | 518 | parse_error(lexem, "'=' expected after identifier\n"); |
510 | next(); | 519 | next(true); |
511 | opt->is_string = false; | 520 | opt->is_string = false; |
512 | opt->val = parse_intexpr(&lctx, cmd_file->constant_list); | 521 | opt->val = parse_intexpr(&lctx, cmd_file->constant_list); |
513 | opt->next = cmd_file->constant_list; | 522 | opt->next = cmd_file->constant_list; |
@@ -515,34 +524,34 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
515 | if(lexem.type != LEX_SEMICOLON) | 524 | if(lexem.type != LEX_SEMICOLON) |
516 | parse_error(lexem, "';' expected after string\n"); | 525 | parse_error(lexem, "';' expected after string\n"); |
517 | } | 526 | } |
518 | next(); | 527 | next(true); |
519 | } | 528 | } |
520 | /* options ? */ | 529 | /* options ? */ |
521 | if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "options")) | 530 | if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "options")) |
522 | { | 531 | { |
523 | next(); | 532 | next(true); |
524 | if(lexem.type != LEX_LBRACE) | 533 | if(lexem.type != LEX_LBRACE) |
525 | parse_error(lexem, "'{' expected after 'options'\n"); | 534 | parse_error(lexem, "'{' expected after 'options'\n"); |
526 | 535 | ||
527 | while(true) | 536 | while(true) |
528 | { | 537 | { |
529 | struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); | 538 | next(true); |
530 | memset(opt, 0, sizeof(struct cmd_option_t)); | ||
531 | next(); | ||
532 | if(lexem.type == LEX_RBRACE) | 539 | if(lexem.type == LEX_RBRACE) |
533 | break; | 540 | break; |
541 | struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); | ||
542 | memset(opt, 0, sizeof(struct cmd_option_t)); | ||
534 | if(lexem.type != LEX_IDENTIFIER) | 543 | if(lexem.type != LEX_IDENTIFIER) |
535 | parse_error(lexem, "Identifier expected in options\n"); | 544 | parse_error(lexem, "Identifier expected in options\n"); |
536 | opt->name = lexem.str; | 545 | opt->name = lexem.str; |
537 | next(); | 546 | next(false); /* lexem string is kept as option name */ |
538 | if(lexem.type != LEX_EQUAL) | 547 | if(lexem.type != LEX_EQUAL) |
539 | parse_error(lexem, "'=' expected after identifier\n"); | 548 | parse_error(lexem, "'=' expected after identifier\n"); |
540 | next(); | 549 | next(true); |
541 | if(lexem.type == LEX_STRING) | 550 | if(lexem.type == LEX_STRING) |
542 | { | 551 | { |
543 | opt->is_string = true; | 552 | opt->is_string = true; |
544 | opt->str = lexem.str; | 553 | opt->str = lexem.str; |
545 | next(); | 554 | next(false); /* lexem string is kept as option name */ |
546 | } | 555 | } |
547 | else | 556 | else |
548 | { | 557 | { |
@@ -554,18 +563,18 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
554 | if(lexem.type != LEX_SEMICOLON) | 563 | if(lexem.type != LEX_SEMICOLON) |
555 | parse_error(lexem, "';' expected after string\n"); | 564 | parse_error(lexem, "';' expected after string\n"); |
556 | } | 565 | } |
557 | next(); | 566 | next(true); |
558 | } | 567 | } |
559 | /* sources */ | 568 | /* sources */ |
560 | if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "sources")) | 569 | if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "sources")) |
561 | parse_error(lexem, "'sources' expected\n"); | 570 | parse_error(lexem, "'sources' expected\n"); |
562 | next(); | 571 | next(true); |
563 | if(lexem.type != LEX_LBRACE) | 572 | if(lexem.type != LEX_LBRACE) |
564 | parse_error(lexem, "'{' expected after 'sources'\n"); | 573 | parse_error(lexem, "'{' expected after 'sources'\n"); |
565 | 574 | ||
566 | while(true) | 575 | while(true) |
567 | { | 576 | { |
568 | next(); | 577 | next(true); |
569 | if(lexem.type == LEX_RBRACE) | 578 | if(lexem.type == LEX_RBRACE) |
570 | break; | 579 | break; |
571 | struct cmd_source_t *src = xmalloc(sizeof(struct cmd_source_t)); | 580 | struct cmd_source_t *src = xmalloc(sizeof(struct cmd_source_t)); |
@@ -573,28 +582,28 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
573 | if(lexem.type != LEX_IDENTIFIER) | 582 | if(lexem.type != LEX_IDENTIFIER) |
574 | parse_error(lexem, "identifier expected in sources\n"); | 583 | parse_error(lexem, "identifier expected in sources\n"); |
575 | src->identifier = lexem.str; | 584 | src->identifier = lexem.str; |
576 | next(); | 585 | next(false); /* lexem string is kept as source name */ |
577 | if(lexem.type != LEX_EQUAL) | 586 | if(lexem.type != LEX_EQUAL) |
578 | parse_error(lexem, "'=' expected after identifier\n"); | 587 | parse_error(lexem, "'=' expected after identifier\n"); |
579 | next(); | 588 | next(true); |
580 | if(lexem.type == LEX_STRING) | 589 | if(lexem.type == LEX_STRING) |
581 | { | 590 | { |
582 | src->is_extern = false; | 591 | src->is_extern = false; |
583 | src->filename = lexem.str; | 592 | src->filename = lexem.str; |
584 | next(); | 593 | next(false); /* lexem string is kept as file name */ |
585 | } | 594 | } |
586 | else if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "extern")) | 595 | else if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "extern")) |
587 | { | 596 | { |
588 | src->is_extern = true; | 597 | src->is_extern = true; |
589 | src->filename = "<extern>"; | 598 | src->filename = strdup("<extern>"); /* duplicate because it will be free'd */ |
590 | next(); | 599 | next(true); |
591 | if(lexem.type != LEX_LPAREN) | 600 | if(lexem.type != LEX_LPAREN) |
592 | parse_error(lexem, "'(' expected after 'extern'\n"); | 601 | parse_error(lexem, "'(' expected after 'extern'\n"); |
593 | next(); | 602 | next(true); |
594 | src->extern_nr = parse_intexpr(&lctx, cmd_file->constant_list); | 603 | src->extern_nr = parse_intexpr(&lctx, cmd_file->constant_list); |
595 | if(lexem.type != LEX_RPAREN) | 604 | if(lexem.type != LEX_RPAREN) |
596 | parse_error(lexem, "')' expected\n"); | 605 | parse_error(lexem, "')' expected\n"); |
597 | next(); | 606 | next(true); |
598 | } | 607 | } |
599 | else | 608 | else |
600 | parse_error(lexem, "String or 'extern' expected after '='\n"); | 609 | parse_error(lexem, "String or 'extern' expected after '='\n"); |
@@ -612,18 +621,18 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
612 | struct cmd_section_t *end_sec = NULL; | 621 | struct cmd_section_t *end_sec = NULL; |
613 | while(true) | 622 | while(true) |
614 | { | 623 | { |
624 | next(true); | ||
625 | if(lexem.type == LEX_EOF) | ||
626 | break; | ||
615 | struct cmd_section_t *sec = xmalloc(sizeof(struct cmd_section_t)); | 627 | struct cmd_section_t *sec = xmalloc(sizeof(struct cmd_section_t)); |
616 | struct cmd_inst_t *end_list = NULL; | 628 | struct cmd_inst_t *end_list = NULL; |
617 | memset(sec, 0, sizeof(struct cmd_section_t)); | 629 | memset(sec, 0, sizeof(struct cmd_section_t)); |
618 | next(); | ||
619 | if(lexem.type == LEX_EOF) | ||
620 | break; | ||
621 | if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "section") != 0) | 630 | if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "section") != 0) |
622 | parse_error(lexem, "'section' expected\n"); | 631 | parse_error(lexem, "'section' expected\n"); |
623 | next(); | 632 | next(true); |
624 | if(lexem.type != LEX_LPAREN) | 633 | if(lexem.type != LEX_LPAREN) |
625 | parse_error(lexem, "'(' expected after 'section'\n"); | 634 | parse_error(lexem, "'(' expected after 'section'\n"); |
626 | next(); | 635 | next(true); |
627 | /* can be any number */ | 636 | /* can be any number */ |
628 | sec->identifier = parse_intexpr(&lctx, cmd_file->constant_list); | 637 | sec->identifier = parse_intexpr(&lctx, cmd_file->constant_list); |
629 | /* options ? */ | 638 | /* options ? */ |
@@ -631,21 +640,21 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
631 | { | 640 | { |
632 | do | 641 | do |
633 | { | 642 | { |
634 | next(); | 643 | next(true); |
635 | struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); | 644 | struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); |
636 | memset(opt, 0, sizeof(struct cmd_option_t)); | 645 | memset(opt, 0, sizeof(struct cmd_option_t)); |
637 | if(lexem.type != LEX_IDENTIFIER) | 646 | if(lexem.type != LEX_IDENTIFIER) |
638 | parse_error(lexem, "Identifier expected for section option\n"); | 647 | parse_error(lexem, "Identifier expected for section option\n"); |
639 | opt->name = lexem.str; | 648 | opt->name = lexem.str; |
640 | next(); | 649 | next(false); /* lexem string is kept as option name */ |
641 | if(lexem.type != LEX_EQUAL) | 650 | if(lexem.type != LEX_EQUAL) |
642 | parse_error(lexem, "'=' expected after option identifier\n"); | 651 | parse_error(lexem, "'=' expected after option identifier\n"); |
643 | next(); | 652 | next(true); |
644 | if(lexem.type == LEX_STRING) | 653 | if(lexem.type == LEX_STRING) |
645 | { | 654 | { |
646 | opt->is_string = true; | 655 | opt->is_string = true; |
647 | opt->str = lexem.str; | 656 | opt->str = lexem.str; |
648 | next(); | 657 | next(false); /* lexem string is kept as option string */ |
649 | } | 658 | } |
650 | else | 659 | else |
651 | { | 660 | { |
@@ -658,18 +667,18 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
658 | } | 667 | } |
659 | if(lexem.type != LEX_RPAREN) | 668 | if(lexem.type != LEX_RPAREN) |
660 | parse_error(lexem, "')' expected after section identifier\n"); | 669 | parse_error(lexem, "')' expected after section identifier\n"); |
661 | next(); | 670 | next(true); |
662 | if(lexem.type == LEX_LBRACE) | 671 | if(lexem.type == LEX_LBRACE) |
663 | { | 672 | { |
664 | sec->is_data = false; | 673 | sec->is_data = false; |
665 | /* commands */ | 674 | /* commands */ |
666 | while(true) | 675 | while(true) |
667 | { | 676 | { |
668 | struct cmd_inst_t *inst = xmalloc(sizeof(struct cmd_inst_t)); | 677 | next(true); |
669 | memset(inst, 0, sizeof(struct cmd_inst_t)); | ||
670 | next(); | ||
671 | if(lexem.type == LEX_RBRACE) | 678 | if(lexem.type == LEX_RBRACE) |
672 | break; | 679 | break; |
680 | struct cmd_inst_t *inst = xmalloc(sizeof(struct cmd_inst_t)); | ||
681 | memset(inst, 0, sizeof(struct cmd_inst_t)); | ||
673 | if(lexem.type != LEX_IDENTIFIER) | 682 | if(lexem.type != LEX_IDENTIFIER) |
674 | parse_error(lexem, "Instruction expected in section\n"); | 683 | parse_error(lexem, "Instruction expected in section\n"); |
675 | if(strcmp(lexem.str, "load") == 0) | 684 | if(strcmp(lexem.str, "load") == 0) |
@@ -682,7 +691,7 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
682 | inst->type = CMD_MODE; | 691 | inst->type = CMD_MODE; |
683 | else | 692 | else |
684 | parse_error(lexem, "Instruction expected in section\n"); | 693 | parse_error(lexem, "Instruction expected in section\n"); |
685 | next(); | 694 | next(true); |
686 | 695 | ||
687 | if(inst->type == CMD_LOAD) | 696 | if(inst->type == CMD_LOAD) |
688 | { | 697 | { |
@@ -691,12 +700,12 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
691 | inst->identifier = lexem.str; | 700 | inst->identifier = lexem.str; |
692 | if(db_find_source_by_id(cmd_file, inst->identifier) == NULL) | 701 | if(db_find_source_by_id(cmd_file, inst->identifier) == NULL) |
693 | parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier); | 702 | parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier); |
694 | next(); | 703 | next(false); /* lexem string kept as identifier */ |
695 | if(lexem.type == LEX_RANGLE) | 704 | if(lexem.type == LEX_RANGLE) |
696 | { | 705 | { |
697 | // load at | 706 | // load at |
698 | inst->type = CMD_LOAD_AT; | 707 | inst->type = CMD_LOAD_AT; |
699 | next(); | 708 | next(true); |
700 | inst->addr = parse_intexpr(&lctx, cmd_file->constant_list); | 709 | inst->addr = parse_intexpr(&lctx, cmd_file->constant_list); |
701 | } | 710 | } |
702 | if(lexem.type != LEX_SEMICOLON) | 711 | if(lexem.type != LEX_SEMICOLON) |
@@ -709,7 +718,7 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
709 | inst->identifier = lexem.str; | 718 | inst->identifier = lexem.str; |
710 | if(db_find_source_by_id(cmd_file, inst->identifier) == NULL) | 719 | if(db_find_source_by_id(cmd_file, inst->identifier) == NULL) |
711 | parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier); | 720 | parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier); |
712 | next(); | 721 | next(false); /* lexem string kept as identifier */ |
713 | } | 722 | } |
714 | else | 723 | else |
715 | { | 724 | { |
@@ -719,11 +728,11 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
719 | 728 | ||
720 | if(lexem.type == LEX_LPAREN) | 729 | if(lexem.type == LEX_LPAREN) |
721 | { | 730 | { |
722 | next(); | 731 | next(true); |
723 | inst->argument = parse_intexpr(&lctx, cmd_file->constant_list); | 732 | inst->argument = parse_intexpr(&lctx, cmd_file->constant_list); |
724 | if(lexem.type != LEX_RPAREN) | 733 | if(lexem.type != LEX_RPAREN) |
725 | parse_error(lexem, "Expected closing brace\n"); | 734 | parse_error(lexem, "Expected closing brace\n"); |
726 | next(); | 735 | next(true); |
727 | } | 736 | } |
728 | if(lexem.type != LEX_SEMICOLON) | 737 | if(lexem.type != LEX_SEMICOLON) |
729 | parse_error(lexem, "';' expected after command\n"); | 738 | parse_error(lexem, "';' expected after command\n"); |
@@ -751,11 +760,11 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
751 | else if(lexem.type == LEX_LE) | 760 | else if(lexem.type == LEX_LE) |
752 | { | 761 | { |
753 | sec->is_data = true; | 762 | sec->is_data = true; |
754 | next(); | 763 | next(true); |
755 | if(lexem.type != LEX_IDENTIFIER) | 764 | if(lexem.type != LEX_IDENTIFIER) |
756 | parse_error(lexem, "Identifier expected after '<='\n"); | 765 | parse_error(lexem, "Identifier expected after '<='\n"); |
757 | sec->source_id = lexem.str; | 766 | sec->source_id = lexem.str; |
758 | next(); | 767 | next(false); /* lexem string is kept as source id */ |
759 | if(lexem.type != LEX_SEMICOLON) | 768 | if(lexem.type != LEX_SEMICOLON) |
760 | parse_error(lexem, "';' expected after identifier\n"); | 769 | parse_error(lexem, "';' expected after identifier\n"); |
761 | } | 770 | } |
@@ -776,6 +785,7 @@ struct cmd_file_t *db_parse_file(const char *file) | |||
776 | #undef lexem | 785 | #undef lexem |
777 | #undef next | 786 | #undef next |
778 | 787 | ||
788 | free(buf); | ||
779 | return cmd_file; | 789 | return cmd_file; |
780 | } | 790 | } |
781 | 791 | ||
@@ -783,3 +793,57 @@ void db_generate_default_sb_version(struct sb_version_t *ver) | |||
783 | { | 793 | { |
784 | ver->major = ver->minor = ver->revision = 0x999; | 794 | ver->major = ver->minor = ver->revision = 0x999; |
785 | } | 795 | } |
796 | |||
797 | void db_free_option_list(struct cmd_option_t *opt_list) | ||
798 | { | ||
799 | while(opt_list) | ||
800 | { | ||
801 | struct cmd_option_t *next = opt_list->next; | ||
802 | fflush(stdout); | ||
803 | free(opt_list->name); | ||
804 | free(opt_list->str); | ||
805 | free(opt_list); | ||
806 | opt_list = next; | ||
807 | } | ||
808 | } | ||
809 | |||
810 | void db_free(struct cmd_file_t *file) | ||
811 | { | ||
812 | db_free_option_list(file->opt_list); | ||
813 | db_free_option_list(file->constant_list); | ||
814 | struct cmd_source_t *src = file->source_list; | ||
815 | while(src) | ||
816 | { | ||
817 | struct cmd_source_t *next = src->next; | ||
818 | free(src->identifier); | ||
819 | fflush(stdout); | ||
820 | free(src->filename); | ||
821 | if(src->loaded) | ||
822 | { | ||
823 | if(src->type == CMD_SRC_BIN) | ||
824 | free(src->bin.data); | ||
825 | if(src->type == CMD_SRC_ELF) | ||
826 | elf_release(&src->elf); | ||
827 | } | ||
828 | free(src); | ||
829 | src = next; | ||
830 | } | ||
831 | struct cmd_section_t *sec = file->section_list; | ||
832 | while(sec) | ||
833 | { | ||
834 | struct cmd_section_t *next = sec->next; | ||
835 | db_free_option_list(sec->opt_list); | ||
836 | free(sec->source_id); | ||
837 | struct cmd_inst_t *inst = sec->inst_list; | ||
838 | while(inst) | ||
839 | { | ||
840 | struct cmd_inst_t *next = inst->next; | ||
841 | free(inst->identifier); | ||
842 | free(inst); | ||
843 | inst = next; | ||
844 | } | ||
845 | free(sec); | ||
846 | sec = next; | ||
847 | } | ||
848 | free(file); | ||
849 | } | ||
diff --git a/utils/sbtools/dbparser.h b/utils/imxtools/dbparser.h index cfb1a692fa..4a36861583 100644 --- a/utils/sbtools/dbparser.h +++ b/utils/imxtools/dbparser.h | |||
@@ -102,7 +102,7 @@ struct cmd_section_t | |||
102 | struct cmd_file_t | 102 | struct cmd_file_t |
103 | { | 103 | { |
104 | struct cmd_option_t *opt_list; | 104 | struct cmd_option_t *opt_list; |
105 | struct cmd_option_t *constant_list; /* constant all always integers */ | 105 | struct cmd_option_t *constant_list; /* constant are always integers */ |
106 | struct cmd_source_t *source_list; | 106 | struct cmd_source_t *source_list; |
107 | struct cmd_section_t *section_list; | 107 | struct cmd_section_t *section_list; |
108 | }; | 108 | }; |
@@ -112,5 +112,7 @@ struct cmd_option_t *db_find_option_by_id(struct cmd_option_t *opt, const char * | |||
112 | bool db_parse_sb_version(struct sb_version_t *ver, char *str); | 112 | bool db_parse_sb_version(struct sb_version_t *ver, char *str); |
113 | void db_generate_default_sb_version(struct sb_version_t *ver); | 113 | void db_generate_default_sb_version(struct sb_version_t *ver); |
114 | struct cmd_file_t *db_parse_file(const char *file); | 114 | struct cmd_file_t *db_parse_file(const char *file); |
115 | void db_free_option_list(struct cmd_option_t *opt_list); | ||
116 | void db_free(struct cmd_file_t *file); | ||
115 | 117 | ||
116 | #endif /* __DBPARSER__ */ | 118 | #endif /* __DBPARSER__ */ |
diff --git a/utils/sbtools/elf.c b/utils/imxtools/elf.c index 91b5d74848..481ab98dd6 100644 --- a/utils/sbtools/elf.c +++ b/utils/imxtools/elf.c | |||
@@ -153,10 +153,7 @@ typedef struct | |||
153 | 153 | ||
154 | void elf_init(struct elf_params_t *params) | 154 | void elf_init(struct elf_params_t *params) |
155 | { | 155 | { |
156 | params->has_start_addr = false; | 156 | memset(params, 0, sizeof(struct elf_params_t)); |
157 | params->start_addr = 0; | ||
158 | params->first_section = NULL; | ||
159 | params->last_section = NULL; | ||
160 | } | 157 | } |
161 | 158 | ||
162 | extern void *xmalloc(size_t s); | 159 | extern void *xmalloc(size_t s); |
@@ -463,6 +460,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, | |||
463 | if(!read(user, shdr.sh_offset, data, shdr.sh_size)) | 460 | if(!read(user, shdr.sh_offset, data, shdr.sh_size)) |
464 | error_printf("error read self section data\n"); | 461 | error_printf("error read self section data\n"); |
465 | elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data); | 462 | elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data); |
463 | free(data); | ||
466 | 464 | ||
467 | if(strtab) | 465 | if(strtab) |
468 | printf(user, false, "create load segment for %s\n", &strtab[shdr.sh_name]); | 466 | printf(user, false, "create load segment for %s\n", &strtab[shdr.sh_name]); |
@@ -480,6 +478,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, | |||
480 | } | 478 | } |
481 | 479 | ||
482 | } | 480 | } |
481 | free(strtab); | ||
483 | /* run through segments */ | 482 | /* run through segments */ |
484 | for(int i = 1; i < ehdr.e_phnum; i++) | 483 | for(int i = 1; i < ehdr.e_phnum; i++) |
485 | { | 484 | { |
@@ -557,16 +556,20 @@ int elf_get_nr_sections(struct elf_params_t *params) | |||
557 | 556 | ||
558 | void elf_release(struct elf_params_t *params) | 557 | void elf_release(struct elf_params_t *params) |
559 | { | 558 | { |
560 | struct elf_section_t *sec, *next_sec; | 559 | struct elf_section_t *sec = params->first_section; |
561 | sec = params->first_section; | ||
562 | while(sec) | 560 | while(sec) |
563 | { | 561 | { |
564 | next_sec = sec->next; | 562 | struct elf_section_t *next_sec = sec->next; |
565 | if(sec->type == EST_LOAD) | 563 | if(sec->type == EST_LOAD) |
566 | free(sec->section); | 564 | free(sec->section); |
567 | free(sec); | 565 | free(sec); |
568 | sec = next_sec; | 566 | sec = next_sec; |
569 | } | 567 | } |
570 | params->first_section = NULL; | 568 | struct elf_segment_t *seg = params->first_segment; |
571 | params->last_section = NULL; | 569 | while(seg) |
570 | { | ||
571 | struct elf_segment_t *next_seg = seg->next; | ||
572 | free(seg); | ||
573 | seg = next_seg; | ||
574 | } | ||
572 | } | 575 | } |
diff --git a/utils/sbtools/elf.h b/utils/imxtools/elf.h index 2166833276..2166833276 100644 --- a/utils/sbtools/elf.h +++ b/utils/imxtools/elf.h | |||
diff --git a/utils/sbtools/elftosb.c b/utils/imxtools/elftosb.c index b8d68b82e7..2f8700551f 100644 --- a/utils/sbtools/elftosb.c +++ b/utils/imxtools/elftosb.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #define _ISOC99_SOURCE | 22 | #define _ISOC99_SOURCE |
23 | #define _POSIX_C_SOURCE 200809L /* for strdup */ | ||
23 | #include <stdio.h> | 24 | #include <stdio.h> |
24 | #include <errno.h> | 25 | #include <errno.h> |
25 | #include <stdlib.h> | 26 | #include <stdlib.h> |
@@ -77,7 +78,9 @@ static void resolve_extern(struct cmd_source_t *src) | |||
77 | src->is_extern = false; | 78 | src->is_extern = false; |
78 | if(src->extern_nr < 0 || src->extern_nr >= g_extern_count) | 79 | if(src->extern_nr < 0 || src->extern_nr >= g_extern_count) |
79 | bug("There aren't enough file on command file to resolve extern(%d)\n", src->extern_nr); | 80 | bug("There aren't enough file on command file to resolve extern(%d)\n", src->extern_nr); |
80 | src->filename = g_extern[src->extern_nr]; | 81 | /* first free the old src->filename content */ |
82 | free(src->filename); | ||
83 | src->filename = strdup(g_extern[src->extern_nr]); | ||
81 | } | 84 | } |
82 | 85 | ||
83 | static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id) | 86 | static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id) |
@@ -206,7 +209,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | |||
206 | 209 | ||
207 | sec->insts[0].inst = SB_INST_DATA; | 210 | sec->insts[0].inst = SB_INST_DATA; |
208 | sec->insts[0].size = bin->size; | 211 | sec->insts[0].size = bin->size; |
209 | sec->insts[0].data = bin->data; | 212 | sec->insts[0].data = memdup(bin->data, bin->size); |
210 | } | 213 | } |
211 | else | 214 | else |
212 | { | 215 | { |
@@ -266,7 +269,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | |||
266 | sec->insts[idx].inst = SB_INST_LOAD; | 269 | sec->insts[idx].inst = SB_INST_LOAD; |
267 | sec->insts[idx].addr = esec->addr; | 270 | sec->insts[idx].addr = esec->addr; |
268 | sec->insts[idx].size = esec->size; | 271 | sec->insts[idx].size = esec->size; |
269 | sec->insts[idx++].data = esec->section; | 272 | sec->insts[idx++].data = memdup(esec->section, esec->size); |
270 | } | 273 | } |
271 | else if(esec->type == EST_FILL) | 274 | else if(esec->type == EST_FILL) |
272 | { | 275 | { |
@@ -296,7 +299,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | |||
296 | struct bin_param_t *bin = &db_find_source_by_id(cmd_file, cinst->identifier)->bin; | 299 | struct bin_param_t *bin = &db_find_source_by_id(cmd_file, cinst->identifier)->bin; |
297 | sec->insts[idx].inst = SB_INST_LOAD; | 300 | sec->insts[idx].inst = SB_INST_LOAD; |
298 | sec->insts[idx].addr = cinst->addr; | 301 | sec->insts[idx].addr = cinst->addr; |
299 | sec->insts[idx].data = bin->data; | 302 | sec->insts[idx].data = memdup(bin->data, bin->size); |
300 | sec->insts[idx++].size = bin->size; | 303 | sec->insts[idx++].size = bin->size; |
301 | } | 304 | } |
302 | else if(cinst->type == CMD_MODE) | 305 | else if(cinst->type == CMD_MODE) |
@@ -431,11 +434,18 @@ int main(int argc, char **argv) | |||
431 | 434 | ||
432 | struct cmd_file_t *cmd_file = db_parse_file(cmd_filename); | 435 | struct cmd_file_t *cmd_file = db_parse_file(cmd_filename); |
433 | struct sb_file_t *sb_file = apply_cmd_file(cmd_file); | 436 | struct sb_file_t *sb_file = apply_cmd_file(cmd_file); |
437 | db_free(cmd_file); | ||
434 | 438 | ||
435 | if(real_key.method == CRYPTO_KEY) | 439 | if(real_key.method == CRYPTO_KEY) |
436 | sb_file->real_key = &real_key.u.key; | 440 | { |
441 | sb_file->override_real_key = true; | ||
442 | memcpy(sb_file->real_key, real_key.u.key, 16); | ||
443 | } | ||
437 | if(crypto_iv.method == CRYPTO_KEY) | 444 | if(crypto_iv.method == CRYPTO_KEY) |
438 | sb_file->crypto_iv = &crypto_iv.u.key; | 445 | { |
446 | sb_file->override_crypto_iv = true; | ||
447 | memcpy(sb_file->crypto_iv, crypto_iv.u.key, 16); | ||
448 | } | ||
439 | 449 | ||
440 | /* fill with default parameters since there is no command file support for them */ | 450 | /* fill with default parameters since there is no command file support for them */ |
441 | sb_file->drive_tag = 0; | 451 | sb_file->drive_tag = 0; |
@@ -444,6 +454,8 @@ int main(int argc, char **argv) | |||
444 | sb_file->minor_version = 1; | 454 | sb_file->minor_version = 1; |
445 | 455 | ||
446 | sb_write_file(sb_file, output_filename); | 456 | sb_write_file(sb_file, output_filename); |
457 | sb_free(sb_file); | ||
458 | clear_keys(); | ||
447 | 459 | ||
448 | return 0; | 460 | return 0; |
449 | } | 461 | } |
diff --git a/utils/sbtools/fuze+_key_file.txt b/utils/imxtools/fuze+_key_file.txt index a965e715f7..a965e715f7 100644 --- a/utils/sbtools/fuze+_key_file.txt +++ b/utils/imxtools/fuze+_key_file.txt | |||
diff --git a/utils/sbtools/misc.c b/utils/imxtools/misc.c index 4eeda4ef33..8d7cea89d7 100644 --- a/utils/sbtools/misc.c +++ b/utils/imxtools/misc.c | |||
@@ -29,6 +29,14 @@ bool g_debug = false; | |||
29 | /** | 29 | /** |
30 | * Misc | 30 | * Misc |
31 | */ | 31 | */ |
32 | |||
33 | void *memdup(void *p, size_t len) | ||
34 | { | ||
35 | void *cpy = xmalloc(len); | ||
36 | memcpy(cpy, p, len); | ||
37 | return cpy; | ||
38 | } | ||
39 | |||
32 | void generate_random_data(void *buf, size_t sz) | 40 | void generate_random_data(void *buf, size_t sz) |
33 | { | 41 | { |
34 | FILE *rand_fd = fopen("/dev/urandom", "rb"); | 42 | FILE *rand_fd = fopen("/dev/urandom", "rb"); |
@@ -144,6 +152,12 @@ void add_keys(key_array_t ka, int kac) | |||
144 | g_nr_keys += kac; | 152 | g_nr_keys += kac; |
145 | } | 153 | } |
146 | 154 | ||
155 | void clear_keys() | ||
156 | { | ||
157 | free(g_key_array); | ||
158 | g_nr_keys = 0; | ||
159 | } | ||
160 | |||
147 | void add_keys_from_file(const char *key_file) | 161 | void add_keys_from_file(const char *key_file) |
148 | { | 162 | { |
149 | int size; | 163 | int size; |
diff --git a/utils/sbtools/misc.h b/utils/imxtools/misc.h index 9f14497680..b0b7dfeba6 100644 --- a/utils/sbtools/misc.h +++ b/utils/imxtools/misc.h | |||
@@ -38,6 +38,7 @@ typedef struct crypto_key_t *key_array_t; | |||
38 | int g_nr_keys; | 38 | int g_nr_keys; |
39 | key_array_t g_key_array; | 39 | key_array_t g_key_array; |
40 | 40 | ||
41 | void *memdup(void *p, size_t len); | ||
41 | void *augment_array(void *arr, size_t elem_sz, size_t cnt, void *aug, size_t aug_cnt); | 42 | void *augment_array(void *arr, size_t elem_sz, size_t cnt, void *aug, size_t aug_cnt); |
42 | void generate_random_data(void *buf, size_t sz); | 43 | void generate_random_data(void *buf, size_t sz); |
43 | void *xmalloc(size_t s); | 44 | void *xmalloc(size_t s); |
@@ -47,6 +48,7 @@ void add_keys(key_array_t ka, int kac); | |||
47 | bool parse_key(char **str, struct crypto_key_t *key); | 48 | bool parse_key(char **str, struct crypto_key_t *key); |
48 | void add_keys_from_file(const char *key_file); | 49 | void add_keys_from_file(const char *key_file); |
49 | void print_key(struct crypto_key_t *key, bool newline); | 50 | void print_key(struct crypto_key_t *key, bool newline); |
51 | void clear_keys(); | ||
50 | 52 | ||
51 | typedef char color_t[]; | 53 | typedef char color_t[]; |
52 | 54 | ||
diff --git a/utils/sbtools/sb.c b/utils/imxtools/sb.c index d620c00f42..44db56b7d1 100644 --- a/utils/sbtools/sb.c +++ b/utils/imxtools/sb.c | |||
@@ -138,7 +138,7 @@ static void compute_sb_offsets(struct sb_file_t *sb) | |||
138 | if(sb->sections[i].is_data) | 138 | if(sb->sections[i].is_data) |
139 | { | 139 | { |
140 | nr_aug_insts = 1; | 140 | nr_aug_insts = 1; |
141 | aug_insts = malloc(sizeof(struct sb_inst_t)); | 141 | aug_insts = xmalloc(sizeof(struct sb_inst_t)); |
142 | memset(aug_insts, 0, sizeof(struct sb_inst_t)); | 142 | memset(aug_insts, 0, sizeof(struct sb_inst_t)); |
143 | aug_insts[0].inst = SB_INST_DATA; | 143 | aug_insts[0].inst = SB_INST_DATA; |
144 | aug_insts[0].size = missing_sz * BLOCK_SIZE; | 144 | aug_insts[0].size = missing_sz * BLOCK_SIZE; |
@@ -150,7 +150,7 @@ static void compute_sb_offsets(struct sb_file_t *sb) | |||
150 | else | 150 | else |
151 | { | 151 | { |
152 | nr_aug_insts = missing_sz; | 152 | nr_aug_insts = missing_sz; |
153 | aug_insts = malloc(sizeof(struct sb_inst_t) * nr_aug_insts); | 153 | aug_insts = xmalloc(sizeof(struct sb_inst_t) * nr_aug_insts); |
154 | memset(aug_insts, 0, sizeof(struct sb_inst_t) * nr_aug_insts); | 154 | memset(aug_insts, 0, sizeof(struct sb_inst_t) * nr_aug_insts); |
155 | for(int j = 0; j < nr_aug_insts; j++) | 155 | for(int j = 0; j < nr_aug_insts; j++) |
156 | { | 156 | { |
@@ -163,6 +163,7 @@ static void compute_sb_offsets(struct sb_file_t *sb) | |||
163 | sb->sections[i].insts = augment_array(sb->sections[i].insts, sizeof(struct sb_inst_t), | 163 | sb->sections[i].insts = augment_array(sb->sections[i].insts, sizeof(struct sb_inst_t), |
164 | sb->sections[i].nr_insts, aug_insts, nr_aug_insts); | 164 | sb->sections[i].nr_insts, aug_insts, nr_aug_insts); |
165 | sb->sections[i].nr_insts += nr_aug_insts; | 165 | sb->sections[i].nr_insts += nr_aug_insts; |
166 | free(aug_insts); | ||
166 | 167 | ||
167 | /* augment image and section size */ | 168 | /* augment image and section size */ |
168 | sb->image_size += missing_sz; | 169 | sb->image_size += missing_sz; |
@@ -299,12 +300,8 @@ void produce_sb_instruction(struct sb_inst_t *inst, | |||
299 | cmd->hdr.checksum = instruction_checksum(&cmd->hdr); | 300 | cmd->hdr.checksum = instruction_checksum(&cmd->hdr); |
300 | } | 301 | } |
301 | 302 | ||
302 | void sb_write_file(struct sb_file_t *sb, const char *filename) | 303 | enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename) |
303 | { | 304 | { |
304 | FILE *fd = fopen(filename, "wb"); | ||
305 | if(fd == NULL) | ||
306 | bugp("cannot open output file"); | ||
307 | |||
308 | struct crypto_key_t real_key; | 305 | struct crypto_key_t real_key; |
309 | real_key.method = CRYPTO_KEY; | 306 | real_key.method = CRYPTO_KEY; |
310 | byte crypto_iv[16]; | 307 | byte crypto_iv[16]; |
@@ -324,8 +321,13 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) | |||
324 | /* produce and write header */ | 321 | /* produce and write header */ |
325 | struct sb_header_t sb_hdr; | 322 | struct sb_header_t sb_hdr; |
326 | produce_sb_header(sb, &sb_hdr); | 323 | produce_sb_header(sb, &sb_hdr); |
324 | /* allocate image */ | ||
325 | byte *buf = xmalloc(sb_hdr.image_size * BLOCK_SIZE); | ||
326 | byte *buf_p = buf; | ||
327 | #define write(p, sz) do { memcpy(buf_p, p, sz); buf_p += sz; } while(0) | ||
328 | |||
327 | sha_1_update(&file_sha1, (byte *)&sb_hdr, sizeof(sb_hdr)); | 329 | sha_1_update(&file_sha1, (byte *)&sb_hdr, sizeof(sb_hdr)); |
328 | fwrite(&sb_hdr, 1, sizeof(sb_hdr), fd); | 330 | write(&sb_hdr, sizeof(sb_hdr)); |
329 | 331 | ||
330 | memcpy(crypto_iv, &sb_hdr, 16); | 332 | memcpy(crypto_iv, &sb_hdr, 16); |
331 | 333 | ||
@@ -340,7 +342,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) | |||
340 | struct sb_section_header_t sb_sec_hdr; | 342 | struct sb_section_header_t sb_sec_hdr; |
341 | produce_sb_section_header(&sb->sections[i], &sb_sec_hdr); | 343 | produce_sb_section_header(&sb->sections[i], &sb_sec_hdr); |
342 | sha_1_update(&file_sha1, (byte *)&sb_sec_hdr, sizeof(sb_sec_hdr)); | 344 | sha_1_update(&file_sha1, (byte *)&sb_sec_hdr, sizeof(sb_sec_hdr)); |
343 | fwrite(&sb_sec_hdr, 1, sizeof(sb_sec_hdr), fd); | 345 | write(&sb_sec_hdr, sizeof(sb_sec_hdr)); |
344 | /* update CBC-MACs */ | 346 | /* update CBC-MACs */ |
345 | for(int j = 0; j < g_nr_keys; j++) | 347 | for(int j = 0; j < g_nr_keys; j++) |
346 | crypto_cbc((byte *)&sb_sec_hdr, NULL, sizeof(sb_sec_hdr) / BLOCK_SIZE, | 348 | crypto_cbc((byte *)&sb_sec_hdr, NULL, sizeof(sb_sec_hdr) / BLOCK_SIZE, |
@@ -354,16 +356,18 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) | |||
354 | crypto_cbc(real_key.u.key, entry.key, 1, &g_key_array[i], | 356 | crypto_cbc(real_key.u.key, entry.key, 1, &g_key_array[i], |
355 | crypto_iv, NULL, 1); | 357 | crypto_iv, NULL, 1); |
356 | 358 | ||
357 | fwrite(&entry, 1, sizeof(entry), fd); | 359 | write(&entry, sizeof(entry)); |
358 | sha_1_update(&file_sha1, (byte *)&entry, sizeof(entry)); | 360 | sha_1_update(&file_sha1, (byte *)&entry, sizeof(entry)); |
359 | } | 361 | } |
360 | 362 | ||
363 | free(cbc_macs); | ||
364 | |||
361 | /* HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK */ | 365 | /* HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK */ |
362 | /* Image crafting, don't use it unless you understand what you do */ | 366 | /* Image crafting, don't use it unless you understand what you do */ |
363 | if(sb->real_key != NULL) | 367 | if(sb->override_real_key) |
364 | memcpy(real_key.u.key, *sb->real_key, 16); | 368 | memcpy(real_key.u.key, sb->real_key, 16); |
365 | if(sb->crypto_iv != NULL) | 369 | if(sb->override_crypto_iv) |
366 | memcpy(crypto_iv, *sb->crypto_iv, 16); | 370 | memcpy(crypto_iv, sb->crypto_iv, 16); |
367 | /* KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH */ | 371 | /* KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH */ |
368 | if(g_debug) | 372 | if(g_debug) |
369 | { | 373 | { |
@@ -386,7 +390,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) | |||
386 | crypto_cbc((byte *)&tag_cmd, (byte *)&tag_cmd, sizeof(tag_cmd) / BLOCK_SIZE, | 390 | crypto_cbc((byte *)&tag_cmd, (byte *)&tag_cmd, sizeof(tag_cmd) / BLOCK_SIZE, |
387 | &real_key, crypto_iv, NULL, 1); | 391 | &real_key, crypto_iv, NULL, 1); |
388 | sha_1_update(&file_sha1, (byte *)&tag_cmd, sizeof(tag_cmd)); | 392 | sha_1_update(&file_sha1, (byte *)&tag_cmd, sizeof(tag_cmd)); |
389 | fwrite(&tag_cmd, 1, sizeof(tag_cmd), fd); | 393 | write(&tag_cmd, sizeof(tag_cmd)); |
390 | /* produce other commands */ | 394 | /* produce other commands */ |
391 | byte cur_cbc_mac[16]; | 395 | byte cur_cbc_mac[16]; |
392 | memcpy(cur_cbc_mac, crypto_iv, 16); | 396 | memcpy(cur_cbc_mac, crypto_iv, 16); |
@@ -402,7 +406,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) | |||
402 | crypto_cbc((byte *)&cmd, (byte *)&cmd, sizeof(cmd) / BLOCK_SIZE, | 406 | crypto_cbc((byte *)&cmd, (byte *)&cmd, sizeof(cmd) / BLOCK_SIZE, |
403 | &real_key, cur_cbc_mac, &cur_cbc_mac, 1); | 407 | &real_key, cur_cbc_mac, &cur_cbc_mac, 1); |
404 | sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd)); | 408 | sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd)); |
405 | fwrite(&cmd, 1, sizeof(cmd), fd); | 409 | write(&cmd, sizeof(cmd)); |
406 | } | 410 | } |
407 | /* data */ | 411 | /* data */ |
408 | if(inst->inst == SB_INST_LOAD || inst->inst == SB_INST_DATA) | 412 | if(inst->inst == SB_INST_LOAD || inst->inst == SB_INST_DATA) |
@@ -415,7 +419,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) | |||
415 | crypto_cbc(data, data, sz / BLOCK_SIZE, | 419 | crypto_cbc(data, data, sz / BLOCK_SIZE, |
416 | &real_key, cur_cbc_mac, &cur_cbc_mac, 1); | 420 | &real_key, cur_cbc_mac, &cur_cbc_mac, 1); |
417 | sha_1_update(&file_sha1, data, sz); | 421 | sha_1_update(&file_sha1, data, sz); |
418 | fwrite(data, 1, sz, fd); | 422 | write(data, sz); |
419 | free(data); | 423 | free(data); |
420 | } | 424 | } |
421 | } | 425 | } |
@@ -427,22 +431,35 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) | |||
427 | generate_random_data(final_sig + 20, 12); | 431 | generate_random_data(final_sig + 20, 12); |
428 | if(g_nr_keys > 0) | 432 | if(g_nr_keys > 0) |
429 | crypto_cbc(final_sig, final_sig, 2, &real_key, crypto_iv, NULL, 1); | 433 | crypto_cbc(final_sig, final_sig, 2, &real_key, crypto_iv, NULL, 1); |
430 | fwrite(final_sig, 1, 32, fd); | 434 | write(final_sig, 32); |
435 | |||
436 | if(buf_p - buf != sb_hdr.image_size * BLOCK_SIZE) | ||
437 | bug("SB image buffer was not entirely filled !"); | ||
431 | 438 | ||
439 | FILE *fd = fopen(filename, "wb"); | ||
440 | if(fd == NULL) | ||
441 | return SB_OPEN_ERROR; | ||
442 | if(fwrite(buf, sb_hdr.image_size * BLOCK_SIZE, 1, fd) != 1) | ||
443 | { | ||
444 | free(buf); | ||
445 | return SB_WRITE_ERROR; | ||
446 | } | ||
432 | fclose(fd); | 447 | fclose(fd); |
433 | } | 448 | free(buf); |
434 | 449 | ||
435 | static void *memdup(void *p, size_t len) | 450 | return SB_SUCCESS; |
436 | { | ||
437 | void *cpy = xmalloc(len); | ||
438 | memcpy(cpy, p, len); | ||
439 | return cpy; | ||
440 | } | 451 | } |
441 | 452 | ||
442 | static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf, | 453 | static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf, |
443 | int size, const char *indent, void *u, sb_color_printf cprintf) | 454 | int size, const char *indent, void *u, sb_color_printf cprintf, enum sb_error_t *err) |
444 | { | 455 | { |
445 | #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__) | 456 | #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__) |
457 | #define fatal(e, ...) \ | ||
458 | do { if(err) *err = e; \ | ||
459 | cprintf(u, true, GREY, __VA_ARGS__); \ | ||
460 | sb_free_section(*sec); \ | ||
461 | free(sec); \ | ||
462 | return NULL; } while(0) | ||
446 | 463 | ||
447 | struct sb_section_t *sec = xmalloc(sizeof(struct sb_section_t)); | 464 | struct sb_section_t *sec = xmalloc(sizeof(struct sb_section_t)); |
448 | memset(sec, 0, sizeof(struct sb_section_t)); | 465 | memset(sec, 0, sizeof(struct sb_section_t)); |
@@ -474,7 +491,7 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf, | |||
474 | printf(OFF, "%s", indent); | 491 | printf(OFF, "%s", indent); |
475 | uint8_t checksum = instruction_checksum(hdr); | 492 | uint8_t checksum = instruction_checksum(hdr); |
476 | if(checksum != hdr->checksum) | 493 | if(checksum != hdr->checksum) |
477 | printf(GREY, "[Bad checksum]"); | 494 | fatal(SB_CHECKSUM_ERROR, "Bad instruction checksum"); |
478 | if(hdr->flags != 0) | 495 | if(hdr->flags != 0) |
479 | { | 496 | { |
480 | printf(GREY, "["); | 497 | printf(GREY, "["); |
@@ -501,7 +518,10 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf, | |||
501 | if(load->crc == computed_crc) | 518 | if(load->crc == computed_crc) |
502 | printf(RED, " Ok\n"); | 519 | printf(RED, " Ok\n"); |
503 | else | 520 | else |
521 | { | ||
504 | printf(RED, " Failed (crc=0x%08x)\n", computed_crc); | 522 | printf(RED, " Failed (crc=0x%08x)\n", computed_crc); |
523 | fatal(SB_CHECKSUM_ERROR, "Instruction data crc error\n"); | ||
524 | } | ||
505 | 525 | ||
506 | pos += load->len + sizeof(struct sb_instruction_load_t); | 526 | pos += load->len + sizeof(struct sb_instruction_load_t); |
507 | } | 527 | } |
@@ -559,7 +579,7 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf, | |||
559 | } | 579 | } |
560 | else | 580 | else |
561 | { | 581 | { |
562 | printf(RED, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos); | 582 | fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos); |
563 | break; | 583 | break; |
564 | } | 584 | } |
565 | 585 | ||
@@ -569,6 +589,7 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf, | |||
569 | 589 | ||
570 | return sec; | 590 | return sec; |
571 | #undef printf | 591 | #undef printf |
592 | #undef fatal | ||
572 | } | 593 | } |
573 | 594 | ||
574 | void sb_fill_section_name(char name[5], uint32_t identifier) | 595 | void sb_fill_section_name(char name[5], uint32_t identifier) |
@@ -595,25 +616,37 @@ static uint32_t guess_alignment(uint32_t off) | |||
595 | } | 616 | } |
596 | 617 | ||
597 | struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, | 618 | struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, |
598 | sb_color_printf cprintf) | 619 | sb_color_printf cprintf, enum sb_error_t *err) |
599 | { | 620 | { |
621 | uint8_t *buf = NULL; | ||
622 | struct sb_file_t *sb_file = NULL; | ||
623 | |||
600 | #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__) | 624 | #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__) |
601 | #define fatal(...) do { cprintf(u, true, GREY, __VA_ARGS__); return NULL; } while(0) | 625 | #define fatal(e, ...) \ |
626 | do { if(err) *err = e; \ | ||
627 | cprintf(u, true, GREY, __VA_ARGS__); \ | ||
628 | free(buf); \ | ||
629 | sb_free(sb_file); \ | ||
630 | return NULL; } while(0) | ||
602 | #define print_hex(c, p, len, nl) \ | 631 | #define print_hex(c, p, len, nl) \ |
603 | do { printf(c, ""); print_hex(p, len, nl); } while(0) | 632 | do { printf(c, ""); print_hex(p, len, nl); } while(0) |
604 | 633 | ||
605 | FILE *f = fopen(filename, "rb"); | 634 | FILE *f = fopen(filename, "rb"); |
606 | if(f == NULL) | 635 | if(f == NULL) |
607 | fatal("Cannot open file for reading\n"); | 636 | fatal(SB_OPEN_ERROR, "Cannot open file for reading\n"); |
608 | fseek(f, 0, SEEK_END); | 637 | fseek(f, 0, SEEK_END); |
609 | long filesize = ftell(f); | 638 | long filesize = ftell(f); |
610 | fseek(f, 0, SEEK_SET); | 639 | fseek(f, 0, SEEK_SET); |
611 | uint8_t *buf = xmalloc(filesize); | 640 | buf = xmalloc(filesize); |
612 | fread(buf, 1, filesize, f); | 641 | if(fread(buf, filesize, 1, f) != 1) |
642 | { | ||
643 | fclose(f); | ||
644 | fatal(SB_READ_ERROR, "Cannot read file\n"); | ||
645 | } | ||
613 | fclose(f); | 646 | fclose(f); |
614 | 647 | ||
615 | struct sha_1_params_t sha_1_params; | 648 | struct sha_1_params_t sha_1_params; |
616 | struct sb_file_t *sb_file = xmalloc(sizeof(struct sb_file_t)); | 649 | sb_file = xmalloc(sizeof(struct sb_file_t)); |
617 | memset(sb_file, 0, sizeof(struct sb_file_t)); | 650 | memset(sb_file, 0, sizeof(struct sb_file_t)); |
618 | struct sb_header_t *sb_header = (struct sb_header_t *)buf; | 651 | struct sb_header_t *sb_header = (struct sb_header_t *)buf; |
619 | 652 | ||
@@ -624,13 +657,13 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, | |||
624 | sb_file->first_boot_sec_id = sb_header->first_boot_sec_id; | 657 | sb_file->first_boot_sec_id = sb_header->first_boot_sec_id; |
625 | 658 | ||
626 | if(memcmp(sb_header->signature, "STMP", 4) != 0) | 659 | if(memcmp(sb_header->signature, "STMP", 4) != 0) |
627 | fatal("Bad signature\n"); | 660 | fatal(SB_FORMAT_ERROR, "Bad signature\n"); |
628 | if(sb_header->image_size * BLOCK_SIZE > filesize) | 661 | if(sb_header->image_size * BLOCK_SIZE > filesize) |
629 | fatal("File too small mismatch"); | 662 | fatal(SB_FORMAT_ERROR, "File too small"); |
630 | if(sb_header->header_size * BLOCK_SIZE != sizeof(struct sb_header_t)) | 663 | if(sb_header->header_size * BLOCK_SIZE != sizeof(struct sb_header_t)) |
631 | fatal("Bad header size"); | 664 | fatal(SB_FORMAT_ERROR, "Bad header size"); |
632 | if(sb_header->sec_hdr_size * BLOCK_SIZE != sizeof(struct sb_section_header_t)) | 665 | if(sb_header->sec_hdr_size * BLOCK_SIZE != sizeof(struct sb_section_header_t)) |
633 | fatal("Bad section header size"); | 666 | fatal(SB_FORMAT_ERROR, "Bad section header size"); |
634 | 667 | ||
635 | if(filesize > sb_header->image_size * BLOCK_SIZE) | 668 | if(filesize > sb_header->image_size * BLOCK_SIZE) |
636 | { | 669 | { |
@@ -707,86 +740,106 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, | |||
707 | /* encryption cbc-mac */ | 740 | /* encryption cbc-mac */ |
708 | byte real_key[16]; | 741 | byte real_key[16]; |
709 | bool valid_key = false; /* false until a matching key was found */ | 742 | bool valid_key = false; /* false until a matching key was found */ |
743 | |||
710 | if(sb_header->nr_keys > 0) | 744 | if(sb_header->nr_keys > 0) |
711 | { | 745 | { |
712 | if(sb_header->nr_keys > g_nr_keys) | 746 | byte (*cbcmacs)[16] = xmalloc(16 * g_nr_keys); |
713 | { | 747 | printf(BLUE, "Encryption keys\n"); |
714 | fatal("SB file has %d keys but only %d were specified\n", | 748 | for(int i = 0; i < g_nr_keys; i++) |
715 | sb_header->nr_keys, g_nr_keys); | ||
716 | } | ||
717 | printf(BLUE, "Encryption data\n"); | ||
718 | for(int i = 0; i < sb_header->nr_keys; i++) | ||
719 | { | 749 | { |
720 | printf(RED, " Key %d: ", i); | 750 | printf(RED, " Key %d: ", i); |
721 | printf(YELLOW, ""); | 751 | printf(YELLOW, ""); |
722 | print_key(&g_key_array[i], true); | 752 | print_key(&g_key_array[i], true); |
723 | printf(GREEN, " CBC-MAC of headers: "); | 753 | printf(GREEN, " CBC-MAC: "); |
754 | /* check it */ | ||
755 | byte zero[16]; | ||
756 | memset(zero, 0, 16); | ||
757 | int ret = crypto_cbc(buf, NULL, sb_header->header_size + sb_header->nr_sections, | ||
758 | &g_key_array[i], zero, &cbcmacs[i], 1); | ||
759 | if(ret != CRYPTO_ERROR_SUCCESS) | ||
760 | { | ||
761 | free(cbcmacs); | ||
762 | fatal(SB_FIRST_CRYPTO_ERROR + ret, "Crypto error: %d", ret); | ||
763 | } | ||
764 | print_hex(YELLOW, cbcmacs[i], 16, true); | ||
765 | } | ||
724 | 766 | ||
767 | printf(BLUE, "DEK\n"); | ||
768 | for(int i = 0; i < sb_header->nr_keys; i++) | ||
769 | { | ||
770 | printf(RED, " Entry %d\n", i); | ||
725 | uint32_t ofs = sizeof(struct sb_header_t) | 771 | uint32_t ofs = sizeof(struct sb_header_t) |
726 | + sizeof(struct sb_section_header_t) * sb_header->nr_sections | 772 | + sizeof(struct sb_section_header_t) * sb_header->nr_sections |
727 | + sizeof(struct sb_key_dictionary_entry_t) * i; | 773 | + sizeof(struct sb_key_dictionary_entry_t) * i; |
728 | struct sb_key_dictionary_entry_t *dict_entry = | 774 | struct sb_key_dictionary_entry_t *dict_entry = |
729 | (struct sb_key_dictionary_entry_t *)&buf[ofs]; | 775 | (struct sb_key_dictionary_entry_t *)&buf[ofs]; |
730 | /* cbc mac */ | 776 | /* cbc mac */ |
777 | printf(GREEN, " Encrypted key: "); | ||
778 | print_hex(YELLOW, dict_entry->key, 16, true); | ||
779 | printf(GREEN, " CBC-MAC : "); | ||
731 | print_hex(YELLOW, dict_entry->hdr_cbc_mac, 16, false); | 780 | print_hex(YELLOW, dict_entry->hdr_cbc_mac, 16, false); |
732 | /* check it */ | 781 | /* check it */ |
733 | byte computed_cbc_mac[16]; | 782 | int idx = 0; |
734 | byte zero[16]; | 783 | while(idx < g_nr_keys && memcmp(dict_entry->hdr_cbc_mac, cbcmacs[idx], 16) != 0) |
735 | memset(zero, 0, 16); | 784 | idx++; |
736 | crypto_cbc(buf, NULL, sb_header->header_size + sb_header->nr_sections, | 785 | if(idx != g_nr_keys) |
737 | &g_key_array[i], zero, &computed_cbc_mac, 1); | ||
738 | |||
739 | bool ok = memcmp(dict_entry->hdr_cbc_mac, computed_cbc_mac, 16) == 0; | ||
740 | if(ok) | ||
741 | { | ||
742 | valid_key = true; | ||
743 | printf(RED, " Ok\n"); | ||
744 | } | ||
745 | else | ||
746 | printf(RED, " Failed\n"); | ||
747 | |||
748 | printf(GREEN, " Encrypted key : "); | ||
749 | print_hex(YELLOW, dict_entry->key, 16, true); | ||
750 | /* decrypt */ | ||
751 | byte decrypted_key[16]; | ||
752 | byte iv[16]; | ||
753 | memcpy(iv, buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */ | ||
754 | crypto_cbc(dict_entry->key, decrypted_key, 1, &g_key_array[i], iv, NULL, 0); | ||
755 | printf(GREEN, " Decrypted key : "); | ||
756 | print_hex(YELLOW, decrypted_key, 16, false); | ||
757 | /* cross-check or copy */ | ||
758 | if(valid_key && ok) | ||
759 | memcpy(real_key, decrypted_key, 16); | ||
760 | else if(valid_key) | ||
761 | { | 786 | { |
762 | if(memcmp(real_key, decrypted_key, 16) == 0) | 787 | printf(RED, " Match\n"); |
763 | printf(RED, " Cross-Check Ok"); | 788 | /* decrypt */ |
789 | byte decrypted_key[16]; | ||
790 | byte iv[16]; | ||
791 | memcpy(iv, buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */ | ||
792 | int ret = crypto_cbc(dict_entry->key, decrypted_key, 1, &g_key_array[idx], iv, NULL, 0); | ||
793 | if(ret != CRYPTO_ERROR_SUCCESS) | ||
794 | { | ||
795 | free(cbcmacs); | ||
796 | fatal(SB_FIRST_CRYPTO_ERROR + ret, "Crypto error: %d\n", ret); | ||
797 | } | ||
798 | printf(GREEN, " Decrypted key: "); | ||
799 | print_hex(YELLOW, decrypted_key, 16, false); | ||
800 | if(valid_key) | ||
801 | { | ||
802 | if(memcmp(real_key, decrypted_key, 16) == 0) | ||
803 | printf(RED, " Cross-Check Ok"); | ||
804 | else | ||
805 | printf(RED, " Cross-Check Failed"); | ||
806 | } | ||
764 | else | 807 | else |
765 | printf(RED, " Cross-Check Failed"); | 808 | { |
809 | memcpy(real_key, decrypted_key, 16); | ||
810 | valid_key = true; | ||
811 | } | ||
812 | printf(OFF, "\n"); | ||
766 | } | 813 | } |
767 | printf(OFF, "\n"); | 814 | else |
815 | printf(RED, " Don't Match\n"); | ||
768 | } | 816 | } |
769 | } | ||
770 | 817 | ||
771 | if(getenv("SB_REAL_KEY") != 0) | 818 | free(cbcmacs); |
772 | { | 819 | |
773 | struct crypto_key_t k; | 820 | if(!valid_key) |
774 | char *env = getenv("SB_REAL_KEY"); | 821 | fatal(SB_NO_VALID_KEY, "No valid key found\n"); |
775 | if(!parse_key(&env, &k) || *env) | 822 | |
776 | bug("Invalid SB_REAL_KEY\n"); | 823 | if(getenv("SB_REAL_KEY") != 0) |
777 | memcpy(real_key, k.u.key, 16); | 824 | { |
778 | } | 825 | struct crypto_key_t k; |
826 | char *env = getenv("SB_REAL_KEY"); | ||
827 | if(!parse_key(&env, &k) || *env) | ||
828 | bug("Invalid SB_REAL_KEY\n"); | ||
829 | memcpy(real_key, k.u.key, 16); | ||
830 | } | ||
779 | 831 | ||
780 | printf(RED, " Summary:\n"); | 832 | printf(RED, " Summary:\n"); |
781 | printf(GREEN, " Real key: "); | 833 | printf(GREEN, " Real key: "); |
782 | print_hex(YELLOW, real_key, 16, true); | 834 | print_hex(YELLOW, real_key, 16, true); |
783 | printf(GREEN, " IV : "); | 835 | printf(GREEN, " IV : "); |
784 | print_hex(YELLOW, buf, 16, true); | 836 | print_hex(YELLOW, buf, 16, true); |
785 | 837 | ||
786 | sb_file->real_key = xmalloc(16); | 838 | sb_file->override_real_key = true; |
787 | memcpy(*sb_file->real_key, real_key, 16); | 839 | memcpy(sb_file->real_key, real_key, 16); |
788 | sb_file->crypto_iv = xmalloc(16); | 840 | sb_file->override_crypto_iv = true; |
789 | memcpy(*sb_file->crypto_iv, buf, 16); | 841 | memcpy(sb_file->crypto_iv, buf, 16); |
842 | } | ||
790 | 843 | ||
791 | /* sections */ | 844 | /* sections */ |
792 | if(!raw_mode) | 845 | if(!raw_mode) |
@@ -831,7 +884,7 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, | |||
831 | memcpy(sec, buf + pos, size); | 884 | memcpy(sec, buf + pos, size); |
832 | 885 | ||
833 | struct sb_section_t *s = read_section(data_sec, sec_hdr->identifier, | 886 | struct sb_section_t *s = read_section(data_sec, sec_hdr->identifier, |
834 | sec, size, " ", u, cprintf); | 887 | sec, size, " ", u, cprintf, err); |
835 | if(s) | 888 | if(s) |
836 | { | 889 | { |
837 | s->is_cleartext = !encrypted; | 890 | s->is_cleartext = !encrypted; |
@@ -839,6 +892,8 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, | |||
839 | memcpy(&sb_file->sections[i], s, sizeof(struct sb_section_t)); | 892 | memcpy(&sb_file->sections[i], s, sizeof(struct sb_section_t)); |
840 | free(s); | 893 | free(s); |
841 | } | 894 | } |
895 | else | ||
896 | fatal(*err, "Error reading section\n"); | ||
842 | 897 | ||
843 | free(sec); | 898 | free(sec); |
844 | } | 899 | } |
@@ -919,7 +974,7 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, | |||
919 | memcpy(sec, buf + pos, size); | 974 | memcpy(sec, buf + pos, size); |
920 | 975 | ||
921 | struct sb_section_t *s = read_section(data_sec, tag->identifier, | 976 | struct sb_section_t *s = read_section(data_sec, tag->identifier, |
922 | sec, size, " ", u, cprintf); | 977 | sec, size, " ", u, cprintf, err); |
923 | if(s) | 978 | if(s) |
924 | { | 979 | { |
925 | s->is_cleartext = !encrypted; | 980 | s->is_cleartext = !encrypted; |
@@ -929,6 +984,8 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, | |||
929 | s, 1); | 984 | s, 1); |
930 | free(s); | 985 | free(s); |
931 | } | 986 | } |
987 | else | ||
988 | fatal(*err, "Error reading section\n"); | ||
932 | free(sec); | 989 | free(sec); |
933 | 990 | ||
934 | /* last one ? */ | 991 | /* last one ? */ |
@@ -938,7 +995,7 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, | |||
938 | } | 995 | } |
939 | else | 996 | else |
940 | { | 997 | { |
941 | printf(RED, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset); | 998 | fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset); |
942 | break; | 999 | break; |
943 | } | 1000 | } |
944 | } | 1001 | } |
@@ -970,7 +1027,10 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, | |||
970 | if(memcmp(decrypted_block, computed_sha1, 20) == 0) | 1027 | if(memcmp(decrypted_block, computed_sha1, 20) == 0) |
971 | printf(RED, " Ok\n"); | 1028 | printf(RED, " Ok\n"); |
972 | else | 1029 | else |
1030 | { | ||
973 | printf(RED, " Failed\n"); | 1031 | printf(RED, " Failed\n"); |
1032 | fatal(SB_CHECKSUM_ERROR, "File SHA-1 error\n"); | ||
1033 | } | ||
974 | free(buf); | 1034 | free(buf); |
975 | 1035 | ||
976 | return sb_file; | 1036 | return sb_file; |
@@ -979,6 +1039,27 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, | |||
979 | #undef print_hex | 1039 | #undef print_hex |
980 | } | 1040 | } |
981 | 1041 | ||
1042 | void sb_free_section(struct sb_section_t sec) | ||
1043 | { | ||
1044 | for(int j = 0; j < sec.nr_insts; j++) | ||
1045 | { | ||
1046 | free(sec.insts[j].padding); | ||
1047 | free(sec.insts[j].data); | ||
1048 | } | ||
1049 | free(sec.insts); | ||
1050 | } | ||
1051 | |||
1052 | void sb_free(struct sb_file_t *file) | ||
1053 | { | ||
1054 | if(!file) return; | ||
1055 | |||
1056 | for(int i = 0; i < file->nr_sections; i++) | ||
1057 | sb_free_section(file->sections[i]); | ||
1058 | |||
1059 | free(file->sections); | ||
1060 | free(file); | ||
1061 | } | ||
1062 | |||
982 | void sb_dump(struct sb_file_t *file, void *u, sb_color_printf cprintf) | 1063 | void sb_dump(struct sb_file_t *file, void *u, sb_color_printf cprintf) |
983 | { | 1064 | { |
984 | #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__) | 1065 | #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__) |
@@ -1007,17 +1088,17 @@ void sb_dump(struct sb_file_t *file, void *u, sb_color_printf cprintf) | |||
1007 | sb_fill_section_name(name, file->first_boot_sec_id); | 1088 | sb_fill_section_name(name, file->first_boot_sec_id); |
1008 | printf(TEXT, "%08x (%s)\n", file->first_boot_sec_id, name); | 1089 | printf(TEXT, "%08x (%s)\n", file->first_boot_sec_id, name); |
1009 | 1090 | ||
1010 | if(file->real_key) | 1091 | if(file->override_real_key) |
1011 | { | 1092 | { |
1012 | printf(TREE, "+-"); | 1093 | printf(TREE, "+-"); |
1013 | printf(HEADER, "Real key: "); | 1094 | printf(HEADER, "Real key: "); |
1014 | print_hex(TEXT, *file->real_key, 16, true); | 1095 | print_hex(TEXT, file->real_key, 16, true); |
1015 | } | 1096 | } |
1016 | if(file->crypto_iv) | 1097 | if(file->override_crypto_iv) |
1017 | { | 1098 | { |
1018 | printf(TREE, "+-"); | 1099 | printf(TREE, "+-"); |
1019 | printf(HEADER, "IV : "); | 1100 | printf(HEADER, "IV : "); |
1020 | print_hex(TEXT, *file->crypto_iv, 16, true); | 1101 | print_hex(TEXT, file->crypto_iv, 16, true); |
1021 | } | 1102 | } |
1022 | printf(TREE, "+-"); | 1103 | printf(TREE, "+-"); |
1023 | printf(HEADER, "Product Version: "); | 1104 | printf(HEADER, "Product Version: "); |
diff --git a/utils/sbtools/sb.h b/utils/imxtools/sb.h index 39bb8ce59b..ced6481a80 100644 --- a/utils/sbtools/sb.h +++ b/utils/imxtools/sb.h | |||
@@ -191,9 +191,11 @@ struct sb_section_t | |||
191 | struct sb_file_t | 191 | struct sb_file_t |
192 | { | 192 | { |
193 | /* override real, otherwise it is randomly generated */ | 193 | /* override real, otherwise it is randomly generated */ |
194 | uint8_t (*real_key)[16]; | 194 | bool override_real_key; |
195 | uint8_t real_key[16]; | ||
195 | /* override crypto IV, use with caution ! Use NULL to generate it */ | 196 | /* override crypto IV, use with caution ! Use NULL to generate it */ |
196 | uint8_t (*crypto_iv)[16]; | 197 | bool override_crypto_iv; |
198 | uint8_t crypto_iv[16]; | ||
197 | 199 | ||
198 | int nr_sections; | 200 | int nr_sections; |
199 | uint16_t drive_tag; | 201 | uint16_t drive_tag; |
@@ -207,13 +209,29 @@ struct sb_file_t | |||
207 | uint32_t image_size; /* in blocks */ | 209 | uint32_t image_size; /* in blocks */ |
208 | }; | 210 | }; |
209 | 211 | ||
210 | void sb_write_file(struct sb_file_t *sb, const char *filename); | 212 | enum sb_error_t |
213 | { | ||
214 | SB_SUCCESS = 0, | ||
215 | SB_ERROR = -1, | ||
216 | SB_OPEN_ERROR = -2, | ||
217 | SB_READ_ERROR = -3, | ||
218 | SB_WRITE_ERROR = -4, | ||
219 | SB_FORMAT_ERROR = -5, | ||
220 | SB_CHECKSUM_ERROR = -6, | ||
221 | SB_NO_VALID_KEY = -7, | ||
222 | SB_FIRST_CRYPTO_ERROR = -8, | ||
223 | SB_LAST_CRYPTO_ERROR = SB_FIRST_CRYPTO_ERROR - CRYPTO_NUM_ERRORS, | ||
224 | }; | ||
225 | |||
226 | enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename); | ||
211 | 227 | ||
212 | typedef void (*sb_color_printf)(void *u, bool err, color_t c, const char *f, ...); | 228 | typedef void (*sb_color_printf)(void *u, bool err, color_t c, const char *f, ...); |
213 | struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, | 229 | struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, |
214 | sb_color_printf printf); | 230 | sb_color_printf printf, enum sb_error_t *err); |
215 | 231 | ||
216 | void sb_fill_section_name(char name[5], uint32_t identifier); | 232 | void sb_fill_section_name(char name[5], uint32_t identifier); |
217 | void sb_dump(struct sb_file_t *file, void *u, sb_color_printf printf); | 233 | void sb_dump(struct sb_file_t *file, void *u, sb_color_printf printf); |
234 | void sb_free_section(struct sb_section_t file); | ||
235 | void sb_free(struct sb_file_t *file); | ||
218 | 236 | ||
219 | #endif /* __SB_H__ */ | 237 | #endif /* __SB_H__ */ |
diff --git a/utils/imx_hid_recovery/imx_hid_recovery.c b/utils/imxtools/sbloader.c index ba4645f8ab..ba4645f8ab 100644 --- a/utils/imx_hid_recovery/imx_hid_recovery.c +++ b/utils/imxtools/sbloader.c | |||
diff --git a/utils/sbtools/sbtoelf.c b/utils/imxtools/sbtoelf.c index 179f91262f..fda70b1180 100644 --- a/utils/sbtools/sbtoelf.c +++ b/utils/imxtools/sbtoelf.c | |||
@@ -268,7 +268,15 @@ int main(int argc, char **argv) | |||
268 | 268 | ||
269 | const char *sb_filename = argv[optind]; | 269 | const char *sb_filename = argv[optind]; |
270 | 270 | ||
271 | struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf); | 271 | enum sb_error_t err; |
272 | struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf, &err); | ||
273 | if(file == NULL) | ||
274 | { | ||
275 | color(OFF); | ||
276 | printf("SB read failed: %d\n", err); | ||
277 | return 1; | ||
278 | } | ||
279 | |||
272 | color(OFF); | 280 | color(OFF); |
273 | if(g_out_prefix) | 281 | if(g_out_prefix) |
274 | extract_sb_file(file); | 282 | extract_sb_file(file); |
@@ -283,12 +291,12 @@ int main(int argc, char **argv) | |||
283 | /* sb_read_file will fill real key and IV but we don't want to override | 291 | /* sb_read_file will fill real key and IV but we don't want to override |
284 | * them when looping back otherwise the output will be inconsistent and | 292 | * them when looping back otherwise the output will be inconsistent and |
285 | * garbage */ | 293 | * garbage */ |
286 | free(file->real_key); | 294 | file->override_real_key = false; |
287 | file->real_key = NULL; | 295 | file->override_crypto_iv = false; |
288 | free(file->crypto_iv); | ||
289 | file->crypto_iv = NULL; | ||
290 | sb_write_file(file, loopback); | 296 | sb_write_file(file, loopback); |
291 | } | 297 | } |
298 | sb_free(file); | ||
299 | clear_keys(); | ||
292 | 300 | ||
293 | return 0; | 301 | return 0; |
294 | } | 302 | } |
diff --git a/utils/sbtools/sha1.c b/utils/imxtools/sha1.c index 0ad05bb5cd..0ad05bb5cd 100644 --- a/utils/sbtools/sha1.c +++ b/utils/imxtools/sha1.c | |||