Firmware Update (FFU) New command was add: "do_emmc50_ffu". This patch depends on patch mmc: Support-FFU-for-eMMC-v5.0 Committed by Avi Shchislowski <avi.shchislowski@xxxxxxxxxxx> FFU will be done in two steps. Two new IOCTL codes will be sent to the driver in order to operate FFU code: 1. FFU_DWONLOAD_OP (sent in ffu_download_image() function) 2. FFU_INSTALL_OP (sent in ffu_install() function) Signed-off-by: Avi Shchislowski <avi.shchislowski@xxxxxxxxxxx> Signed-off-by: Alex Lemberg <alex.lemberg@xxxxxxxxxxx> diff --git a/mmc.c b/mmc.c index 926e92f..ee23cd3 100644 --- a/mmc.c +++ b/mmc.c @@ -110,6 +110,11 @@ static struct Command commands[] = { "Send Sanitize command to the <device>.\nThis will delete the unmapped memory region of the device.", NULL }, + { do_emmc50_ffu, -2, + "ffu", "<image name> <device>\n" + "run eMMC 5.0 Field firmware update.\n.", + NULL + }, { 0, 0, 0, 0 } }; diff --git a/mmc.h b/mmc.h index 9871d62..b338e1d 100644 --- a/mmc.h +++ b/mmc.h @@ -64,6 +64,7 @@ #define EXT_CSD_ENH_START_ADDR_2 138 #define EXT_CSD_ENH_START_ADDR_1 137 #define EXT_CSD_ENH_START_ADDR_0 136 +#define EXT_CSD_REV 192 #define EXT_CSD_NATIVE_SECTOR_SIZE 63 /* R */ #define EXT_CSD_USE_NATIVE_SECTOR 62 /* R/W */ #define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ @@ -79,6 +80,9 @@ */ #define BKOPS_ENABLE (1<<0) +#define MMC_FFU_DOWNLOAD_OP 302 +#define MMC_FFU_INSTALL_OP 303 + /* * EXT_CSD field definitions */ diff --git a/mmc_cmds.c b/mmc_cmds.c index b8afa74..71a2ce3 100644 --- a/mmc_cmds.c +++ b/mmc_cmds.c @@ -1142,7 +1142,7 @@ int do_sanitize(int nargs, char **argv) char *device; CHECK(nargs != 2, "Usage: mmc sanitize </path/to/mmcblkX>\n", - exit(1)); + exit(1)); device = argv[1]; @@ -1163,3 +1163,94 @@ int do_sanitize(int nargs, char **argv) } +static int ffu_download_image(char *fname, int mmc_fd, int blk_size) +{ + int ret = 0; + struct mmc_ioc_cmd mmc_ioc_cmd; + char firmware_name[512]; + + memset(firmware_name, 0, sizeof(firmware_name)); + memcpy(firmware_name, fname, strlen(fname)); + + /* prepare and send ioctl */ + memset(&mmc_ioc_cmd, 0, sizeof(mmc_ioc_cmd)); + mmc_ioc_cmd.opcode = MMC_FFU_DOWNLOAD_OP; + mmc_ioc_cmd.blksz = blk_size; + mmc_ioc_cmd.blocks = 1; + 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, firmware_name); + ret = ioctl(mmc_fd, MMC_IOC_CMD, &mmc_ioc_cmd); + if (ret) { + fprintf(stderr, "ioctl FW download error%d\n", ret); + return ret; + } + + return ret; +} + +static int ffu_install(int mmc_fd, int blk_size) +{ + int ret; + struct mmc_ioc_cmd mmc_ioc_cmd; + + memset(&mmc_ioc_cmd, 0, sizeof(mmc_ioc_cmd)); + mmc_ioc_cmd.opcode = MMC_FFU_INSTALL_OP; + mmc_ioc_cmd.blksz = blk_size; + mmc_ioc_cmd.blocks = 0; + mmc_ioc_cmd.arg = 0; + mmc_ioc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + mmc_ioc_cmd.write_flag = 0; + ret = ioctl(mmc_fd, MMC_IOC_CMD, &mmc_ioc_cmd); + + return ret; +} + +int do_emmc50_ffu (int nargs, char **argv) +{ + int fd, ret; + char *device; + char *path; + __u8 ext_csd[512]; + int blk_size; + + CHECK(nargs != 3, "Usage: ffu <image name> </path/to/mmcblkX> \n", + exit(1)); + + device = argv[2]; + fd = open(device, O_RDWR); + if (fd < 0) { + perror("open"); + exit(1); + } + + ret = read_extcsd(fd, ext_csd); + if (ret) { + fprintf(stderr, "Could not read EXT_CSD from %s\n", device); + exit(1); + } + + if (ext_csd[EXT_CSD_REV] < 7) { + fprintf(stderr, "FFU is not supported on device %s\n", device); + exit(1); + } + + blk_size = (ext_csd[EXT_CSD_DATA_SECTOR_SIZE] == 0) ? 512 : 4096; + path = argv[1]; + ret = ffu_download_image(path, fd, blk_size); + if (ret) { + fprintf(stderr, "FFU failed %d\n", ret); + exit(1); + } + + ret = ffu_install(fd, blk_size); + if (ret) { + fprintf(stderr, "FFU failed %d\n", ret); + exit(1); + } + + close(fd); + fprintf(stderr, "FFU finished with status %d \n", ret); + return ret; +} diff --git a/mmc_cmds.h b/mmc_cmds.h index f06cc10..3ff3440 100644 --- a/mmc_cmds.h +++ b/mmc_cmds.h @@ -28,3 +28,4 @@ int do_sanitize(int nargs, char **argv); 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); -- 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