Implement GetPLDMVersion command

This commit implements the GetPLDMVersion which is required
as part of the base PLDM support to know the version of a
given PLDM type.

Change-Id: I1bcbd938c5b6833f62e0ee2f474b04d76b6970d9
Signed-off-by: Sampa Misra <sampmisr@in.ibm.com>
diff --git a/libpldm/base.c b/libpldm/base.c
index c85aead..7354fb1 100644
--- a/libpldm/base.c
+++ b/libpldm/base.c
@@ -161,3 +161,100 @@
 
 	return PLDM_SUCCESS;
 }
+
+int encode_get_version_req(uint8_t instance_id, uint32_t transfer_handle,
+			   uint8_t transfer_opflag, uint8_t type,
+			   struct pldm_msg *msg)
+{
+	struct pldm_header_info header = {0};
+	int rc = PLDM_SUCCESS;
+
+	if (NULL == msg) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	header.msg_type = PLDM_REQUEST;
+	header.instance = instance_id;
+	header.pldm_type = PLDM_BASE;
+	header.command = PLDM_GET_PLDM_VERSION;
+
+	if ((rc = pack_pldm_header(&header, &(msg->hdr))) > PLDM_SUCCESS) {
+		return rc;
+	}
+
+	uint8_t *dst = msg->body.payload;
+	transfer_handle = htole32(transfer_handle);
+	memcpy(dst, &transfer_handle, sizeof(transfer_handle));
+	dst += sizeof(transfer_handle);
+
+	memcpy(dst, &transfer_opflag, sizeof(transfer_opflag));
+	dst += sizeof(transfer_opflag);
+
+	memcpy(dst, &type, sizeof(type));
+
+	return PLDM_SUCCESS;
+}
+
+int encode_get_version_resp(uint8_t instance_id, uint8_t completion_code,
+			    uint32_t next_transfer_handle,
+			    uint8_t transfer_flag,
+			    const struct pldm_version *version_data,
+			    size_t version_size, struct pldm_msg *msg)
+{
+	struct pldm_header_info header = {0};
+	int rc = PLDM_SUCCESS;
+
+	msg->body.payload[0] = completion_code;
+	if (msg->body.payload[0] == PLDM_SUCCESS) {
+
+		header.msg_type = PLDM_RESPONSE;
+		header.instance = instance_id;
+		header.pldm_type = PLDM_BASE;
+		header.command = PLDM_GET_PLDM_VERSION;
+
+		if ((rc = pack_pldm_header(&header, &(msg->hdr))) >
+		    PLDM_SUCCESS) {
+			return rc;
+		}
+		uint8_t *dst = msg->body.payload + sizeof(msg->body.payload[0]);
+
+		next_transfer_handle = htole32(next_transfer_handle);
+
+		memcpy(dst, &next_transfer_handle,
+		       sizeof(next_transfer_handle));
+		dst += sizeof(next_transfer_handle);
+		memcpy(dst, &transfer_flag, sizeof(transfer_flag));
+
+		dst += sizeof(transfer_flag);
+		memcpy(dst, version_data, version_size);
+	}
+	return PLDM_SUCCESS;
+}
+
+int decode_get_version_req(const struct pldm_msg_payload *msg,
+			   uint32_t *transfer_handle, uint8_t *transfer_opflag,
+			   uint8_t *type)
+{
+	const uint8_t *start = msg->payload;
+	*transfer_handle = le32toh(*((uint32_t *)start));
+	*transfer_opflag = *(start + sizeof(*transfer_handle));
+	*type = *(start + sizeof(*transfer_handle) + sizeof(*transfer_opflag));
+
+	return PLDM_SUCCESS;
+}
+
+int decode_get_version_resp(const struct pldm_msg_payload *msg,
+			    uint32_t *next_transfer_handle,
+			    uint8_t *transfer_flag,
+			    struct pldm_version *version)
+{
+	const uint8_t *start = msg->payload + sizeof(uint8_t);
+	*next_transfer_handle = le32toh(*((uint32_t *)start));
+	*transfer_flag = *(start + sizeof(*next_transfer_handle));
+
+	*version =
+	    *((struct pldm_version *)(start + sizeof(*next_transfer_handle) +
+				      sizeof(*transfer_flag)));
+
+	return PLDM_SUCCESS;
+}