Re: [U-Boot] [PATCH V5 1/3] eMMC: add support for operations in RPMB partition

2014-05-23 Thread Pantelis Antoniou
Hi Pierre,

On Apr 24, 2014, at 11:30 AM, Pierre Aubert wrote:

 This patch adds functions for read, write and authentication
 key programming for the Replay Protected Memory Block partition
 in the eMMC.
 
 Signed-off-by: Pierre Aubert p.aub...@staubli.com
 CC: Pantelis Antoniou pa...@antoniou-consulting.com
 ---
 Changes in V5:
 - move changelog to the right place
 - change lib/Makefile for adding sha256 when CONFIG_SUPPORT_EMMC_RPMB is 
  defined
 
 V3, V4: no changes
 
 Changes in V2:
 - use ALLOC_CACHE_ALIGN_BUFFER in rpmb.c instead of a static buffer for the
  RPMB frames.
 
 drivers/mmc/Makefile |1 +
 drivers/mmc/rpmb.c   |  323 ++
 include/mmc.h|   10 ++-
 lib/Makefile |1 +
 4 files changed, 334 insertions(+), 1 deletions(-)
 create mode 100644 drivers/mmc/rpmb.c
 
 diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
 index 931922b..4c6ab9e 100644
 --- a/drivers/mmc/Makefile
 +++ b/drivers/mmc/Makefile
 @@ -30,6 +30,7 @@ obj-$(CONFIG_DWMMC) += dw_mmc.o
 obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
 obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
 obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
 +obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
 else
 diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c
 new file mode 100644
 index 000..05936f5
 --- /dev/null
 +++ b/drivers/mmc/rpmb.c
 @@ -0,0 +1,323 @@
 +/*
 + * Copyright 2014, Staubli Faverges
 + * Pierre Aubert
 + *
 + * eMMC- Replay Protected Memory Block
 + * According to JEDEC Standard No. 84-A441
 + *
 + * SPDX-License-Identifier:  GPL-2.0+
 + */
 +
 +#include config.h
 +#include common.h
 +#include mmc.h
 +#include sha256.h
 +#include mmc_private.h
 +
 +/* Request codes */
 +#define RPMB_REQ_KEY 1
 +#define RPMB_REQ_WCOUNTER2
 +#define RPMB_REQ_WRITE_DATA  3
 +#define RPMB_REQ_READ_DATA   4
 +#define RPMB_REQ_STATUS  5
 +
 +/* Response code */
 +#define RPMB_RESP_KEY0x0100
 +#define RPMB_RESP_WCOUNTER   0x0200
 +#define RPMB_RESP_WRITE_DATA 0x0300
 +#define RPMB_RESP_READ_DATA  0x0400
 +
 +/* Error codes */
 +#define RPMB_OK  0
 +#define RPMB_ERR_GENERAL 1
 +#define RPMB_ERR_AUTH2
 +#define RPMB_ERR_COUNTER 3
 +#define RPMB_ERR_ADDRESS 4
 +#define RPMB_ERR_WRITE   5
 +#define RPMB_ERR_READ6
 +#define RPMB_ERR_KEY 7
 +#define RPMB_ERR_CNT_EXPIRED 0x80
 +#define RPMB_ERR_MSK 0x7
 +
 +/* Sizes of RPMB data frame */
 +#define RPMB_SZ_STUFF196
 +#define RPMB_SZ_MAC  32
 +#define RPMB_SZ_DATA 256
 +#define RPMB_SZ_NONCE16
 +
 +#define SHA256_BLOCK_SIZE64
 +
 +/* Error messages */
 +static const char * const rpmb_err_msg[] = {
 + ,
 + General failure,
 + Authentication failure,
 + Counter failure,
 + Address failure,
 + Write failure,
 + Read failure,
 + Authentication key not yet programmed,
 +};
 +
 +
 +/* Structure of RPMB data frame. */
 +struct s_rpmb {
 + unsigned char stuff[RPMB_SZ_STUFF];
 + unsigned char mac[RPMB_SZ_MAC];
 + unsigned char data[RPMB_SZ_DATA];
 + unsigned char nonce[RPMB_SZ_NONCE];
 + unsigned long write_counter;
 + unsigned short address;
 + unsigned short block_count;
 + unsigned short result;
 + unsigned short request;
 +};
 +
 +static int mmc_set_blockcount(struct mmc *mmc, unsigned int blockcount,
 +   bool is_rel_write)
 +{
 + struct mmc_cmd cmd = {0};
 +
 + cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
 + cmd.cmdarg = blockcount  0x;
 + if (is_rel_write)
 + cmd.cmdarg |= 1  31;
 + cmd.resp_type = MMC_RSP_R1;
 +
 + return mmc_send_cmd(mmc, cmd, NULL);
 +}
 +static int mmc_rpmb_request(struct mmc *mmc, const struct s_rpmb *s,
 + unsigned int count, bool is_rel_write)
 +{
 + struct mmc_cmd cmd = {0};
 + struct mmc_data data;
 + int ret;
 +
 + ret = mmc_set_blockcount(mmc, count, is_rel_write);
 + if (ret) {
 +#ifdef CONFIG_MMC_RPMB_TRACE
 + printf(%s:mmc_set_blockcount- %d\n, __func__, ret);
 +#endif
 + return 1;
 + }
 +
 + cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
 + cmd.cmdarg = 0;
 + cmd.resp_type = MMC_RSP_R1b;
 +
 + data.src = (const char *)s;
 + data.blocks = 1;
 + data.blocksize = MMC_MAX_BLOCK_LEN;
 + data.flags = MMC_DATA_WRITE;
 +
 + ret = mmc_send_cmd(mmc, cmd, data);
 + if (ret) {
 +#ifdef CONFIG_MMC_RPMB_TRACE
 + printf(%s:mmc_send_cmd- %d\n, __func__, ret);
 +#endif
 + return 1;
 + }
 + return 0;
 +}
 +static int mmc_rpmb_response(struct mmc *mmc, struct s_rpmb *s,
 +  unsigned short expected)
 +{
 + struct mmc_cmd cmd = {0};
 + struct mmc_data data;
 + int ret;
 +
 + ret = 

[U-Boot] [PATCH V5 1/3] eMMC: add support for operations in RPMB partition

2014-04-24 Thread Pierre Aubert
This patch adds functions for read, write and authentication
key programming for the Replay Protected Memory Block partition
in the eMMC.

Signed-off-by: Pierre Aubert p.aub...@staubli.com
CC: Pantelis Antoniou pa...@antoniou-consulting.com
---
Changes in V5:
- move changelog to the right place
- change lib/Makefile for adding sha256 when CONFIG_SUPPORT_EMMC_RPMB is 
  defined

V3, V4: no changes

Changes in V2:
- use ALLOC_CACHE_ALIGN_BUFFER in rpmb.c instead of a static buffer for the
  RPMB frames.

 drivers/mmc/Makefile |1 +
 drivers/mmc/rpmb.c   |  323 ++
 include/mmc.h|   10 ++-
 lib/Makefile |1 +
 4 files changed, 334 insertions(+), 1 deletions(-)
 create mode 100644 drivers/mmc/rpmb.c

diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 931922b..4c6ab9e 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_DWMMC) += dw_mmc.o
 obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
 obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
 obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
+obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
 else
diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c
new file mode 100644
index 000..05936f5
--- /dev/null
+++ b/drivers/mmc/rpmb.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright 2014, Staubli Faverges
+ * Pierre Aubert
+ *
+ * eMMC- Replay Protected Memory Block
+ * According to JEDEC Standard No. 84-A441
+ *
+ * SPDX-License-Identifier:GPL-2.0+
+ */
+
+#include config.h
+#include common.h
+#include mmc.h
+#include sha256.h
+#include mmc_private.h
+
+/* Request codes */
+#define RPMB_REQ_KEY   1
+#define RPMB_REQ_WCOUNTER  2
+#define RPMB_REQ_WRITE_DATA3
+#define RPMB_REQ_READ_DATA 4
+#define RPMB_REQ_STATUS5
+
+/* Response code */
+#define RPMB_RESP_KEY  0x0100
+#define RPMB_RESP_WCOUNTER 0x0200
+#define RPMB_RESP_WRITE_DATA   0x0300
+#define RPMB_RESP_READ_DATA0x0400
+
+/* Error codes */
+#define RPMB_OK0
+#define RPMB_ERR_GENERAL   1
+#define RPMB_ERR_AUTH  2
+#define RPMB_ERR_COUNTER   3
+#define RPMB_ERR_ADDRESS   4
+#define RPMB_ERR_WRITE 5
+#define RPMB_ERR_READ  6
+#define RPMB_ERR_KEY   7
+#define RPMB_ERR_CNT_EXPIRED   0x80
+#define RPMB_ERR_MSK   0x7
+
+/* Sizes of RPMB data frame */
+#define RPMB_SZ_STUFF  196
+#define RPMB_SZ_MAC32
+#define RPMB_SZ_DATA   256
+#define RPMB_SZ_NONCE  16
+
+#define SHA256_BLOCK_SIZE  64
+
+/* Error messages */
+static const char * const rpmb_err_msg[] = {
+   ,
+   General failure,
+   Authentication failure,
+   Counter failure,
+   Address failure,
+   Write failure,
+   Read failure,
+   Authentication key not yet programmed,
+};
+
+
+/* Structure of RPMB data frame. */
+struct s_rpmb {
+   unsigned char stuff[RPMB_SZ_STUFF];
+   unsigned char mac[RPMB_SZ_MAC];
+   unsigned char data[RPMB_SZ_DATA];
+   unsigned char nonce[RPMB_SZ_NONCE];
+   unsigned long write_counter;
+   unsigned short address;
+   unsigned short block_count;
+   unsigned short result;
+   unsigned short request;
+};
+
+static int mmc_set_blockcount(struct mmc *mmc, unsigned int blockcount,
+ bool is_rel_write)
+{
+   struct mmc_cmd cmd = {0};
+
+   cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
+   cmd.cmdarg = blockcount  0x;
+   if (is_rel_write)
+   cmd.cmdarg |= 1  31;
+   cmd.resp_type = MMC_RSP_R1;
+
+   return mmc_send_cmd(mmc, cmd, NULL);
+}
+static int mmc_rpmb_request(struct mmc *mmc, const struct s_rpmb *s,
+   unsigned int count, bool is_rel_write)
+{
+   struct mmc_cmd cmd = {0};
+   struct mmc_data data;
+   int ret;
+
+   ret = mmc_set_blockcount(mmc, count, is_rel_write);
+   if (ret) {
+#ifdef CONFIG_MMC_RPMB_TRACE
+   printf(%s:mmc_set_blockcount- %d\n, __func__, ret);
+#endif
+   return 1;
+   }
+
+   cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
+   cmd.cmdarg = 0;
+   cmd.resp_type = MMC_RSP_R1b;
+
+   data.src = (const char *)s;
+   data.blocks = 1;
+   data.blocksize = MMC_MAX_BLOCK_LEN;
+   data.flags = MMC_DATA_WRITE;
+
+   ret = mmc_send_cmd(mmc, cmd, data);
+   if (ret) {
+#ifdef CONFIG_MMC_RPMB_TRACE
+   printf(%s:mmc_send_cmd- %d\n, __func__, ret);
+#endif
+   return 1;
+   }
+   return 0;
+}
+static int mmc_rpmb_response(struct mmc *mmc, struct s_rpmb *s,
+unsigned short expected)
+{
+   struct mmc_cmd cmd = {0};
+   struct mmc_data data;
+   int ret;
+
+   ret = mmc_set_blockcount(mmc, 1, false);
+   if (ret) {
+#ifdef CONFIG_MMC_RPMB_TRACE
+   printf(%s:mmc_set_blockcount- %d\n,