165 lines
5.6 KiB
Diff
165 lines
5.6 KiB
Diff
From 30f8936c4797495b36f75c56d931b4424eac1162 Mon Sep 17 00:00:00 2001
|
|
From: Tomas Winkler <tomas.winkler@intel.com>
|
|
Date: Sat, 28 Apr 2018 22:01:32 +0300
|
|
Subject: [PATCH 027/743] rpmb: add nvme rpmb frame type
|
|
|
|
The NVMe RPMB frame differs in layout and endianity
|
|
from the one defined by JDEC.
|
|
|
|
Change-Id: Ifae77454e1bc8733eb1e5bcb2146dc198f94151d
|
|
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
|
|
---
|
|
drivers/char/rpmb/cdev.c | 26 ++++++++++++++++++-------
|
|
include/uapi/linux/rpmb.h | 41 +++++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 60 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/drivers/char/rpmb/cdev.c b/drivers/char/rpmb/cdev.c
|
|
index bdac3894b111..028c7ecd2ac7 100644
|
|
--- a/drivers/char/rpmb/cdev.c
|
|
+++ b/drivers/char/rpmb/cdev.c
|
|
@@ -67,18 +67,28 @@ static int rpmb_release(struct inode *inode, struct file *fp)
|
|
return 0;
|
|
}
|
|
|
|
+static size_t rpmb_ioc_frames_len(struct rpmb_dev *rdev, size_t nframes)
|
|
+{
|
|
+ if (rdev->ops->type == RPMB_TYPE_NVME)
|
|
+ return rpmb_ioc_frames_len_nvme(nframes);
|
|
+ else
|
|
+ return rpmb_ioc_frames_len_jdec(nframes);
|
|
+}
|
|
+
|
|
/**
|
|
* rpmb_cmd_copy_from_user - copy rpmb command from the user space
|
|
*
|
|
+ * @rdev: rpmb device
|
|
* @cmd: internal cmd structure
|
|
* @ucmd: user space cmd structure
|
|
*
|
|
* Return: 0 on success, <0 on error
|
|
*/
|
|
-static int rpmb_cmd_copy_from_user(struct rpmb_cmd *cmd,
|
|
+static int rpmb_cmd_copy_from_user(struct rpmb_dev *rdev,
|
|
+ struct rpmb_cmd *cmd,
|
|
struct rpmb_ioc_cmd __user *ucmd)
|
|
{
|
|
- struct rpmb_frame *frames;
|
|
+ void *frames;
|
|
u64 frames_ptr;
|
|
|
|
if (get_user(cmd->flags, &ucmd->flags))
|
|
@@ -95,7 +105,7 @@ static int rpmb_cmd_copy_from_user(struct rpmb_cmd *cmd,
|
|
return -EFAULT;
|
|
|
|
frames = memdup_user(u64_to_user_ptr(frames_ptr),
|
|
- rpmb_ioc_frames_len_jdec(cmd->nframes));
|
|
+ rpmb_ioc_frames_len(rdev, cmd->nframes));
|
|
if (IS_ERR(frames))
|
|
return PTR_ERR(frames);
|
|
|
|
@@ -106,12 +116,14 @@ static int rpmb_cmd_copy_from_user(struct rpmb_cmd *cmd,
|
|
/**
|
|
* rpmb_cmd_copy_to_user - copy rpmb command to the user space
|
|
*
|
|
+ * @rdev: rpmb device
|
|
* @ucmd: user space cmd structure
|
|
* @cmd: internal cmd structure
|
|
*
|
|
* Return: 0 on success, <0 on error
|
|
*/
|
|
-static int rpmb_cmd_copy_to_user(struct rpmb_ioc_cmd __user *ucmd,
|
|
+static int rpmb_cmd_copy_to_user(struct rpmb_dev *rdev,
|
|
+ struct rpmb_ioc_cmd __user *ucmd,
|
|
struct rpmb_cmd *cmd)
|
|
{
|
|
u64 frames_ptr;
|
|
@@ -121,7 +133,7 @@ static int rpmb_cmd_copy_to_user(struct rpmb_ioc_cmd __user *ucmd,
|
|
|
|
/* some archs have issues with 64bit get_user */
|
|
if (copy_to_user(u64_to_user_ptr(frames_ptr), cmd->frames,
|
|
- rpmb_ioc_frames_len_jdec(cmd->nframes)))
|
|
+ rpmb_ioc_frames_len(rdev, cmd->nframes)))
|
|
return -EFAULT;
|
|
|
|
return 0;
|
|
@@ -167,7 +179,7 @@ static long rpmb_ioctl_seq_cmd(struct rpmb_dev *rdev,
|
|
|
|
ucmds = (struct rpmb_ioc_cmd __user *)ptr->cmds;
|
|
for (i = 0; i < ncmds; i++) {
|
|
- ret = rpmb_cmd_copy_from_user(&cmds[i], &ucmds[i]);
|
|
+ ret = rpmb_cmd_copy_from_user(rdev, &cmds[i], &ucmds[i]);
|
|
if (ret)
|
|
goto out;
|
|
}
|
|
@@ -177,7 +189,7 @@ static long rpmb_ioctl_seq_cmd(struct rpmb_dev *rdev,
|
|
goto out;
|
|
|
|
for (i = 0; i < ncmds; i++) {
|
|
- ret = rpmb_cmd_copy_to_user(&ucmds[i], &cmds[i]);
|
|
+ ret = rpmb_cmd_copy_to_user(rdev, &ucmds[i], &cmds[i]);
|
|
if (ret)
|
|
goto out;
|
|
}
|
|
diff --git a/include/uapi/linux/rpmb.h b/include/uapi/linux/rpmb.h
|
|
index d304701cd258..f41a28ea9765 100644
|
|
--- a/include/uapi/linux/rpmb.h
|
|
+++ b/include/uapi/linux/rpmb.h
|
|
@@ -68,6 +68,44 @@ struct rpmb_frame_jdec {
|
|
(sizeof(struct rpmb_frame_jdec) - \
|
|
offsetof(struct rpmb_frame_jdec, data))
|
|
|
|
+/**
|
|
+ * struct rpmb_frame_nvme - rpmb frame as defined by specs
|
|
+ *
|
|
+ * @key_mac : The authentication key or the message authentication
|
|
+ * code (MAC) depending on the request/response type.
|
|
+ * The MAC will be delivered in the last (or the only)
|
|
+ * block of data.
|
|
+ * @rpmb_target : RPMB target to access.
|
|
+ * @nonce : Random number generated by the host for the requests
|
|
+ * and copied to the response by the RPMB engine.
|
|
+ * @write_counter: Counter value for the total amount of the successful
|
|
+ * authenticated data write requests made by the host.
|
|
+ * @addr : Address of the data to be programmed to or read
|
|
+ * from the RPMB. Address is the serial number of
|
|
+ * the accessed block (half sector 256B).
|
|
+ * @block_count : Number of sctors (sectors, 512B) requested to be
|
|
+ * read/programmed. (In spec this field is named sector_count).
|
|
+ * @result : Includes information about the status of the write counter
|
|
+ * (valid, expired) and result of the access made to the RPMB.
|
|
+ * @req_resp : Defines the type of request and response to/from the memory.
|
|
+ * @data : variable sized payload 512 * block_count
|
|
+ */
|
|
+struct rpmb_frame_nvme {
|
|
+ __u8 key_mac[223];
|
|
+ __u8 rpmb_target;
|
|
+ __u8 nonce[16];
|
|
+ __le32 write_counter;
|
|
+ __le32 addr;
|
|
+ __le32 block_count;
|
|
+ __le16 result;
|
|
+ __le16 req_resp;
|
|
+ __u8 data[0];
|
|
+} __attribute__((packed));
|
|
+
|
|
+#define rpmb_nvme_hmac_data_len \
|
|
+ (sizeof(struct rpmb_frame_nvme) - \
|
|
+ offsetof(struct rpmb_frame_nvme, rpmb_target))
|
|
+
|
|
#define RPMB_PROGRAM_KEY 0x0001 /* Program RPMB Authentication Key */
|
|
#define RPMB_GET_WRITE_COUNTER 0x0002 /* Read RPMB write counter */
|
|
#define RPMB_WRITE_DATA 0x0003 /* Write data to RPMB partition */
|
|
@@ -142,6 +180,9 @@ struct rpmb_ioc_cmd {
|
|
#define rpmb_ioc_frames_len_jdec(_n) \
|
|
(((_n) ?: 1) * sizeof(struct rpmb_frame_jdec))
|
|
|
|
+#define rpmb_ioc_frames_len_nvme(_n) \
|
|
+ (sizeof(struct rpmb_frame_nvme) + (_n) * 512)
|
|
+
|
|
/**
|
|
* struct rpmb_ioc_seq_cmd - rpmb command sequence
|
|
*
|
|
--
|
|
2.19.2
|
|
|