libpldm: Add decode API for UpdateComponent response

The update agent sends UpdateComponent command to request updating a
specific firmware component. The decode API will decode the response
from the firmware device. This implementation works with
DSP0267_1.1.0, DSP0267_1.0.1 and DSP0267_1.0.0.

Tested: Unit tests passed

Signed-off-by: gokulsanker <gokul.sanker.v.g@intel.com>
Change-Id: Icf841a9a6feb4678206ba8b19bf8184467a42276
diff --git a/libpldm/firmware_update.c b/libpldm/firmware_update.c
index 8699bb5..3b881e5 100644
--- a/libpldm/firmware_update.c
+++ b/libpldm/firmware_update.c
@@ -119,6 +119,55 @@
 	}

 }

 

+/** @brief Check whether ComponentCompatibilityResponse is valid

+ *

+ *  @return true if ComponentCompatibilityResponse is valid, false if not

+ */

+static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)

+{

+	switch (comp_compatibility_resp) {

+	case PLDM_CCR_COMP_CAN_BE_UPDATED:

+	case PLDM_CCR_COMP_CANNOT_BE_UPDATED:

+		return true;

+

+	default:

+		return false;

+	}

+}

+

+/** @brief Check whether ComponentCompatibilityResponse Code is valid

+ *

+ *  @return true if ComponentCompatibilityResponse Code is valid, false if not

+ */

+static bool

+is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)

+{

+	switch (comp_compatibility_resp_code) {

+	case PLDM_CCRC_NO_RESPONSE_CODE:

+	case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:

+	case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:

+	case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:

+	case PLDM_CCRC_COMP_CONFLICT:

+	case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:

+	case PLDM_CCRC_COMP_NOT_SUPPORTED:

+	case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:

+	case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:

+	case PLDM_CCRC_COMP_INFO_NO_MATCH:

+	case PLDM_CCRC_COMP_VER_STR_IDENTICAL:

+	case PLDM_CCRC_COMP_VER_STR_LOWER:

+		return true;

+

+	default:

+		if (comp_compatibility_resp_code >=

+			PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&

+		    comp_compatibility_resp_code <=

+			PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {

+			return true;

+		}

+		return false;

+	}

+}

+

 int decode_pldm_package_header_info(

     const uint8_t *data, size_t length,

     struct pldm_package_header_information *package_header_info,

@@ -897,4 +946,51 @@
 	       comp_ver_str->ptr, comp_ver_str->length);

 

 	return PLDM_SUCCESS;

+}

+

+int decode_update_component_resp(const struct pldm_msg *msg,

+				 size_t payload_length,

+				 uint8_t *completion_code,

+				 uint8_t *comp_compatability_resp,

+				 uint8_t *comp_compatability_resp_code,

+				 bitfield32_t *update_option_flags_enabled,

+				 uint16_t *time_before_req_fw_data)

+{

+	if (msg == NULL || completion_code == NULL ||

+	    comp_compatability_resp == NULL ||

+	    comp_compatability_resp_code == NULL ||

+	    update_option_flags_enabled == NULL ||

+	    time_before_req_fw_data == NULL || !payload_length) {

+		return PLDM_ERROR_INVALID_DATA;

+	}

+

+	*completion_code = msg->payload[0];

+	if (*completion_code != PLDM_SUCCESS) {

+		return PLDM_SUCCESS;

+	}

+

+	if (payload_length != sizeof(struct pldm_update_component_resp)) {

+		return PLDM_ERROR_INVALID_LENGTH;

+	}

+

+	struct pldm_update_component_resp *response =

+	    (struct pldm_update_component_resp *)msg->payload;

+

+	if (!is_comp_compatibility_resp_valid(

+		response->comp_compatability_resp)) {

+		return PLDM_ERROR_INVALID_DATA;

+	}

+

+	if (!is_comp_compatibility_resp_code_valid(

+		response->comp_compatability_resp_code)) {

+		return PLDM_ERROR_INVALID_DATA;

+	}

+

+	*comp_compatability_resp = response->comp_compatability_resp;

+	*comp_compatability_resp_code = response->comp_compatability_resp_code;

+	update_option_flags_enabled->value =

+	    le32toh(response->update_option_flags_enabled.value);

+	*time_before_req_fw_data = le16toh(response->time_before_req_fw_data);

+

+	return PLDM_SUCCESS;

 }
\ No newline at end of file