This change adds support to invoke Samsung eMMC 4.5 field firmware update (ffu) process. New command was added: "emmc45 ffu". Samsung eMMC 4.5 FFU protocol is similar with eMMC 5.0 FFU without MODE_OPERATION. It uses the different EXT_CSD offset. This patch depends on patch mmc-utils: Support-sending-eMMC-v5.0 committed by Avi Shchislowski <avi.shchislowski@xxxxxxxxxxx> and mmc: Support FFU for Samsung eMMC v4.5 committed by Seunguk Shin <seunguk.shin@xxxxxxxxxxx> --- mmc.c | 5 ++++ mmc.h | 1 + mmc_cmds.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mmc_cmds.h | 1 + 4 files changed, 94 insertions(+) diff --git a/mmc.c b/mmc.c index 7234953..44aaf6d 100644 --- a/mmc.c +++ b/mmc.c @@ -115,6 +115,11 @@ static struct Command commands[] = { "run eMMC 5.0 Field firmware update.\n.", NULL }, + { do_emmc45_ffu, -2, + "emmc45 ffu", "<image path> <device>\n" + "run eMMC 4.5 Field firmware update for samsung.\n.", + NULL + }, { 0, 0, 0, 0 } }; diff --git a/mmc.h b/mmc.h index 19eaaba..ca4b70b 100644 --- a/mmc.h +++ b/mmc.h @@ -86,6 +86,7 @@ #define FFU_DWONLOAD_OP 302 #define FFU_INSTALL_OP 303 +#define FFU_SAMSUNG45_OP 304 /* * EXT_CSD field definitions diff --git a/mmc_cmds.c b/mmc_cmds.c index f667d10..17e50d8 100644 --- a/mmc_cmds.c +++ b/mmc_cmds.c @@ -1271,3 +1271,90 @@ exit: return ret; } +static int ffu_execute(int fw_fd, int mmc_fd) +{ + int ret = 0; + struct mmc_ioc_cmd mmc_ioc_cmd; + char data_buff[MMC_IOC_MAX_BYTES]; + int file_size; + int data_length; + + memset(data_buff, 0, sizeof(data_buff)); + /* get file size */ + file_size = lseek(fw_fd, 0, SEEK_END); + if (file_size < 0) { + ret = -1; + perror("seek file error \n"); + goto exit; + } + + lseek(fw_fd, 0, SEEK_SET); + + if (file_size > MMC_IOC_MAX_BYTES) { + ret = -1; + perror("firmware file size error \n"); + goto exit; + } else { + /* Read FW data from file */ + data_length = read(fw_fd, data_buff, file_size); + if (data_length == -1) { + ret = -1; + goto exit; + } + /* prepare and send ioctl */ + memset(&mmc_ioc_cmd, 0, sizeof(mmc_ioc_cmd)); + mmc_ioc_cmd.opcode = FFU_SAMSUNG45_OP; + mmc_ioc_cmd.blksz = CARD_BLOCK_SIZE; + mmc_ioc_cmd.blocks = (data_length + mmc_ioc_cmd.blksz - 1) / + mmc_ioc_cmd.blksz; + mmc_ioc_cmd.arg = 0; + mmc_ioc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + mmc_ioc_cmd.write_flag = 1; + mmc_ioc_cmd_set_data(mmc_ioc_cmd, data_buff); + ret = ioctl(mmc_fd, MMC_IOC_CMD, &mmc_ioc_cmd); + + if (ret) { + perror("ioctl FW download"); + goto exit; + } + } + +exit: + + return ret; +} + +int do_emmc45_ffu(int nargs, char **argv) +{ + int fd, fw_fd, ret; + char *device; + + CHECK(nargs != 3, "Usage: ffu <image path> </path/to/mmcblkX> \n", + exit(1)); + + device = argv[2]; + fd = open(device, O_RDWR); + if (fd < 0) { + perror("device open error \n"); + exit(1); + } + + /* open eMMC4.5 firmware image file */ + fw_fd = open(argv[1], O_RDONLY); + if (fw_fd < 0) { + perror("open eMMC4.5 firmware file"); + ret = -1; + goto exit; + } + + ret = ffu_execute(fw_fd, fd); + if (ret) + goto exit; + +exit: + close(fd); + close(fw_fd); + + return ret; +} + diff --git a/mmc_cmds.h b/mmc_cmds.h index 3ff3440..1ab9cd5 100644 --- a/mmc_cmds.h +++ b/mmc_cmds.h @@ -29,3 +29,4 @@ int do_status_get(int nargs, char **argv); int do_enh_area_set(int nargs, char **argv); int do_write_reliability_set(int nargs, char **argv); int do_emmc50_ffu(int nargs, char **argv); +int do_emmc45_ffu(int nargs, char **argv); -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html