Commit aef913e3 authored by Nikita Maslov's avatar Nikita Maslov Committed by Chris Ball
Browse files

mmc-utils: use MMC_IOC_MULTI_CMD for RPMB access



On some systems which use MMC as a main storage device
it is possible that RPMB commands are mixed with
generic MMC access commands which invalidates RPMB.

This patch uses MMC_IOC_MULTI_CMD.
Signed-off-by: default avatarClément Péron <peron.clem@gmail.com>
Reviewed-by: default avatarAvri Altman <avri.altman@wdc.com>
Signed-off-by: default avatarChris Ball <chris@printf.net>
parent 485b05ec
...@@ -1825,6 +1825,8 @@ int do_sanitize(int nargs, char **argv) ...@@ -1825,6 +1825,8 @@ int do_sanitize(int nargs, char **argv)
ret; \ ret; \
}) })
#define RPMB_MULTI_CMD_MAX_CMDS 3
enum rpmb_op_type { enum rpmb_op_type {
MMC_RPMB_WRITE_KEY = 0x01, MMC_RPMB_WRITE_KEY = 0x01,
MMC_RPMB_READ_CNT = 0x02, MMC_RPMB_READ_CNT = 0x02,
...@@ -1847,6 +1849,17 @@ struct rpmb_frame { ...@@ -1847,6 +1849,17 @@ struct rpmb_frame {
u_int16_t req_resp; u_int16_t req_resp;
}; };
static inline void set_single_cmd(struct mmc_ioc_cmd *ioc, __u32 opcode,
int write_flag, unsigned int blocks)
{
ioc->opcode = opcode;
ioc->write_flag = write_flag;
ioc->arg = 0x0;
ioc->blksz = 512;
ioc->blocks = blocks;
ioc->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
}
/* Performs RPMB operation. /* Performs RPMB operation.
* *
* @fd: RPMB device on which we should perform ioctl command * @fd: RPMB device on which we should perform ioctl command
...@@ -1861,22 +1874,28 @@ static int do_rpmb_op(int fd, ...@@ -1861,22 +1874,28 @@ static int do_rpmb_op(int fd,
struct rpmb_frame *frame_out, struct rpmb_frame *frame_out,
unsigned int out_cnt) unsigned int out_cnt)
{ {
#ifndef MMC_IOC_MULTI_CMD
fprintf(stderr, "mmc-utils has been compiled without MMC_IOC_MULTI_CMD"
" support, needed by RPMB operation.\n");
exit(1);
#else
int err; int err;
u_int16_t rpmb_type; u_int16_t rpmb_type;
struct mmc_ioc_multi_cmd *mioc;
struct mmc_ioc_cmd ioc = { struct mmc_ioc_cmd *ioc;
.arg = 0x0, struct rpmb_frame frame_status = {0};
.blksz = 512,
.blocks = 1,
.write_flag = 1,
.opcode = MMC_WRITE_MULTIPLE_BLOCK,
.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC,
.data_ptr = (uintptr_t)frame_in
};
if (!frame_in || !frame_out || !out_cnt) if (!frame_in || !frame_out || !out_cnt)
return -EINVAL; return -EINVAL;
/* prepare arguments for MMC_IOC_MULTI_CMD ioctl */
mioc = (struct mmc_ioc_multi_cmd *)
malloc(sizeof (struct mmc_ioc_multi_cmd) +
RPMB_MULTI_CMD_MAX_CMDS * sizeof (struct mmc_ioc_cmd));
if (!mioc) {
return -ENOMEM;
}
rpmb_type = be16toh(frame_in->req_resp); rpmb_type = be16toh(frame_in->req_resp);
switch(rpmb_type) { switch(rpmb_type) {
...@@ -1887,33 +1906,23 @@ static int do_rpmb_op(int fd, ...@@ -1887,33 +1906,23 @@ static int do_rpmb_op(int fd,
goto out; goto out;
} }
mioc->num_of_cmds = 3;
/* Write request */ /* Write request */
ioc.write_flag |= (1<<31); ioc = &mioc->cmds[0];
err = ioctl(fd, MMC_IOC_CMD, &ioc); set_single_cmd(ioc, MMC_WRITE_MULTIPLE_BLOCK, (1 << 31) | 1, 1);
if (err < 0) { mmc_ioc_cmd_set_data((*ioc), frame_in);
err = -errno;
goto out;
}
/* Result request */ /* Result request */
memset(frame_out, 0, sizeof(*frame_out)); ioc = &mioc->cmds[1];
frame_out->req_resp = htobe16(MMC_RPMB_READ_RESP); frame_status.req_resp = htobe16(MMC_RPMB_READ_RESP);
ioc.write_flag = 1; set_single_cmd(ioc, MMC_WRITE_MULTIPLE_BLOCK, 1, 1);
ioc.data_ptr = (uintptr_t)frame_out; mmc_ioc_cmd_set_data((*ioc), &frame_status);
err = ioctl(fd, MMC_IOC_CMD, &ioc);
if (err < 0) {
err = -errno;
goto out;
}
/* Get response */ /* Get response */
ioc.write_flag = 0; ioc = &mioc->cmds[2];
ioc.opcode = MMC_READ_MULTIPLE_BLOCK; set_single_cmd(ioc, MMC_READ_MULTIPLE_BLOCK, 0, 1);
err = ioctl(fd, MMC_IOC_CMD, &ioc); mmc_ioc_cmd_set_data((*ioc), frame_out);
if (err < 0) {
err = -errno;
goto out;
}
break; break;
case MMC_RPMB_READ_CNT: case MMC_RPMB_READ_CNT:
...@@ -1924,23 +1933,17 @@ static int do_rpmb_op(int fd, ...@@ -1924,23 +1933,17 @@ static int do_rpmb_op(int fd,
/* fall through */ /* fall through */
case MMC_RPMB_READ: case MMC_RPMB_READ:
/* Request */ mioc->num_of_cmds = 2;
err = ioctl(fd, MMC_IOC_CMD, &ioc);
if (err < 0) { /* Read request */
err = -errno; ioc = &mioc->cmds[0];
goto out; set_single_cmd(ioc, MMC_WRITE_MULTIPLE_BLOCK, 1, 1);
} mmc_ioc_cmd_set_data((*ioc), frame_in);
/* Get response */ /* Get response */
ioc.write_flag = 0; ioc = &mioc->cmds[1];
ioc.opcode = MMC_READ_MULTIPLE_BLOCK; set_single_cmd(ioc, MMC_READ_MULTIPLE_BLOCK, 0, out_cnt);
ioc.blocks = out_cnt; mmc_ioc_cmd_set_data((*ioc), frame_out);
ioc.data_ptr = (uintptr_t)frame_out;
err = ioctl(fd, MMC_IOC_CMD, &ioc);
if (err < 0) {
err = -errno;
goto out;
}
break; break;
default: default:
...@@ -1948,8 +1951,12 @@ static int do_rpmb_op(int fd, ...@@ -1948,8 +1951,12 @@ static int do_rpmb_op(int fd,
goto out; goto out;
} }
err = ioctl(fd, MMC_IOC_MULTI_CMD, mioc);
out: out:
free(mioc);
return err; return err;
#endif /* !MMC_IOC_MULTI_CMD */
} }
int do_rpmb_write_key(int nargs, char **argv) int do_rpmb_write_key(int nargs, char **argv)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment