mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-22 22:33:48 -07:00
Flasher: read the firmware file in one go
This commit is contained in:
parent
2a705d3a44
commit
72f7bc762d
3 changed files with 120 additions and 191 deletions
|
@ -85,7 +85,8 @@ static int chipid_to_mem_avail(uint32_t iChipID) {
|
||||||
|
|
||||||
// Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent
|
// Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent
|
||||||
// unaligned segments if needed
|
// unaligned segments if needed
|
||||||
static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, uint32_t flash_end) {
|
static int build_segs_from_phdrs(flash_file_t *ctx, uint32_t flash_size) {
|
||||||
|
uint32_t flash_end = FLASH_START + flash_size;
|
||||||
Elf32_Phdr_t *phdr = ctx->phdrs;
|
Elf32_Phdr_t *phdr = ctx->phdrs;
|
||||||
flash_seg_t *seg;
|
flash_seg_t *seg;
|
||||||
uint32_t last_end = 0;
|
uint32_t last_end = 0;
|
||||||
|
@ -149,11 +150,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, uint32_t flash_end
|
||||||
PrintAndLogEx(ERR, "Error: Out of memory");
|
PrintAndLogEx(ERR, "Error: Out of memory");
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
if (fseek(fd, offset, SEEK_SET) < 0 || fread(data, 1, filesz, fd) != filesz) {
|
memcpy(data, ctx->elf + offset, filesz);
|
||||||
PrintAndLogEx(ERR, "Error while reading PHDR payload");
|
|
||||||
free(data);
|
|
||||||
return PM3_EFILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t block_offset = paddr & (BLOCK_SIZE - 1);
|
uint32_t block_offset = paddr & (BLOCK_SIZE - 1);
|
||||||
if (block_offset) {
|
if (block_offset) {
|
||||||
|
@ -209,7 +206,8 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, uint32_t flash_end
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check segments and check for bootloader writes
|
// Sanity check segments and check for bootloader writes
|
||||||
static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_end) {
|
static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_size) {
|
||||||
|
uint32_t flash_end = FLASH_START + flash_size;
|
||||||
for (int i = 0; i < ctx->num_segs; i++) {
|
for (int i = 0; i < ctx->num_segs; i++) {
|
||||||
flash_seg_t *seg = &ctx->segments[i];
|
flash_seg_t *seg = &ctx->segments[i];
|
||||||
|
|
||||||
|
@ -237,172 +235,15 @@ static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_end) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read an ELF file and do some checks
|
// Load an ELF file for flashing
|
||||||
int flash_check(flash_file_t *ctx, const char *name) {
|
int flash_load(flash_file_t *ctx) {
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
Elf32_Ehdr_t ehdr;
|
Elf32_Ehdr_t *ehdr;
|
||||||
Elf32_Phdr_t *phdrs = NULL;
|
|
||||||
Elf32_Shdr_t *shdrs = NULL;
|
Elf32_Shdr_t *shdrs = NULL;
|
||||||
uint16_t num_phdrs;
|
|
||||||
uint16_t num_shdrs;
|
|
||||||
uint8_t *shstr = NULL;
|
uint8_t *shstr = NULL;
|
||||||
struct version_information_t *vi = NULL;
|
struct version_information_t *vi = NULL;
|
||||||
int res = PM3_EUNDEF;
|
int res = PM3_EUNDEF;
|
||||||
|
|
||||||
fd = fopen(name, "rb");
|
|
||||||
if (!fd) {
|
|
||||||
PrintAndLogEx(ERR, _RED_("Could not open file") " %s >>> ", name);
|
|
||||||
res = PM3_EFILE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, _CYAN_("Loading ELF file") _YELLOW_(" %s"), name);
|
|
||||||
|
|
||||||
if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) {
|
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF file header");
|
|
||||||
res = PM3_EFILE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident))
|
|
||||||
|| le32(ehdr.e_version) != 1) {
|
|
||||||
PrintAndLogEx(ERR, "Not an ELF file or wrong ELF type");
|
|
||||||
res = PM3_EFILE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (le16(ehdr.e_type) != ET_EXEC) {
|
|
||||||
PrintAndLogEx(ERR, "ELF is not executable");
|
|
||||||
res = PM3_EFILE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (le16(ehdr.e_machine) != EM_ARM) {
|
|
||||||
PrintAndLogEx(ERR, "Wrong ELF architecture");
|
|
||||||
res = PM3_EFILE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (!ehdr.e_phnum || !ehdr.e_phoff) {
|
|
||||||
PrintAndLogEx(ERR, "ELF has no PHDRs");
|
|
||||||
res = PM3_EFILE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (le16(ehdr.e_phentsize) != sizeof(Elf32_Phdr_t)) {
|
|
||||||
// could be a structure padding issue...
|
|
||||||
PrintAndLogEx(ERR, "Either the ELF file or this code is made of fail");
|
|
||||||
res = PM3_EFILE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
num_phdrs = le16(ehdr.e_phnum);
|
|
||||||
|
|
||||||
phdrs = calloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr_t), sizeof(uint8_t));
|
|
||||||
if (!phdrs) {
|
|
||||||
PrintAndLogEx(ERR, "Out of memory");
|
|
||||||
res = PM3_EMALLOC;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (fseek(fd, le32(ehdr.e_phoff), SEEK_SET) < 0) {
|
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF PHDRs");
|
|
||||||
res = PM3_EFILE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (fread(phdrs, sizeof(Elf32_Phdr_t), num_phdrs, fd) != num_phdrs) {
|
|
||||||
res = PM3_EFILE;
|
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF PHDRs");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
num_shdrs = le16(ehdr.e_shnum);
|
|
||||||
|
|
||||||
shdrs = calloc(le16(ehdr.e_shnum) * sizeof(Elf32_Shdr_t), sizeof(uint8_t));
|
|
||||||
if (!shdrs) {
|
|
||||||
PrintAndLogEx(ERR, "Out of memory");
|
|
||||||
res = PM3_EMALLOC;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (fseek(fd, le32(ehdr.e_shoff), SEEK_SET) < 0) {
|
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF SHDRs");
|
|
||||||
res = PM3_EFILE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (fread(shdrs, sizeof(Elf32_Shdr_t), num_shdrs, fd) != num_shdrs) {
|
|
||||||
res = PM3_EFILE;
|
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF SHDRs");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
shstr = calloc(shdrs[ehdr.e_shstrndx].sh_size, sizeof(uint8_t));
|
|
||||||
if (!shstr) {
|
|
||||||
PrintAndLogEx(ERR, "Out of memory");
|
|
||||||
res = PM3_EMALLOC;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (fseek(fd, le32(shdrs[ehdr.e_shstrndx].sh_offset), SEEK_SET) < 0) {
|
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF section string table");
|
|
||||||
res = PM3_EFILE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (fread(shstr, shdrs[ehdr.e_shstrndx].sh_size, 1, fd) != 1) {
|
|
||||||
res = PM3_EFILE;
|
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF section string table");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint16_t i = 0; i < ehdr.e_shnum; i++) {
|
|
||||||
if (strcmp(((char *)shstr) + shdrs[i].sh_name, ".version_information") == 0) {
|
|
||||||
vi = calloc(shdrs[i].sh_size, sizeof(uint8_t));
|
|
||||||
if (!vi) {
|
|
||||||
PrintAndLogEx(ERR, "Out of memory");
|
|
||||||
res = PM3_EMALLOC;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (fseek(fd, le32(shdrs[i].sh_offset), SEEK_SET) < 0) {
|
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF version_information section");
|
|
||||||
res = PM3_EFILE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (fread(vi, shdrs[i].sh_size, 1, fd) != 1) {
|
|
||||||
res = PM3_EFILE;
|
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF version_information section");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (strlen(g_version_information.armsrc) == 9) {
|
|
||||||
if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) {
|
|
||||||
PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled"));
|
|
||||||
PrintAndLogEx(WARNING, "Make sure to flash a correct and up-to-date version");
|
|
||||||
// TODO: prompt user to continue or abort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(vi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(shdrs);
|
|
||||||
free(shstr);
|
|
||||||
fclose(fd);
|
|
||||||
ctx->filename = name;
|
|
||||||
ctx->phdrs = phdrs;
|
|
||||||
ctx->num_phdrs = num_phdrs;
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
if (phdrs)
|
|
||||||
free(phdrs);
|
|
||||||
if (shdrs)
|
|
||||||
free(shdrs);
|
|
||||||
if (shstr)
|
|
||||||
free(shstr);
|
|
||||||
if (vi)
|
|
||||||
free(vi);
|
|
||||||
if (fd)
|
|
||||||
fclose(fd);
|
|
||||||
flash_free(ctx);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load an ELF file and prepare it for flashing
|
|
||||||
int flash_load(flash_file_t *ctx, int can_write_bl, int flash_size) {
|
|
||||||
FILE *fd;
|
|
||||||
uint32_t flash_end = FLASH_START + flash_size;
|
|
||||||
int res = PM3_EUNDEF;
|
|
||||||
|
|
||||||
fd = fopen(ctx->filename, "rb");
|
fd = fopen(ctx->filename, "rb");
|
||||||
if (!fd) {
|
if (!fd) {
|
||||||
PrintAndLogEx(ERR, _RED_("Could not open file") " %s >>> ", ctx->filename);
|
PrintAndLogEx(ERR, _RED_("Could not open file") " %s >>> ", ctx->filename);
|
||||||
|
@ -410,19 +251,104 @@ int flash_load(flash_file_t *ctx, int can_write_bl, int flash_size) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = build_segs_from_phdrs(ctx, fd, flash_end);
|
PrintAndLogEx(SUCCESS, _CYAN_("Loading ELF file") _YELLOW_(" %s"), ctx->filename);
|
||||||
if (res != PM3_SUCCESS)
|
|
||||||
goto fail;
|
|
||||||
res = check_segs(ctx, can_write_bl, flash_end);
|
|
||||||
if (res != PM3_SUCCESS)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
|
// get filesize in order to malloc memory
|
||||||
|
fseek(fd, 0, SEEK_END);
|
||||||
|
long fsize = ftell(fd);
|
||||||
|
fseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (fsize <= 0) {
|
||||||
|
PrintAndLogEx(ERR, "Error, when getting filesize");
|
||||||
|
res = PM3_EFILE;
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->elf = calloc(fsize, sizeof(uint8_t));
|
||||||
|
if (!ctx->elf) {
|
||||||
|
PrintAndLogEx(ERR, "Error, cannot allocate memory");
|
||||||
|
res = PM3_EMALLOC;
|
||||||
|
fclose(fd);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bytes_read = fread(ctx->elf, 1, fsize, fd);
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
if (bytes_read != fsize) {
|
||||||
|
PrintAndLogEx(ERR, "Error, bytes read mismatch file size");
|
||||||
|
res = PM3_EFILE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ehdr = (Elf32_Ehdr_t *)ctx->elf;
|
||||||
|
if (memcmp(ehdr->e_ident, elf_ident, sizeof(elf_ident))
|
||||||
|
|| le32(ehdr->e_version) != 1) {
|
||||||
|
PrintAndLogEx(ERR, "Not an ELF file or wrong ELF type");
|
||||||
|
res = PM3_EFILE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (le16(ehdr->e_type) != ET_EXEC) {
|
||||||
|
PrintAndLogEx(ERR, "ELF is not executable");
|
||||||
|
res = PM3_EFILE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (le16(ehdr->e_machine) != EM_ARM) {
|
||||||
|
PrintAndLogEx(ERR, "Wrong ELF architecture");
|
||||||
|
res = PM3_EFILE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!ehdr->e_phnum || !ehdr->e_phoff) {
|
||||||
|
PrintAndLogEx(ERR, "ELF has no PHDRs");
|
||||||
|
res = PM3_EFILE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (le16(ehdr->e_phentsize) != sizeof(Elf32_Phdr_t)) {
|
||||||
|
// could be a structure padding issue...
|
||||||
|
PrintAndLogEx(ERR, "Either the ELF file or this code is made of fail");
|
||||||
|
res = PM3_EFILE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
ctx->num_phdrs = le16(ehdr->e_phnum);
|
||||||
|
ctx->phdrs = (Elf32_Phdr_t *)(ctx->elf + le32(ehdr->e_phoff));
|
||||||
|
shdrs = (Elf32_Shdr_t *)(ctx->elf + le32(ehdr->e_shoff));
|
||||||
|
shdrs = (Elf32_Shdr_t *)(ctx->elf + le32(ehdr->e_shoff));
|
||||||
|
shstr = ctx->elf + le32(shdrs[ehdr->e_shstrndx].sh_offset);
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < le16(ehdr->e_shnum); i++) {
|
||||||
|
if (strcmp(((char *)shstr) + shdrs[i].sh_name, ".version_information") == 0) {
|
||||||
|
vi = (struct version_information_t *)(ctx->elf + le32(shdrs[i].sh_offset));
|
||||||
|
if (strlen(g_version_information.armsrc) == 9) {
|
||||||
|
if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) {
|
||||||
|
PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled"));
|
||||||
|
PrintAndLogEx(WARNING, "Make sure to flash a correct and up-to-date version");
|
||||||
|
// TODO: prompt user to continue or abort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
flash_free(ctx);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare an ELF file for flashing
|
||||||
|
int flash_prepare(flash_file_t *ctx, int can_write_bl, int flash_size) {
|
||||||
|
int res = PM3_EUNDEF;
|
||||||
|
|
||||||
|
res = build_segs_from_phdrs(ctx, flash_size);
|
||||||
|
if (res != PM3_SUCCESS)
|
||||||
|
goto fail;
|
||||||
|
res = check_segs(ctx, can_write_bl, flash_size);
|
||||||
|
if (res != PM3_SUCCESS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (fd)
|
|
||||||
fclose(fd);
|
|
||||||
flash_free(ctx);
|
flash_free(ctx);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -719,6 +645,16 @@ int flash_write(flash_file_t *ctx) {
|
||||||
void flash_free(flash_file_t *ctx) {
|
void flash_free(flash_file_t *ctx) {
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return;
|
return;
|
||||||
|
if (ctx->filename != NULL) {
|
||||||
|
free(ctx->filename);
|
||||||
|
ctx->filename = NULL;
|
||||||
|
}
|
||||||
|
if (ctx->elf) {
|
||||||
|
free(ctx->elf);
|
||||||
|
ctx->elf = NULL;
|
||||||
|
ctx->phdrs = NULL;
|
||||||
|
ctx->num_phdrs = 0;
|
||||||
|
}
|
||||||
if (ctx->segments) {
|
if (ctx->segments) {
|
||||||
for (int i = 0; i < ctx->num_segs; i++)
|
for (int i = 0; i < ctx->num_segs; i++)
|
||||||
free(ctx->segments[i].data);
|
free(ctx->segments[i].data);
|
||||||
|
@ -726,11 +662,6 @@ void flash_free(flash_file_t *ctx) {
|
||||||
ctx->segments = NULL;
|
ctx->segments = NULL;
|
||||||
ctx->num_segs = 0;
|
ctx->num_segs = 0;
|
||||||
}
|
}
|
||||||
if (ctx->phdrs) {
|
|
||||||
free(ctx->phdrs);
|
|
||||||
ctx->phdrs = NULL;
|
|
||||||
ctx->num_phdrs = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// just reset the unit
|
// just reset the unit
|
||||||
|
|
|
@ -32,7 +32,8 @@ typedef struct {
|
||||||
} flash_seg_t;
|
} flash_seg_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *filename;
|
char *filename;
|
||||||
|
uint8_t *elf;
|
||||||
Elf32_Phdr_t *phdrs;
|
Elf32_Phdr_t *phdrs;
|
||||||
uint16_t num_phdrs;
|
uint16_t num_phdrs;
|
||||||
int can_write_bl;
|
int can_write_bl;
|
||||||
|
@ -40,8 +41,8 @@ typedef struct {
|
||||||
flash_seg_t *segments;
|
flash_seg_t *segments;
|
||||||
} flash_file_t;
|
} flash_file_t;
|
||||||
|
|
||||||
int flash_check(flash_file_t *ctx, const char *name);
|
int flash_load(flash_file_t *ctx);
|
||||||
int flash_load(flash_file_t *ctx, int can_write_bl, int flash_size);
|
int flash_prepare(flash_file_t *ctx, int can_write_bl, int flash_size);
|
||||||
int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *max_allowed);
|
int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *max_allowed);
|
||||||
int flash_write(flash_file_t *ctx);
|
int flash_write(flash_file_t *ctx);
|
||||||
void flash_free(flash_file_t *ctx);
|
void flash_free(flash_file_t *ctx);
|
||||||
|
|
|
@ -607,7 +607,6 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[
|
||||||
int ret = PM3_EUNDEF;
|
int ret = PM3_EUNDEF;
|
||||||
flash_file_t files[FLASH_MAX_FILES];
|
flash_file_t files[FLASH_MAX_FILES];
|
||||||
memset(files, 0, sizeof(files));
|
memset(files, 0, sizeof(files));
|
||||||
char *filepaths[FLASH_MAX_FILES] = {0};
|
|
||||||
|
|
||||||
if (serial_port_name == NULL) {
|
if (serial_port_name == NULL) {
|
||||||
PrintAndLogEx(ERR, "You must specify a port.\n");
|
PrintAndLogEx(ERR, "You must specify a port.\n");
|
||||||
|
@ -627,16 +626,16 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[
|
||||||
if (ret != PM3_SUCCESS) {
|
if (ret != PM3_SUCCESS) {
|
||||||
goto finish2;
|
goto finish2;
|
||||||
}
|
}
|
||||||
filepaths[i] = path;
|
files[i].filename = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "About to use the following file%s:", num_files > 1 ? "s" : "");
|
PrintAndLogEx(SUCCESS, "About to use the following file%s:", num_files > 1 ? "s" : "");
|
||||||
for (int i = 0 ; i < num_files; ++i) {
|
for (int i = 0 ; i < num_files; ++i) {
|
||||||
PrintAndLogEx(SUCCESS, " "_YELLOW_("%s"), filepaths[i]);
|
PrintAndLogEx(SUCCESS, " "_YELLOW_("%s"), files[i].filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0 ; i < num_files; ++i) {
|
for (int i = 0 ; i < num_files; ++i) {
|
||||||
ret = flash_check(&files[i], filepaths[i]);
|
ret = flash_load(&files[i]);
|
||||||
if (ret != PM3_SUCCESS) {
|
if (ret != PM3_SUCCESS) {
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
@ -661,7 +660,7 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
for (int i = 0 ; i < num_files; ++i) {
|
for (int i = 0 ; i < num_files; ++i) {
|
||||||
ret = flash_load(&files[i], can_write_bl, max_allowed * ONE_KB);
|
ret = flash_prepare(&files[i], can_write_bl, max_allowed * ONE_KB);
|
||||||
if (ret != PM3_SUCCESS) {
|
if (ret != PM3_SUCCESS) {
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
@ -686,8 +685,6 @@ finish:
|
||||||
finish2:
|
finish2:
|
||||||
for (int i = 0 ; i < num_files; ++i) {
|
for (int i = 0 ; i < num_files; ++i) {
|
||||||
flash_free(&files[i]);
|
flash_free(&files[i]);
|
||||||
if (filepaths[i] != NULL)
|
|
||||||
free(filepaths[i]);
|
|
||||||
}
|
}
|
||||||
if (ret == PM3_SUCCESS)
|
if (ret == PM3_SUCCESS)
|
||||||
PrintAndLogEx(SUCCESS, _CYAN_("All done"));
|
PrintAndLogEx(SUCCESS, _CYAN_("All done"));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue