455 lines
15 KiB
Diff
455 lines
15 KiB
Diff
From: Hector Palacios <hector.palacios@digi.com>
|
|
Date: Wed, 16 Oct 2013 10:30:14 +0200
|
|
Subject: added option to verify data written to flash
|
|
|
|
This patch adds a -c (check) option to the update command.
|
|
This option will read back the data written to the flash and
|
|
compare to the original contents in RAM, to verify the write
|
|
operation was successful.
|
|
|
|
Signed-off-by: Hector Palacios <hector.palacios@digi.com>
|
|
Reviewed-by: Robert Hodaszi <robert.hodaszi@digi.com>
|
|
---
|
|
src/main.c | 22 ++++++--
|
|
src/mtd.c | 138 +++++++++++++++++++++++++++++++++++++++----------
|
|
src/mtd.h | 10 ++--
|
|
src/plat_boot_config.h | 2 +-
|
|
4 files changed, 136 insertions(+), 36 deletions(-)
|
|
|
|
diff --git a/src/main.c b/src/main.c
|
|
index 70517b0..8774045 100644
|
|
--- a/src/main.c
|
|
+++ b/src/main.c
|
|
@@ -82,10 +82,12 @@ void usage(void)
|
|
" -x .................................... Add 1k-padding in the head\n"
|
|
" -n .................................... Dry run (don't commit to flash)\n"
|
|
" -w .................................... Commit to flash\n"
|
|
+ " -c .................................... Check committed data in flash\n"
|
|
"\n"
|
|
" update [-v] [KEY] [KOBS] [-0|1] <file> .. Update a single bootstream\n"
|
|
" -v .................................... Verbose mode\n"
|
|
" -0|1 .................................. Update specified bootstream #\n"
|
|
+ " -c .................................... Check committed data in flash\n"
|
|
"\n"
|
|
" extract [-v] [KEY] [KOBS] [-0|1] <file> . Extract a bootstream from flash\n"
|
|
" -v .................................... Verbose mode\n"
|
|
@@ -390,7 +392,8 @@ int extract_main(int argc, char **argv)
|
|
return 0;
|
|
}
|
|
|
|
-static int perform_bootstream_update(struct mtd_data *md, FILE *infp, int image_mask)
|
|
+static int perform_bootstream_update(struct mtd_data *md, FILE *infp,
|
|
+ int image_mask, int check)
|
|
{
|
|
int i, r;
|
|
unsigned int size, start, avail, end, update;
|
|
@@ -435,7 +438,8 @@ static int perform_bootstream_update(struct mtd_data *md, FILE *infp, int image_
|
|
update |= UPDATE_BS(i);
|
|
}
|
|
|
|
- r = plat_config_data->rom_mtd_commit_structures(md, infp, UPDATE_LDLB | update);
|
|
+ r = plat_config_data->rom_mtd_commit_structures(md, infp,
|
|
+ UPDATE_LDLB | update, check);
|
|
if (r < 0) {
|
|
fprintf(stderr, "FAILED to commit structures\n");
|
|
return -1;
|
|
@@ -457,6 +461,7 @@ int update_main(int argc, char **argv)
|
|
char ascii[20 * 2 + 1];
|
|
int device_key;
|
|
uint8_t *keyp;
|
|
+ int check;
|
|
|
|
memset(key, 0, sizeof(key));
|
|
device_key = 0;
|
|
@@ -473,6 +478,7 @@ int update_main(int argc, char **argv)
|
|
image_mask = 0; /* no image */
|
|
flags = 0;
|
|
j = 0;
|
|
+ check = 0;
|
|
for (i = 1; i < argc; i++) {
|
|
|
|
if (argv[i][0] != '-') {
|
|
@@ -500,6 +506,9 @@ int update_main(int argc, char **argv)
|
|
exit(5);
|
|
}
|
|
break;
|
|
+ case 'c':
|
|
+ check = 1;
|
|
+ break;
|
|
case 'v':
|
|
flags |= F_VERBOSE;
|
|
break;
|
|
@@ -545,7 +554,7 @@ int update_main(int argc, char **argv)
|
|
if (flags & F_VERBOSE)
|
|
mtd_dump(md);
|
|
|
|
- r = perform_bootstream_update(md, infp, image_mask);
|
|
+ r = perform_bootstream_update(md, infp, image_mask, check);
|
|
if (r != 0) {
|
|
fprintf(stderr, "Unable to perform bootstream update\n");
|
|
usage();
|
|
@@ -597,6 +606,7 @@ int init_main(int argc, char **argv)
|
|
FILE *infp;
|
|
loff_t ofs;
|
|
int dryrun;
|
|
+ int check;
|
|
int padding = 0;
|
|
struct mtd_config cfg;
|
|
uint8_t key[16];
|
|
@@ -619,6 +629,7 @@ int init_main(int argc, char **argv)
|
|
image = 0; /* first image */
|
|
flags = 0;
|
|
dryrun = 0;
|
|
+ check = 0;
|
|
j = 0;
|
|
for (i = 1; i < argc; i++) {
|
|
|
|
@@ -640,6 +651,9 @@ int init_main(int argc, char **argv)
|
|
case 'w':
|
|
dryrun = 0;
|
|
break;
|
|
+ case 'c':
|
|
+ check = 1;
|
|
+ break;
|
|
case 'n':
|
|
dryrun = 1;
|
|
break;
|
|
@@ -738,7 +752,7 @@ int init_main(int argc, char **argv)
|
|
mtd_dump_structure(md);
|
|
|
|
if (!dryrun) {
|
|
- r = plat_config_data->rom_mtd_commit_structures(md, infp, UPDATE_ALL);
|
|
+ r = plat_config_data->rom_mtd_commit_structures(md, infp, UPDATE_ALL, check);
|
|
if (r < 0) {
|
|
fprintf(stderr, "FAILED to commit structures\n");
|
|
exit(5);
|
|
diff --git a/src/mtd.c b/src/mtd.c
|
|
index 9ea92ad..77ba307 100644
|
|
--- a/src/mtd.c
|
|
+++ b/src/mtd.c
|
|
@@ -2344,7 +2344,7 @@ int v4_rom_mtd_init(struct mtd_data *md, FILE *fp)
|
|
|
|
int mtd_commit_bcb(struct mtd_data *md, char *bcb_name,
|
|
loff_t ofs1, loff_t ofs2, loff_t ofs_mchip,
|
|
- loff_t end, size_t size, int ecc)
|
|
+ loff_t end, size_t size, int ecc, int verify)
|
|
{
|
|
int chip;
|
|
loff_t end_index, search_area_indices[2], o;
|
|
@@ -2355,6 +2355,13 @@ int mtd_commit_bcb(struct mtd_data *md, char *bcb_name,
|
|
unsigned search_area_size_in_strides;
|
|
unsigned search_area_size_in_bytes;
|
|
unsigned count;
|
|
+ char *readbuf = NULL;
|
|
+
|
|
+ if (verify) {
|
|
+ readbuf = malloc(mtd_writesize(md));
|
|
+ if (NULL == readbuf)
|
|
+ return -1;
|
|
+ }
|
|
|
|
vp(md, "-------------- Start to write the [ %s ] -----\n", bcb_name);
|
|
//----------------------------------------------------------------------
|
|
@@ -2457,6 +2464,20 @@ int mtd_commit_bcb(struct mtd_data *md, char *bcb_name,
|
|
err ++;
|
|
}
|
|
|
|
+ if (verify) {
|
|
+ //------------------------------------------------------
|
|
+ // Verify the written data
|
|
+ //------------------------------------------------------
|
|
+ r = pread(md->part[chip].fd, readbuf, mtd_writesize(md), o);
|
|
+ if (r != mtd_writesize(md)) {
|
|
+ fprintf(stderr, "mtd: Failed to read @0x%llx (%d)\n", o, r);
|
|
+ goto err_free;
|
|
+ }
|
|
+ if (memcmp(md->buf, readbuf, mtd_writesize(md))) {
|
|
+ fprintf(stderr, "mtd: Verification error @0x%llx\n", o);
|
|
+ goto err_free;
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
}
|
|
@@ -2466,16 +2487,31 @@ int mtd_commit_bcb(struct mtd_data *md, char *bcb_name,
|
|
if (md->flags & F_VERBOSE)
|
|
printf("%s(%s): status %d\n\n", __func__, bcb_name, err);
|
|
|
|
- return err;
|
|
+err_free:
|
|
+ if (verify)
|
|
+ free(readbuf);
|
|
+ if (err) {
|
|
+ fprintf(stderr, "mtd: %d errors\n", err);
|
|
+ return -1;
|
|
+ }
|
|
+ else
|
|
+ return 0;
|
|
}
|
|
|
|
-int write_boot_stream(struct mtd_data *md, FILE *fp)
|
|
+int write_boot_stream(struct mtd_data *md, FILE *fp, int verify)
|
|
{
|
|
int startpage, start, size;
|
|
loff_t ofs, end;
|
|
- int i, r, chunk;
|
|
+ int i, r = 0, chunk;
|
|
int chip = 0;
|
|
struct fcb_block *fcb = &md->fcb.FCB_Block;
|
|
+ char *readbuf = NULL;
|
|
+
|
|
+ if (verify) {
|
|
+ readbuf = malloc(mtd_writesize(md));
|
|
+ if (NULL == readbuf)
|
|
+ return -1;
|
|
+ }
|
|
|
|
vp(md, "---------- Start to write the [ %s ]----\n", (char*)md->private);
|
|
for (i = 0; i < 2; i++) {
|
|
@@ -2530,7 +2566,7 @@ int write_boot_stream(struct mtd_data *md, FILE *fp)
|
|
r = fread(md->buf, 1, chunk, fp);
|
|
if (r < 0) {
|
|
fprintf(stderr, "mtd: Failed %d (fread %d)\n", r, chunk);
|
|
- return -1;
|
|
+ goto err_free;
|
|
}
|
|
if (r < chunk) {
|
|
memset(md->buf + r, 0, chunk - r);
|
|
@@ -2539,10 +2575,30 @@ int write_boot_stream(struct mtd_data *md, FILE *fp)
|
|
|
|
/* write page */
|
|
r = mtd_write_page(md, chip, ofs, 1);
|
|
- if (r != mtd_writesize(md))
|
|
+ if (r != mtd_writesize(md)) {
|
|
fprintf(stderr, "mtd: Failed to write BS @0x%llx (%d)\n",
|
|
ofs, r);
|
|
+ r = -1;
|
|
+ goto err_free;
|
|
+ }
|
|
|
|
+ if (verify) {
|
|
+ //------------------------------------------------------
|
|
+ // Verify the written data
|
|
+ //------------------------------------------------------
|
|
+ r = pread(md->part[chip].fd, readbuf,
|
|
+ mtd_writesize(md), ofs);
|
|
+ if (r != mtd_writesize(md)) {
|
|
+ fprintf(stderr, "mtd: Failed to read BS @0x%llx (%d)\n", ofs, r);
|
|
+ r = -1;
|
|
+ goto err_free;
|
|
+ }
|
|
+ if (memcmp(md->buf, readbuf, mtd_writesize(md))) {
|
|
+ fprintf(stderr, "mtd: Verification error @0x%llx\n", ofs);
|
|
+ r = -1;
|
|
+ goto err_free;
|
|
+ }
|
|
+ }
|
|
ofs += mtd_writesize(md);
|
|
size -= chunk;
|
|
}
|
|
@@ -2555,19 +2611,26 @@ int write_boot_stream(struct mtd_data *md, FILE *fp)
|
|
*/
|
|
memset(md->buf, 0, mtd_writesize(md));
|
|
r = mtd_write_page(md, chip, ofs, 1);
|
|
- if (r != mtd_writesize(md))
|
|
+ if (r != mtd_writesize(md)) {
|
|
fprintf(stderr, "Failed to write safe page\n");
|
|
+ r = -1;
|
|
+ goto err_free;
|
|
+ }
|
|
vp(md, "mtd: We write one page for save guard. *\n");
|
|
-
|
|
if (ofs >= end) {
|
|
fprintf(stderr, "mtd: Failed to write BS#%d\n", i);
|
|
- return -1;
|
|
+ r = -1;
|
|
+ goto err_free;
|
|
}
|
|
}
|
|
- return 0;
|
|
+
|
|
+err_free:
|
|
+ if (verify)
|
|
+ free(readbuf);
|
|
+ return r;
|
|
}
|
|
|
|
-int v0_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
+int v0_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags, int verify)
|
|
{
|
|
int startpage, start, size;
|
|
unsigned int search_area_sz, stride;
|
|
@@ -2666,7 +2729,9 @@ int v0_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
if (r < 0)
|
|
return r;
|
|
|
|
- mtd_commit_bcb(md, "NCB", 0, 1, 0, 1, size, false);
|
|
+ r = mtd_commit_bcb(md, "NCB", 0, 1, 0, 1, size, false, verify);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
}
|
|
|
|
if (flags & UPDATE_LDLB) {
|
|
@@ -2675,7 +2740,10 @@ int v0_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
memset(md->buf, 0, mtd_writesize(md));
|
|
memcpy(md->buf, md->curr_ldlb, sizeof(*md->curr_ldlb));
|
|
|
|
- mtd_commit_bcb(md, "LDLB", 2, 3, 1, 1, mtd_writesize(md), true);
|
|
+ r = mtd_commit_bcb(md, "LDLB", 2, 3, 1, 1, mtd_writesize(md), true,
|
|
+ verify);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
}
|
|
|
|
if (flags & UPDATE_DBBT) {
|
|
@@ -2684,7 +2752,11 @@ int v0_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
memset(md->buf, 0, mtd_writesize(md));
|
|
memcpy(md->buf, md->curr_dbbt, sizeof(*md->curr_dbbt));
|
|
|
|
- mtd_commit_bcb(md, "DBBT", 4, 5, 2, 1, mtd_writesize(md), true);
|
|
+ r = mtd_commit_bcb(md, "DBBT", 4, 5, 2, 1, mtd_writesize(md), true,
|
|
+ verify);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+
|
|
for (i = 0; i < 2; i++) {
|
|
for (j = 0; j < 2; j++) {
|
|
if (md->flags & F_MULTICHIP) {
|
|
@@ -2766,7 +2838,7 @@ static void write_dbbt(struct mtd_data *md, int dbbt_num)
|
|
}
|
|
}
|
|
|
|
-int v1_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
+int v1_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags, int verify)
|
|
{
|
|
int size ,r;
|
|
|
|
@@ -2779,8 +2851,11 @@ int v1_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
size = mtd_writesize(md) + mtd_oobsize(md);
|
|
r = fcb_encrypt(&md->fcb, md->buf, size, 1);
|
|
if (r < 0)
|
|
- return r;
|
|
- mtd_commit_bcb(md, "FCB", 0, 0, 0, 1, size, false);
|
|
+ return -1;
|
|
+
|
|
+ r = mtd_commit_bcb(md, "FCB", 0, 0, 0, 1, size, false, verify);
|
|
+ if (r < 0)
|
|
+ return -1;
|
|
|
|
//----------------------------------------------------------------------
|
|
// Write the DBBT search area.
|
|
@@ -2788,14 +2863,17 @@ int v1_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
memset(md->buf, 0, mtd_writesize(md));
|
|
memcpy(md->buf, &(md->dbbt28), sizeof(md->dbbt28));
|
|
dbbt_checksum(md, &md->dbbt28);
|
|
- mtd_commit_bcb(md, "DBBT", 1, 1, 1, 1, mtd_writesize(md), true);
|
|
+ r = mtd_commit_bcb(md, "DBBT", 1, 1, 1, 1, mtd_writesize(md), true,
|
|
+ verify);
|
|
+ if (r < 0)
|
|
+ return -1;
|
|
write_dbbt(md, 1); /* only write the DBBT for nand0 */
|
|
|
|
/* write the boot image. */
|
|
- return write_boot_stream(md, fp);
|
|
+ return write_boot_stream(md, fp, verify);
|
|
}
|
|
|
|
-int v2_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
+int v2_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags, int verify)
|
|
{
|
|
int startpage, start, size;
|
|
unsigned int search_area_size_in_bytes, stride_size_in_bytes;
|
|
@@ -2832,7 +2910,9 @@ int v2_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
memset(md->buf, 0, mtd_writesize(md));
|
|
memcpy(md->buf, &(md->fcb), sizeof(md->fcb));
|
|
|
|
- mtd_commit_bcb(md, "FCB", 0, 0, 0, 1, mtd_writesize(md), true);
|
|
+ r = mtd_commit_bcb(md, "FCB", 0, 0, 0, 1, mtd_writesize(md), true, verify);
|
|
+ if (r < 0)
|
|
+ return -1;
|
|
|
|
//----------------------------------------------------------------------
|
|
// Write the DBBT search area.
|
|
@@ -2841,7 +2921,9 @@ int v2_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
memset(md->buf, 0, mtd_writesize(md));
|
|
memcpy(md->buf, &(md->dbbt28), sizeof(md->dbbt28));
|
|
|
|
- mtd_commit_bcb(md, "DBBT", 1, 1, 1, 1, mtd_writesize(md), true);
|
|
+ r = mtd_commit_bcb(md, "DBBT", 1, 1, 1, 1, mtd_writesize(md), true, verify);
|
|
+ if (r < 0)
|
|
+ return -1;
|
|
|
|
//----------------------------------------------------------------------
|
|
// Write the DBBT table area.
|
|
@@ -2985,7 +3067,7 @@ int v2_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
return 0;
|
|
}
|
|
|
|
-int v4_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
+int v4_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags, int verify)
|
|
{
|
|
int size, i, r, chip = 0;
|
|
loff_t ofs;
|
|
@@ -2997,12 +3079,16 @@ int v4_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
r = fcb_encrypt(&md->fcb, md->buf, size, 1);
|
|
if (r < 0)
|
|
return r;
|
|
- mtd_commit_bcb(md, "FCB", 0, 0, 0, 1, size, false);
|
|
+ r = mtd_commit_bcb(md, "FCB", 0, 0, 0, 1, size, false, verify);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
|
|
/* [2] Write the DBBT search area. */
|
|
memset(md->buf, 0, mtd_writesize(md));
|
|
memcpy(md->buf, &(md->dbbt50), sizeof(md->dbbt50));
|
|
- mtd_commit_bcb(md, "DBBT", 1, 1, 1, 1, mtd_writesize(md), true);
|
|
+ r = mtd_commit_bcb(md, "DBBT", 1, 1, 1, 1, mtd_writesize(md), true, verify);
|
|
+ if (r < 0)
|
|
+ return -1;
|
|
|
|
/* Write the DBBT table area. */
|
|
memset(md->buf, 0, mtd_writesize(md));
|
|
@@ -3023,7 +3109,7 @@ int v4_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
|
|
}
|
|
|
|
/* [3] Write the two boot streams. */
|
|
- return write_boot_stream(md, fp);
|
|
+ return write_boot_stream(md, fp, verify);
|
|
}
|
|
|
|
#undef ARG
|
|
diff --git a/src/mtd.h b/src/mtd.h
|
|
index 18e4d70..699e505 100644
|
|
--- a/src/mtd.h
|
|
+++ b/src/mtd.h
|
|
@@ -295,11 +295,11 @@ int mtd_markbad(struct mtd_data *md, int chip, loff_t ofs);
|
|
#define UPDATE_BS(x) (0x08 << ((x) & 1))
|
|
#define UPDATE_ALL (UPDATE_NCB | UPDATE_LDLB | UPDATE_DBBT | UPDATE_BS0 | UPDATE_BS1)
|
|
|
|
-int v0_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags);
|
|
-int v1_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags);
|
|
-int v2_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags);
|
|
-int v3_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags);
|
|
-int v4_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags);
|
|
+int v0_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags, int verify);
|
|
+int v1_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags, int verify);
|
|
+int v2_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags, int verify);
|
|
+int v3_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags, int verify);
|
|
+int v4_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags, int verify);
|
|
|
|
int mtd_set_ecc_mode(struct mtd_data *md, int ecc);
|
|
|
|
diff --git a/src/plat_boot_config.h b/src/plat_boot_config.h
|
|
index 8242ede..a3c03a7 100644
|
|
--- a/src/plat_boot_config.h
|
|
+++ b/src/plat_boot_config.h
|
|
@@ -55,7 +55,7 @@ typedef struct _platform_config_t {
|
|
uint32_t m_u32Arm_type;
|
|
uint32_t m_u32DBBT_FingerPrint;
|
|
int (* rom_mtd_init)(struct mtd_data *md, FILE *fp);
|
|
- int (* rom_mtd_commit_structures)(struct mtd_data *md, FILE *fp, int flags);
|
|
+ int (* rom_mtd_commit_structures)(struct mtd_data *md, FILE *fp, int flags, int verify);
|
|
} platform_config;
|
|
|
|
extern platform_config *plat_config_data;
|