libpldm/base: Add MultipartReceive req decoding

Adds MultipartReceive (0x09) request decoding, per DSP0240 v1.1.0
section 8.6.5.

Signed-off-by: Joe Komlodi <komlodi@google.com>
Change-Id: I8d37a9abb7361cc7a238b5b322907739343ff473
diff --git a/libpldm/base.c b/libpldm/base.c
index 83cd22a..9a5ae09 100644
--- a/libpldm/base.c
+++ b/libpldm/base.c
@@ -398,6 +398,56 @@
 	return PLDM_SUCCESS;
 }
 
+int decode_multipart_receive_req(
+    const struct pldm_msg *msg, size_t payload_length, uint8_t *pldm_type,
+    uint8_t *transfer_opflag, uint32_t *transfer_ctx, uint32_t *transfer_handle,
+    uint32_t *section_offset, uint32_t *section_length)
+{
+	if (msg == NULL || pldm_type == NULL || transfer_opflag == NULL ||
+	    transfer_ctx == NULL || transfer_handle == NULL ||
+	    section_offset == NULL || section_length == NULL) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	if (payload_length != PLDM_MULTIPART_RECEIVE_REQ_BYTES) {
+		return PLDM_ERROR_INVALID_LENGTH;
+	}
+
+	struct pldm_multipart_receive_req *request =
+	    (struct pldm_multipart_receive_req *)msg->payload;
+
+	if (request->pldm_type != PLDM_BASE) {
+		return PLDM_ERROR_INVALID_PLDM_TYPE;
+	}
+
+	// Any enum value above PLDM_XFER_CURRENT_PART is invalid.
+	if (request->transfer_opflag > PLDM_XFER_CURRENT_PART) {
+		return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
+	}
+
+	// A section offset of 0 is only valid on FIRST_PART or COMPLETE Xfers.
+	uint32_t sec_offset = le32toh(request->section_offset);
+	if (sec_offset == 0 &&
+	    (request->transfer_opflag != PLDM_XFER_FIRST_PART &&
+	     request->transfer_opflag != PLDM_XFER_COMPLETE)) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	uint32_t handle = le32toh(request->transfer_handle);
+	if (handle == 0 && request->transfer_opflag != PLDM_XFER_COMPLETE) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	*pldm_type = request->pldm_type;
+	*transfer_opflag = request->transfer_opflag;
+	*transfer_ctx = request->transfer_ctx;
+	*transfer_handle = handle;
+	*section_offset = sec_offset;
+	*section_length = le32toh(request->section_length);
+
+	return PLDM_SUCCESS;
+}
+
 int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command,
 			uint8_t cc, struct pldm_msg *msg)
 {