From 6aab70df4cd0e46bea9d5831aaecebdc6782219d Mon Sep 17 00:00:00 2001 From: Michael Heimpold Date: Mon, 15 Apr 2019 21:28:59 +0200 Subject: [PATCH] mmc-utils: update to latest git head 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 --- utils/mmc-utils/Makefile | 6 +- ...erly-set-fortify-source-in-makefile.patch} | 0 ...eturn-value-before-using-the-pointer.patch | 30 ++ .../0002-Cleanup-memory-in-error-case.patch | 33 +++ ...ix-parsing-of-character-in-to_binstr.patch | 33 +++ .../0004-Optimize-to_binstr-function.patch | 56 ++++ ...0005-Add-eMMC-vendor-Micron-to-table.patch | 30 ++ ...f-Product-Revision-and-Serial-Number.patch | 29 ++ ...Add-various-SD-eMMC-vendors-to-table.patch | 97 ++++++ .../patches/0008-Various-fixes.patch | 276 ++++++++++++++++++ ...ils-let-FFU-mode-use-CMD23-and-CMD25.patch | 188 ++++++++++++ 11 files changed, 774 insertions(+), 4 deletions(-) rename utils/mmc-utils/patches/{001-properly-set-fortify-source-in-makefile.patch => 0000-properly-set-fortify-source-in-makefile.patch} (100%) create mode 100644 utils/mmc-utils/patches/0001-Check-calloc-s-return-value-before-using-the-pointer.patch create mode 100644 utils/mmc-utils/patches/0002-Cleanup-memory-in-error-case.patch create mode 100644 utils/mmc-utils/patches/0003-Fix-parsing-of-character-in-to_binstr.patch create mode 100644 utils/mmc-utils/patches/0004-Optimize-to_binstr-function.patch create mode 100644 utils/mmc-utils/patches/0005-Add-eMMC-vendor-Micron-to-table.patch create mode 100644 utils/mmc-utils/patches/0006-Fix-parsing-of-Product-Revision-and-Serial-Number.patch create mode 100644 utils/mmc-utils/patches/0007-Add-various-SD-eMMC-vendors-to-table.patch create mode 100644 utils/mmc-utils/patches/0008-Various-fixes.patch create mode 100644 utils/mmc-utils/patches/0009-mmc-utils-let-FFU-mode-use-CMD23-and-CMD25.patch diff --git a/utils/mmc-utils/Makefile b/utils/mmc-utils/Makefile index 5ceec2a8e3..9783f54a5c 100644 --- a/utils/mmc-utils/Makefile +++ b/utils/mmc-utils/Makefile @@ -13,16 +13,14 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc-utils.git PKG_SOURCE_DATE:=2018-12-09 -PKG_SOURCE_VERSION:=485b05ec40031a06077db9c84ae75a36ebd3db25 -PKG_MIRROR_HASH:=043d706a5bb7c206ccfdc1a5e604bf03bd744f8dcfaeccba1a7ef845a18fbd26 +PKG_SOURCE_VERSION:=aef913e31b659462fe6b9320d241676cba97f67b +PKG_MIRROR_HASH:=8c3d872be1392b7a140a36ce75ed48ef300ee6b6f1ce1b37dad1ad263d338dc3 PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:= PKG_MAINTAINER:=Michael Heimpold -PKG_BUILD_PARALLEL:=1 - include $(INCLUDE_DIR)/package.mk define Package/mmc-utils diff --git a/utils/mmc-utils/patches/001-properly-set-fortify-source-in-makefile.patch b/utils/mmc-utils/patches/0000-properly-set-fortify-source-in-makefile.patch similarity index 100% rename from utils/mmc-utils/patches/001-properly-set-fortify-source-in-makefile.patch rename to utils/mmc-utils/patches/0000-properly-set-fortify-source-in-makefile.patch diff --git a/utils/mmc-utils/patches/0001-Check-calloc-s-return-value-before-using-the-pointer.patch b/utils/mmc-utils/patches/0001-Check-calloc-s-return-value-before-using-the-pointer.patch new file mode 100644 index 0000000000..004cfb7a59 --- /dev/null +++ b/utils/mmc-utils/patches/0001-Check-calloc-s-return-value-before-using-the-pointer.patch @@ -0,0 +1,30 @@ +From bf96e1b2f48eab26c4a0c2a0903d9d7b9a311a1d Mon Sep 17 00:00:00 2001 +From: Michael Heimpold +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 +Cc: Michael Heimpold +--- + 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 + diff --git a/utils/mmc-utils/patches/0002-Cleanup-memory-in-error-case.patch b/utils/mmc-utils/patches/0002-Cleanup-memory-in-error-case.patch new file mode 100644 index 0000000000..689d69396a --- /dev/null +++ b/utils/mmc-utils/patches/0002-Cleanup-memory-in-error-case.patch @@ -0,0 +1,33 @@ +From 9214f2a4002bafef73c9593464ab3841ba7bac12 Mon Sep 17 00:00:00 2001 +From: Michael Heimpold +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 +Cc: Michael Heimpold +--- + 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 + diff --git a/utils/mmc-utils/patches/0003-Fix-parsing-of-character-in-to_binstr.patch b/utils/mmc-utils/patches/0003-Fix-parsing-of-character-in-to_binstr.patch new file mode 100644 index 0000000000..3a5780d5c5 --- /dev/null +++ b/utils/mmc-utils/patches/0003-Fix-parsing-of-character-in-to_binstr.patch @@ -0,0 +1,33 @@ +From a59d98003c0b2364929ee23ed331d610029c6dcf Mon Sep 17 00:00:00 2001 +From: Michael Heimpold +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 +Cc: Michael Heimpold +--- + 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 + diff --git a/utils/mmc-utils/patches/0004-Optimize-to_binstr-function.patch b/utils/mmc-utils/patches/0004-Optimize-to_binstr-function.patch new file mode 100644 index 0000000000..6ac8606c1e --- /dev/null +++ b/utils/mmc-utils/patches/0004-Optimize-to_binstr-function.patch @@ -0,0 +1,56 @@ +From f1fc04d7609ab074647aa00e96d4c66d5135b155 Mon Sep 17 00:00:00 2001 +From: Michael Heimpold +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 +Cc: Michael Heimpold +--- + 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 + diff --git a/utils/mmc-utils/patches/0005-Add-eMMC-vendor-Micron-to-table.patch b/utils/mmc-utils/patches/0005-Add-eMMC-vendor-Micron-to-table.patch new file mode 100644 index 0000000000..7c2630f4bb --- /dev/null +++ b/utils/mmc-utils/patches/0005-Add-eMMC-vendor-Micron-to-table.patch @@ -0,0 +1,30 @@ +From c0375ecea6f3731c0f65ff6abd2c194b90153b26 Mon Sep 17 00:00:00 2001 +From: Michael Heimpold +Date: Tue, 18 Dec 2018 15:09:42 +0100 +Subject: [PATCH 5/9] Add eMMC vendor Micron to table + +Signed-off-by: Michael Heimpold +Cc: Michael Heimpold +--- + 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 + diff --git a/utils/mmc-utils/patches/0006-Fix-parsing-of-Product-Revision-and-Serial-Number.patch b/utils/mmc-utils/patches/0006-Fix-parsing-of-Product-Revision-and-Serial-Number.patch new file mode 100644 index 0000000000..882b8a7596 --- /dev/null +++ b/utils/mmc-utils/patches/0006-Fix-parsing-of-Product-Revision-and-Serial-Number.patch @@ -0,0 +1,29 @@ +From 6bcf573f9056c6a4fb2ace5aece08a53dc5dceca Mon Sep 17 00:00:00 2001 +From: Stephane Fillod +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 +Acked-by: Avri Altman +--- + 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 + diff --git a/utils/mmc-utils/patches/0007-Add-various-SD-eMMC-vendors-to-table.patch b/utils/mmc-utils/patches/0007-Add-various-SD-eMMC-vendors-to-table.patch new file mode 100644 index 0000000000..ff331b71dc --- /dev/null +++ b/utils/mmc-utils/patches/0007-Add-various-SD-eMMC-vendors-to-table.patch @@ -0,0 +1,97 @@ +From c9c90f4f74ee5318ee9a2f581b665d474f6f90c5 Mon Sep 17 00:00:00 2001 +From: Stephane Fillod +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 +--- + 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 + diff --git a/utils/mmc-utils/patches/0008-Various-fixes.patch b/utils/mmc-utils/patches/0008-Various-fixes.patch new file mode 100644 index 0000000000..42d69bebe3 --- /dev/null +++ b/utils/mmc-utils/patches/0008-Various-fixes.patch @@ -0,0 +1,276 @@ +From 6ace4329870d9d7b2a2c3603af316b3f1a75e9f2 Mon Sep 17 00:00:00 2001 +From: Stephane Fillod +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 +Reviewed-by: Michael Heimpold +--- + 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< +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 +Reviewed-by: Avri Altman +--- + 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 \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 +