diff mbox series

[1/4] block: sed-opal: Implement IOC_OPAL_DISCOVERY

Message ID 20220706023935.875994-2-gjoyce@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show
Series sed-opal: keyrings, discovery, revert and key store | expand

Commit Message

Greg Joyce July 6, 2022, 2:39 a.m. UTC
From: Greg Joyce <gjoyce@linux.vnet.ibm.com>

When IOC_OPAL_DISCOVERY is called, the opal_discovery structure is
passed down to the "discovery0" step, instead of NULL for the
normal cases during all other commands. The processing of the
received discovery data in opal_discovery0_end() then checks for
a non-NULL structure pointer, and if found will copy the raw
discovery data to the provided user buffer. If the user buffer is NULL
then no data is copied. If the user buffer is too small, then not
all data is copied. In all cases, the return value is the length
of the actual data received from the drive.
---
 block/sed-opal.c              | 38 ++++++++++++++++++++++++++++++++---
 include/linux/sed-opal.h      |  1 +
 include/uapi/linux/sed-opal.h |  7 +++++++
 3 files changed, 43 insertions(+), 3 deletions(-)

Comments

Christoph Hellwig July 6, 2022, 8:10 a.m. UTC | #1
On Tue, Jul 05, 2022 at 09:39:32PM -0500, gjoyce@linux.vnet.ibm.com wrote:
> From: Greg Joyce <gjoyce@linux.vnet.ibm.com>
> 
> When IOC_OPAL_DISCOVERY is called, the opal_discovery structure is
> passed down to the "discovery0" step, instead of NULL for the
> normal cases during all other commands. The processing of the
> received discovery data in opal_discovery0_end() then checks for
> a non-NULL structure pointer, and if found will copy the raw
> discovery data to the provided user buffer. If the user buffer is NULL
> then no data is copied. If the user buffer is too small, then not
> all data is copied. In all cases, the return value is the length
> of the actual data received from the drive.

You don't need to describe what you do, everyone familar with C can
discover that themsevels.  Explain why you do it.
diff mbox series

Patch

diff --git a/block/sed-opal.c b/block/sed-opal.c
index 9700197000f2..4b9a7ffbf00f 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -426,8 +426,11 @@  static int execute_steps(struct opal_dev *dev,
 	return error;
 }
 
-static int opal_discovery0_end(struct opal_dev *dev)
+static int opal_discovery0_end(struct opal_dev *dev, void *data)
 {
+	struct opal_discovery *discv_out = data; /* may be NULL */
+	u8 __user *buf_out;
+	u64 len_out;
 	bool found_com_id = false, supported = true, single_user = false;
 	const struct d0_header *hdr = (struct d0_header *)dev->resp;
 	const u8 *epos = dev->resp, *cpos = dev->resp;
@@ -443,6 +446,15 @@  static int opal_discovery0_end(struct opal_dev *dev)
 		return -EFAULT;
 	}
 
+	if (discv_out) {
+		buf_out = (u8 __user *)(uintptr_t)discv_out->data;
+		len_out = min(discv_out->size, (u64)hlen);
+		if (buf_out && copy_to_user(buf_out, dev->resp, len_out)) {
+			return -EFAULT;
+		}
+		discv_out->size = hlen; /* actual size of data */
+	}
+
 	epos += hlen; /* end of buffer */
 	cpos += sizeof(*hdr); /* current position on buffer */
 
@@ -517,13 +529,13 @@  static int opal_discovery0(struct opal_dev *dev, void *data)
 	if (ret)
 		return ret;
 
-	return opal_discovery0_end(dev);
+	return opal_discovery0_end(dev, data);
 }
 
 static int opal_discovery0_step(struct opal_dev *dev)
 {
 	const struct opal_step discovery0_step = {
-		opal_discovery0,
+		opal_discovery0, NULL
 	};
 
 	return execute_step(dev, &discovery0_step, 0);
@@ -2179,6 +2191,22 @@  static int opal_secure_erase_locking_range(struct opal_dev *dev,
 	return ret;
 }
 
+static int opal_get_discv(struct opal_dev *dev, struct opal_discovery *discv)
+{
+	const struct opal_step discovery0_step = {
+		opal_discovery0, discv
+	};
+	int ret = 0;
+
+	mutex_lock(&dev->dev_lock);
+	setup_opal_dev(dev);
+	ret = execute_step(dev, &discovery0_step, 0);
+	mutex_unlock(&dev->dev_lock);
+	if (ret)
+		return ret;
+	return discv->size; /* modified to actual length of data */
+}
+
 static int opal_erase_locking_range(struct opal_dev *dev,
 				    struct opal_session_info *opal_session)
 {
@@ -2685,6 +2713,10 @@  int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
 	case IOC_OPAL_GENERIC_TABLE_RW:
 		ret = opal_generic_read_write_table(dev, p);
 		break;
+	case IOC_OPAL_DISCOVERY:
+		ret = opal_get_discv(dev, p);
+		break;
+
 	default:
 		break;
 	}
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index 1ac0d712a9c3..9197b7a628f2 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -43,6 +43,7 @@  static inline bool is_sed_ioctl(unsigned int cmd)
 	case IOC_OPAL_MBR_DONE:
 	case IOC_OPAL_WRITE_SHADOW_MBR:
 	case IOC_OPAL_GENERIC_TABLE_RW:
+	case IOC_OPAL_DISCOVERY:
 		return true;
 	}
 	return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index 6f5af1a84213..114636c19d31 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -132,6 +132,12 @@  struct opal_read_write_table {
 	__u64 priv;
 };
 
+struct opal_discovery {
+	__u64 data;
+	__u64 size;
+};
+
+
 #define IOC_OPAL_SAVE		    _IOW('p', 220, struct opal_lock_unlock)
 #define IOC_OPAL_LOCK_UNLOCK	    _IOW('p', 221, struct opal_lock_unlock)
 #define IOC_OPAL_TAKE_OWNERSHIP	    _IOW('p', 222, struct opal_key)
@@ -148,5 +154,6 @@  struct opal_read_write_table {
 #define IOC_OPAL_MBR_DONE           _IOW('p', 233, struct opal_mbr_done)
 #define IOC_OPAL_WRITE_SHADOW_MBR   _IOW('p', 234, struct opal_shadow_mbr)
 #define IOC_OPAL_GENERIC_TABLE_RW   _IOW('p', 235, struct opal_read_write_table)
+#define IOC_OPAL_DISCOVERY          _IOW('p', 236, struct opal_discovery)
 
 #endif /* _UAPI_SED_OPAL_H */