Skip to contentSkip to conversation

mmc-utils: Support sending Samsung eMMC 4.5 FFU

PATCH In review Seunguk Shin 3 participants 3 messages Apr 4, 2014 – Apr 8, 2014 MMC, SD and SDIO

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 mmc-utils: Support sending Samsung eMMC 4.5 FFU

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 <[email protected]> and mmc: Support FFU for Samsung eMMC v4.5 committed by Seunguk Shin <[email protected]>

---
 mmc.c      |  5 ++++
 mmc.h      |  1 +
 mmc_cmds.c | 87
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 mmc_cmds.h |  1 +
 4 files changed, 94 insertions(+)
mmc.c +5 -0
index 7234953..44aaf6d 100644
@@ -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 }
 };
 
mmc.h +1 -0
index 19eaaba..ca4b70b 100644
@@ -86,6 +86,7 @@
 
 #define FFU_DWONLOAD_OP        302
 #define FFU_INSTALL_OP 303
+#define FFU_SAMSUNG45_OP	304
 
 /*
  * EXT_CSD field definitions
mmc_cmds.c +38 -0
index f667d10..17e50d8 100644
@@ -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;
+}
+

mmc_cmds.h +1 -0
index 3ff3440..1ab9cd5 100644
@@ -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);
Signature · 1 line
1.8.3.2
Reviewed-by on v1 1/1
#1 lore raw
Quoted 25 lines · Seunguk Shin

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 <[email protected]> and mmc: Support FFU for Samsung eMMC v4.5 committed by Seunguk Shin <[email protected]>

---
 mmc.c      |  5 ++++
 mmc.h      |  1 +
 mmc_cmds.c | 87
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 mmc_cmds.h |  1 +
 4 files changed, 94 insertions(+)
mmc.c +0 -0
index 7234953..44aaf6d 100644

mmc.c static struct Command commands[] = { · line 119

Quoted 5 lines
mmc.c +2 -0
@@ -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"

I think this is a good starting point and I think we should adopt this patch as-is. Partly because I want to see Seunguk's name _and_ email address "permanently" recorded as the original author. I'm particularly interested in making sure @samsung.com is listed as the original author. :)

I understand this code depends on a patch that hasn't been accepted yet. :) So effectively this might not matter:

Sorry, I'll dump some more thoughts here:
I was originally thinking mmc-utils should be looking at the ext_csd[CSD_REV] to determine which FFU method would be used.

But the kernel knows enough about the device (e.g. eMMC version and MANFID) to select the right FFU method in the IOCTL calls. The user space really only needs "upload this file for FFU".

Is there any reason we wouldn't want to "install" once the FFU has successfully completed?

I reread Avi's previous patches and it's not explained why FFU_INSTALL_OP should be a separate step for user space. If not, the kernel will know when the FFU is complete and can perform "install" automatically. I think it's a good idea to keep the kernel internal implementation as two discrete steps though.

I'm reading "install" to mean issue some magic commands that will trigger the new firmware to start executing on the device.

cheers,
grant

Quoted 130 lines
mmc.c +3 -0
+               "run eMMC 4.5 Field firmware update for samsung.\n.",
+         NULL
+       },
        { 0, 0, 0, 0 }
 };
 
mmc.h +1 -0
index 19eaaba..ca4b70b 100644
@@ -86,6 +86,7 @@
 
 #define FFU_DWONLOAD_OP        302
 #define FFU_INSTALL_OP 303
+#define FFU_SAMSUNG45_OP       304
 
 /*
  * EXT_CSD field definitions
mmc_cmds.c +38 -0
index f667d10..17e50d8 100644
@@ -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_cmds.c +49 -0
+               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;
+}
+
mmc_cmds.h +1 -1
index 3ff3440..1ab9cd5 100644
@@ -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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#2 lore raw

Hi Grant,

Quoted 73 lines

-----Original Message-----
From: [email protected] [mailto:linux-mmc- [email protected]] On Behalf Of Grant Grundler
Sent: Tuesday, April 08, 2014 8:06 AM
To: Seunguk Shin
Cc: [email protected]; Chris Ball; CPGS; Avi Shchislowski; Puthikorn Voravootivat
Subject: Re: [PATCH] mmc-utils: Support sending Samsung eMMC 4.5 FFU

Quoted 14 lines · Seunguk Shin

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 <[email protected]> and mmc:
Support FFU for Samsung eMMC v4.5 committed by Seunguk Shin <[email protected]>

Quoted 5 lines
---
 mmc.c      |  5 ++++
 mmc.h      |  1 +
 mmc_cmds.c | 87

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

mmc.c static struct Command commands[] = { · line 119

Quoted 13 lines
 mmc_cmds.h |  1 +
 4 files changed, 94 insertions(+)
mmc.c +2 -0
index 7234953..44aaf6d 100644
@@ -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"

I think this is a good starting point and I think we should adopt this patch as- is. Partly because I want to see Seunguk's name _and_ email address "permanently" recorded as the original author. I'm particularly interested in making sure @samsung.com is listed as the original author. :)

I understand this code depends on a patch that hasn't been accepted yet. :) So effectively this might not matter:

Sorry, I'll dump some more thoughts here:
I was originally thinking mmc-utils should be looking at the ext_csd[CSD_REV] to determine which FFU method would be used.

But the kernel knows enough about the device (e.g. eMMC version and MANFID) to select the right FFU method in the IOCTL calls. The user space really only needs "upload this file for FFU".

Is there any reason we wouldn't want to "install" once the FFU has successfully completed?

I reread Avi's previous patches and it's not explained why FFU_INSTALL_OP should be a separate step for user space.
If not, the kernel will know when the FFU is complete and can perform "install" automatically. I think it's a good idea to keep the kernel internal implementation as two discrete steps though.

Quoted 6 lines

I'm reading "install" to mean issue some magic commands that will trigger the new firmware to start executing on the device.

cheers,
grant

The FFU flow allows to make reboot (Power Cycle) to eMMC device after completing FW data transfer operation.
This restart operation will trigger the new firmware to start executing on the device.
The reason why we decided to separate FFU to two steps/operations - is getting some platforms more flexibility in running the FFU process (i.e. making reboot after completing FW upload).

Thanks,
Alex & Avi

Quoted 133 lines
Quoted 124 lines
mmc.c +3 -0
+               "run eMMC 4.5 Field firmware update for samsung.\n.",
+         NULL
+       },
        { 0, 0, 0, 0 }
 };
 
mmc.h +1 -0
index 19eaaba..ca4b70b 100644
@@ -86,6 +86,7 @@
 
 #define FFU_DWONLOAD_OP        302
 #define FFU_INSTALL_OP 303
+#define FFU_SAMSUNG45_OP       304
 
 /*
  * EXT_CSD field definitions
mmc_cmds.c +37 -0
index f667d10..17e50d8 100644
@@ -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_cmds.c +48 -0
+               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;
+}
+
mmc_cmds.h +0 -0
index 3ff3440..1ab9cd5 100644
@@ -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

Quoted 3 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected] More

majordomo

Quoted 1 line

info at http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected] More majordomo info at
http://vger.kernel.org/majordomo-info.html