Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package mmc-utils for openSUSE:Factory checked in at 2023-03-24 15:21:37 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mmc-utils (Old) and /work/SRC/openSUSE:Factory/.mmc-utils.new.31432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mmc-utils" Fri Mar 24 15:21:37 2023 rev:20 rq:1074096 version:0.1+git.20230209 Changes: -------- --- /work/SRC/openSUSE:Factory/mmc-utils/mmc-utils.changes 2022-02-17 23:41:45.735700300 +0100 +++ /work/SRC/openSUSE:Factory/.mmc-utils.new.31432/mmc-utils.changes 2023-03-24 15:21:51.111335553 +0100 @@ -1,0 +2,19 @@ +Fri Mar 24 08:08:30 UTC 2023 - Martin Pluskal <[email protected]> + +- Update to version 0.1+git.20230209: + * mmc-utils: Add basic erase error check + * mmc-utils: Add a command to write extcsd registers + * mmc-utils: Implement alternative boot operation + * mmc-utils: Add CMD0 softreset and preidle command + * mmc-utils: Allow for custom sanitize timeout + * mmc-utils: Refactor switch to allow custom timeout + * mmc-utils: Fix a typo for ATP mid + * mmc-utils: Fix ffu in case of unsupported MODE_OPERATION_CODES + * mmc-utils: fix warning on uninitialized 'cnt' + * mmc-utils: correct and clean up the file handling + * mmc-utils: Fix 4k sector size block count in FFU + * mmc-utils: Add General command CMD56 read support + * mmc-utils: Fix build error MMC_BLOCK_MAJOR undeclared + * Enhancement to do_status_get() function for detailed Response info + +------------------------------------------------------------------- Old: ---- mmc-utils-0.1+git.20220208.obscpio New: ---- mmc-utils-0.1+git.20230209.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mmc-utils.spec ++++++ --- /var/tmp/diff_new_pack.UbayAV/_old 2023-03-24 15:21:51.615338181 +0100 +++ /var/tmp/diff_new_pack.UbayAV/_new 2023-03-24 15:21:51.627338244 +0100 @@ -1,7 +1,7 @@ # # spec file for package mmc-utils # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: mmc-utils -Version: 0.1+git.20220208 +Version: 0.1+git.20230209 Release: 0 Summary: Tools for MMC/SD devices License: GPL-2.0-only ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.UbayAV/_old 2023-03-24 15:21:51.679338514 +0100 +++ /var/tmp/diff_new_pack.UbayAV/_new 2023-03-24 15:21:51.687338557 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc-utils.git</param> - <param name="changesrevision">4637a7c0df49ba349f9f0e4ab0828133fc06cc81</param></service></servicedata> + <param name="changesrevision">d4c2910981ff99b983734426dfa99632fb81ac6b</param></service></servicedata> (No newline at EOF) ++++++ mmc-utils-0.1+git.20220208.obscpio -> mmc-utils-0.1+git.20230209.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmc-utils-0.1+git.20220208/lsmmc.c new/mmc-utils-0.1+git.20230209/lsmmc.c --- old/mmc-utils-0.1+git.20220208/lsmmc.c 2022-02-08 16:15:35.000000000 +0100 +++ new/mmc-utils-0.1+git.20230209/lsmmc.c 2023-02-09 15:16:51.000000000 +0100 @@ -237,7 +237,7 @@ { .type = "mmc", .id = 0x44, - .manufacturer = "SanDisk", + .manufacturer = "ATP", }, { .type = "mmc", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmc-utils-0.1+git.20220208/mmc.c new/mmc-utils-0.1+git.20230209/mmc.c --- old/mmc-utils-0.1+git.20220208/mmc.c 2022-02-08 16:15:35.000000000 +0100 +++ new/mmc-utils-0.1+git.20230209/mmc.c 2023-02-09 15:16:51.000000000 +0100 @@ -58,6 +58,11 @@ "Print extcsd data from <device>.", NULL }, + { do_write_extcsd, 3, + "extcsd write", "<offset> <value> <device>\n" + "Write <value> at offset <offset> to <device>'s extcsd.", + NULL + }, { do_writeprotect_boot_get, -1, "writeprotect boot get", "<device>\n" "Print the boot partitions write protect status for <device>.", @@ -150,7 +155,7 @@ NULL }, { do_sanitize, -1, - "sanitize", "<device>\n" + "sanitize", "<device> [timeout_ms]\n" "Send Sanitize command to the <device>.\nThis will delete the unmapped memory region of the device.", NULL }, @@ -237,6 +242,36 @@ "secure-trim1 | secure-trim2 | trim \n", NULL }, + { do_general_cmd_read, -1, + "gen_cmd read", "<device> [arg]\n" + "Send GEN_CMD (CMD56) to read vendor-specific format/meaning data from <device>\n\n" + "NOTE!: [arg] is optional and defaults to 0x1. If [arg] is specified, then [arg]\n" + "must be a 32-bit hexadecimal number, prefixed with 0x/0X. And bit0 in [arg] must\n" + "be 1.", + NULL + }, + { do_softreset, -1, + "softreset", "<device>\n" + "Issues a CMD0 softreset, e.g. for testing if hardware reset for UHS works", + NULL + }, + { do_preidle, -1, + "preidle", "<device>\n" + "Issues a CMD0 GO_PRE_IDLE", + NULL + }, + { do_alt_boot_op, -1, + "boot_operation", "<boot_data_file> <device>\n" + "Does the alternative boot operation and writes the specified starting blocks of boot data into the requested file.\n\n" + "Note some limitations\n:" + "1. The boot operation must be configured, e.g. for legacy speed:\n" + "mmc-utils bootbus set single_backward retain x8 /dev/mmcblk2\n" + "mmc-utils bootpart enable 1 0 /dev/mmcblk2\n" + "2. The MMC must currently be running at the bus mode that is configured for the boot operation (HS200 and HS400 not supported at all).\n" + "3. Only up to 512K bytes of boot data will be transferred.\n" + "4. The MMC will perform a soft reset, if your system cannot handle that do not use the boot operation from mmc-utils.\n", + NULL + }, { 0, 0, 0, 0 } }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmc-utils-0.1+git.20220208/mmc.h new/mmc-utils-0.1+git.20230209/mmc.h --- old/mmc-utils-0.1+git.20220208/mmc.h 2022-02-08 16:15:35.000000000 +0100 +++ new/mmc-utils-0.1+git.20230209/mmc.h 2023-02-09 15:16:51.000000000 +0100 @@ -17,9 +17,14 @@ * those modifications are Copyright (c) 2016 SanDisk Corp. */ +#include <linux/major.h> #include <linux/mmc/ioctl.h> /* From kernel linux/mmc/mmc.h */ +#define MMC_GO_IDLE_STATE 0 /* bc */ +#define MMC_GO_IDLE_STATE_ARG 0x0 +#define MMC_GO_PRE_IDLE_STATE_ARG 0xF0F0F0F0 +#define MMC_BOOT_INITIATION_ARG 0xFFFFFFFA #define MMC_SWITCH 6 /* ac [31:0] See below R1b */ #define MMC_SEND_EXT_CSD 8 /* adtc R1 */ #define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ @@ -41,6 +46,30 @@ [1] Discard Enable [0] Identify Write Blocks for Erase (or TRIM Enable) R1b */ +#define MMC_GEN_CMD 56 /* adtc [31:1] stuff bits. + [0]: RD/WR1 R1 */ + +#define R1_OUT_OF_RANGE (1 << 31) /* er, c */ +#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ +#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ +#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ +#define R1_ERASE_PARAM (1 << 27) /* ex, c */ +#define R1_WP_VIOLATION (1 << 26) /* erx, c */ +#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ +#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ +#define R1_COM_CRC_ERROR (1 << 23) /* er, b */ +#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ +#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ +#define R1_CC_ERROR (1 << 20) /* erx, c */ +#define R1_ERROR (1 << 19) /* erx, c */ +#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ +#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ +#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ +#define R1_ERASE_RESET (1 << 13) /* sr, c */ +#define R1_READY_FOR_DATA (1 << 8) /* sx, a */ +#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */ +#define R1_APP_CMD (1 << 5) /* sr, c */ + /* * EXT_CSD fields */ @@ -69,6 +98,7 @@ #define EXT_CSD_CACHE_SIZE_0 249 #define EXT_CSD_SEC_FEATURE_SUPPORT 231 #define EXT_CSD_BOOT_INFO 228 /* R/W */ +#define EXT_CSD_BOOT_MULT 226 /* RO */ #define EXT_CSD_HC_ERASE_GRP_SIZE 224 #define EXT_CSD_HC_WP_GRP_SIZE 221 #define EXT_CSD_SEC_COUNT_3 215 @@ -201,6 +231,7 @@ /* From kernel linux/mmc/core.h */ +#define MMC_RSP_NONE 0 /* no response */ #define MMC_RSP_PRESENT (1 << 0) #define MMC_RSP_136 (1 << 1) /* 136 bit response */ #define MMC_RSP_CRC (1 << 2) /* expect valid crc */ @@ -209,6 +240,7 @@ #define MMC_CMD_AC (0 << 5) #define MMC_CMD_ADTC (1 << 5) +#define MMC_CMD_BC (2 << 5) #define MMC_RSP_SPI_S1 (1 << 7) /* one status byte */ #define MMC_RSP_SPI_BUSY (1 << 10) /* card may send busy */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmc-utils-0.1+git.20220208/mmc_cmds.c new/mmc-utils-0.1+git.20230209/mmc_cmds.c --- old/mmc-utils-0.1+git.20220208/mmc_cmds.c 2022-02-08 16:15:35.000000000 +0100 +++ new/mmc-utils-0.1+git.20230209/mmc_cmds.c 2023-02-09 15:16:51.000000000 +0100 @@ -54,7 +54,6 @@ #define WPTYPE_PWRON 2 #define WPTYPE_PERM 3 - int read_extcsd(int fd, __u8 *ext_csd) { int ret = 0; @@ -76,7 +75,7 @@ return ret; } -int write_extcsd_value(int fd, __u8 index, __u8 value) +int write_extcsd_value(int fd, __u8 index, __u8 value, unsigned int timeout_ms) { int ret = 0; struct mmc_ioc_cmd idata; @@ -89,6 +88,8 @@ (value << 8) | EXT_CSD_CMD_SET_NORMAL; idata.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + /* Kernel will set cmd_timeout_ms if 0 is set */ + idata.cmd_timeout_ms = timeout_ms; ret = ioctl(fd, MMC_IOC_CMD, &idata); if (ret) @@ -341,7 +342,7 @@ value |= permanent ? EXT_CSD_BOOT_WP_B_PERM_WP_EN : EXT_CSD_BOOT_WP_B_PWR_WP_EN; - ret = write_extcsd_value(fd, EXT_CSD_BOOT_WP, value); + ret = write_extcsd_value(fd, EXT_CSD_BOOT_WP, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to " "EXT_CSD[%d] in %s\n", @@ -508,7 +509,7 @@ break; } if (user_wp != ext_csd[EXT_CSD_USER_WP]) { - ret = write_extcsd_value(fd, EXT_CSD_USER_WP, user_wp); + ret = write_extcsd_value(fd, EXT_CSD_USER_WP, user_wp, 0); if (ret) { fprintf(stderr, "Error setting EXT_CSD\n"); exit(1); @@ -526,7 +527,7 @@ } if (wptype != WPTYPE_NONE) { ret = write_extcsd_value(fd, EXT_CSD_USER_WP, - ext_csd[EXT_CSD_USER_WP]); + ext_csd[EXT_CSD_USER_WP], 0); if (ret) { fprintf(stderr, "Error restoring EXT_CSD\n"); exit(1); @@ -571,7 +572,7 @@ if (native_sector_size && !data_sector_size && (wr_rel_param & EN_REL_WR)) { - ret = write_extcsd_value(fd, EXT_CSD_USE_NATIVE_SECTOR, 1); + ret = write_extcsd_value(fd, EXT_CSD_USE_NATIVE_SECTOR, 1, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n", @@ -650,7 +651,7 @@ else value &= ~EXT_CSD_PART_CONFIG_ACC_ACK; - ret = write_extcsd_value(fd, EXT_CSD_PART_CONFIG, value); + ret = write_extcsd_value(fd, EXT_CSD_PART_CONFIG, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to " "EXT_CSD[%d] in %s\n", @@ -720,7 +721,7 @@ printf("Changing ext_csd[BOOT_BUS_CONDITIONS] from 0x%02x to 0x%02x\n", ext_csd[EXT_CSD_BOOT_BUS_CONDITIONS], value); - ret = write_extcsd_value(fd, EXT_CSD_BOOT_BUS_CONDITIONS, value); + ret = write_extcsd_value(fd, EXT_CSD_BOOT_BUS_CONDITIONS, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to " "EXT_CSD[%d] in %s\n", @@ -771,7 +772,7 @@ exit(1); } - ret = write_extcsd_value(fd, EXT_CSD_RST_N_FUNCTION, value); + ret = write_extcsd_value(fd, EXT_CSD_RST_N_FUNCTION, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n", @@ -825,9 +826,9 @@ fprintf(stderr, "%s doesn't support AUTO_EN in the BKOPS_EN register\n", device); exit(1); } - ret = write_extcsd_value(fd, EXT_CSD_BKOPS_EN, BKOPS_AUTO_ENABLE); + ret = write_extcsd_value(fd, EXT_CSD_BKOPS_EN, BKOPS_AUTO_ENABLE, 0); } else if (strcmp(en_type, "manual") == 0) { - ret = write_extcsd_value(fd, EXT_CSD_BKOPS_EN, BKOPS_MAN_ENABLE); + ret = write_extcsd_value(fd, EXT_CSD_BKOPS_EN, BKOPS_MAN_ENABLE, 0); } else { fprintf(stderr, "%s invalid mode for BKOPS_EN requested: %s. Valid options: auto or manual\n", en_type, device); exit(1); @@ -848,6 +849,8 @@ __u32 response; int fd, ret; char *device; + const char *str; + __u8 state; if (nargs != 2) { fprintf(stderr, "Usage: mmc status get </path/to/mmcblkX>\n"); @@ -870,6 +873,89 @@ printf("SEND_STATUS response: 0x%08x\n", response); + if (response & R1_OUT_OF_RANGE) + printf("ERROR: ADDRESS_OUT_OF_RANGE\n"); + if (response & R1_ADDRESS_ERROR) + printf("ERROR: ADDRESS_MISALIGN\n"); + if (response & R1_BLOCK_LEN_ERROR) + printf("ERROR: BLOCK_LEN_ERROR\n"); + if (response & R1_ERASE_SEQ_ERROR) + printf("ERROR: ERASE_SEQ_ERROR\n"); + if (response & R1_ERASE_PARAM) + printf("ERROR: ERASE_PARAM_ERROR\n"); + if (response & R1_WP_VIOLATION) + printf("ERROR: WP_VOILATION\n"); + if (response & R1_CARD_IS_LOCKED) + printf("STATUS: DEVICE_IS_LOCKED\n"); + if (response & R1_LOCK_UNLOCK_FAILED) + printf("ERROR: LOCK_UNLOCK_IS_FAILED\n"); + if (response & R1_COM_CRC_ERROR) + printf("ERROR: COM_CRC_ERROR\n"); + if (response & R1_ILLEGAL_COMMAND) + printf("ERROR: ILLEGAL_COMMAND\n"); + if (response & R1_CARD_ECC_FAILED) + printf("ERROR: DEVICE_ECC_FAILED\n"); + if (response & R1_CC_ERROR) + printf("ERROR: CC_ERROR\n"); + if (response & R1_ERROR) + printf("ERROR: ERROR\n"); + if (response & R1_CID_CSD_OVERWRITE) + printf("ERROR: CID/CSD OVERWRITE\n"); + if (response & R1_WP_ERASE_SKIP) + printf("ERROR: WP_ERASE_SKIP\n"); + if (response & R1_ERASE_RESET) + printf("ERROR: ERASE_RESET\n"); + + state = (response >> 9) & 0xF; + switch (state) { + case 0: + str = "IDLE"; + break; + case 1: + str = "READY"; + break; + case 2: + str = "IDENT"; + break; + case 3: + str = "STDBY"; + break; + case 4: + str = "TRANS"; + break; + case 5: + str = "DATA"; + break; + case 6: + str = "RCV"; + break; + case 7: + str = "PRG"; + break; + case 8: + str = "DIS"; + break; + case 9: + str = "BTST"; + break; + case 10: + str = "SLP"; + break; + default: + printf("Attention : Device state is INVALID: Kindly check the Response\n"); + goto out_free; + } + + printf("DEVICE STATE: %s\n", str); + if (response & R1_READY_FOR_DATA) + printf("STATUS: READY_FOR_DATA\n"); + if (response & R1_SWITCH_ERROR) + printf("ERROR: SWITCH_ERROR\n"); + if (response & R1_EXCEPTION_EVENT) + printf("STATUS: EXCEPTION_EVENT\n"); /* Check EXCEPTION_EVENTS_STATUS fields for further actions */ + if (response & R1_APP_CMD) + printf("STATUS: APP_CMD\n"); +out_free: close(fd); return ret; } @@ -917,7 +1003,7 @@ } fprintf(stderr, "setting OTP PARTITION_SETTING_COMPLETED!\n"); - ret = write_extcsd_value(fd, EXT_CSD_PARTITION_SETTING_COMPLETED, 0x1); + ret = write_extcsd_value(fd, EXT_CSD_PARTITION_SETTING_COMPLETED, 0x1, 0); if (ret) { fprintf(stderr, "Could not write 0x1 to " "EXT_CSD[%d] in %s\n", @@ -1103,7 +1189,7 @@ gp_size_mult = (length_kib + align/2l) / align; /* set EXT_CSD_ERASE_GROUP_DEF bit 0 */ - ret = write_extcsd_value(fd, EXT_CSD_ERASE_GROUP_DEF, 0x1); + ret = write_extcsd_value(fd, EXT_CSD_ERASE_GROUP_DEF, 0x1, 0); if (ret) { fprintf(stderr, "Could not write 0x1 to EXT_CSD[%d] in %s\n", EXT_CSD_ERASE_GROUP_DEF, device); @@ -1112,7 +1198,7 @@ value = (gp_size_mult >> 16) & 0xff; address = EXT_CSD_GP_SIZE_MULT_1_2 + (partition - 1) * 3; - ret = write_extcsd_value(fd, address, value); + ret = write_extcsd_value(fd, address, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n", value, address, device); @@ -1120,7 +1206,7 @@ } value = (gp_size_mult >> 8) & 0xff; address = EXT_CSD_GP_SIZE_MULT_1_1 + (partition - 1) * 3; - ret = write_extcsd_value(fd, address, value); + ret = write_extcsd_value(fd, address, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n", value, address, device); @@ -1128,7 +1214,7 @@ } value = gp_size_mult & 0xff; address = EXT_CSD_GP_SIZE_MULT_1_0 + (partition - 1) * 3; - ret = write_extcsd_value(fd, address, value); + ret = write_extcsd_value(fd, address, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n", value, address, device); @@ -1141,7 +1227,7 @@ else value &= ~(1 << partition); - ret = write_extcsd_value(fd, EXT_CSD_PARTITIONS_ATTRIBUTE, value); + ret = write_extcsd_value(fd, EXT_CSD_PARTITIONS_ATTRIBUTE, value, 0); if (ret) { fprintf(stderr, "Could not write EXT_CSD_ENH_%x to EXT_CSD[%d] in %s\n", partition, EXT_CSD_PARTITIONS_ATTRIBUTE, device); @@ -1155,7 +1241,7 @@ else value &= (0xF << (4 * ((partition % 2)))); - ret = write_extcsd_value(fd, address, value); + ret = write_extcsd_value(fd, address, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%x to EXT_CSD[%d] in %s\n", value, address, device); @@ -1232,7 +1318,7 @@ enh_start_addr *= align; /* set EXT_CSD_ERASE_GROUP_DEF bit 0 */ - ret = write_extcsd_value(fd, EXT_CSD_ERASE_GROUP_DEF, 0x1); + ret = write_extcsd_value(fd, EXT_CSD_ERASE_GROUP_DEF, 0x1, 0); if (ret) { fprintf(stderr, "Could not write 0x1 to " "EXT_CSD[%d] in %s\n", @@ -1242,7 +1328,7 @@ /* write to ENH_START_ADDR and ENH_SIZE_MULT and PARTITIONS_ATTRIBUTE's ENH_USR bit */ value = (enh_start_addr >> 24) & 0xff; - ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_3, value); + ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_3, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to " "EXT_CSD[%d] in %s\n", value, @@ -1250,7 +1336,7 @@ exit(1); } value = (enh_start_addr >> 16) & 0xff; - ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_2, value); + ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_2, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to " "EXT_CSD[%d] in %s\n", value, @@ -1258,7 +1344,7 @@ exit(1); } value = (enh_start_addr >> 8) & 0xff; - ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_1, value); + ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_1, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to " "EXT_CSD[%d] in %s\n", value, @@ -1266,7 +1352,7 @@ exit(1); } value = enh_start_addr & 0xff; - ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_0, value); + ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_0, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to " "EXT_CSD[%d] in %s\n", value, @@ -1275,7 +1361,7 @@ } value = (enh_size_mult >> 16) & 0xff; - ret = write_extcsd_value(fd, EXT_CSD_ENH_SIZE_MULT_2, value); + ret = write_extcsd_value(fd, EXT_CSD_ENH_SIZE_MULT_2, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to " "EXT_CSD[%d] in %s\n", value, @@ -1283,7 +1369,7 @@ exit(1); } value = (enh_size_mult >> 8) & 0xff; - ret = write_extcsd_value(fd, EXT_CSD_ENH_SIZE_MULT_1, value); + ret = write_extcsd_value(fd, EXT_CSD_ENH_SIZE_MULT_1, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to " "EXT_CSD[%d] in %s\n", value, @@ -1291,7 +1377,7 @@ exit(1); } value = enh_size_mult & 0xff; - ret = write_extcsd_value(fd, EXT_CSD_ENH_SIZE_MULT_0, value); + ret = write_extcsd_value(fd, EXT_CSD_ENH_SIZE_MULT_0, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to " "EXT_CSD[%d] in %s\n", value, @@ -1299,7 +1385,7 @@ exit(1); } value = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] | EXT_CSD_ENH_USR; - ret = write_extcsd_value(fd, EXT_CSD_PARTITIONS_ATTRIBUTE, value); + ret = write_extcsd_value(fd, EXT_CSD_PARTITIONS_ATTRIBUTE, value, 0); if (ret) { fprintf(stderr, "Could not write EXT_CSD_ENH_USR to " "EXT_CSD[%d] in %s\n", @@ -1370,7 +1456,7 @@ } value = ext_csd[EXT_CSD_WR_REL_SET] | (1<<partition); - ret = write_extcsd_value(fd, EXT_CSD_WR_REL_SET, value); + ret = write_extcsd_value(fd, EXT_CSD_WR_REL_SET, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n", value, EXT_CSD_WR_REL_SET, device); @@ -1895,16 +1981,52 @@ return ret; } +int do_write_extcsd(int nargs, char **argv) +{ + int fd, ret; + int offset, value; + char *device; + + if (nargs != 4) { + fprintf(stderr, "Usage: mmc extcsd write <offset> <value> </path/to/mmcblkX>\n"); + exit(1); + } + + offset = strtol(argv[1], NULL, 0); + value = strtol(argv[2], NULL, 0); + device = argv[3]; + + fd = open(device, O_RDWR); + if (fd < 0) { + perror("open"); + exit(1); + } + + ret = write_extcsd_value(fd, offset, value, 0); + if (ret) { + fprintf(stderr, + "Could not write 0x%02x to EXT_CSD[%d] in %s\n", + value, offset, device); + exit(1); + } + + return ret; +} + int do_sanitize(int nargs, char **argv) { int fd, ret; char *device; + unsigned int timeout = 0; - if (nargs != 2) { - fprintf(stderr, "Usage: mmc sanitize </path/to/mmcblkX>\n"); + if (nargs != 2 && nargs != 3) { + fprintf(stderr, "Usage: mmc sanitize </path/to/mmcblkX> [timeout_in_ms]\n"); exit(1); } + if (nargs == 3) + timeout = strtol(argv[2], NULL, 10); + device = argv[1]; fd = open(device, O_RDWR); @@ -1913,7 +2035,7 @@ exit(1); } - ret = write_extcsd_value(fd, EXT_CSD_SANITIZE_START, 1); + ret = write_extcsd_value(fd, EXT_CSD_SANITIZE_START, 1, timeout); if (ret) { fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n", 1, EXT_CSD_SANITIZE_START, device); @@ -2153,8 +2275,10 @@ } /* Check RPMB response */ - if (frame_out.result != 0) + if (frame_out.result != 0) { + *cnt = 0; return be16toh(frame_out.result); + } *cnt = be32toh(frame_out.write_counter); @@ -2500,7 +2624,7 @@ device); exit(1); } - ret = write_extcsd_value(fd, EXT_CSD_CACHE_CTRL, value); + ret = write_extcsd_value(fd, EXT_CSD_CACHE_CTRL, value, 0); if (ret) { fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n", @@ -2575,6 +2699,18 @@ if (ret) perror("Erase multi-cmd ioctl"); + /* Does not work for SPI cards */ + if (multi_cmd->cmds[1].response[0] & R1_ERASE_PARAM) { + fprintf(stderr, "Erase start response: 0x%08x\n", + multi_cmd->cmds[0].response[0]); + ret = -EIO; + } + if (multi_cmd->cmds[2].response[0] & R1_ERASE_SEQ_ERROR) { + fprintf(stderr, "Erase response: 0x%08x\n", + multi_cmd->cmds[2].response[0]); + ret = -EIO; + } + free(multi_cmd); return ret; } @@ -2680,10 +2816,8 @@ __u8 *buf = NULL; __u32 arg; off_t fw_size; - ssize_t chunk_size; char *device; struct mmc_ioc_multi_cmd *multi_cmd = NULL; - __u32 blocks = 1; if (nargs != 3) { fprintf(stderr, "Usage: ffu <image name> </path/to/mmcblkX> \n"); @@ -2741,15 +2875,13 @@ goto out; } + /* ensure fw is multiple of native sector size */ sect_size = (ext_csd[EXT_CSD_DATA_SECTOR_SIZE] == 0) ? 512 : 4096; if (fw_size % sect_size) { fprintf(stderr, "Firmware data size (%jd) is not aligned!\n", (intmax_t)fw_size); 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 | @@ -2772,13 +2904,17 @@ /* send block count */ multi_cmd->cmds[1].opcode = MMC_SET_BLOCK_COUNT; - multi_cmd->cmds[1].arg = blocks; + multi_cmd->cmds[1].arg = fw_size / 512; multi_cmd->cmds[1].flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; /* send image chunk */ multi_cmd->cmds[2].opcode = MMC_WRITE_MULTIPLE_BLOCK; - multi_cmd->cmds[2].blksz = sect_size; - multi_cmd->cmds[2].blocks = blocks; + /* + * blksz and blocks essentially do not matter, as long as the product + * is fw_size, but some hosts don't handle larger blksz well. + */ + multi_cmd->cmds[2].blksz = 512; + multi_cmd->cmds[2].blocks = fw_size / 512; 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; @@ -2793,45 +2929,54 @@ 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 */ + /* read firmware */ lseek(img_fd, 0, SEEK_SET); - chunk_size = read(img_fd, buf, fw_size); + if (read(img_fd, buf, fw_size) != fw_size) { + perror("Could not read the firmware file: "); + ret = -ENOSPC; + goto out; + } - if (chunk_size > 0) { - /* send ioctl with multi-cmd */ - ret = ioctl(dev_fd, MMC_IOC_MULTI_CMD, multi_cmd); +do_retry: + /* 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[3]); - goto out; - } + 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[3]); + goto out; + } - ret = read_extcsd(dev_fd, ext_csd); - if (ret) { - fprintf(stderr, "Could not read EXT_CSD from %s\n", device); - goto out; - } + /* + * By spec - check if mode operation codes are supported in ffu features, + * if not then skip checking number of sectors programmed after install + */ + if (!ext_csd[EXT_CSD_FFU_FEATURES]) { + fprintf(stderr, "Please reboot to complete firmware installation on %s\n", device); + ret = 0; + goto out; + } - /* Test if we need to restart the download */ - sect_done = ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG_0] | - ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG_1] << 8 | - ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG_2] << 16 | - ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG_3] << 24; - /* By spec, host should re-start download from the first sector if sect_done is 0 */ - if (sect_done == 0) { - if (retry > 0) { - retry--; - fprintf(stderr, "Programming failed. Retrying... (%d)\n", retry); - goto do_retry; - } - fprintf(stderr, "Programming failed! Aborting...\n"); - goto out; - } else { - fprintf(stderr, "Programmed %d/%jd bytes\r", sect_done * sect_size, (intmax_t)fw_size); + ret = read_extcsd(dev_fd, ext_csd); + if (ret) { + fprintf(stderr, "Could not read EXT_CSD from %s\n", device); + goto out; + } + + /* Test if we need to restart the download */ + sect_done = ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG_0] | + ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG_1] << 8 | + ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG_2] << 16 | + ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG_3] << 24; + /* By spec, host should re-start download from the first sector if sect_done is 0 */ + if (sect_done == 0) { + if (retry--) { + fprintf(stderr, "Programming failed. Retrying... (%d)\n", retry); + goto do_retry; } + fprintf(stderr, "Programming failed! Aborting...\n"); + goto out; } if ((sect_done * sect_size) == fw_size) { @@ -2843,49 +2988,44 @@ goto out; } - /* check mode operation for ffu install*/ - if (!ext_csd[EXT_CSD_FFU_FEATURES]) { - fprintf(stderr, "Please reboot to complete firmware installation on %s\n", device); - } else { - fprintf(stderr, "Installing firmware on %s...\n", device); - /* Re-enter ffu mode and install the firmware */ - multi_cmd->num_of_cmds = 2; - - /* set ext_csd to install mode */ - multi_cmd->cmds[1].opcode = MMC_SWITCH; - multi_cmd->cmds[1].blksz = 0; - multi_cmd->cmds[1].blocks = 0; - multi_cmd->cmds[1].arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | - (EXT_CSD_MODE_OPERATION_CODES << 16) | - (EXT_CSD_FFU_INSTALL << 8) | - EXT_CSD_CMD_SET_NORMAL; - multi_cmd->cmds[1].flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; - multi_cmd->cmds[1].write_flag = 1; + fprintf(stderr, "Installing firmware on %s...\n", device); + /* Re-enter ffu mode and install the firmware */ + multi_cmd->num_of_cmds = 2; + + /* set ext_csd to install mode */ + multi_cmd->cmds[1].opcode = MMC_SWITCH; + multi_cmd->cmds[1].blksz = 0; + multi_cmd->cmds[1].blocks = 0; + multi_cmd->cmds[1].arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_MODE_OPERATION_CODES << 16) | + (EXT_CSD_FFU_INSTALL << 8) | + EXT_CSD_CMD_SET_NORMAL; + multi_cmd->cmds[1].flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + multi_cmd->cmds[1].write_flag = 1; - /* send ioctl with multi-cmd */ - ret = ioctl(dev_fd, MMC_IOC_MULTI_CMD, multi_cmd); + /* send ioctl with multi-cmd */ + ret = ioctl(dev_fd, MMC_IOC_MULTI_CMD, multi_cmd); - 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[3]); - goto out; - } + 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[3]); + goto out; + } - ret = read_extcsd(dev_fd, ext_csd); - if (ret) { - fprintf(stderr, "Could not read EXT_CSD from %s\n", device); - goto out; - } + ret = read_extcsd(dev_fd, ext_csd); + if (ret) { + fprintf(stderr, "Could not read EXT_CSD from %s\n", device); + goto out; + } - /* return status */ - ret = ext_csd[EXT_CSD_FFU_STATUS]; - if (ret) { - fprintf(stderr, "%s: error %d during FFU install:\n", device, ret); - goto out; - } else { - fprintf(stderr, "FFU finished successfully\n"); - } + /* return status */ + ret = ext_csd[EXT_CSD_FFU_STATUS]; + if (ret) { + fprintf(stderr, "%s: error %d during FFU install:\n", device, ret); + goto out; + } else { + fprintf(stderr, "FFU finished successfully\n"); } out: @@ -2896,3 +3036,214 @@ return ret; #endif } + +int do_general_cmd_read(int nargs, char **argv) +{ + int dev_fd; + char *device; + char *endptr; + __u8 buf[512]; + __u32 arg = 0x01; + int ret = -EINVAL, i; + struct mmc_ioc_cmd idata; + + if (nargs != 2 && nargs != 3) { + fprintf(stderr, "Usage: gen_cmd read </path/to/mmcblkX> [arg]\n"); + exit(1); + } + + device = argv[1]; + dev_fd = open(device, O_RDWR); + if (dev_fd < 0) { + perror("device open failed"); + exit(1); + } + + /* arg is specified */ + if (nargs == 3) { + arg = strtol(argv[2], &endptr, 16); + if (errno != 0 || *endptr != '\0' || !(arg & 0x1)) { + fprintf(stderr, "Wrong ARG, it should be Hex number and bit0 must be 1\n"); + goto out; + } + } + + memset(&idata, 0, sizeof(idata)); + idata.write_flag = 0; + idata.opcode = MMC_GEN_CMD; + idata.arg = arg; + idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + idata.blksz = 512; + idata.blocks = 1; + mmc_ioc_cmd_set_data(idata, buf); + + ret = ioctl(dev_fd, MMC_IOC_CMD, &idata); + if (ret) { + perror("ioctl"); + goto out; + } + + printf("Data:\n"); + for (i = 0; i < 512; i++) { + printf("%2x ", buf[i]); + if ((i + 1) % 16 == 0) + printf("\n"); + } +out: + close(dev_fd); + return ret; +} + +static void issue_cmd0(char *device, __u32 arg) +{ + struct mmc_ioc_cmd idata; + int fd; + + fd = open(device, O_RDWR); + if (fd < 0) { + perror("open"); + exit(1); + } + + memset(&idata, 0, sizeof(idata)); + idata.opcode = MMC_GO_IDLE_STATE; + idata.arg = arg; + idata.flags = MMC_RSP_NONE | MMC_CMD_BC; + + /* No need to check for error, it is expected */ + ioctl(fd, MMC_IOC_CMD, &idata); + close(fd); +} + +int do_softreset(int nargs, char **argv) +{ + char *device; + + if (nargs != 2) { + fprintf(stderr, "Usage: mmc softreset </path/to/mmcblkX>\n"); + exit(1); + } + + device = argv[1]; + issue_cmd0(device, MMC_GO_IDLE_STATE_ARG); + + return 0; +} + +int do_preidle(int nargs, char **argv) +{ + char *device; + + if (nargs != 2) { + fprintf(stderr, "Usage: mmc preidle </path/to/mmcblkX>\n"); + exit(1); + } + + device = argv[1]; + issue_cmd0(device, MMC_GO_PRE_IDLE_STATE_ARG); + + return 0; +} + +int do_alt_boot_op(int nargs, char **argv) +{ + int fd, ret, boot_data_fd; + char *device, *boot_data_file; + struct mmc_ioc_multi_cmd *mioc; + __u8 ext_csd[512]; + __u8 *boot_buf; + unsigned int boot_blocks, ext_csd_boot_size; + + if (nargs != 3) { + fprintf(stderr, "Usage: mmc boot_op <boot_data_file> </path/to/mmcblkX>\n"); + exit(1); + } + boot_data_file = argv[1]; + device = argv[2]; + + fd = open(device, O_RDWR); + if (fd < 0) { + perror("open device"); + exit(1); + } + + ret = read_extcsd(fd, ext_csd); + if (ret) { + perror("read extcsd"); + goto dev_fd_close; + } + if (!(ext_csd[EXT_CSD_BOOT_INFO] & EXT_CSD_BOOT_INFO_ALT)) { + ret = -EINVAL; + perror("Card does not support alternative boot mode"); + goto dev_fd_close; + } + if (ext_csd[EXT_CSD_PART_CONFIG] & EXT_CSD_PART_CONFIG_ACC_ACK) { + ret = -EINVAL; + perror("Boot Ack must not be enabled"); + goto dev_fd_close; + } + ext_csd_boot_size = ext_csd[EXT_CSD_BOOT_MULT] * 128 * 1024; + boot_blocks = ext_csd_boot_size / 512; + if (ext_csd_boot_size > MMC_IOC_MAX_BYTES) { + printf("Boot partition size is bigger than IOCTL limit, limiting to 512K\n"); + boot_blocks = MMC_IOC_MAX_BYTES / 512; + } + + boot_data_fd = open(boot_data_file, O_WRONLY | O_CREAT, 0644); + if (boot_data_fd < 0) { + perror("open boot data file"); + ret = 1; + goto boot_data_close; + } + + boot_buf = calloc(1, sizeof(__u8) * boot_blocks * 512); + mioc = calloc(1, sizeof(struct mmc_ioc_multi_cmd) + + 2 * sizeof(struct mmc_ioc_cmd)); + if (!mioc || !boot_buf) { + perror("Failed to allocate memory"); + ret = -ENOMEM; + goto alloced_error; + } + + mioc->num_of_cmds = 2; + mioc->cmds[0].opcode = MMC_GO_IDLE_STATE; + mioc->cmds[0].arg = MMC_GO_PRE_IDLE_STATE_ARG; + mioc->cmds[0].flags = MMC_RSP_NONE | MMC_CMD_AC; + mioc->cmds[0].write_flag = 0; + + mioc->cmds[1].opcode = MMC_GO_IDLE_STATE; + mioc->cmds[1].arg = MMC_BOOT_INITIATION_ARG; + mioc->cmds[1].flags = MMC_RSP_NONE | MMC_CMD_ADTC; + mioc->cmds[1].write_flag = 0; + mioc->cmds[1].blksz = 512; + mioc->cmds[1].blocks = boot_blocks; + /* Access time of boot part differs wildly, spec mandates 1s */ + mioc->cmds[1].data_timeout_ns = 2 * 1000 * 1000 * 1000; + mmc_ioc_cmd_set_data(mioc->cmds[1], boot_buf); + + ret = ioctl(fd, MMC_IOC_MULTI_CMD, mioc); + if (ret) { + perror("multi-cmd ioctl error\n"); + goto alloced_error; + } + + ret = DO_IO(write, boot_data_fd, boot_buf, boot_blocks * 512); + if (ret < 0) { + perror("Write error\n"); + goto alloced_error; + } + ret = 0; + +alloced_error: + if (mioc) + free(mioc); + if (boot_buf) + free(boot_buf); +boot_data_close: + close(boot_data_fd); +dev_fd_close: + close(fd); + if (ret) + exit(1); + return 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmc-utils-0.1+git.20220208/mmc_cmds.h new/mmc-utils-0.1+git.20230209/mmc_cmds.h --- old/mmc-utils-0.1+git.20220208/mmc_cmds.h 2022-02-08 16:15:35.000000000 +0100 +++ new/mmc-utils-0.1+git.20230209/mmc_cmds.h 2023-02-09 15:16:51.000000000 +0100 @@ -46,3 +46,7 @@ int do_read_cid(int argc, char **argv); int do_read_csd(int argc, char **argv); int do_erase(int nargs, char **argv); +int do_general_cmd_read(int nargs, char **argv); +int do_softreset(int nargs, char **argv); +int do_preidle(int nargs, char **argv); +int do_alt_boot_op(int nargs, char **argv); ++++++ mmc-utils.obsinfo ++++++ --- /var/tmp/diff_new_pack.UbayAV/_old 2023-03-24 15:21:51.835339328 +0100 +++ /var/tmp/diff_new_pack.UbayAV/_new 2023-03-24 15:21:51.839339349 +0100 @@ -1,5 +1,5 @@ name: mmc-utils -version: 0.1+git.20220208 -mtime: 1644333335 -commit: 4637a7c0df49ba349f9f0e4ab0828133fc06cc81 +version: 0.1+git.20230209 +mtime: 1675952211 +commit: d4c2910981ff99b983734426dfa99632fb81ac6b
