forked from len0rd/rockbox
mkimxboot: refactor code, no functional change
The mkimxboot was becoming messy with juge functions and redundant code. Factor reading/writing/loading code into smaller functions. Introduce the concept of rockbox firmware to simplify support of other formats than scramble. Change-Id: I3a61295ca5abca1a0eee8c9e8709c6b8dfa256a6
This commit is contained in:
parent
6483e23f07
commit
58e27b9fa1
2 changed files with 258 additions and 228 deletions
|
|
@ -28,6 +28,14 @@
|
|||
#include "dualboot.h"
|
||||
#include "md5.h"
|
||||
|
||||
/* abstract structure to represent a Rockbox firmware. It can be a scrambled file
|
||||
* or an ELF file or whatever. */
|
||||
struct rb_fw_t
|
||||
{
|
||||
void *boot;
|
||||
size_t boot_sz;
|
||||
};
|
||||
|
||||
struct imx_fw_variant_desc_t
|
||||
{
|
||||
/* Offset within file */
|
||||
|
|
@ -160,7 +168,7 @@ static const struct imx_model_desc_t imx_models[] =
|
|||
#define MAGIC_NORMAL 0xcafebabe
|
||||
|
||||
static enum imx_error_t patch_std_zero_host_play(int jump_before, int model,
|
||||
enum imx_output_type_t type, struct sb_file_t *sb_file, void *boot, size_t boot_sz)
|
||||
enum imx_output_type_t type, struct sb_file_t *sb_file, struct rb_fw_t boot_fw)
|
||||
{
|
||||
/* We assume the file has three boot sections: ____, host, play and one
|
||||
* resource section rsrc.
|
||||
|
|
@ -229,8 +237,8 @@ static enum imx_error_t patch_std_zero_host_play(int jump_before, int model,
|
|||
rock_sec.insts = xmalloc(2 * sizeof(struct sb_inst_t));
|
||||
memset(rock_sec.insts, 0, 2 * sizeof(struct sb_inst_t));
|
||||
rock_sec.insts[0].inst = SB_INST_LOAD;
|
||||
rock_sec.insts[0].size = boot_sz;
|
||||
rock_sec.insts[0].data = memdup(boot, boot_sz);
|
||||
rock_sec.insts[0].size = boot_fw.boot_sz;
|
||||
rock_sec.insts[0].data = memdup(boot_fw.boot, boot_fw.boot_sz);
|
||||
rock_sec.insts[0].addr = imx_models[model].bootloader_addr;
|
||||
rock_sec.insts[1].inst = SB_INST_JUMP;
|
||||
rock_sec.insts[1].addr = imx_models[model].bootloader_addr;
|
||||
|
|
@ -253,13 +261,13 @@ static enum imx_error_t patch_std_zero_host_play(int jump_before, int model,
|
|||
sb_free_instruction(sec->insts[i]);
|
||||
memset(new_insts + jump_idx, 0, 2 * sizeof(struct sb_inst_t));
|
||||
new_insts[jump_idx + 0].inst = SB_INST_LOAD;
|
||||
new_insts[jump_idx + 0].size = boot_sz;
|
||||
new_insts[jump_idx + 0].data = memdup(boot, boot_sz);
|
||||
new_insts[jump_idx + 0].size = boot_fw.boot_sz;
|
||||
new_insts[jump_idx + 0].data = memdup(boot_fw.boot, boot_fw.boot_sz);
|
||||
new_insts[jump_idx + 0].addr = imx_models[model].bootloader_addr;
|
||||
new_insts[jump_idx + 1].inst = SB_INST_JUMP;
|
||||
new_insts[jump_idx + 1].addr = imx_models[model].bootloader_addr;
|
||||
new_insts[jump_idx + 1].argument = recovery ? MAGIC_RECOVERY : MAGIC_NORMAL;
|
||||
|
||||
|
||||
free(sec->insts);
|
||||
sec->insts = new_insts;
|
||||
sec->nr_insts = jump_idx + 2;
|
||||
|
|
@ -327,7 +335,7 @@ static enum imx_error_t parse_version(const char *s, struct sb_version_t *ver)
|
|||
|
||||
static enum imx_error_t patch_firmware(enum imx_model_t model,
|
||||
enum imx_firmware_variant_t variant, enum imx_output_type_t type,
|
||||
struct sb_file_t *sb_file, void *boot, size_t boot_sz,
|
||||
struct sb_file_t *sb_file, struct rb_fw_t boot_fw,
|
||||
const char *force_version)
|
||||
{
|
||||
if(force_version)
|
||||
|
|
@ -342,11 +350,11 @@ static enum imx_error_t patch_firmware(enum imx_model_t model,
|
|||
case MODEL_FUZEPLUS:
|
||||
/* The Fuze+ uses the standard ____, host, play sections, patch after third
|
||||
* call in ____ section */
|
||||
return patch_std_zero_host_play(3, model, type, sb_file, boot, boot_sz);
|
||||
return patch_std_zero_host_play(3, model, type, sb_file, boot_fw);
|
||||
case MODEL_ZENXFI3:
|
||||
/* The ZEN X-Fi3 uses the standard ____, hSst, pSay sections, patch after third
|
||||
* call in ____ section. Although sections names use the S variant, they are standard. */
|
||||
return patch_std_zero_host_play(3, model, type, sb_file, boot, boot_sz);
|
||||
return patch_std_zero_host_play(3, model, type, sb_file, boot_fw);
|
||||
case MODEL_ZENXFI2:
|
||||
/* The ZEN X-Fi2 has two types of firmware: recovery and normal.
|
||||
* Normal uses the standard ___, host, play sections and recovery only ____ */
|
||||
|
|
@ -355,7 +363,7 @@ static enum imx_error_t patch_firmware(enum imx_model_t model,
|
|||
case VARIANT_ZENXFI2_RECOVERY:
|
||||
case VARIANT_ZENXFI2_NAND:
|
||||
case VARIANT_ZENXFI2_SD:
|
||||
return patch_std_zero_host_play(1, model, type, sb_file, boot, boot_sz);
|
||||
return patch_std_zero_host_play(1, model, type, sb_file, boot_fw);
|
||||
default:
|
||||
return IMX_DONT_KNOW_HOW_TO_PATCH;
|
||||
}
|
||||
|
|
@ -413,180 +421,98 @@ void dump_imx_dev_info(const char *prefix)
|
|||
}
|
||||
}
|
||||
|
||||
enum imx_error_t mkimxboot(const char *infile, const char *bootfile,
|
||||
const char *outfile, struct imx_option_t opt)
|
||||
/* find an entry into imx_sums which matches the MD5 sum of a file */
|
||||
static enum imx_error_t find_model_by_md5sum(uint8_t file_md5sum[16], int *md5_idx)
|
||||
{
|
||||
/* Dump tables */
|
||||
if(opt.fw_variant > VARIANT_COUNT) {
|
||||
return IMX_ERROR;
|
||||
}
|
||||
dump_imx_dev_info("[INFO] ");
|
||||
/* compute MD5 sum of the file */
|
||||
uint8_t file_md5sum[16];
|
||||
do
|
||||
int i = 0;
|
||||
while(i < NR_IMX_SUMS)
|
||||
{
|
||||
FILE *f = fopen(infile, "rb");
|
||||
if(f == NULL)
|
||||
uint8_t md5[20];
|
||||
if(strlen(imx_sums[i].md5sum) != 32)
|
||||
{
|
||||
printf("[ERR] Cannot open input file\n");
|
||||
return IMX_OPEN_ERROR;
|
||||
printf("[INFO] Invalid MD5 sum in imx_sums\n");
|
||||
return IMX_ERROR;
|
||||
}
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t sz = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
void *buf = xmalloc(sz);
|
||||
if(fread(buf, sz, 1, f) != 1)
|
||||
for(int j = 0; j < 16; j++)
|
||||
{
|
||||
fclose(f);
|
||||
free(buf);
|
||||
printf("[ERR] Cannot read file\n");
|
||||
return IMX_READ_ERROR;
|
||||
}
|
||||
fclose(f);
|
||||
md5_context ctx;
|
||||
md5_starts(&ctx);
|
||||
md5_update(&ctx, buf, sz);
|
||||
md5_finish(&ctx, file_md5sum);
|
||||
free(buf);
|
||||
}while(0);
|
||||
printf("[INFO] MD5 sum of the file: ");
|
||||
print_hex(file_md5sum, 16, true);
|
||||
/* find model */
|
||||
enum imx_model_t model;
|
||||
int md5_idx;
|
||||
do
|
||||
{
|
||||
int i = 0;
|
||||
while(i < NR_IMX_SUMS)
|
||||
{
|
||||
uint8_t md5[20];
|
||||
if(strlen(imx_sums[i].md5sum) != 32)
|
||||
byte a, b;
|
||||
if(convxdigit(imx_sums[i].md5sum[2 * j], &a) || convxdigit(imx_sums[i].md5sum[2 * j + 1], &b))
|
||||
{
|
||||
printf("[INFO] Invalid MD5 sum in imx_sums\n");
|
||||
printf("[ERR][INTERNAL] Bad checksum format: %s\n", imx_sums[i].md5sum);
|
||||
return IMX_ERROR;
|
||||
}
|
||||
for(int j = 0; j < 16; j++)
|
||||
{
|
||||
byte a, b;
|
||||
if(convxdigit(imx_sums[i].md5sum[2 * j], &a) || convxdigit(imx_sums[i].md5sum[2 * j + 1], &b))
|
||||
{
|
||||
printf("[ERR][INTERNAL] Bad checksum format: %s\n", imx_sums[i].md5sum);
|
||||
return IMX_ERROR;
|
||||
}
|
||||
md5[j] = (a << 4) | b;
|
||||
}
|
||||
if(memcmp(file_md5sum, md5, 16) == 0)
|
||||
break;
|
||||
i++;
|
||||
md5[j] = (a << 4) | b;
|
||||
}
|
||||
if(i == NR_IMX_SUMS)
|
||||
{
|
||||
printf("[ERR] MD5 sum doesn't match any known file\n");
|
||||
return IMX_NO_MATCH;
|
||||
}
|
||||
model = imx_sums[i].model;
|
||||
md5_idx = i;
|
||||
}while(0);
|
||||
printf("[INFO] File is for model %d (%s, version %s)\n", model,
|
||||
imx_models[model].model_name, imx_sums[md5_idx].version);
|
||||
/* load rockbox file */
|
||||
uint8_t *boot;
|
||||
size_t boot_size;
|
||||
do
|
||||
if(memcmp(file_md5sum, md5, 16) == 0)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
if(i == NR_IMX_SUMS)
|
||||
{
|
||||
FILE *f = fopen(bootfile, "rb");
|
||||
if(f == NULL)
|
||||
{
|
||||
printf("[ERR] Cannot open boot file\n");
|
||||
return IMX_OPEN_ERROR;
|
||||
}
|
||||
fseek(f, 0, SEEK_END);
|
||||
boot_size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
boot = xmalloc(boot_size);
|
||||
if(fread(boot, boot_size, 1, f) != 1)
|
||||
{
|
||||
free(boot);
|
||||
fclose(f);
|
||||
printf("[ERR] Cannot read boot file\n");
|
||||
return IMX_READ_ERROR;
|
||||
}
|
||||
fclose(f);
|
||||
}while(0);
|
||||
/* Check boot file */
|
||||
do
|
||||
{
|
||||
if(boot_size < 8)
|
||||
{
|
||||
printf("[ERR] Bootloader file is too small to be valid\n");
|
||||
free(boot);
|
||||
return IMX_BOOT_INVALID;
|
||||
}
|
||||
/* check model name */
|
||||
uint8_t *name = boot + 4;
|
||||
if(memcmp(name, imx_models[model].rb_model_name, 4) != 0)
|
||||
{
|
||||
printf("[ERR] Bootloader model doesn't match found model for input file\n");
|
||||
free(boot);
|
||||
return IMX_BOOT_MISMATCH;
|
||||
}
|
||||
/* check checksum */
|
||||
uint32_t sum = imx_models[model].rb_model_num;
|
||||
for(int i = 8; i < boot_size; i++)
|
||||
sum += boot[i];
|
||||
if(sum != get_uint32be(boot))
|
||||
{
|
||||
printf("[ERR] Bootloader checksum mismatch\n");
|
||||
free(boot);
|
||||
return IMX_BOOT_CHECKSUM_ERROR;
|
||||
}
|
||||
}while(0);
|
||||
/* load OF file */
|
||||
struct sb_file_t *sb_file;
|
||||
do
|
||||
{
|
||||
if(imx_sums[md5_idx].fw_variants[opt.fw_variant].size == 0)
|
||||
{
|
||||
printf("[ERR] Input file does not contain variant '%s'\n", imx_fw_variant[opt.fw_variant]);
|
||||
free(boot);
|
||||
return IMX_VARIANT_MISMATCH;
|
||||
}
|
||||
enum sb_error_t err;
|
||||
g_debug = opt.debug;
|
||||
clear_keys();
|
||||
add_keys(imx_models[model].keys, imx_models[model].nr_keys);
|
||||
sb_file = sb_read_file_ex(infile, imx_sums[md5_idx].fw_variants[opt.fw_variant].offset,
|
||||
imx_sums[md5_idx].fw_variants[opt.fw_variant].size, false, NULL, &imx_printf, &err);
|
||||
if(sb_file == NULL)
|
||||
{
|
||||
clear_keys();
|
||||
free(boot);
|
||||
return IMX_FIRST_SB_ERROR + err;
|
||||
}
|
||||
}while(0);
|
||||
/* produce file */
|
||||
enum imx_error_t ret = patch_firmware(model, opt.fw_variant, opt.output,
|
||||
sb_file, boot + 8, boot_size - 8, opt.force_version);
|
||||
if(ret == IMX_SUCCESS)
|
||||
ret = sb_write_file(sb_file, outfile);
|
||||
|
||||
clear_keys();
|
||||
free(boot);
|
||||
sb_free(sb_file);
|
||||
return ret;
|
||||
printf("[ERR] MD5 sum doesn't match any known file\n");
|
||||
return IMX_NO_MATCH;
|
||||
}
|
||||
*md5_idx = i;
|
||||
return IMX_SUCCESS;
|
||||
}
|
||||
|
||||
enum imx_error_t extract_firmware(const char *infile,
|
||||
enum imx_firmware_variant_t fw_variant, const char *outfile)
|
||||
/* read a file to a buffer */
|
||||
static enum imx_error_t read_file(const char *file, void **buffer, size_t *size)
|
||||
{
|
||||
/* Dump tables */
|
||||
if(fw_variant > VARIANT_COUNT) {
|
||||
return IMX_ERROR;
|
||||
FILE *f = fopen(file, "rb");
|
||||
if(f == NULL)
|
||||
{
|
||||
printf("[ERR] Cannot open file '%s' for reading: %m\n", file);
|
||||
return IMX_OPEN_ERROR;
|
||||
}
|
||||
dump_imx_dev_info("[INFO] ");
|
||||
/* compute MD5 sum of the file */
|
||||
uint8_t file_md5sum[16];
|
||||
FILE *f = fopen(infile, "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
*size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
*buffer = xmalloc(*size);
|
||||
if(fread(*buffer, *size, 1, f) != 1)
|
||||
{
|
||||
free(*buffer);
|
||||
fclose(f);
|
||||
printf("[ERR] Cannot read file '%s': %m\n", file);
|
||||
return IMX_READ_ERROR;
|
||||
}
|
||||
fclose(f);
|
||||
return IMX_SUCCESS;
|
||||
}
|
||||
|
||||
/* write a file from a buffer */
|
||||
static enum imx_error_t write_file(const char *file, void *buffer, size_t size)
|
||||
{
|
||||
FILE *f = fopen(file, "wb");
|
||||
if(f == NULL)
|
||||
{
|
||||
printf("[ERR] Cannot open file '%s' for writing: %m\n", file);
|
||||
return IMX_OPEN_ERROR;
|
||||
}
|
||||
if(fwrite(buffer, size, 1, f) != 1)
|
||||
{
|
||||
fclose(f);
|
||||
printf("[ERR] Cannot write file '%s': %m\n", file);
|
||||
return IMX_WRITE_ERROR;
|
||||
}
|
||||
fclose(f);
|
||||
return IMX_SUCCESS;
|
||||
}
|
||||
|
||||
/* compute MD5 sum of a buffer */
|
||||
static enum imx_error_t compute_md5sum_buf(void *buf, size_t sz, uint8_t file_md5sum[16])
|
||||
{
|
||||
md5_context ctx;
|
||||
md5_starts(&ctx);
|
||||
md5_update(&ctx, buf, sz);
|
||||
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])
|
||||
{
|
||||
FILE *f = fopen(file, "rb");
|
||||
if(f == NULL)
|
||||
{
|
||||
printf("[ERR] Cannot open input file\n");
|
||||
|
|
@ -603,54 +529,171 @@ enum imx_error_t extract_firmware(const char *infile,
|
|||
printf("[ERR] Cannot read file\n");
|
||||
return IMX_READ_ERROR;
|
||||
}
|
||||
md5_context ctx;
|
||||
md5_starts(&ctx);
|
||||
md5_update(&ctx, buf, sz);
|
||||
md5_finish(&ctx, file_md5sum);
|
||||
fclose(f);
|
||||
|
||||
compute_md5sum_buf(buf, sz, file_md5sum);
|
||||
free(buf);
|
||||
return IMX_SUCCESS;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if(imx_sums[md5_idx].fw_variants[opt.fw_variant].size == 0)
|
||||
{
|
||||
printf("[ERR] Input file does not contain variant '%s'\n", imx_fw_variant[opt.fw_variant]);
|
||||
return IMX_VARIANT_MISMATCH;
|
||||
}
|
||||
enum imx_model_t model = imx_sums[md5_idx].model;
|
||||
enum sb_error_t err;
|
||||
g_debug = opt.debug;
|
||||
clear_keys();
|
||||
add_keys(imx_models[model].keys, imx_models[model].nr_keys);
|
||||
*sb_file = sb_read_file_ex(file, imx_sums[md5_idx].fw_variants[opt.fw_variant].offset,
|
||||
imx_sums[md5_idx].fw_variants[opt.fw_variant].size, false, NULL, &imx_printf, &err);
|
||||
if(*sb_file == NULL)
|
||||
{
|
||||
clear_keys();
|
||||
return IMX_FIRST_SB_ERROR + err;
|
||||
}
|
||||
return IMX_SUCCESS;
|
||||
}
|
||||
|
||||
/* Load a rockbox firwmare from a buffer. Data is copied. */
|
||||
static enum imx_error_t rb_fw_load_buf(struct rb_fw_t *fw, uint8_t *buf, size_t sz,
|
||||
enum imx_model_t model)
|
||||
{
|
||||
if(sz < 8)
|
||||
{
|
||||
printf("[ERR] Bootloader file is too small to be valid\n");
|
||||
return IMX_BOOT_INVALID;
|
||||
}
|
||||
/* check model name */
|
||||
uint8_t *name = buf + 4;
|
||||
if(memcmp(name, imx_models[model].rb_model_name, 4) != 0)
|
||||
{
|
||||
printf("[ERR] Bootloader model doesn't match found model for input file\n");
|
||||
return IMX_BOOT_MISMATCH;
|
||||
}
|
||||
/* check checksum */
|
||||
uint32_t sum = imx_models[model].rb_model_num;
|
||||
for(int i = 8; i < sz; i++)
|
||||
sum += buf[i];
|
||||
if(sum != get_uint32be(buf))
|
||||
{
|
||||
printf("[ERR] Bootloader checksum mismatch\n");
|
||||
return IMX_BOOT_CHECKSUM_ERROR;
|
||||
}
|
||||
fw->boot = memdup(buf + 8, sz - 8);
|
||||
fw->boot_sz = sz - 8;
|
||||
return IMX_SUCCESS;
|
||||
}
|
||||
|
||||
/* load a rockbox firmware from a file. */
|
||||
static enum imx_error_t rb_fw_load(struct rb_fw_t *fw, const char *file,
|
||||
enum imx_model_t model)
|
||||
{
|
||||
void *buf;
|
||||
size_t sz;
|
||||
int ret = read_file(file, &buf, &sz);
|
||||
if(ret == IMX_SUCCESS)
|
||||
{
|
||||
ret = rb_fw_load_buf(fw, buf, sz, model);
|
||||
free(buf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* free rockbox firmware */
|
||||
static void rb_fw_free(struct rb_fw_t *fw)
|
||||
{
|
||||
free(fw->boot);
|
||||
fw->boot = NULL;
|
||||
fw->boot_sz = 0;
|
||||
}
|
||||
|
||||
enum imx_error_t mkimxboot(const char *infile, const char *bootfile,
|
||||
const char *outfile, struct imx_option_t opt)
|
||||
{
|
||||
/* sanity check */
|
||||
if(opt.fw_variant > VARIANT_COUNT)
|
||||
return IMX_ERROR;
|
||||
/* Dump tables */
|
||||
dump_imx_dev_info("[INFO] ");
|
||||
/* compute MD5 sum of the file */
|
||||
uint8_t file_md5sum[16];
|
||||
enum imx_error_t ret = compute_md5sum(infile, file_md5sum);
|
||||
if(ret != IMX_SUCCESS)
|
||||
return ret;
|
||||
printf("[INFO] MD5 sum of the file: ");
|
||||
print_hex(file_md5sum, 16, true);
|
||||
/* find model */
|
||||
enum imx_model_t model;
|
||||
int md5_idx;
|
||||
do
|
||||
{
|
||||
int i = 0;
|
||||
while(i < NR_IMX_SUMS)
|
||||
{
|
||||
uint8_t md5[20];
|
||||
if(strlen(imx_sums[i].md5sum) != 32)
|
||||
{
|
||||
printf("[INFO] Invalid MD5 sum in imx_sums\n");
|
||||
return IMX_ERROR;
|
||||
}
|
||||
for(int j = 0; j < 16; j++)
|
||||
{
|
||||
byte a, b;
|
||||
if(convxdigit(imx_sums[i].md5sum[2 * j], &a) || convxdigit(imx_sums[i].md5sum[2 * j + 1], &b))
|
||||
{
|
||||
printf("[ERR][INTERNAL] Bad checksum format: %s\n", imx_sums[i].md5sum);
|
||||
free(buf);
|
||||
return IMX_ERROR;
|
||||
}
|
||||
md5[j] = (a << 4) | b;
|
||||
}
|
||||
if(memcmp(file_md5sum, md5, 16) == 0)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
if(i == NR_IMX_SUMS)
|
||||
{
|
||||
printf("[ERR] MD5 sum doesn't match any known file\n");
|
||||
return IMX_NO_MATCH;
|
||||
}
|
||||
model = imx_sums[i].model;
|
||||
md5_idx = i;
|
||||
}while(0);
|
||||
ret = find_model_by_md5sum(file_md5sum, &md5_idx);
|
||||
if(ret != IMX_SUCCESS)
|
||||
return ret;
|
||||
enum imx_model_t model = imx_sums[md5_idx].model;
|
||||
printf("[INFO] File is for model %d (%s, version %s)\n", model,
|
||||
imx_models[model].model_name, imx_sums[md5_idx].version);
|
||||
/* load rockbox file */
|
||||
struct rb_fw_t boot_fw;
|
||||
ret = rb_fw_load(&boot_fw, bootfile, model);
|
||||
if(ret != IMX_SUCCESS)
|
||||
return ret;
|
||||
/* load OF file */
|
||||
struct sb_file_t *sb_file;
|
||||
ret = load_sb_file(infile, md5_idx, opt, &sb_file);
|
||||
if(ret != IMX_SUCCESS)
|
||||
{
|
||||
rb_fw_free(&boot_fw);
|
||||
return ret;
|
||||
}
|
||||
/* produce file */
|
||||
ret = patch_firmware(model, opt.fw_variant, opt.output,
|
||||
sb_file, boot_fw, opt.force_version);
|
||||
if(ret == IMX_SUCCESS)
|
||||
ret = sb_write_file(sb_file, outfile);
|
||||
|
||||
clear_keys();
|
||||
rb_fw_free(&boot_fw);
|
||||
sb_free(sb_file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum imx_error_t extract_firmware(const char *infile,
|
||||
enum imx_firmware_variant_t fw_variant, const char *outfile)
|
||||
{
|
||||
/* sanity check */
|
||||
if(fw_variant > VARIANT_COUNT)
|
||||
return IMX_ERROR;
|
||||
/* dump tables */
|
||||
dump_imx_dev_info("[INFO] ");
|
||||
/* compute MD5 sum of the file */
|
||||
void *buf;
|
||||
size_t sz;
|
||||
uint8_t file_md5sum[16];
|
||||
int ret = read_file(infile, &buf, &sz);
|
||||
if(ret != IMX_SUCCESS)
|
||||
return ret;
|
||||
ret = compute_md5sum_buf(buf, sz, file_md5sum);
|
||||
if(ret != IMX_SUCCESS)
|
||||
{
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
printf("[INFO] MD5 sum of the file: ");
|
||||
print_hex(file_md5sum, 16, true);
|
||||
/* find model */
|
||||
int md5_idx;
|
||||
ret = find_model_by_md5sum(file_md5sum, &md5_idx);
|
||||
if(ret != IMX_SUCCESS)
|
||||
{
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
enum imx_model_t model = imx_sums[md5_idx].model;
|
||||
printf("[INFO] File is for model %d (%s, version %s)\n", model,
|
||||
imx_models[model].model_name, imx_sums[md5_idx].version);
|
||||
/* extract firmware */
|
||||
if(imx_sums[md5_idx].fw_variants[fw_variant].size == 0)
|
||||
{
|
||||
printf("[ERR] Input file does not contain variant '%s'\n", imx_fw_variant[fw_variant]);
|
||||
|
|
@ -658,23 +701,9 @@ enum imx_error_t extract_firmware(const char *infile,
|
|||
return IMX_VARIANT_MISMATCH;
|
||||
}
|
||||
|
||||
f = fopen(outfile, "wb");
|
||||
if(f == NULL)
|
||||
{
|
||||
printf("[ERR] Cannot open input file\n");
|
||||
free(buf);
|
||||
return IMX_OPEN_ERROR;
|
||||
}
|
||||
enum imx_error_t ret = IMX_SUCCESS;
|
||||
|
||||
if(fwrite(buf + imx_sums[md5_idx].fw_variants[fw_variant].offset,
|
||||
imx_sums[md5_idx].fw_variants[fw_variant].size, 1, f) != 1)
|
||||
{
|
||||
printf("[ERR] Cannot write file\n");
|
||||
ret = IMX_ERROR;
|
||||
}
|
||||
fclose(f);
|
||||
ret = write_file(outfile,
|
||||
buf + imx_sums[md5_idx].fw_variants[fw_variant].offset,
|
||||
imx_sums[md5_idx].fw_variants[fw_variant].size);
|
||||
free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ enum imx_error_t
|
|||
IMX_BOOT_CHECKSUM_ERROR = -7,
|
||||
IMX_DONT_KNOW_HOW_TO_PATCH = -8,
|
||||
IMX_VARIANT_MISMATCH = -9,
|
||||
IMX_FIRST_SB_ERROR = -10,
|
||||
IMX_WRITE_ERROR = -10,
|
||||
IMX_FIRST_SB_ERROR = -11,
|
||||
};
|
||||
|
||||
enum imx_output_type_t
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue