From: Bean Huo <beanhuo@xxxxxxxxxx> FFU mode 4 initiates firmware download with CMD6 to enter FFU mode, followed by CMD24 for single-block write. After each block is written, CMD6 is used to exit FFU mode. Signed-off-by: Bean Huo <beanhuo@xxxxxxxxxx> --- mmc.c | 3 ++- mmc_ffu.c | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/mmc.c b/mmc.c index 73b694d..2fdfdce 100644 --- a/mmc.c +++ b/mmc.c @@ -235,7 +235,8 @@ static struct Command commands[] = { "[-m <ffu_mode>] Optional, provides five firmware bundle download command modes:\n" " -m 1: Default mode (CMD6+CMD23+CMD25+CMD6 repeated), may exit FFU mode if the firmware size exceeds chunk size.\n" " -m 2: FFU mode 2 (enter FFU mode, CMD23+CMD25 repeated, exit FFU mode), stays in FFU mode until firmware download completes.\n" - " -m 3: FFU mode 3 (enter FFU mode, CMD25+CMD12 repeated, exit FFU mode), stays in FFU mode until firmware download completes.\n", + " -m 3: FFU mode 3 (enter FFU mode, CMD25+CMD12 repeated, exit FFU mode), stays in FFU mode until firmware download completes.\n" + " -m 4: FFU mode 4 (CMD6+CMD24+CMD6 repeated), exits FFU mode after each cycle.\n", NULL }, { do_erase, -4, diff --git a/mmc_ffu.c b/mmc_ffu.c index 7193a67..d342c7b 100644 --- a/mmc_ffu.c +++ b/mmc_ffu.c @@ -55,6 +55,11 @@ static void set_ffu_download_cmd(struct mmc_ioc_multi_cmd *multi_cmd, __u8 *ext_ set_single_cmd(&multi_cmd->cmds[1], MMC_STOP_TRANSMISSION, 0, 0, 0); multi_cmd->cmds[1].flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + } else if (ffu_mode == 4) { + fill_switch_cmd(&multi_cmd->cmds[0], EXT_CSD_MODE_CONFIG, EXT_CSD_FFU_MODE); + set_single_cmd(&multi_cmd->cmds[1], MMC_WRITE_BLOCK, 1, 1, arg); + mmc_ioc_cmd_set_data(multi_cmd->cmds[1], buf + offset); + fill_switch_cmd(&multi_cmd->cmds[2], EXT_CSD_MODE_CONFIG, EXT_CSD_NORMAL_MODE); } } @@ -141,8 +146,10 @@ static int do_ffu_download(int *dev_fd, __u8 *ext_csd, __u8 *fw_buf, off_t fw_si return -EINVAL; } - if (ffu_mode != 1) /* only in FFU mode 1, mmc_ioc_multi_cmd contains 4 commands */ + if (ffu_mode == 2 || ffu_mode == 3) /* only in FFU mode 1, mmc_ioc_multi_cmd contains 4 commands */ num_of_cmds = 2; + else if (ffu_mode == 4) + num_of_cmds = 3; /* allocate maximum required */ multi_cmd = calloc(1, sizeof(struct mmc_ioc_multi_cmd) + num_of_cmds * sizeof(struct mmc_ioc_cmd)); @@ -240,7 +247,7 @@ int do_ffu(int nargs, char **argv) break; case 'm': ffu_mode = atoi(optarg); - if (ffu_mode > 3) { + if (ffu_mode > 4) { fprintf(stderr, "Unsupported ffu mode `%d'.\n", ffu_mode); abort(); } @@ -254,6 +261,11 @@ int do_ffu(int nargs, char **argv) abort(); } } + + if (ffu_mode ==4) + /* FFU mode 4 uses CMD24, the write is limited to single-block operations*/ + default_chunk = 512; + fprintf(stderr, "eMMC Devie: %s, fw %s, FFU mode %d, chunk size: %d\n", device, fw_img, ffu_mode, default_chunk); dev_fd = open(device, O_RDWR); -- 2.34.1