diff --git a/mmc.c b/mmc.c
index 926e92f..a01852d 100644
--- a/mmc.c
+++ b/mmc.c
@@ -36,9 +36,9 @@ struct Command {
                                   if >= 0, number of arguments,
                                   if < 0, _minimum_ number of arguments */
        char    *verb;          /* verb */
-       char    *help;          /* help lines; from the 2nd line onward they
+       char    *help;          /* help lines; from the 2nd line onward they
                                    are automatically indented */
-        char    *adv_help;      /* advanced help message; from the 2nd line
+        char    *adv_help;      /* advanced help message; from the 2nd line
                                    onward they are automatically indented */

        /* the following fields are run-time filled by the program */ @@ -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,
+       "emmc50 ffu", "<image path> <device>\n"
+         "run eMMC 5.0 Field firmware update.\n.",
+         NULL
+       },
        { 0, 0, 0, 0 }
 };

@@ -362,7 +367,7 @@ static int parse_args(int argc, char **argv,
                        matchcmd->verb, matchcmd->nargs);
                        return -2;
        }
-
+
         if (prepare_args( nargs_, args_, prgname, matchcmd )){
                 fprintf(stderr, "ERROR: not enough memory\\n");
                return -20;
diff --git a/mmc.h b/mmc.h
index 9871d62..3be6db0 100644
--- a/mmc.h
+++ b/mmc.h
@@ -80,6 +80,14 @@
 #define BKOPS_ENABLE   (1<<0)

 /*
+ * sector size
+*/
+#define CARD_BLOCK_SIZE        512
+
+#define FFU_DWONLOAD_OP        302
+#define FFU_INSTALL_OP 303
+
+/*
  * EXT_CSD field definitions
  */
 #define EXT_CSD_HPI_SUPP               (1<<0)
diff --git a/mmc_cmds.c b/mmc_cmds.c
index b8afa74..24c4a6b 100644
--- a/mmc_cmds.c
+++ b/mmc_cmds.c
@@ -1163,3 +1163,112 @@ int do_sanitize(int nargs, char **argv)

 }

+static int ffu_download_image(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 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);
+       do {
+               size = (file_size > MMC_IOC_MAX_BYTES) ?
+                               MMC_IOC_MAX_BYTES : file_size;
+               /* Read FW data from file */
+               data_length = read(fw_fd, data_buff, 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_DWONLOAD_OP;
+               mmc_ioc_cmd.blksz = CARD_BLOCK_SIZE;
+               mmc_ioc_cmd.blocks = data_length / 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;
+               }
+
+               file_size = file_size - size;
+               printf("firmware file loading, remaining:   %d\n", file_size);
+       } while (file_size > 0);
+
+exit:
+
+       return ret;
+}
+
+static int ffu_install(int mmc_fd)
+{
+       int ret;
+       struct mmc_ioc_cmd mmc_ioc_cmd;
+
+       memset(&mmc_ioc_cmd, 0, sizeof(mmc_ioc_cmd));
+       mmc_ioc_cmd.opcode = FFU_INSTALL_OP;
+       mmc_ioc_cmd.blksz = CARD_BLOCK_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);
+       if (ret)
+               perror("ioctl install");
+
+       printf("ffu_install ret %d \n", ret);
+       return ret;
+}
+
+int do_emmc50_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("open");
+               exit(1);
+       }
+
+       /* open eMMC5.0 firmware image file */
+       fw_fd = open(argv[1], O_RDONLY);
+       if (fw_fd < 0) {
+               perror("open eMMC5.0 firmware file");
+               ret = -1;
+               goto exit;
+       }
+
+       ret = ffu_download_image(fw_fd, fd);
+       if (ret)
+               goto exit;
+
+       ret = ffu_install(fd);
+       if (ret)
+               goto exit;
+
+exit:
+       close(fd);
+       close(fw_fd);
+
+       return ret;
+}
diff --git a/mmc_cmds.h b/mmc_cmds.h
index f06cc10..77a6cb8 100644
--- a/mmc_cmds.h
+++ b/mmc_cmds.h
@@ -28,3 +28,5 @@ 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);
+
--
1.7.5.4


