Also add some valueable patches from mailing-list - upstream seems not to care so much about, but giving them a broader audience does not hurt. Signed-off-by: Michael Heimpold <mhei@heimpold.de>lilik-openwrt-22.03
@ -0,0 +1,30 @@ | |||
From bf96e1b2f48eab26c4a0c2a0903d9d7b9a311a1d Mon Sep 17 00:00:00 2001 | |||
From: Michael Heimpold <michael.heimpold@i2se.com> | |||
Date: Tue, 18 Dec 2018 14:47:16 +0100 | |||
Subject: [PATCH 1/9] Check calloc's return value before using the pointer | |||
If calloc fails, bail out immediately instead of trying to | |||
use the NULL pointer. | |||
Signed-off-by: Michael Heimpold <michael.heimpold@i2se.com> | |||
Cc: Michael Heimpold <mhei@heimpold.de> | |||
--- | |||
lsmmc.c | 2 ++ | |||
1 file changed, 2 insertions(+) | |||
diff --git a/lsmmc.c b/lsmmc.c | |||
index 9737b37..e514c83 100644 | |||
--- a/lsmmc.c | |||
+++ b/lsmmc.c | |||
@@ -374,6 +374,8 @@ char *to_binstr(char *hexstr) | |||
char *binstr; | |||
binstr = calloc(strlen(hexstr) * 4 + 1, sizeof(char)); | |||
+ if (!binstr) | |||
+ return NULL; | |||
while (hexstr && *hexstr != '\0') { | |||
if (!isxdigit(*hexstr)) | |||
-- | |||
2.17.1 | |||
@ -0,0 +1,33 @@ | |||
From 9214f2a4002bafef73c9593464ab3841ba7bac12 Mon Sep 17 00:00:00 2001 | |||
From: Michael Heimpold <michael.heimpold@i2se.com> | |||
Date: Tue, 18 Dec 2018 14:49:37 +0100 | |||
Subject: [PATCH 2/9] Cleanup memory in error case | |||
In case that we leave due to malformed string, | |||
free the allocated memory before returning. | |||
Signed-off-by: Michael Heimpold <michael.heimpold@i2se.com> | |||
Cc: Michael Heimpold <mhei@heimpold.de> | |||
--- | |||
lsmmc.c | 4 +++- | |||
1 file changed, 3 insertions(+), 1 deletion(-) | |||
diff --git a/lsmmc.c b/lsmmc.c | |||
index e514c83..a53bc57 100644 | |||
--- a/lsmmc.c | |||
+++ b/lsmmc.c | |||
@@ -378,8 +378,10 @@ char *to_binstr(char *hexstr) | |||
return NULL; | |||
while (hexstr && *hexstr != '\0') { | |||
- if (!isxdigit(*hexstr)) | |||
+ if (!isxdigit(*hexstr)) { | |||
+ free(binstr); | |||
return NULL; | |||
+ } | |||
if (isdigit(*hexstr)) | |||
strcat(binstr, bindigits[*hexstr - '0']); | |||
-- | |||
2.17.1 | |||
@ -0,0 +1,33 @@ | |||
From a59d98003c0b2364929ee23ed331d610029c6dcf Mon Sep 17 00:00:00 2001 | |||
From: Michael Heimpold <michael.heimpold@i2se.com> | |||
Date: Tue, 18 Dec 2018 14:52:12 +0100 | |||
Subject: [PATCH 3/9] Fix parsing of character in to_binstr() | |||
When a hex-digit > 'a' or 'A' is read, we have to add an offset of 10 | |||
to access the valid symbol in our mapping table. | |||
Signed-off-by: Michael Heimpold <michael.heimpold@i2se.com> | |||
Cc: Michael Heimpold <mhei@heimpold.de> | |||
--- | |||
lsmmc.c | 4 ++-- | |||
1 file changed, 2 insertions(+), 2 deletions(-) | |||
diff --git a/lsmmc.c b/lsmmc.c | |||
index a53bc57..e64117c 100644 | |||
--- a/lsmmc.c | |||
+++ b/lsmmc.c | |||
@@ -386,9 +386,9 @@ char *to_binstr(char *hexstr) | |||
if (isdigit(*hexstr)) | |||
strcat(binstr, bindigits[*hexstr - '0']); | |||
else if (islower(*hexstr)) | |||
- strcat(binstr, bindigits[*hexstr - 'a']); | |||
+ strcat(binstr, bindigits[*hexstr - 'a' + 10]); | |||
else | |||
- strcat(binstr, bindigits[*hexstr - 'A']); | |||
+ strcat(binstr, bindigits[*hexstr - 'A' + 10]); | |||
hexstr++; | |||
} | |||
-- | |||
2.17.1 | |||
@ -0,0 +1,56 @@ | |||
From f1fc04d7609ab074647aa00e96d4c66d5135b155 Mon Sep 17 00:00:00 2001 | |||
From: Michael Heimpold <michael.heimpold@i2se.com> | |||
Date: Tue, 18 Dec 2018 15:02:25 +0100 | |||
Subject: [PATCH 4/9] Optimize to_binstr() function | |||
Appending multiple times to same string is slow since strcat() needs | |||
to determine the end during each run. So manually maintain a pointer | |||
to the end to speed-up things. | |||
Signed-off-by: Michael Heimpold <michael.heimpold@i2se.com> | |||
Cc: Michael Heimpold <mhei@heimpold.de> | |||
--- | |||
lsmmc.c | 11 +++++++---- | |||
1 file changed, 7 insertions(+), 4 deletions(-) | |||
diff --git a/lsmmc.c b/lsmmc.c | |||
index e64117c..86713f7 100644 | |||
--- a/lsmmc.c | |||
+++ b/lsmmc.c | |||
@@ -371,12 +371,14 @@ char *to_binstr(char *hexstr) | |||
"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", | |||
"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111", | |||
}; | |||
- char *binstr; | |||
+ char *binstr, *tail; | |||
binstr = calloc(strlen(hexstr) * 4 + 1, sizeof(char)); | |||
if (!binstr) | |||
return NULL; | |||
+ tail = binstr; | |||
+ | |||
while (hexstr && *hexstr != '\0') { | |||
if (!isxdigit(*hexstr)) { | |||
free(binstr); | |||
@@ -384,13 +386,14 @@ char *to_binstr(char *hexstr) | |||
} | |||
if (isdigit(*hexstr)) | |||
- strcat(binstr, bindigits[*hexstr - '0']); | |||
+ strcat(tail, bindigits[*hexstr - '0']); | |||
else if (islower(*hexstr)) | |||
- strcat(binstr, bindigits[*hexstr - 'a' + 10]); | |||
+ strcat(tail, bindigits[*hexstr - 'a' + 10]); | |||
else | |||
- strcat(binstr, bindigits[*hexstr - 'A' + 10]); | |||
+ strcat(tail, bindigits[*hexstr - 'A' + 10]); | |||
hexstr++; | |||
+ tail += 4; | |||
} | |||
return binstr; | |||
-- | |||
2.17.1 | |||
@ -0,0 +1,30 @@ | |||
From c0375ecea6f3731c0f65ff6abd2c194b90153b26 Mon Sep 17 00:00:00 2001 | |||
From: Michael Heimpold <michael.heimpold@i2se.com> | |||
Date: Tue, 18 Dec 2018 15:09:42 +0100 | |||
Subject: [PATCH 5/9] Add eMMC vendor Micron to table | |||
Signed-off-by: Michael Heimpold <michael.heimpold@i2se.com> | |||
Cc: Michael Heimpold <mhei@heimpold.de> | |||
--- | |||
lsmmc.c | 5 +++++ | |||
1 file changed, 5 insertions(+) | |||
diff --git a/lsmmc.c b/lsmmc.c | |||
index 86713f7..4f687ac 100644 | |||
--- a/lsmmc.c | |||
+++ b/lsmmc.c | |||
@@ -194,6 +194,11 @@ struct ids_database database[] = { | |||
.id = 0x11, | |||
.manufacturer = "Toshiba", | |||
}, | |||
+ { | |||
+ .type = "mmc", | |||
+ .id = 0x13, | |||
+ .manufacturer = "Micron", | |||
+ }, | |||
{ | |||
.type = "mmc", | |||
.id = 0x15, | |||
-- | |||
2.17.1 | |||
@ -0,0 +1,29 @@ | |||
From 6bcf573f9056c6a4fb2ace5aece08a53dc5dceca Mon Sep 17 00:00:00 2001 | |||
From: Stephane Fillod <f8cfe@free.fr> | |||
Date: Mon, 14 Jan 2019 17:50:50 +0100 | |||
Subject: [PATCH 6/9] Fix parsing of Product Revision and Serial Number | |||
According to MMC Standard (similar to SDCard Standard). | |||
Signed-off-by: Stephane Fillod <f8cfe@free.fr> | |||
Acked-by: Avri Altman <avri.altman@wdc.com> | |||
--- | |||
lsmmc.c | 2 +- | |||
1 file changed, 1 insertion(+), 1 deletion(-) | |||
diff --git a/lsmmc.c b/lsmmc.c | |||
index 4f687ac..b627b79 100644 | |||
--- a/lsmmc.c | |||
+++ b/lsmmc.c | |||
@@ -562,7 +562,7 @@ void print_mmc_cid(struct config *config, char *cid) | |||
unsigned int crc; | |||
parse_bin(cid, "8u6r2u8u48a4u4u32u4u4u7u1r", | |||
- &mid, &cbx, &oid, &pnm[0], &psn, &prv_major, &prv_minor, | |||
+ &mid, &cbx, &oid, &pnm[0], &prv_major, &prv_minor, &psn, | |||
&mdt_year, &mdt_month, &crc); | |||
pnm[6] = '\0'; | |||
-- | |||
2.17.1 | |||
@ -0,0 +1,97 @@ | |||
From c9c90f4f74ee5318ee9a2f581b665d474f6f90c5 Mon Sep 17 00:00:00 2001 | |||
From: Stephane Fillod <f8cfe@free.fr> | |||
Date: Tue, 15 Jan 2019 14:56:15 +0100 | |||
Subject: [PATCH 7/9] Add various SD/eMMC vendors to table | |||
Part if this list update comes from a compilation of this web site[1]. | |||
[1] https://www.cameramemoryspeed.com/sd-memory-card-faq/reading-sd-card-cid-serial-psn-internal-numbers/ | |||
Signed-off-by: Stephane Fillod <f8cfe@free.fr> | |||
--- | |||
lsmmc.c | 34 ++++++++++++++++++++++++++++++++-- | |||
1 file changed, 32 insertions(+), 2 deletions(-) | |||
diff --git a/lsmmc.c b/lsmmc.c | |||
index b627b79..63504d2 100644 | |||
--- a/lsmmc.c | |||
+++ b/lsmmc.c | |||
@@ -112,7 +112,7 @@ struct ids_database database[] = { | |||
{ | |||
.type = "sd", | |||
.id = 0x1b, | |||
- .manufacturer = "Transcend", | |||
+ .manufacturer = "Transcend/Samsung", | |||
}, | |||
{ | |||
.type = "sd", | |||
@@ -122,7 +122,7 @@ struct ids_database database[] = { | |||
{ | |||
.type = "sd", | |||
.id = 0x1d, | |||
- .manufacturer = "Corsair", | |||
+ .manufacturer = "Corsair/AData", | |||
}, | |||
{ | |||
.type = "sd", | |||
@@ -134,6 +134,11 @@ struct ids_database database[] = { | |||
.id = 0x1f, | |||
.manufacturer = "Kingston", | |||
}, | |||
+ { | |||
+ .type = "sd", | |||
+ .id = 0x27, | |||
+ .manufacturer = "Delkin/Phison", | |||
+ }, | |||
{ | |||
.type = "sd", | |||
.id = 0x28, | |||
@@ -144,6 +149,11 @@ struct ids_database database[] = { | |||
.id = 0x30, | |||
.manufacturer = "SanDisk", | |||
}, | |||
+ { | |||
+ .type = "sd", | |||
+ .id = 0x31, | |||
+ .manufacturer = "Silicon Power", | |||
+ }, | |||
{ | |||
.type = "sd", | |||
.id = 0x33, | |||
@@ -159,6 +169,21 @@ struct ids_database database[] = { | |||
.id = 0x6f, | |||
.manufacturer = "STMicroelectronics", | |||
}, | |||
+ { | |||
+ .type = "sd", | |||
+ .id = 0x74, | |||
+ .manufacturer = "Transcend", | |||
+ }, | |||
+ { | |||
+ .type = "sd", | |||
+ .id = 0x76, | |||
+ .manufacturer = "Patriot", | |||
+ }, | |||
+ { | |||
+ .type = "sd", | |||
+ .id = 0x82, | |||
+ .manufacturer = "Gobe/Sony", | |||
+ }, | |||
{ | |||
.type = "sd", | |||
.id = 0x89, | |||
@@ -224,6 +249,11 @@ struct ids_database database[] = { | |||
.id = 0x70, | |||
.manufacturer = "Kingston", | |||
}, | |||
+ { | |||
+ .type = "mmc", | |||
+ .id = 0xfe, | |||
+ .manufacturer = "Micron", | |||
+ }, | |||
}; | |||
/* Command line parsing functions */ | |||
-- | |||
2.17.1 | |||
@ -0,0 +1,276 @@ | |||
From 6ace4329870d9d7b2a2c3603af316b3f1a75e9f2 Mon Sep 17 00:00:00 2001 | |||
From: Stephane Fillod <f8cfe@free.fr> | |||
Date: Tue, 15 Jan 2019 15:06:03 +0100 | |||
Subject: [PATCH 8/9] Various fixes | |||
These warnings were mainly found using cppcheck. | |||
Signed-off-by: Stephane Fillod <f8cfe@free.fr> | |||
Reviewed-by: Michael Heimpold <mhei@heimpold.de> | |||
--- | |||
lsmmc.c | 42 +++++++++++++++++++++--------------------- | |||
mmc_cmds.c | 14 ++++++++++++-- | |||
2 files changed, 33 insertions(+), 23 deletions(-) | |||
diff --git a/lsmmc.c b/lsmmc.c | |||
index 63504d2..06cc0b8 100644 | |||
--- a/lsmmc.c | |||
+++ b/lsmmc.c | |||
@@ -554,9 +554,9 @@ void print_sd_cid(struct config *config, char *cid) | |||
printf("\tOID: %s\n", oid); | |||
printf("\tPNM: %s\n", pnm); | |||
printf("\tPRV: 0x%01x%01x ", prv_major, prv_minor); | |||
- printf("(%d.%d)\n", prv_major, prv_minor); | |||
+ printf("(%u.%u)\n", prv_major, prv_minor); | |||
printf("\tPSN: 0x%08x\n", psn); | |||
- printf("\tMDT: 0x%02x%01x %d %s\n", mdt_year, mdt_month, | |||
+ printf("\tMDT: 0x%02x%01x %u %s\n", mdt_year, mdt_month, | |||
2000 + mdt_year, months[mdt_month]); | |||
printf("\tCRC: 0x%02x\n", crc); | |||
} else { | |||
@@ -566,9 +566,9 @@ void print_sd_cid(struct config *config, char *cid) | |||
else | |||
printf("manufacturer: 'Unlisted' '%s'\n", oid); | |||
- printf("product: '%s' %d.%d\n", pnm, prv_major, prv_minor); | |||
+ printf("product: '%s' %u.%u\n", pnm, prv_major, prv_minor); | |||
printf("serial: 0x%08x\n", psn); | |||
- printf("manfacturing date: %d %s\n", 2000 + mdt_year, | |||
+ printf("manufacturing date: %u %s\n", 2000 + mdt_year, | |||
months[mdt_month]); | |||
} | |||
} | |||
@@ -625,9 +625,9 @@ void print_mmc_cid(struct config *config, char *cid) | |||
printf("\tOID: 0x%01x\n", oid); | |||
printf("\tPNM: %s\n", pnm); | |||
printf("\tPRV: 0x%01x%01x ", prv_major, prv_minor); | |||
- printf("(%d.%d)\n", prv_major, prv_minor); | |||
+ printf("(%u.%u)\n", prv_major, prv_minor); | |||
printf("\tPSN: 0x%08x\n", psn); | |||
- printf("\tMDT: 0x%01x%01x %d %s\n", mdt_month, mdt_year, | |||
+ printf("\tMDT: 0x%01x%01x %u %s\n", mdt_month, mdt_year, | |||
1997 + mdt_year, months[mdt_month]); | |||
printf("\tCRC: 0x%02x\n", crc); | |||
} else { | |||
@@ -637,9 +637,9 @@ void print_mmc_cid(struct config *config, char *cid) | |||
else | |||
printf("manufacturer: 'Unlisted' '%c'\n", oid); | |||
- printf("product: '%s' %d.%d\n", pnm, prv_major, prv_minor); | |||
+ printf("product: '%s' %u.%u\n", pnm, prv_major, prv_minor); | |||
printf("serial: 0x%08x\n", psn); | |||
- printf("manfacturing date: %d %s\n", 1997 + mdt_year, | |||
+ printf("manufacturing date: %u %s\n", 1997 + mdt_year, | |||
months[mdt_month]); | |||
} | |||
} | |||
@@ -729,7 +729,7 @@ void print_sd_csd(struct config *config, char *csd) | |||
printf("======SD/CSD======\n"); | |||
- printf("\tCSD_STRUCTURE: %d\n", csd_structure); | |||
+ printf("\tCSD_STRUCTURE: %u\n", csd_structure); | |||
printf("\tTAAC: 0x%02x (", taac); | |||
switch (taac_timevalue) { | |||
@@ -816,7 +816,7 @@ void print_sd_csd(struct config *config, char *csd) | |||
if (csd_structure == 1 && taac != 0x0e) | |||
printf("Warn: Invalid TAAC (should be 0x0e)\n"); | |||
- printf("\tNSAC: %d clocks\n", nsac); | |||
+ printf("\tNSAC: %u clocks\n", nsac); | |||
if (csd_structure == 1 && nsac != 0x00) | |||
printf("Warn: Invalid NSAC (should be 0x00)\n"); | |||
@@ -1103,12 +1103,12 @@ void print_sd_csd(struct config *config, char *csd) | |||
if (erase_blk_en != 0x01) | |||
printf("Warn: Invalid ERASE_BLK_EN (should be 0x01)\n"); | |||
- printf("\tSECTOR_SIZE: 0x%02x (Erasable sector: %d blocks)\n", | |||
+ printf("\tSECTOR_SIZE: 0x%02x (Erasable sector: %u blocks)\n", | |||
sector_size, sector_size + 1); | |||
if (sector_size != 0x7f) | |||
printf("Warn: Invalid SECTOR_SIZE (should be 0x7f)\n"); | |||
- printf("\tWP_GRP_SIZE: 0x%02x (Write protect group: %d blocks)\n", | |||
+ printf("\tWP_GRP_SIZE: 0x%02x (Write protect group: %u blocks)\n", | |||
wp_grp_size, wp_grp_size + 1); | |||
if (wp_grp_size != 0x00) | |||
printf("Warn: Invalid WP_GRP_SIZE (should be 0x00)\n"); | |||
@@ -1117,7 +1117,7 @@ void print_sd_csd(struct config *config, char *csd) | |||
if (wp_grp_enable != 0x00) | |||
printf("Warn: Invalid WP_GRP_ENABLE (should be 0x00)\n"); | |||
- printf("\tR2W_FACTOR: 0x%01x (Write %d times read)\n", | |||
+ printf("\tR2W_FACTOR: 0x%01x (Write %u times read)\n", | |||
r2w_factor, r2w_factor); | |||
if (r2w_factor != 0x02) | |||
printf("Warn: Invalid R2W_FACTOR (should be 0x02)\n"); | |||
@@ -1199,7 +1199,7 @@ void print_sd_csd(struct config *config, char *csd) | |||
else | |||
printf("%.2fbyte", memory_capacity * 1.0); | |||
- printf(" (%lld bytes, %lld sectors, %d bytes each)\n", | |||
+ printf(" (%llu bytes, %llu sectors, %d bytes each)\n", | |||
memory_capacity, blocks, block_size); | |||
} else { | |||
unsigned long long blocks = 0; | |||
@@ -1262,7 +1262,7 @@ void print_sd_csd(struct config *config, char *csd) | |||
else | |||
printf("%.2fbyte", memory_capacity * 1.0); | |||
- printf(" (%lld bytes, %lld sectors, %d bytes each)\n", | |||
+ printf(" (%llu bytes, %llu sectors, %d bytes each)\n", | |||
memory_capacity, blocks, block_size); | |||
} | |||
} | |||
@@ -1456,7 +1456,7 @@ void print_mmc_csd(struct config *config, char *csd) | |||
break; | |||
} | |||
- printf("\tNSAC: %d clocks\n", nsac); | |||
+ printf("\tNSAC: %u clocks\n", nsac); | |||
printf("\tTRAN_SPEED: 0x%02x (", tran_speed); | |||
switch (tran_speed_timevalue) { | |||
case 0x0: | |||
@@ -1764,10 +1764,10 @@ void print_mmc_csd(struct config *config, char *csd) | |||
printf("\tC_SIZE_MULT: 0x%01x\n", c_size_mult); | |||
printf("\tERASE_GRP_SIZE: 0x%02x\n", erase_grp_size); | |||
- printf("\tERASE_GRP_MULT: 0x%02x (%d write blocks/erase group)\n", | |||
+ printf("\tERASE_GRP_MULT: 0x%02x (%u write blocks/erase group)\n", | |||
erase_grp_mult, (erase_grp_size + 1) * | |||
(erase_grp_mult + 1)); | |||
- printf("\tWP_GRP_SIZE: 0x%02x (%d blocks/write protect group)\n", | |||
+ printf("\tWP_GRP_SIZE: 0x%02x (%u blocks/write protect group)\n", | |||
wp_grp_size, wp_grp_size + 1); | |||
printf("\tWP_GRP_ENABLE: 0x%01x\n", wp_grp_enable); | |||
@@ -1784,7 +1784,7 @@ void print_mmc_csd(struct config *config, char *csd) | |||
break; | |||
} | |||
- printf("\tR2W_FACTOR: 0x%01x (Write %d times read)\n", | |||
+ printf("\tR2W_FACTOR: 0x%01x (Write %u times read)\n", | |||
r2w_factor, r2w_factor); | |||
printf("\tWRITE_BL_LEN: 0x%01x (", write_bl_len); | |||
@@ -1914,7 +1914,7 @@ void print_mmc_csd(struct config *config, char *csd) | |||
else | |||
printf("%.2fbyte", memory_capacity * 1.0); | |||
- printf(" (%lld bytes, %lld sectors, %d bytes each)\n", | |||
+ printf(" (%llu bytes, %llu sectors, %d bytes each)\n", | |||
memory_capacity, blocks, block_size); | |||
} else { | |||
int mult; | |||
@@ -1991,7 +1991,7 @@ void print_mmc_csd(struct config *config, char *csd) | |||
printf("%.2fKbyte", memory_capacity / (1024.0)); | |||
else | |||
printf("%.2fbyte", memory_capacity * 1.0); | |||
- printf(" (%lld bytes, %lld sectors, %d bytes each)\n", | |||
+ printf(" (%llu bytes, %llu sectors, %d bytes each)\n", | |||
memory_capacity, blocks, block_size); | |||
} | |||
} | |||
diff --git a/mmc_cmds.c b/mmc_cmds.c | |||
index 19a9da1..9402112 100644 | |||
--- a/mmc_cmds.c | |||
+++ b/mmc_cmds.c | |||
@@ -252,6 +252,7 @@ int do_writeprotect_boot_get(int nargs, char **argv) | |||
print_writeprotect_boot_status(ext_csd); | |||
+ close(fd); | |||
return ret; | |||
} | |||
@@ -290,6 +291,7 @@ int do_writeprotect_boot_set(int nargs, char **argv) | |||
exit(1); | |||
} | |||
+ close(fd); | |||
return ret; | |||
} | |||
@@ -378,6 +380,7 @@ int do_writeprotect_user_get(int nargs, char **argv) | |||
if (last_wpblk != (x + y - 1)) | |||
print_wp_status(wp_sizeblks, last_wpblk, cnt - 1, last_prot); | |||
+ close(fd); | |||
return ret; | |||
} | |||
@@ -524,6 +527,7 @@ int do_disable_512B_emulation(int nargs, char **argv) | |||
printf("MMC does not support disabling 512B emulation mode.\n"); | |||
} | |||
+ close(fd); | |||
return ret; | |||
} | |||
@@ -595,6 +599,7 @@ int do_write_boot_en(int nargs, char **argv) | |||
value, EXT_CSD_PART_CONFIG, device); | |||
exit(1); | |||
} | |||
+ close(fd); | |||
return ret; | |||
} | |||
@@ -716,6 +721,7 @@ int do_hwreset(int value, int nargs, char **argv) | |||
exit(1); | |||
} | |||
+ close(fd); | |||
return ret; | |||
} | |||
@@ -766,6 +772,7 @@ int do_write_bkops_en(int nargs, char **argv) | |||
exit(1); | |||
} | |||
+ close(fd); | |||
return ret; | |||
} | |||
@@ -796,6 +803,7 @@ int do_status_get(int nargs, char **argv) | |||
printf("SEND_STATUS response: 0x%08x\n", response); | |||
+ close(fd); | |||
return ret; | |||
} | |||
@@ -1615,11 +1623,11 @@ int do_read_extcsd(int nargs, char **argv) | |||
printf("Write reliability setting register" | |||
" [WR_REL_SET]: 0x%02x\n", reg); | |||
- printf(" user area: %s\n", reg & (1<<0) ? reliable : fast); | |||
+ printf(" user area: %s\n", (reg & (1<<0)) ? reliable : fast); | |||
int i; | |||
for (i = 1; i <= 4; i++) { | |||
printf(" partition %d: %s\n", i, | |||
- reg & (1<<i) ? reliable : fast); | |||
+ (reg & (1<<i)) ? reliable : fast); | |||
} | |||
reg = ext_csd[EXT_CSD_WR_REL_PARAM]; | |||
@@ -1805,6 +1813,7 @@ int do_sanitize(int nargs, char **argv) | |||
exit(1); | |||
} | |||
+ close(fd); | |||
return ret; | |||
} | |||
@@ -2390,6 +2399,7 @@ int do_cache_ctrl(int value, int nargs, char **argv) | |||
exit(1); | |||
} | |||
+ close(fd); | |||
return ret; | |||
} | |||
-- | |||
2.17.1 | |||
@ -0,0 +1,188 @@ | |||
From 5425e4e96559b29b36459080190e8bcc1c92f7c2 Mon Sep 17 00:00:00 2001 | |||
From: "Shivamurthy Shastri (sshivamurthy)" <sshivamurthy@micron.com> | |||
Date: Wed, 10 Apr 2019 13:38:08 +0000 | |||
Subject: [PATCH 9/9] mmc-utils: let FFU mode use CMD23 and CMD25 | |||
As per specification, the host can use either CMD24 or CMD25 in | |||
closed-ended or open-ended way. | |||
CMD25 is better option as it can flash the firmware image in one go. | |||
Signed-off-by: Shivamurthy Shastri <sshivamurthy@micron.com> | |||
Reviewed-by: Avri Altman <avri.altman@wdc.com> | |||
--- | |||
mmc.h | 2 ++ | |||
mmc_cmds.c | 70 ++++++++++++++++++++++++++++++------------------------ | |||
2 files changed, 41 insertions(+), 31 deletions(-) | |||
diff --git a/mmc.h b/mmc.h | |||
index 285c1f1..a4cbba4 100644 | |||
--- a/mmc.h | |||
+++ b/mmc.h | |||
@@ -25,10 +25,12 @@ | |||
/* From kernel linux/mmc/mmc.h */ | |||
#define MMC_SWITCH 6 /* ac [31:0] See below R1b */ | |||
#define MMC_SEND_EXT_CSD 8 /* adtc R1 */ | |||
+#define MMC_STOP_TRANSMISSION 12 /* ac R1b */ | |||
#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ | |||
#define R1_SWITCH_ERROR (1 << 7) /* sx, c */ | |||
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ | |||
#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ | |||
+#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */ | |||
#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */ | |||
#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */ | |||
#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */ | |||
diff --git a/mmc_cmds.c b/mmc_cmds.c | |||
index 9402112..0a3788a 100644 | |||
--- a/mmc_cmds.c | |||
+++ b/mmc_cmds.c | |||
@@ -2424,12 +2424,13 @@ int do_ffu(int nargs, char **argv) | |||
int sect_done = 0, retry = 3, ret = -EINVAL; | |||
unsigned int sect_size; | |||
__u8 ext_csd[512]; | |||
- __u8 *buf; | |||
+ __u8 *buf = NULL; | |||
__u32 arg; | |||
off_t fw_size; | |||
ssize_t chunk_size; | |||
char *device; | |||
- struct mmc_ioc_multi_cmd *multi_cmd; | |||
+ struct mmc_ioc_multi_cmd *multi_cmd = NULL; | |||
+ __u32 blocks = 1; | |||
if (nargs != 3) { | |||
fprintf(stderr, "Usage: ffu <image name> </path/to/mmcblkX> \n"); | |||
@@ -2449,14 +2450,6 @@ int do_ffu(int nargs, char **argv) | |||
exit(1); | |||
} | |||
- buf = malloc(512); | |||
- multi_cmd = calloc(1, sizeof(struct mmc_ioc_multi_cmd) + | |||
- 3 * sizeof(struct mmc_ioc_cmd)); | |||
- if (!buf || !multi_cmd) { | |||
- perror("failed to allocate memory"); | |||
- goto out; | |||
- } | |||
- | |||
ret = read_extcsd(dev_fd, ext_csd); | |||
if (ret) { | |||
fprintf(stderr, "Could not read EXT_CSD from %s\n", device); | |||
@@ -2481,9 +2474,17 @@ int do_ffu(int nargs, char **argv) | |||
} | |||
fw_size = lseek(img_fd, 0, SEEK_END); | |||
+ if (fw_size > MMC_IOC_MAX_BYTES || fw_size == 0) { | |||
+ fprintf(stderr, "Wrong firmware size"); | |||
+ goto out; | |||
+ } | |||
- if (fw_size == 0) { | |||
- fprintf(stderr, "Firmware image is empty"); | |||
+ /* allocate maximum required */ | |||
+ buf = malloc(fw_size); | |||
+ multi_cmd = calloc(1, sizeof(struct mmc_ioc_multi_cmd) + | |||
+ 4 * sizeof(struct mmc_ioc_cmd)); | |||
+ if (!buf || !multi_cmd) { | |||
+ perror("failed to allocate memory"); | |||
goto out; | |||
} | |||
@@ -2493,14 +2494,19 @@ int do_ffu(int nargs, char **argv) | |||
goto out; | |||
} | |||
+ /* calculate required fw blocks for CMD25 */ | |||
+ blocks = fw_size / sect_size; | |||
+ | |||
/* set CMD ARG */ | |||
arg = ext_csd[EXT_CSD_FFU_ARG_0] | | |||
ext_csd[EXT_CSD_FFU_ARG_1] << 8 | | |||
ext_csd[EXT_CSD_FFU_ARG_2] << 16 | | |||
ext_csd[EXT_CSD_FFU_ARG_3] << 24; | |||
+ /* prepare multi_cmd for FFU based on cmd to be used */ | |||
+ | |||
/* prepare multi_cmd to be sent */ | |||
- multi_cmd->num_of_cmds = 3; | |||
+ multi_cmd->num_of_cmds = 4; | |||
/* put device into ffu mode */ | |||
multi_cmd->cmds[0].opcode = MMC_SWITCH; | |||
@@ -2511,37 +2517,42 @@ int do_ffu(int nargs, char **argv) | |||
multi_cmd->cmds[0].flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | |||
multi_cmd->cmds[0].write_flag = 1; | |||
+ /* send block count */ | |||
+ multi_cmd->cmds[1].opcode = MMC_SET_BLOCK_COUNT; | |||
+ multi_cmd->cmds[1].arg = blocks; | |||
+ multi_cmd->cmds[1].flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | |||
+ | |||
/* send image chunk */ | |||
- multi_cmd->cmds[1].opcode = MMC_WRITE_BLOCK; | |||
- multi_cmd->cmds[1].blksz = sect_size; | |||
- multi_cmd->cmds[1].blocks = 1; | |||
- multi_cmd->cmds[1].arg = arg; | |||
- multi_cmd->cmds[1].flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; | |||
- multi_cmd->cmds[1].write_flag = 1; | |||
- mmc_ioc_cmd_set_data(multi_cmd->cmds[1], buf); | |||
+ multi_cmd->cmds[2].opcode = MMC_WRITE_MULTIPLE_BLOCK; | |||
+ multi_cmd->cmds[2].blksz = sect_size; | |||
+ multi_cmd->cmds[2].blocks = blocks; | |||
+ multi_cmd->cmds[2].arg = arg; | |||
+ multi_cmd->cmds[2].flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; | |||
+ multi_cmd->cmds[2].write_flag = 1; | |||
+ mmc_ioc_cmd_set_data(multi_cmd->cmds[2], buf); | |||
/* return device into normal mode */ | |||
- multi_cmd->cmds[2].opcode = MMC_SWITCH; | |||
- multi_cmd->cmds[2].arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | | |||
+ multi_cmd->cmds[3].opcode = MMC_SWITCH; | |||
+ multi_cmd->cmds[3].arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | | |||
(EXT_CSD_MODE_CONFIG << 16) | | |||
(EXT_CSD_NORMAL_MODE << 8) | | |||
EXT_CSD_CMD_SET_NORMAL; | |||
- multi_cmd->cmds[2].flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | |||
- multi_cmd->cmds[2].write_flag = 1; | |||
+ multi_cmd->cmds[3].flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | |||
+ multi_cmd->cmds[3].write_flag = 1; | |||
do_retry: | |||
/* read firmware chunk */ | |||
lseek(img_fd, 0, SEEK_SET); | |||
- chunk_size = read(img_fd, buf, 512); | |||
+ chunk_size = read(img_fd, buf, fw_size); | |||
- while (chunk_size > 0) { | |||
+ if (chunk_size > 0) { | |||
/* send ioctl with multi-cmd */ | |||
ret = ioctl(dev_fd, MMC_IOC_MULTI_CMD, multi_cmd); | |||
if (ret) { | |||
perror("Multi-cmd ioctl"); | |||
/* In case multi-cmd ioctl failed before exiting from ffu mode */ | |||
- ioctl(dev_fd, MMC_IOC_CMD, &multi_cmd->cmds[2]); | |||
+ ioctl(dev_fd, MMC_IOC_CMD, &multi_cmd->cmds[3]); | |||
goto out; | |||
} | |||
@@ -2568,9 +2579,6 @@ do_retry: | |||
} else { | |||
fprintf(stderr, "Programmed %d/%jd bytes\r", sect_done * sect_size, (intmax_t)fw_size); | |||
} | |||
- | |||
- /* read the next firmware chunk (if any) */ | |||
- chunk_size = read(img_fd, buf, 512); | |||
} | |||
if ((sect_done * sect_size) == fw_size) { | |||
@@ -2607,7 +2615,7 @@ do_retry: | |||
if (ret) { | |||
perror("Multi-cmd ioctl failed setting install mode"); | |||
/* In case multi-cmd ioctl failed before exiting from ffu mode */ | |||
- ioctl(dev_fd, MMC_IOC_CMD, &multi_cmd->cmds[2]); | |||
+ ioctl(dev_fd, MMC_IOC_CMD, &multi_cmd->cmds[3]); | |||
goto out; | |||
} | |||
-- | |||
2.17.1 | |||