From 782d9c0d80f1edc29955dbe7e7f42770f730b597 Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Thu, 29 May 2014 21:45:51 +0200 Subject: mkimxboot: add the concept of soft MD5 sum Change-Id: I7e83218ce0dccc1f4c4a7a6bb9c1df00dacf260b --- rbutil/mkimxboot/main.c | 86 +++++++++++++++++++++++++++++++++++- rbutil/mkimxboot/mkimxboot.c | 101 ++++++++++++++++++++++++++++++++++++++++++- rbutil/mkimxboot/mkimxboot.h | 3 ++ 3 files changed, 187 insertions(+), 3 deletions(-) diff --git a/rbutil/mkimxboot/main.c b/rbutil/mkimxboot/main.c index bcc443d7f2..611715f7c1 100644 --- a/rbutil/mkimxboot/main.c +++ b/rbutil/mkimxboot/main.c @@ -43,6 +43,26 @@ static struct imx_variant_t imx_variants[] = #define NR_VARIANTS sizeof(imx_variants) / sizeof(imx_variants[0]) +struct model_t +{ + const char *name; + enum imx_model_t model; +}; + +struct model_t imx_models[] = +{ + { "unknown", MODEL_UNKNOWN }, + { "fuzeplus", MODEL_FUZEPLUS }, + { "zenxfi2", MODEL_ZENXFI2 }, + { "zenxfi3", MODEL_ZENXFI3 }, + { "zenxfistyle", MODEL_ZENXFISTYLE }, + { "zenstyle", MODEL_ZENSTYLE }, + { "nwze370", MODEL_NWZE370 }, + { "nwze360", MODEL_NWZE360 }, +}; + +#define NR_MODELS sizeof(imx_models) / sizeof(imx_models[0]) + static void usage(void) { printf("Usage: mkimxboot [options | file]...\n"); @@ -57,6 +77,8 @@ static void usage(void) printf(" -x Dump device informations\n"); printf(" -w Extract the original firmware\n"); printf(" -p Force product and component version\n"); + printf(" -5 Compute MD5 sum of the input file\n"); + printf(" -m Specify model (useful for soft MD5 sum)\n"); printf("Supported variants: (default is standard)\n"); printf(" "); for(size_t i = 0; i < NR_VARIANTS; i++) @@ -66,15 +88,51 @@ static void usage(void) printf("%s", imx_variants[i].name); } printf("\n"); + printf("Supported models: (default is unknown)\n"); + for(size_t i = 0; i < NR_MODELS; i++) + { + if(i != 0) + printf(", "); + printf("%s", imx_models[i].name); + } + printf("\n"); printf("By default a dualboot image is built\n"); printf("This tools supports the following format for the boot file:\n"); printf("- rockbox scramble format\n"); printf("- elf format\n"); printf("Additional checks will be performed on rockbox scramble format to\n"); printf("ensure soundness of operation.\n"); + printf("There are two types of MD5 sums: 'full' or 'soft'.\n"); + printf("- full MD5 sum applies to the whole file\n"); + printf("- soft MD5 sum for SB files accounts for relevant parts only\n"); exit(1); } +static int print_md5(const char *file, enum imx_model_t model, const char *type) +{ + uint8_t md5sum[16]; + enum imx_error_t err; + if(strcmp(type, "full") == 0) + err = compute_md5sum(file, md5sum); + else if(strcmp(type, "soft") == 0) + err = compute_soft_md5sum(file, model, md5sum); + else + { + printf("Invalid md5sum type '%s'\n", type); + return 1; + } + if(err != IMX_SUCCESS) + { + printf("There was an error when computing the MD5 sum: %d\n", err); + return 2; + } + printf("%s MD5 sum: ", type); + for(int i = 0; i < 16; i++) + printf("%02x", md5sum[i]); + printf("\n"); + return 0; +} + int main(int argc, char *argv[]) { char *infile = NULL; @@ -82,8 +140,10 @@ int main(int argc, char *argv[]) char *bootfile = NULL; enum imx_firmware_variant_t variant = VARIANT_DEFAULT; enum imx_output_type_t type = IMX_DUALBOOT; + enum imx_model_t model = MODEL_UNKNOWN; bool debug = false; bool extract_of = false; + const char *md5type = NULL; const char *force_version = NULL; if(argc == 1) @@ -101,10 +161,12 @@ int main(int argc, char *argv[]) {"type", required_argument, 0, 't'}, {"variant", required_argument, 0, 'v'}, {"dev-info", no_argument, 0, 'x'}, + {"model", required_argument, 0, 'm'}, + {"md5", required_argument, 0, '5'}, {0, 0, 0, 0} }; - int c = getopt_long(argc, argv, "?di:o:b:t:v:xwp:", long_options, NULL); + int c = getopt_long(argc, argv, "?di:o:b:t:v:xwp:m:5:", long_options, NULL); if(c == -1) break; switch(c) @@ -167,6 +229,24 @@ int main(int argc, char *argv[]) case 'p': force_version = optarg; break; + case '5': + md5type = optarg; + break; + case 'm': + if(model != MODEL_UNKNOWN) + { + printf("You cannot specify two models\n"); + return 1; + } + for(int i = 0; i < NR_MODELS; i++) + if(strcmp(optarg, imx_models[i].name) == 0) + { + model = imx_models[i].model; + break; + } + if(model == MODEL_UNKNOWN) + printf("Unknown model '%s'\n", optarg); + break; default: abort(); } @@ -177,6 +257,10 @@ int main(int argc, char *argv[]) printf("You must specify an input file\n"); return 1; } + + if(md5type) + return print_md5(infile, md5type); + if(!outfile) { printf("You must specify an output file\n"); diff --git a/rbutil/mkimxboot/mkimxboot.c b/rbutil/mkimxboot/mkimxboot.c index 436b3ebff4..909dad8641 100644 --- a/rbutil/mkimxboot/mkimxboot.c +++ b/rbutil/mkimxboot/mkimxboot.c @@ -597,8 +597,77 @@ static enum imx_error_t compute_md5sum_buf(void *buf, size_t sz, uint8_t file_md return IMX_SUCCESS; } +/* compute MD5 sum of a buffer */ +static enum imx_error_t compute_soft_md5sum_buf(struct sb_file_t *sb, uint8_t file_md5sum[16]) +{ + md5_context ctx; + md5_starts(&ctx); +#define hash(obj) \ + md5_update(&ctx, (void *)&obj, sizeof(obj)) + /* various header fiels */ + hash(sb->timestamp); + hash(sb->drive_tag); + hash(sb->drive_tag); + hash(sb->first_boot_sec_id); + hash(sb->flags); + hash(sb->product_ver); + hash(sb->component_ver); + + for(int i = 0; i < sb->nr_sections; i++) + { + struct sb_section_t *sec = &sb->sections[i]; + hash(sec->identifier); + uint32_t flags = sec->other_flags; + if(!sec->is_data) + flags |= SECTION_BOOTABLE; + if(sec->is_cleartext) + flags |= SECTION_CLEARTEXT; + hash(flags); + + for(int j = 0; j < sec->nr_insts; j++) + { + struct sb_inst_t *inst = &sec->insts[j]; + switch(inst->inst) + { + case SB_INST_NOP: + /* ignore them totally because they are used for padding */ + break; + case SB_INST_LOAD: + hash(inst->inst); + hash(inst->addr); + md5_update(&ctx, inst->data, inst->size); + break; + case SB_INST_FILL: + hash(inst->inst); + hash(inst->addr); + hash(inst->pattern); + break; + case SB_INST_JUMP: + case SB_INST_CALL: + hash(inst->inst); + hash(inst->addr); + hash(inst->argument); + break; + case SB_INST_MODE: + hash(inst->inst); + hash(inst->argument); + break; + case SB_INST_DATA: + md5_update(&ctx, inst->data, inst->size); + break; + default: + printf("[ERR][INTERNAL] Unexpected instruction %d\n", inst->inst); + return IMX_ERROR; + } + } + } +#undef hash + md5_finish(&ctx, file_md5sum); + return IMX_SUCCESS; +} + /* compute MD5 of a file */ -static enum imx_error_t compute_md5sum(const char *file, uint8_t file_md5sum[16]) +enum imx_error_t compute_md5sum(const char *file, uint8_t file_md5sum[16]) { void *buf; size_t sz; @@ -610,6 +679,32 @@ static enum imx_error_t compute_md5sum(const char *file, uint8_t file_md5sum[16] return IMX_SUCCESS; } +/* compute soft MD5 of a file */ +enum imx_error_t compute_soft_md5sum(const char *file, enum imx_model_t model, + uint8_t soft_md5sum[16]) +{ + if(model == MODEL_UNKNOWN) + { + printf("[ERR] Cannot compute soft MD5 without knowing the model\n"); + return IMX_ERROR; + } + clear_keys(); + add_keys(imx_models[model].keys, imx_models[model].nr_keys); + /* read file */ + enum sb_error_t err; + struct sb_file_t *sb = sb_read_file(file, false, NULL, generic_std_printf, &err); + if(sb == NULL) + { + printf("[ERR] Cannot load SB file: %d\n", err); + return err; + } + /* compute sum */ + err = compute_soft_md5sum_buf(sb, soft_md5sum); + /* release file */ + sb_free(sb); + return err; +} + static enum imx_error_t load_sb_file(const char *file, int md5_idx, struct imx_option_t opt, struct sb_file_t **sb_file) { @@ -792,7 +887,9 @@ enum imx_error_t mkimxboot(const char *infile, const char *bootfile, if(ret != IMX_SUCCESS) return ret; printf("[INFO] MD5 sum of the file: "); - print_hex(NULL, misc_std_printf, file_md5sum, 16, true); + for(int i = 0; i < 16; i++) + printf("%02x", file_md5sum[i]); + printf("\n"); /* find model */ int md5_idx; ret = find_model_by_md5sum(file_md5sum, &md5_idx); diff --git a/rbutil/mkimxboot/mkimxboot.h b/rbutil/mkimxboot/mkimxboot.h index 512a658c35..3157bd7daa 100644 --- a/rbutil/mkimxboot/mkimxboot.h +++ b/rbutil/mkimxboot/mkimxboot.h @@ -98,6 +98,9 @@ enum imx_error_t mkimxboot(const char *infile, const char *bootfile, const char *outfile, struct imx_option_t opt); enum imx_error_t extract_firmware(const char *infile, enum imx_firmware_variant_t fw_variant, const char *outfile); +enum imx_error_t compute_md5sum(const char *file, uint8_t file_md5sum[16]); +enum imx_error_t compute_soft_md5sum(const char *file, enum imx_model_t model, + uint8_t soft_md5sum[16]); #ifdef __cplusplus } -- cgit v1.2.3