decode APIs: decode completion code as well

Have the decode APIs decode PLDM completion code as well, instead on
relying on the caller to do this. If the code indicates failure, bail
out from further decoding.

Change-Id: I43c9cc924b1d182df40fbf05702cd89a7d5e5a3f
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/libpldm/base.c b/libpldm/base.c
index 3aca2c3..afba5a1 100644
--- a/libpldm/base.c
+++ b/libpldm/base.c
@@ -165,11 +165,18 @@
 }
 
 int decode_get_types_resp(const struct pldm_msg_payload *msg,
-			  bitfield8_t *types)
+			  uint8_t *completion_code, bitfield8_t *types)
 {
-	if (msg == NULL || types == NULL) {
+	if (msg == NULL || types == NULL || msg->payload == NULL ||
+	    completion_code == NULL) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
+
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	};
+
 	const uint8_t *src = msg->payload + sizeof(uint8_t);
 	memcpy(&(types->byte), src, PLDM_MAX_TYPES / 8);
 
@@ -177,11 +184,18 @@
 }
 
 int decode_get_commands_resp(const struct pldm_msg_payload *msg,
-			     bitfield8_t *commands)
+			     uint8_t *completion_code, bitfield8_t *commands)
 {
-	if (msg == NULL || commands == NULL) {
+	if (msg == NULL || commands == NULL || msg->payload == NULL ||
+	    completion_code == NULL) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
+
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	};
+
 	const uint8_t *src = msg->payload + sizeof(uint8_t);
 	memcpy(&(commands->byte), src, PLDM_MAX_CMDS_PER_TYPE / 8);
 
@@ -269,9 +283,21 @@
 }
 
 int decode_get_version_resp(const struct pldm_msg_payload *msg,
+			    uint8_t *completion_code,
 			    uint32_t *next_transfer_handle,
 			    uint8_t *transfer_flag, ver32_t *version)
 {
+	if (msg == NULL || next_transfer_handle == NULL ||
+	    transfer_flag == NULL || msg->payload == NULL ||
+	    completion_code == NULL) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	};
+
 	const uint8_t *start = msg->payload + sizeof(uint8_t);
 	*next_transfer_handle = le32toh(*((uint32_t *)start));
 	*transfer_flag = *(start + sizeof(*next_transfer_handle));
diff --git a/libpldm/base.h b/libpldm/base.h
index e0362f4..4fb94fb 100644
--- a/libpldm/base.h
+++ b/libpldm/base.h
@@ -173,12 +173,13 @@
 /** @brief Decode a GetPLDMTypes response message
  *
  *  @param[in] msg - Response message payload
+ *  @param[out] completion_code - Pointer to response msg's PLDM completion code
  *  @param[out] types - pointer to array bitfield8_t[8] containing supported
  *              types (MAX_TYPES/8) = 8), as per DSP0240
  *  @return pldm_completion_codes
  */
 int decode_get_types_resp(const struct pldm_msg_payload *msg,
-			  bitfield8_t *types);
+			  uint8_t *completion_code, bitfield8_t *types);
 
 /* GetPLDMCommands */
 
@@ -198,12 +199,13 @@
 /** @brief Decode a GetPLDMCommands response message
  *
  *  @param[in] msg - Response message payload
+ *  @param[out] completion_code - Pointer to response msg's PLDM completion code
  *  @param[in] commands - pointer to array bitfield8_t[32] containing supported
  *             commands (PLDM_MAX_CMDS_PER_TYPE/8) = 32), as per DSP0240
  *  @return pldm_completion_codes
  */
 int decode_get_commands_resp(const struct pldm_msg_payload *msg,
-			     bitfield8_t *commands);
+			     uint8_t *completion_code, bitfield8_t *commands);
 
 /* GetPLDMVersion */
 
@@ -228,11 +230,13 @@
 /** @brief Decode a GetPLDMVersion response message
  *
  *  @param[in] msg - Response message payload
+ *  @param[out] completion_code - Pointer to response msg's PLDM completion code
  *  @param[out] next_transfer_handle - the next handle for the next part of data
  *  @param[out] transfer_flag - flag to indicate the part of data
  *  @return pldm_completion_codes
  */
 int decode_get_version_resp(const struct pldm_msg_payload *msg,
+			    uint8_t *completion_code,
 			    uint32_t *next_transfer_handle,
 			    uint8_t *transfer_flag, ver32_t *version);
 
diff --git a/test/libpldm_base_test.cpp b/test/libpldm_base_test.cpp
index 24ad513..d6bdc47 100644
--- a/test/libpldm_base_test.cpp
+++ b/test/libpldm_base_test.cpp
@@ -273,10 +273,13 @@
     response.payload[2] = 2;
     response.payload[3] = 3;
     std::array<bitfield8_t, PLDM_MAX_TYPES / 8> outTypes{};
+    uint8_t completion_code;
 
-    auto rc = decode_get_types_resp(&response, outTypes.data());
+    auto rc =
+        decode_get_types_resp(&response, &completion_code, outTypes.data());
 
     ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(completion_code, PLDM_SUCCESS);
     ASSERT_EQ(response.payload[1], outTypes[0].byte);
     ASSERT_EQ(response.payload[2], outTypes[1].byte);
     ASSERT_EQ(response.payload[3], outTypes[2].byte);
@@ -292,10 +295,13 @@
     response.payload[2] = 2;
     response.payload[3] = 3;
     std::array<bitfield8_t, PLDM_MAX_CMDS_PER_TYPE / 8> outTypes{};
+    uint8_t completion_code;
 
-    auto rc = decode_get_commands_resp(&response, outTypes.data());
+    auto rc =
+        decode_get_commands_resp(&response, &completion_code, outTypes.data());
 
     ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(completion_code, PLDM_SUCCESS);
     ASSERT_EQ(response.payload[1], outTypes[0].byte);
     ASSERT_EQ(response.payload[2], outTypes[1].byte);
     ASSERT_EQ(response.payload[3], outTypes[2].byte);
@@ -392,6 +398,7 @@
     uint8_t completionCode = 0;
     ver32_t version = {0xFF, 0xFF, 0xFF, 0xFF};
     ver32_t versionOut;
+    uint8_t completion_code;
 
     memcpy(response.payload + sizeof(completionCode), &transferHandle,
            sizeof(transferHandle));
@@ -401,8 +408,8 @@
                sizeof(flag),
            &version, sizeof(version));
 
-    auto rc = decode_get_version_resp(&response, &retTransferHandle, &retFlag,
-                                      &versionOut);
+    auto rc = decode_get_version_resp(
+        &response, &completion_code, &retTransferHandle, &retFlag, &versionOut);
     ASSERT_EQ(rc, PLDM_SUCCESS);
     ASSERT_EQ(transferHandle, retTransferHandle);
     ASSERT_EQ(flag, retFlag);