* [PATCH v8 1/5] spdm-socket: add seperate send/recv functions
2025-10-03 11:39 [PATCH v8 0/5] NVMe: Add SPDM over the storage transport support Wilfred Mallawa
@ 2025-10-03 11:39 ` Wilfred Mallawa
2025-10-03 11:39 ` [PATCH v8 2/5] spdm: add spdm storage transport virtual header Wilfred Mallawa
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Wilfred Mallawa @ 2025-10-03 11:39 UTC (permalink / raw)
To: Alistair Francis
Cc: Keith Busch, Klaus Jensen, Stefan Hajnoczi, Jonathan Cameron,
qemu-devel, qemu-block, Wilfred Mallawa
From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
This is to support uni-directional transports such as SPDM over Storage.
As specified by the DMTF DSP0286.
Also update spdm_socket_rsp() to use the new send()/receive() functions. For
the case of spdm_socket_receive(), this allows us to do error checking
in one place with the addition of spdm_socket_command_valid().
Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
backends/spdm-socket.c | 56 ++++++++++++++++++++++++++++--------
include/system/spdm-socket.h | 32 +++++++++++++++++++++
2 files changed, 76 insertions(+), 12 deletions(-)
diff --git a/backends/spdm-socket.c b/backends/spdm-socket.c
index 2c709c68c8..ab74a02d9c 100644
--- a/backends/spdm-socket.c
+++ b/backends/spdm-socket.c
@@ -184,29 +184,61 @@ int spdm_socket_connect(uint16_t port, Error **errp)
return client_socket;
}
-uint32_t spdm_socket_rsp(const int socket, uint32_t transport_type,
- void *req, uint32_t req_len,
- void *rsp, uint32_t rsp_len)
+static bool spdm_socket_command_valid(uint32_t command)
+{
+ switch (command) {
+ case SPDM_SOCKET_COMMAND_NORMAL:
+ case SPDM_SOCKET_STORAGE_CMD_IF_SEND:
+ case SPDM_SOCKET_STORAGE_CMD_IF_RECV:
+ case SOCKET_SPDM_STORAGE_ACK_STATUS:
+ case SPDM_SOCKET_COMMAND_OOB_ENCAP_KEY_UPDATE:
+ case SPDM_SOCKET_COMMAND_CONTINUE:
+ case SPDM_SOCKET_COMMAND_SHUTDOWN:
+ case SPDM_SOCKET_COMMAND_UNKOWN:
+ case SPDM_SOCKET_COMMAND_TEST:
+ return true;
+ default:
+ return false;
+ }
+}
+
+uint32_t spdm_socket_receive(const int socket, uint32_t transport_type,
+ void *rsp, uint32_t rsp_len)
{
uint32_t command;
bool result;
- result = send_platform_data(socket, transport_type,
- SPDM_SOCKET_COMMAND_NORMAL,
- req, req_len);
- if (!result) {
+ result = receive_platform_data(socket, transport_type, &command,
+ (uint8_t *)rsp, &rsp_len);
+
+ /* we may have received some data, but check if the command is valid */
+ if (!result || !spdm_socket_command_valid(command)) {
return 0;
}
- result = receive_platform_data(socket, transport_type, &command,
- (uint8_t *)rsp, &rsp_len);
+ return rsp_len;
+}
+
+bool spdm_socket_send(const int socket, uint32_t socket_cmd,
+ uint32_t transport_type, void *req, uint32_t req_len)
+{
+ return send_platform_data(socket, transport_type, socket_cmd, req,
+ req_len);
+}
+
+uint32_t spdm_socket_rsp(const int socket, uint32_t transport_type,
+ void *req, uint32_t req_len,
+ void *rsp, uint32_t rsp_len)
+{
+ bool result;
+
+ result = spdm_socket_send(socket, SPDM_SOCKET_COMMAND_NORMAL,
+ transport_type, req, req_len);
if (!result) {
return 0;
}
- assert(command != 0);
-
- return rsp_len;
+ return spdm_socket_receive(socket, transport_type, rsp, rsp_len);
}
void spdm_socket_close(const int socket, uint32_t transport_type)
diff --git a/include/system/spdm-socket.h b/include/system/spdm-socket.h
index 5d8bd9aa4e..29aa04fd52 100644
--- a/include/system/spdm-socket.h
+++ b/include/system/spdm-socket.h
@@ -50,6 +50,35 @@ uint32_t spdm_socket_rsp(const int socket, uint32_t transport_type,
void *req, uint32_t req_len,
void *rsp, uint32_t rsp_len);
+/**
+ * spdm_socket_rsp: Receive a message from an SPDM server
+ * @socket: socket returned from spdm_socket_connect()
+ * @transport_type: SPDM_SOCKET_TRANSPORT_TYPE_* macro
+ * @rsp: response buffer
+ * @rsp_len: response buffer length
+ *
+ * Receives a message from the SPDM server and returns the number of bytes
+ * received or 0 on failure. This can be used to receive a message from the SPDM
+ * server without sending anything first.
+ */
+uint32_t spdm_socket_receive(const int socket, uint32_t transport_type,
+ void *rsp, uint32_t rsp_len);
+
+/**
+ * spdm_socket_rsp: Sends a message to an SPDM server
+ * @socket: socket returned from spdm_socket_connect()
+ * @socket_cmd: socket command type (normal/if_recv/if_send etc...)
+ * @transport_type: SPDM_SOCKET_TRANSPORT_TYPE_* macro
+ * @req: request buffer
+ * @req_len: request buffer length
+ *
+ * Sends platform data to a SPDM server on socket, returns true on success.
+ * The response from the server must then be fetched by using
+ * spdm_socket_receive().
+ */
+bool spdm_socket_send(const int socket, uint32_t socket_cmd,
+ uint32_t transport_type, void *req, uint32_t req_len);
+
/**
* spdm_socket_close: send a shutdown command to the server
* @socket: socket returned from spdm_socket_connect()
@@ -60,6 +89,9 @@ uint32_t spdm_socket_rsp(const int socket, uint32_t transport_type,
void spdm_socket_close(const int socket, uint32_t transport_type);
#define SPDM_SOCKET_COMMAND_NORMAL 0x0001
+#define SPDM_SOCKET_STORAGE_CMD_IF_SEND 0x0002
+#define SPDM_SOCKET_STORAGE_CMD_IF_RECV 0x0003
+#define SOCKET_SPDM_STORAGE_ACK_STATUS 0x0004
#define SPDM_SOCKET_COMMAND_OOB_ENCAP_KEY_UPDATE 0x8001
#define SPDM_SOCKET_COMMAND_CONTINUE 0xFFFD
#define SPDM_SOCKET_COMMAND_SHUTDOWN 0xFFFE
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v8 2/5] spdm: add spdm storage transport virtual header
2025-10-03 11:39 [PATCH v8 0/5] NVMe: Add SPDM over the storage transport support Wilfred Mallawa
2025-10-03 11:39 ` [PATCH v8 1/5] spdm-socket: add seperate send/recv functions Wilfred Mallawa
@ 2025-10-03 11:39 ` Wilfred Mallawa
2025-10-03 11:39 ` [PATCH v8 3/5] hw/nvme: add NVMe Admin Security SPDM support Wilfred Mallawa
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Wilfred Mallawa @ 2025-10-03 11:39 UTC (permalink / raw)
To: Alistair Francis
Cc: Keith Busch, Klaus Jensen, Stefan Hajnoczi, Jonathan Cameron,
qemu-devel, qemu-block, Wilfred Mallawa
From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
This header contains the transport encoding for an SPDM message that
uses the SPDM over Storage transport as defined by the DMTF DSP0286.
Note that in the StorageSpdmTransportHeader structure, security_protocol
field is defined in the SCSI Primary Commands 5 (SPC-5) specification.
The NVMe specification also refers to the SPC-5 for this definition.
The security_protocol_specific field is defined in DSP0286 and is
referred to as SP Specific for NVMe and ATA.
Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
include/system/spdm-socket.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/include/system/spdm-socket.h b/include/system/spdm-socket.h
index 29aa04fd52..8c07dc12d2 100644
--- a/include/system/spdm-socket.h
+++ b/include/system/spdm-socket.h
@@ -88,6 +88,20 @@ bool spdm_socket_send(const int socket, uint32_t socket_cmd,
*/
void spdm_socket_close(const int socket, uint32_t transport_type);
+/*
+ * Defines the transport encoding for SPDM, this information shall be passed
+ * down to the SPDM server, when conforming to the SPDM over Storage standard
+ * as defined by DSP0286.
+ */
+typedef struct {
+ uint8_t security_protocol; /* Must be 0xE8 for SPDM Commands
+ as per SCSI Primary Commands 5 */
+ uint16_t security_protocol_specific; /* Bit[7:2] SPDM Operation
+ Bit[0:1] Connection ID
+ per DSP0286 1.0: Section 7.2 */
+ uint32_t length; /* Length of the SPDM Message*/
+} QEMU_PACKED StorageSpdmTransportHeader;
+
#define SPDM_SOCKET_COMMAND_NORMAL 0x0001
#define SPDM_SOCKET_STORAGE_CMD_IF_SEND 0x0002
#define SPDM_SOCKET_STORAGE_CMD_IF_RECV 0x0003
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v8 3/5] hw/nvme: add NVMe Admin Security SPDM support
2025-10-03 11:39 [PATCH v8 0/5] NVMe: Add SPDM over the storage transport support Wilfred Mallawa
2025-10-03 11:39 ` [PATCH v8 1/5] spdm-socket: add seperate send/recv functions Wilfred Mallawa
2025-10-03 11:39 ` [PATCH v8 2/5] spdm: add spdm storage transport virtual header Wilfred Mallawa
@ 2025-10-03 11:39 ` Wilfred Mallawa
2025-10-03 11:39 ` [PATCH v8 4/5] spdm: define SPDM transport enum types Wilfred Mallawa
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Wilfred Mallawa @ 2025-10-03 11:39 UTC (permalink / raw)
To: Alistair Francis
Cc: Keith Busch, Klaus Jensen, Stefan Hajnoczi, Jonathan Cameron,
qemu-devel, qemu-block, Wilfred Mallawa, Klaus Jensen
From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
Adds the NVMe Admin Security Send/Receive command support with support
for DMTFs SPDM. The transport binding for SPDM is defined in the
DMTF DSP0286.
Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
hw/nvme/ctrl.c | 212 ++++++++++++++++++++++++++++++++++-
hw/nvme/nvme.h | 5 +
include/block/nvme.h | 15 +++
include/system/spdm-socket.h | 2 +
4 files changed, 233 insertions(+), 1 deletion(-)
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index f5ee6bf260..ad52e8f569 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -282,6 +282,8 @@ static const uint32_t nvme_cse_acs_default[256] = {
[NVME_ADM_CMD_FORMAT_NVM] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC,
[NVME_ADM_CMD_DIRECTIVE_RECV] = NVME_CMD_EFF_CSUPP,
[NVME_ADM_CMD_DIRECTIVE_SEND] = NVME_CMD_EFF_CSUPP,
+ [NVME_ADM_CMD_SECURITY_SEND] = NVME_CMD_EFF_CSUPP,
+ [NVME_ADM_CMD_SECURITY_RECV] = NVME_CMD_EFF_CSUPP,
};
static const uint32_t nvme_cse_iocs_nvm_default[256] = {
@@ -7282,6 +7284,207 @@ static uint16_t nvme_dbbuf_config(NvmeCtrl *n, const NvmeRequest *req)
return NVME_SUCCESS;
}
+static uint16_t nvme_sec_prot_spdm_send(NvmeCtrl *n, NvmeRequest *req)
+{
+ StorageSpdmTransportHeader hdr = {0};
+ g_autofree uint8_t *sec_buf = NULL;
+ uint32_t transfer_len = le32_to_cpu(req->cmd.cdw11);
+ uint32_t transport_transfer_len = transfer_len;
+ uint32_t dw10 = le32_to_cpu(req->cmd.cdw10);
+ uint32_t recvd;
+ uint16_t nvme_cmd_status, ret;
+ uint8_t secp = extract32(dw10, 24, 8);
+ uint16_t spsp = extract32(dw10, 8, 16);
+ bool spdm_res;
+
+ if (transport_transfer_len > UINT32_MAX - sizeof(hdr)) {
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+
+ transport_transfer_len += sizeof(hdr);
+ if (transport_transfer_len > SPDM_SOCKET_MAX_MESSAGE_BUFFER_SIZE) {
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+
+ ret = nvme_check_mdts(n, transport_transfer_len);
+ if (ret != NVME_SUCCESS) {
+ return ret;
+ }
+
+ /* Generate the NVMe transport header */
+ hdr.security_protocol = secp;
+ hdr.security_protocol_specific = cpu_to_le16(spsp);
+ hdr.length = cpu_to_le32(transfer_len);
+
+ sec_buf = g_try_malloc0(transport_transfer_len);
+ if (!sec_buf) {
+ return NVME_INTERNAL_DEV_ERROR;
+ }
+
+ /* Attach the transport header */
+ memcpy(sec_buf, &hdr, sizeof(hdr));
+ ret = nvme_h2c(n, sec_buf + sizeof(hdr), transfer_len, req);
+ if (ret) {
+ return ret;
+ }
+
+ spdm_res = spdm_socket_send(n->spdm_socket, SPDM_SOCKET_STORAGE_CMD_IF_SEND,
+ SPDM_SOCKET_TRANSPORT_TYPE_NVME, sec_buf,
+ transport_transfer_len);
+ if (!spdm_res) {
+ return NVME_DATA_TRAS_ERROR | NVME_DNR;
+ }
+
+ /* The responder shall ack with message status */
+ recvd = spdm_socket_receive(n->spdm_socket, SPDM_SOCKET_TRANSPORT_TYPE_NVME,
+ &nvme_cmd_status,
+ SPDM_SOCKET_MAX_MSG_STATUS_LEN);
+
+ nvme_cmd_status = be16_to_cpu(nvme_cmd_status);
+
+ if (recvd < SPDM_SOCKET_MAX_MSG_STATUS_LEN) {
+ return NVME_DATA_TRAS_ERROR | NVME_DNR;
+ }
+
+ return nvme_cmd_status;
+}
+
+/* From host to controller */
+static uint16_t nvme_security_send(NvmeCtrl *n, NvmeRequest *req)
+{
+ uint32_t dw10 = le32_to_cpu(req->cmd.cdw10);
+ uint8_t secp = extract32(dw10, 24, 8);
+
+ switch (secp) {
+ case NVME_SEC_PROT_DMTF_SPDM:
+ if (n->spdm_socket < 0) {
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+ return nvme_sec_prot_spdm_send(n, req);
+ default:
+ /* Unsupported Security Protocol Type */
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+
+ return NVME_INVALID_FIELD | NVME_DNR;
+}
+
+static uint16_t nvme_sec_prot_spdm_receive(NvmeCtrl *n, NvmeRequest *req)
+{
+ StorageSpdmTransportHeader hdr;
+ g_autofree uint8_t *rsp_spdm_buf = NULL;
+ uint32_t dw10 = le32_to_cpu(req->cmd.cdw10);
+ uint32_t alloc_len = le32_to_cpu(req->cmd.cdw11);
+ uint32_t recvd, spdm_res;
+ uint16_t nvme_cmd_status, ret;
+ uint8_t secp = extract32(dw10, 24, 8);
+ uint8_t spsp = extract32(dw10, 8, 16);
+ if (!alloc_len) {
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+
+ /* Generate the NVMe transport header */
+ hdr = (StorageSpdmTransportHeader) {
+ .security_protocol = secp,
+ .security_protocol_specific = cpu_to_le16(spsp),
+ .length = cpu_to_le32(alloc_len),
+ };
+
+ /* Forward if_recv to the SPDM Server with SPSP0 */
+ spdm_res = spdm_socket_send(n->spdm_socket, SPDM_SOCKET_STORAGE_CMD_IF_RECV,
+ SPDM_SOCKET_TRANSPORT_TYPE_NVME,
+ &hdr, sizeof(hdr));
+ if (!spdm_res) {
+ return NVME_DATA_TRAS_ERROR | NVME_DNR;
+ }
+
+ /* The responder shall ack with message status */
+ recvd = spdm_socket_receive(n->spdm_socket, SPDM_SOCKET_TRANSPORT_TYPE_NVME,
+ &nvme_cmd_status,
+ SPDM_SOCKET_MAX_MSG_STATUS_LEN);
+ if (recvd < SPDM_SOCKET_MAX_MSG_STATUS_LEN) {
+ return NVME_DATA_TRAS_ERROR | NVME_DNR;
+ }
+
+ nvme_cmd_status = be16_to_cpu(nvme_cmd_status);
+ /* An error here implies the prior if_recv from requester was spurious */
+ if (nvme_cmd_status != NVME_SUCCESS) {
+ return nvme_cmd_status;
+ }
+
+ /* Clear to start receiving data from the server */
+ rsp_spdm_buf = g_try_malloc0(alloc_len);
+ if (!rsp_spdm_buf) {
+ return NVME_INTERNAL_DEV_ERROR;
+ }
+
+ recvd = spdm_socket_receive(n->spdm_socket,
+ SPDM_SOCKET_TRANSPORT_TYPE_NVME,
+ rsp_spdm_buf, alloc_len);
+ if (!recvd) {
+ return NVME_DATA_TRAS_ERROR | NVME_DNR;
+ }
+
+ ret = nvme_c2h(n, rsp_spdm_buf, MIN(recvd, alloc_len), req);
+ if (ret) {
+ return ret;
+ }
+
+ return NVME_SUCCESS;
+}
+
+static uint16_t nvme_get_sec_prot_info(NvmeCtrl *n, NvmeRequest *req)
+{
+ uint32_t alloc_len = le32_to_cpu(req->cmd.cdw11);
+ uint8_t resp[10] = {
+ /* Support Security Protol List Length */
+ [6] = 0, /* MSB */
+ [7] = 2, /* LSB */
+ /* Support Security Protocol List */
+ [8] = SFSC_SECURITY_PROT_INFO,
+ [9] = 0,
+ };
+
+ if (n->spdm_socket >= 0) {
+ resp[9] = NVME_SEC_PROT_DMTF_SPDM;
+ }
+
+ if (alloc_len < 10) {
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+
+ return nvme_c2h(n, resp, sizeof(resp), req);
+}
+
+/* From controller to host */
+static uint16_t nvme_security_receive(NvmeCtrl *n, NvmeRequest *req)
+{
+ uint32_t dw10 = le32_to_cpu(req->cmd.cdw10);
+ uint16_t spsp = extract32(dw10, 8, 16);
+ uint8_t secp = extract32(dw10, 24, 8);
+
+ switch (secp) {
+ case SFSC_SECURITY_PROT_INFO:
+ switch (spsp) {
+ case 0:
+ /* Supported security protocol list */
+ return nvme_get_sec_prot_info(n, req);
+ case 1:
+ /* Certificate data */
+ /* fallthrough */
+ default:
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+ case NVME_SEC_PROT_DMTF_SPDM:
+ if (n->spdm_socket < 0) {
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+ return nvme_sec_prot_spdm_receive(n, req);
+ default:
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+}
+
static uint16_t nvme_directive_send(NvmeCtrl *n, NvmeRequest *req)
{
return NVME_INVALID_FIELD | NVME_DNR;
@@ -7389,6 +7592,10 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeRequest *req)
return nvme_directive_send(n, req);
case NVME_ADM_CMD_DIRECTIVE_RECV:
return nvme_directive_receive(n, req);
+ case NVME_ADM_CMD_SECURITY_SEND:
+ return nvme_security_send(n, req);
+ case NVME_ADM_CMD_SECURITY_RECV:
+ return nvme_security_receive(n, req);
default:
g_assert_not_reached();
}
@@ -8459,6 +8666,8 @@ static void nvme_init_state(NvmeCtrl *n)
sctrl->vfn = cpu_to_le16(i + 1);
}
+ n->spdm_socket = -1;
+
cap->cntlid = cpu_to_le16(n->cntlid);
cap->crt = NVME_CRT_VQ | NVME_CRT_VI;
@@ -8824,7 +9033,8 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
id->mdts = n->params.mdts;
id->ver = cpu_to_le32(NVME_SPEC_VER);
- oacs = NVME_OACS_NMS | NVME_OACS_FORMAT | NVME_OACS_DIRECTIVES;
+ oacs = NVME_OACS_NMS | NVME_OACS_FORMAT | NVME_OACS_DIRECTIVES |
+ NVME_OACS_SECURITY;
if (n->params.dbcs) {
oacs |= NVME_OACS_DBCS;
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index b5c9378ea4..67ed562e00 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -461,6 +461,8 @@ static inline const char *nvme_adm_opc_str(uint8_t opc)
case NVME_ADM_CMD_DIRECTIVE_RECV: return "NVME_ADM_CMD_DIRECTIVE_RECV";
case NVME_ADM_CMD_DBBUF_CONFIG: return "NVME_ADM_CMD_DBBUF_CONFIG";
case NVME_ADM_CMD_FORMAT_NVM: return "NVME_ADM_CMD_FORMAT_NVM";
+ case NVME_ADM_CMD_SECURITY_SEND: return "NVME_ADM_CMD_SECURITY_SEND";
+ case NVME_ADM_CMD_SECURITY_RECV: return "NVME_ADM_CMD_SECURITY_RECV";
default: return "NVME_ADM_CMD_UNKNOWN";
}
}
@@ -648,6 +650,9 @@ typedef struct NvmeCtrl {
} next_pri_ctrl_cap; /* These override pri_ctrl_cap after reset */
uint32_t dn; /* Disable Normal */
NvmeAtomic atomic;
+
+ /* Socket mapping to SPDM over NVMe Security In/Out commands */
+ int spdm_socket;
} NvmeCtrl;
typedef enum NvmeResetType {
diff --git a/include/block/nvme.h b/include/block/nvme.h
index 358e516e38..9fa2ecaf28 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -1779,6 +1779,21 @@ enum NvmeDirectiveOperations {
NVME_DIRECTIVE_RETURN_PARAMS = 0x1,
};
+typedef enum SfscSecurityProtocol {
+ SFSC_SECURITY_PROT_INFO = 0x00,
+} SfscSecurityProtocol;
+
+typedef enum NvmeSecurityProtocols {
+ NVME_SEC_PROT_DMTF_SPDM = 0xE8,
+} NvmeSecurityProtocols;
+
+typedef enum SpdmOperationCodes {
+ SPDM_STORAGE_DISCOVERY = 0x1, /* Mandatory */
+ SPDM_STORAGE_PENDING_INFO = 0x2, /* Optional */
+ SPDM_STORAGE_MSG = 0x5, /* Mandatory */
+ SPDM_STORAGE_SEC_MSG = 0x6, /* Optional */
+} SpdmOperationCodes;
+
typedef struct QEMU_PACKED NvmeFdpConfsHdr {
uint16_t num_confs;
uint8_t version;
diff --git a/include/system/spdm-socket.h b/include/system/spdm-socket.h
index 8c07dc12d2..e611633812 100644
--- a/include/system/spdm-socket.h
+++ b/include/system/spdm-socket.h
@@ -114,7 +114,9 @@ typedef struct {
#define SPDM_SOCKET_TRANSPORT_TYPE_MCTP 0x01
#define SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE 0x02
+#define SPDM_SOCKET_TRANSPORT_TYPE_NVME 0x04
#define SPDM_SOCKET_MAX_MESSAGE_BUFFER_SIZE 0x1200
+#define SPDM_SOCKET_MAX_MSG_STATUS_LEN 0x02
#endif
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v8 4/5] spdm: define SPDM transport enum types
2025-10-03 11:39 [PATCH v8 0/5] NVMe: Add SPDM over the storage transport support Wilfred Mallawa
` (2 preceding siblings ...)
2025-10-03 11:39 ` [PATCH v8 3/5] hw/nvme: add NVMe Admin Security SPDM support Wilfred Mallawa
@ 2025-10-03 11:39 ` Wilfred Mallawa
2025-10-03 11:39 ` [PATCH v8 5/5] hw/nvme: connect SPDM over NVMe Security Send/Recv Wilfred Mallawa
2025-10-07 8:05 ` [PATCH v8 0/5] NVMe: Add SPDM over the storage transport support Klaus Jensen
5 siblings, 0 replies; 8+ messages in thread
From: Wilfred Mallawa @ 2025-10-03 11:39 UTC (permalink / raw)
To: Alistair Francis
Cc: Keith Busch, Klaus Jensen, Stefan Hajnoczi, Jonathan Cameron,
qemu-devel, qemu-block, Wilfred Mallawa
From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
SPDM maybe used over different transports. This patch specifies the
trasnport types as an enum with a qdev property definition such that
a user input transport type (string) can be mapped directly into the
respective SPDM transportenum for internal use.
Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
backends/spdm-socket.c | 23 +++++++++++++++++++++++
include/system/spdm-socket.h | 19 +++++++++++++++----
2 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/backends/spdm-socket.c b/backends/spdm-socket.c
index ab74a02d9c..6d8f02d3b9 100644
--- a/backends/spdm-socket.c
+++ b/backends/spdm-socket.c
@@ -13,6 +13,9 @@
#include "qemu/osdep.h"
#include "system/spdm-socket.h"
#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/core/qdev-prop-internal.h"
static bool read_bytes(const int socket, uint8_t *buffer,
size_t number_of_bytes)
@@ -246,3 +249,23 @@ void spdm_socket_close(const int socket, uint32_t transport_type)
send_platform_data(socket, transport_type,
SPDM_SOCKET_COMMAND_SHUTDOWN, NULL, 0);
}
+
+const QEnumLookup SpdmTransport_lookup = {
+ .array = (const char *const[]) {
+ [SPDM_SOCKET_TRANSPORT_TYPE_UNSPEC] = "unspecified",
+ [SPDM_SOCKET_TRANSPORT_TYPE_MCTP] = "mctp",
+ [SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE] = "doe",
+ [SPDM_SOCKET_TRANSPORT_TYPE_SCSI] = "scsi",
+ [SPDM_SOCKET_TRANSPORT_TYPE_NVME] = "nvme",
+ },
+ .size = SPDM_SOCKET_TRANSPORT_TYPE_MAX
+};
+
+const PropertyInfo qdev_prop_spdm_trans = {
+ .type = "SpdmTransportType",
+ .description = "Spdm Transport, doe/nvme/mctp/scsi/unspecified",
+ .enum_table = &SpdmTransport_lookup,
+ .get = qdev_propinfo_get_enum,
+ .set = qdev_propinfo_set_enum,
+ .set_default_value = qdev_propinfo_set_default_value_enum,
+};
diff --git a/include/system/spdm-socket.h b/include/system/spdm-socket.h
index e611633812..00cb0e97f3 100644
--- a/include/system/spdm-socket.h
+++ b/include/system/spdm-socket.h
@@ -112,11 +112,22 @@ typedef struct {
#define SPDM_SOCKET_COMMAND_UNKOWN 0xFFFF
#define SPDM_SOCKET_COMMAND_TEST 0xDEAD
-#define SPDM_SOCKET_TRANSPORT_TYPE_MCTP 0x01
-#define SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE 0x02
-#define SPDM_SOCKET_TRANSPORT_TYPE_NVME 0x04
-
#define SPDM_SOCKET_MAX_MESSAGE_BUFFER_SIZE 0x1200
#define SPDM_SOCKET_MAX_MSG_STATUS_LEN 0x02
+typedef enum SpdmTransportType {
+ SPDM_SOCKET_TRANSPORT_TYPE_UNSPEC = 0,
+ SPDM_SOCKET_TRANSPORT_TYPE_MCTP,
+ SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE,
+ SPDM_SOCKET_TRANSPORT_TYPE_SCSI,
+ SPDM_SOCKET_TRANSPORT_TYPE_NVME,
+ SPDM_SOCKET_TRANSPORT_TYPE_MAX
+} SpdmTransportType;
+
+extern const PropertyInfo qdev_prop_spdm_trans;
+
+#define DEFINE_PROP_SPDM_TRANS(_name, _state, _field, _default) \
+ DEFINE_PROP_UNSIGNED(_name, _state, _field, _default, \
+ qdev_prop_spdm_trans, SpdmTransportType)
+
#endif
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v8 5/5] hw/nvme: connect SPDM over NVMe Security Send/Recv
2025-10-03 11:39 [PATCH v8 0/5] NVMe: Add SPDM over the storage transport support Wilfred Mallawa
` (3 preceding siblings ...)
2025-10-03 11:39 ` [PATCH v8 4/5] spdm: define SPDM transport enum types Wilfred Mallawa
@ 2025-10-03 11:39 ` Wilfred Mallawa
2025-10-07 8:05 ` [PATCH v8 0/5] NVMe: Add SPDM over the storage transport support Klaus Jensen
5 siblings, 0 replies; 8+ messages in thread
From: Wilfred Mallawa @ 2025-10-03 11:39 UTC (permalink / raw)
To: Alistair Francis
Cc: Keith Busch, Klaus Jensen, Stefan Hajnoczi, Jonathan Cameron,
qemu-devel, qemu-block, Wilfred Mallawa, Klaus Jensen
From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
This patch extends the existing support we have for NVMe with only DoE
to also add support to SPDM over the NVMe Security Send/Recv commands.
With the new definition of the `spdm-trans` argument, users can specify
`spdm_trans=nvme` or `spdm_trans=doe`. This allows us to select the SPDM
transport respectively. SPDM over the NVMe Security Send/Recv commands
are defined in the DMTF DSP0286.
Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
docs/specs/spdm.rst | 10 +++++++--
hw/nvme/ctrl.c | 45 ++++++++++++++++++++++++++++---------
include/hw/pci/pci_device.h | 2 ++
3 files changed, 44 insertions(+), 13 deletions(-)
diff --git a/docs/specs/spdm.rst b/docs/specs/spdm.rst
index f7de080ff0..dd6cfbbd68 100644
--- a/docs/specs/spdm.rst
+++ b/docs/specs/spdm.rst
@@ -98,7 +98,7 @@ Then you can add this to your QEMU command line:
.. code-block:: shell
-drive file=blknvme,if=none,id=mynvme,format=raw \
- -device nvme,drive=mynvme,serial=deadbeef,spdm_port=2323
+ -device nvme,drive=mynvme,serial=deadbeef,spdm_port=2323,spdm_trans=doe
At which point QEMU will try to connect to the SPDM server.
@@ -113,7 +113,13 @@ of the default. So the entire QEMU command might look like this
-append "root=/dev/vda console=ttyS0" \
-net none -nographic \
-drive file=blknvme,if=none,id=mynvme,format=raw \
- -device nvme,drive=mynvme,serial=deadbeef,spdm_port=2323
+ -device nvme,drive=mynvme,serial=deadbeef,spdm_port=2323,spdm_trans=doe
+
+The `spdm_trans` argument defines the underlying transport type that is emulated
+by QEMU. For an PCIe NVMe controller, both "doe" and "nvme" are supported. Where,
+"doe" does SPDM transport over the PCIe extended capability Data Object Exchange
+(DOE), and "nvme" uses the NVMe Admin Security Send/Receive commands to
+implement the SPDM transport.
.. _DMTF:
https://www.dmtf.org/standards/SPDM
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index ad52e8f569..7928e9b0a9 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -8947,19 +8947,31 @@ static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
pcie_cap_deverr_init(pci_dev);
- /* DOE Initialisation */
+ /* SPDM Initialisation */
if (pci_dev->spdm_port) {
- uint16_t doe_offset = n->params.sriov_max_vfs ?
- PCI_CONFIG_SPACE_SIZE + PCI_ARI_SIZEOF
- : PCI_CONFIG_SPACE_SIZE;
+ switch (pci_dev->spdm_trans) {
+ case SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE:
+ uint16_t doe_offset = n->params.sriov_max_vfs ?
+ PCI_CONFIG_SPACE_SIZE + PCI_ARI_SIZEOF
+ : PCI_CONFIG_SPACE_SIZE;
- pcie_doe_init(pci_dev, &pci_dev->doe_spdm, doe_offset,
- doe_spdm_prot, true, 0);
+ pcie_doe_init(pci_dev, &pci_dev->doe_spdm, doe_offset,
+ doe_spdm_prot, true, 0);
- pci_dev->doe_spdm.spdm_socket = spdm_socket_connect(pci_dev->spdm_port,
- errp);
+ pci_dev->doe_spdm.spdm_socket =
+ spdm_socket_connect(pci_dev->spdm_port, errp);
- if (pci_dev->doe_spdm.spdm_socket < 0) {
+ if (pci_dev->doe_spdm.spdm_socket < 0) {
+ return false;
+ }
+ break;
+ case SPDM_SOCKET_TRANSPORT_TYPE_NVME:
+ n->spdm_socket = spdm_socket_connect(pci_dev->spdm_port, errp);
+ if (n->spdm_socket < 0) {
+ return false;
+ }
+ break;
+ default:
return false;
}
}
@@ -9250,9 +9262,14 @@ static void nvme_exit(PCIDevice *pci_dev)
g_free(n->cmb.buf);
}
+ /* Only one of the `spdm_socket`s below should have been setup */
+ assert(!(pci_dev->doe_spdm.spdm_socket > 0 && n->spdm_socket >= 0));
if (pci_dev->doe_spdm.spdm_socket > 0) {
spdm_socket_close(pci_dev->doe_spdm.spdm_socket,
SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE);
+ } else if (n->spdm_socket >= 0) {
+ spdm_socket_close(pci_dev->doe_spdm.spdm_socket,
+ SPDM_SOCKET_TRANSPORT_TYPE_NVME);
}
if (n->pmr.dev) {
@@ -9307,6 +9324,8 @@ static const Property nvme_props[] = {
false),
DEFINE_PROP_UINT16("mqes", NvmeCtrl, params.mqes, 0x7ff),
DEFINE_PROP_UINT16("spdm_port", PCIDevice, spdm_port, 0),
+ DEFINE_PROP_SPDM_TRANS("spdm_trans", PCIDevice, spdm_trans,
+ SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE),
DEFINE_PROP_BOOL("ctratt.mem", NvmeCtrl, params.ctratt.mem, false),
DEFINE_PROP_BOOL("atomic.dn", NvmeCtrl, params.atomic_dn, 0),
DEFINE_PROP_UINT16("atomic.awun", NvmeCtrl, params.atomic_awun, 0),
@@ -9382,7 +9401,9 @@ static void nvme_pci_write_config(PCIDevice *dev, uint32_t address,
{
uint16_t old_num_vfs = pcie_sriov_num_vfs(dev);
- if (pcie_find_capability(dev, PCI_EXT_CAP_ID_DOE)) {
+ /* DOE is only initialised if SPDM over DOE is used */
+ if (pcie_find_capability(dev, PCI_EXT_CAP_ID_DOE) &&
+ dev->spdm_trans == SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE) {
pcie_doe_write_config(&dev->doe_spdm, address, val, len);
}
pci_default_write_config(dev, address, val, len);
@@ -9393,7 +9414,9 @@ static void nvme_pci_write_config(PCIDevice *dev, uint32_t address,
static uint32_t nvme_pci_read_config(PCIDevice *dev, uint32_t address, int len)
{
uint32_t val;
- if (dev->spdm_port && pcie_find_capability(dev, PCI_EXT_CAP_ID_DOE)) {
+
+ if (dev->spdm_port && pcie_find_capability(dev, PCI_EXT_CAP_ID_DOE) &&
+ (dev->spdm_trans == SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE)) {
if (pcie_doe_read_config(&dev->doe_spdm, address, len, &val)) {
return val;
}
diff --git a/include/hw/pci/pci_device.h b/include/hw/pci/pci_device.h
index eee0338568..88ccea5011 100644
--- a/include/hw/pci/pci_device.h
+++ b/include/hw/pci/pci_device.h
@@ -4,6 +4,7 @@
#include "hw/pci/pci.h"
#include "hw/pci/pcie.h"
#include "hw/pci/pcie_doe.h"
+#include "system/spdm-socket.h"
#define TYPE_PCI_DEVICE "pci-device"
typedef struct PCIDeviceClass PCIDeviceClass;
@@ -166,6 +167,7 @@ struct PCIDevice {
/* SPDM */
uint16_t spdm_port;
+ SpdmTransportType spdm_trans;
/* DOE */
DOECap doe_spdm;
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v8 0/5] NVMe: Add SPDM over the storage transport support
2025-10-03 11:39 [PATCH v8 0/5] NVMe: Add SPDM over the storage transport support Wilfred Mallawa
` (4 preceding siblings ...)
2025-10-03 11:39 ` [PATCH v8 5/5] hw/nvme: connect SPDM over NVMe Security Send/Recv Wilfred Mallawa
@ 2025-10-07 8:05 ` Klaus Jensen
2025-10-09 2:47 ` Alistair Francis
5 siblings, 1 reply; 8+ messages in thread
From: Klaus Jensen @ 2025-10-07 8:05 UTC (permalink / raw)
To: Wilfred Mallawa
Cc: Alistair Francis, Keith Busch, Stefan Hajnoczi, Jonathan Cameron,
qemu-devel, qemu-block, Wilfred Mallawa
[-- Attachment #1: Type: text/plain, Size: 4564 bytes --]
Alistair,
I'm ready to merge this. Are you OK with me sending the pull request
including the SPDM changes, or do you want to take that part through
your tree?
On Oct 3 21:39, Wilfred Mallawa wrote:
> From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
>
> This series extends the existing SPDM support in QEMU to support the DSP0286
> SPDM Storage Transport [1] for NVMe. SPDM Storage Transport uses the NVMe
> Admin Security Send/Receive commands, as such, support for these commands have
> also been added.
>
> With the addition of a new `spdm-trans` CLI argument for NVMe controllers,
> users can specify `spdm_trans=nvme` or `spdm_trans=doe`. This allows for the
> selection of the SPDM transport. The `doe` option is the current default,
> `nvme` would select SPDM Storage Transport for the controller, where SPDM
> communication happens over the NVMe Admin Security Send/Receive commands.
>
> Support for DSP0286 already exists in `libspdm` [2] and support for the QEMU
> SPDM server is being upstreamed for `spdm-utils` [3]. This series was tested by
> using `spdm-utils` as the qemu SPDM server with SPDM Storage Transport support
> built with `libspdm` v3.8.0, and `spdm-utils` also as the SPDM requester.
>
> Changes V1 -> V2:
> - spdm_socket_rsp() now uses the new spdm_socket_send/receive()
> functions. spdm_socket_command_valid() is added to parse the
> command value incase some bytes were received (result = true) but
> with an invalid command.
>
> - Added inline comments to describe fields of
> StorageSpdmTransportHeader. Checkpatch generates warnings, but lots of
> existing code does this. The QEMU_PACKED attribute now follows the
> StorageSpdmTransportHeader struct definition.
>
> - Use extract32() instead of manual shifting/masking in
> nvme_sec_prot_spdm_send/recv().
>
> - Use g_autofree for send/recv buffer allocation
> in nvme_sec_prot_spdm_send/recv().
>
> - Added explicit fallthrough comment for checking `secp` in
> nvme_security_receive()
>
> - Added enum support for SPDM transport type, such that a user defined
> transport type string, can be mapped to the respective enum for
> internal use.
>
> Changes V2 -> V3:
> - Fixed up the incorrect use of `NVME_NO_COMPLETE` to more appropriate
> NVMe error codes in Patch [3/5]. Note that DSP0286 does not define
> error codes for transport level failures.
>
> - Removed NULL check for g_malloc0(). Should abort instead.
>
> Changes V3 -> V4:
> - Added integer overflow and MDTS checking for spdm_sends
> - Use g_try_malloc0() over g_malloc0()
> - Fixed up endian conversion for command status received from
> the server.
> - Added check to only accept SPDM send/receive if the socket
> has been setup.
> - Only show SPDM as a supported protocol if the socket
> has been setup.
>
> Changes V4 -> V5:
> - Init spdm_socket fd to -1 for NVMe. Allow 0 to be a valid file descriptor
> for the socket.
> - Move transport definitions to the patches they are used in.
> - Avoid splitting SPSP0/SPSP1. Use a uint16 instead.
> - Fixup up incorrect (uint8_t *) casting in calls to
> spdm_socket_receive/send().
> - Default to SPDM over DoE if transport is not specified.
> - Fixup alignment (style).
>
> Changes V5 -> V6:
> - Minor comment style fixup for the description of StorageSpdmTransportHeader
> - Change spdm_socket_rsp() to directly return spdm_socket_receive()
>
> Changes V6 -> V7:
> - Added an assert() to check that only one spdm socket was setup in
> nvme_exit().
> - Merged spdm_socket_close() calls into an else if for DoE/NVMe.
>
> Changes V7 -> V8:
> - Added specification references for StorageSpdmTransportHeader
>
> Wilfred Mallawa (5):
> spdm-socket: add seperate send/recv functions
> spdm: add spdm storage transport virtual header
> hw/nvme: add NVMe Admin Security SPDM support
> spdm: define SPDM transport enum types
> hw/nvme: connect SPDM over NVMe Security Send/Recv
>
> backends/spdm-socket.c | 79 +++++++++--
> docs/specs/spdm.rst | 10 +-
> hw/nvme/ctrl.c | 257 +++++++++++++++++++++++++++++++++--
> hw/nvme/nvme.h | 5 +
> include/block/nvme.h | 15 ++
> include/hw/pci/pci_device.h | 2 +
> include/system/spdm-socket.h | 65 ++++++++-
> 7 files changed, 404 insertions(+), 29 deletions(-)
>
> --
> 2.51.0
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH v8 0/5] NVMe: Add SPDM over the storage transport support
2025-10-07 8:05 ` [PATCH v8 0/5] NVMe: Add SPDM over the storage transport support Klaus Jensen
@ 2025-10-09 2:47 ` Alistair Francis
0 siblings, 0 replies; 8+ messages in thread
From: Alistair Francis @ 2025-10-09 2:47 UTC (permalink / raw)
To: Klaus Jensen
Cc: Wilfred Mallawa, Alistair Francis, Keith Busch, Stefan Hajnoczi,
Jonathan Cameron, qemu-devel, qemu-block, Wilfred Mallawa
On Tue, Oct 7, 2025 at 6:06 PM Klaus Jensen <its@irrelevant.dk> wrote:
>
> Alistair,
>
> I'm ready to merge this. Are you OK with me sending the pull request
> including the SPDM changes, or do you want to take that part through
> your tree?
Great!
Please go ahead and send the pull request including the SPDM changes.
Keeping it all together is much simpler.
Alistair
>
> On Oct 3 21:39, Wilfred Mallawa wrote:
> > From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
> >
> > This series extends the existing SPDM support in QEMU to support the DSP0286
> > SPDM Storage Transport [1] for NVMe. SPDM Storage Transport uses the NVMe
> > Admin Security Send/Receive commands, as such, support for these commands have
> > also been added.
> >
> > With the addition of a new `spdm-trans` CLI argument for NVMe controllers,
> > users can specify `spdm_trans=nvme` or `spdm_trans=doe`. This allows for the
> > selection of the SPDM transport. The `doe` option is the current default,
> > `nvme` would select SPDM Storage Transport for the controller, where SPDM
> > communication happens over the NVMe Admin Security Send/Receive commands.
> >
> > Support for DSP0286 already exists in `libspdm` [2] and support for the QEMU
> > SPDM server is being upstreamed for `spdm-utils` [3]. This series was tested by
> > using `spdm-utils` as the qemu SPDM server with SPDM Storage Transport support
> > built with `libspdm` v3.8.0, and `spdm-utils` also as the SPDM requester.
> >
> > Changes V1 -> V2:
> > - spdm_socket_rsp() now uses the new spdm_socket_send/receive()
> > functions. spdm_socket_command_valid() is added to parse the
> > command value incase some bytes were received (result = true) but
> > with an invalid command.
> >
> > - Added inline comments to describe fields of
> > StorageSpdmTransportHeader. Checkpatch generates warnings, but lots of
> > existing code does this. The QEMU_PACKED attribute now follows the
> > StorageSpdmTransportHeader struct definition.
> >
> > - Use extract32() instead of manual shifting/masking in
> > nvme_sec_prot_spdm_send/recv().
> >
> > - Use g_autofree for send/recv buffer allocation
> > in nvme_sec_prot_spdm_send/recv().
> >
> > - Added explicit fallthrough comment for checking `secp` in
> > nvme_security_receive()
> >
> > - Added enum support for SPDM transport type, such that a user defined
> > transport type string, can be mapped to the respective enum for
> > internal use.
> >
> > Changes V2 -> V3:
> > - Fixed up the incorrect use of `NVME_NO_COMPLETE` to more appropriate
> > NVMe error codes in Patch [3/5]. Note that DSP0286 does not define
> > error codes for transport level failures.
> >
> > - Removed NULL check for g_malloc0(). Should abort instead.
> >
> > Changes V3 -> V4:
> > - Added integer overflow and MDTS checking for spdm_sends
> > - Use g_try_malloc0() over g_malloc0()
> > - Fixed up endian conversion for command status received from
> > the server.
> > - Added check to only accept SPDM send/receive if the socket
> > has been setup.
> > - Only show SPDM as a supported protocol if the socket
> > has been setup.
> >
> > Changes V4 -> V5:
> > - Init spdm_socket fd to -1 for NVMe. Allow 0 to be a valid file descriptor
> > for the socket.
> > - Move transport definitions to the patches they are used in.
> > - Avoid splitting SPSP0/SPSP1. Use a uint16 instead.
> > - Fixup up incorrect (uint8_t *) casting in calls to
> > spdm_socket_receive/send().
> > - Default to SPDM over DoE if transport is not specified.
> > - Fixup alignment (style).
> >
> > Changes V5 -> V6:
> > - Minor comment style fixup for the description of StorageSpdmTransportHeader
> > - Change spdm_socket_rsp() to directly return spdm_socket_receive()
> >
> > Changes V6 -> V7:
> > - Added an assert() to check that only one spdm socket was setup in
> > nvme_exit().
> > - Merged spdm_socket_close() calls into an else if for DoE/NVMe.
> >
> > Changes V7 -> V8:
> > - Added specification references for StorageSpdmTransportHeader
> >
> > Wilfred Mallawa (5):
> > spdm-socket: add seperate send/recv functions
> > spdm: add spdm storage transport virtual header
> > hw/nvme: add NVMe Admin Security SPDM support
> > spdm: define SPDM transport enum types
> > hw/nvme: connect SPDM over NVMe Security Send/Recv
> >
> > backends/spdm-socket.c | 79 +++++++++--
> > docs/specs/spdm.rst | 10 +-
> > hw/nvme/ctrl.c | 257 +++++++++++++++++++++++++++++++++--
> > hw/nvme/nvme.h | 5 +
> > include/block/nvme.h | 15 ++
> > include/hw/pci/pci_device.h | 2 +
> > include/system/spdm-socket.h | 65 ++++++++-
> > 7 files changed, 404 insertions(+), 29 deletions(-)
> >
> > --
> > 2.51.0
> >
> >
^ permalink raw reply [flat|nested] 8+ messages in thread