Re: [U-Boot] [PATCH V5 1/3] eMMC: add support for operations in RPMB partition
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
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,