148761c62SAndrew Jeffery /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2830c1eb4SAndrew Jeffery #include "api.h"
3b6ef35b4SChris Wang #include "dsp/base.h"
448761c62SAndrew Jeffery #include "msgbuf.h"
548761c62SAndrew Jeffery #include <libpldm/firmware_update.h>
648761c62SAndrew Jeffery #include <libpldm/utils.h>
748761c62SAndrew Jeffery
848761c62SAndrew Jeffery #include <endian.h>
948761c62SAndrew Jeffery #include <stdbool.h>
1048761c62SAndrew Jeffery #include <string.h>
1148761c62SAndrew Jeffery
12cf9a2df3SMatt Johnston static_assert(PLDM_FIRMWARE_MAX_STRING <= UINT8_MAX, "too large");
13cf9a2df3SMatt Johnston
1448761c62SAndrew Jeffery /** @brief Check whether string type value is valid
1548761c62SAndrew Jeffery *
1648761c62SAndrew Jeffery * @return true if string type value is valid, false if not
1748761c62SAndrew Jeffery */
is_string_type_valid(uint8_t string_type)1848761c62SAndrew Jeffery static bool is_string_type_valid(uint8_t string_type)
1948761c62SAndrew Jeffery {
2048761c62SAndrew Jeffery switch (string_type) {
2148761c62SAndrew Jeffery case PLDM_STR_TYPE_UNKNOWN:
2248761c62SAndrew Jeffery return false;
2348761c62SAndrew Jeffery case PLDM_STR_TYPE_ASCII:
2448761c62SAndrew Jeffery case PLDM_STR_TYPE_UTF_8:
2548761c62SAndrew Jeffery case PLDM_STR_TYPE_UTF_16:
2648761c62SAndrew Jeffery case PLDM_STR_TYPE_UTF_16LE:
2748761c62SAndrew Jeffery case PLDM_STR_TYPE_UTF_16BE:
2848761c62SAndrew Jeffery return true;
2948761c62SAndrew Jeffery default:
3048761c62SAndrew Jeffery return false;
3148761c62SAndrew Jeffery }
3248761c62SAndrew Jeffery }
3348761c62SAndrew Jeffery
3448761c62SAndrew Jeffery /** @brief Return the length of the descriptor type described in firmware update
3548761c62SAndrew Jeffery * specification
3648761c62SAndrew Jeffery *
3748761c62SAndrew Jeffery * @return length of the descriptor type if descriptor type is valid else
3848761c62SAndrew Jeffery * return 0
3948761c62SAndrew Jeffery */
get_descriptor_type_length(uint16_t descriptor_type)4048761c62SAndrew Jeffery static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
4148761c62SAndrew Jeffery {
4248761c62SAndrew Jeffery switch (descriptor_type) {
4348761c62SAndrew Jeffery case PLDM_FWUP_PCI_VENDOR_ID:
4448761c62SAndrew Jeffery return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
4548761c62SAndrew Jeffery case PLDM_FWUP_IANA_ENTERPRISE_ID:
4648761c62SAndrew Jeffery return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
4748761c62SAndrew Jeffery case PLDM_FWUP_UUID:
4848761c62SAndrew Jeffery return PLDM_FWUP_UUID_LENGTH;
4948761c62SAndrew Jeffery case PLDM_FWUP_PNP_VENDOR_ID:
5048761c62SAndrew Jeffery return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
5148761c62SAndrew Jeffery case PLDM_FWUP_ACPI_VENDOR_ID:
5248761c62SAndrew Jeffery return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
5348761c62SAndrew Jeffery case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
5448761c62SAndrew Jeffery return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
5548761c62SAndrew Jeffery case PLDM_FWUP_SCSI_VENDOR_ID:
5648761c62SAndrew Jeffery return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
5748761c62SAndrew Jeffery case PLDM_FWUP_PCI_DEVICE_ID:
5848761c62SAndrew Jeffery return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
5948761c62SAndrew Jeffery case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
6048761c62SAndrew Jeffery return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
6148761c62SAndrew Jeffery case PLDM_FWUP_PCI_SUBSYSTEM_ID:
6248761c62SAndrew Jeffery return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
6348761c62SAndrew Jeffery case PLDM_FWUP_PCI_REVISION_ID:
6448761c62SAndrew Jeffery return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
6548761c62SAndrew Jeffery case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
6648761c62SAndrew Jeffery return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
6748761c62SAndrew Jeffery case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
6848761c62SAndrew Jeffery return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
6948761c62SAndrew Jeffery case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
7048761c62SAndrew Jeffery return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
7148761c62SAndrew Jeffery case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
7248761c62SAndrew Jeffery return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
7348761c62SAndrew Jeffery case PLDM_FWUP_SCSI_PRODUCT_ID:
7448761c62SAndrew Jeffery return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
7548761c62SAndrew Jeffery case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
7648761c62SAndrew Jeffery return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
7748761c62SAndrew Jeffery default:
7848761c62SAndrew Jeffery return 0;
7948761c62SAndrew Jeffery }
8048761c62SAndrew Jeffery }
8148761c62SAndrew Jeffery
is_downstream_device_update_support_valid(uint8_t resp)8248761c62SAndrew Jeffery static bool is_downstream_device_update_support_valid(uint8_t resp)
8348761c62SAndrew Jeffery {
8448761c62SAndrew Jeffery switch (resp) {
8548761c62SAndrew Jeffery case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
8648761c62SAndrew Jeffery case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
8748761c62SAndrew Jeffery return true;
8848761c62SAndrew Jeffery default:
8948761c62SAndrew Jeffery return false;
9048761c62SAndrew Jeffery }
9148761c62SAndrew Jeffery }
9248761c62SAndrew Jeffery
9348761c62SAndrew Jeffery static bool
is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)9448761c62SAndrew Jeffery is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)
9548761c62SAndrew Jeffery {
9648761c62SAndrew Jeffery switch (transfer_op_flag) {
9748761c62SAndrew Jeffery case PLDM_GET_NEXTPART:
9848761c62SAndrew Jeffery case PLDM_GET_FIRSTPART:
9948761c62SAndrew Jeffery return true;
10048761c62SAndrew Jeffery default:
10148761c62SAndrew Jeffery return false;
10248761c62SAndrew Jeffery }
10348761c62SAndrew Jeffery }
10448761c62SAndrew Jeffery
10548761c62SAndrew Jeffery /** @brief Check whether ComponentResponse is valid
10648761c62SAndrew Jeffery *
10748761c62SAndrew Jeffery * @return true if ComponentResponse is valid, false if not
10848761c62SAndrew Jeffery */
is_comp_resp_valid(uint8_t comp_resp)10948761c62SAndrew Jeffery static bool is_comp_resp_valid(uint8_t comp_resp)
11048761c62SAndrew Jeffery {
11148761c62SAndrew Jeffery switch (comp_resp) {
11248761c62SAndrew Jeffery case PLDM_CR_COMP_CAN_BE_UPDATED:
11348761c62SAndrew Jeffery case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
11448761c62SAndrew Jeffery return true;
11548761c62SAndrew Jeffery
11648761c62SAndrew Jeffery default:
11748761c62SAndrew Jeffery return false;
11848761c62SAndrew Jeffery }
11948761c62SAndrew Jeffery }
12048761c62SAndrew Jeffery
12148761c62SAndrew Jeffery /** @brief Check whether ComponentResponseCode is valid
12248761c62SAndrew Jeffery *
12348761c62SAndrew Jeffery * @return true if ComponentResponseCode is valid, false if not
12448761c62SAndrew Jeffery */
is_comp_resp_code_valid(uint8_t comp_resp_code)12548761c62SAndrew Jeffery static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
12648761c62SAndrew Jeffery {
12748761c62SAndrew Jeffery switch (comp_resp_code) {
12848761c62SAndrew Jeffery case PLDM_CRC_COMP_CAN_BE_UPDATED:
12948761c62SAndrew Jeffery case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
13048761c62SAndrew Jeffery case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
13148761c62SAndrew Jeffery case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
13248761c62SAndrew Jeffery case PLDM_CRC_COMP_CONFLICT:
13348761c62SAndrew Jeffery case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
13448761c62SAndrew Jeffery case PLDM_CRC_COMP_NOT_SUPPORTED:
13548761c62SAndrew Jeffery case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
13648761c62SAndrew Jeffery case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
13748761c62SAndrew Jeffery case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
13848761c62SAndrew Jeffery case PLDM_CRC_COMP_VER_STR_IDENTICAL:
13948761c62SAndrew Jeffery case PLDM_CRC_COMP_VER_STR_LOWER:
14048761c62SAndrew Jeffery return true;
14148761c62SAndrew Jeffery
14248761c62SAndrew Jeffery default:
14348761c62SAndrew Jeffery if (comp_resp_code >=
14448761c62SAndrew Jeffery PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
14548761c62SAndrew Jeffery comp_resp_code <=
14648761c62SAndrew Jeffery PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
14748761c62SAndrew Jeffery return true;
14848761c62SAndrew Jeffery }
14948761c62SAndrew Jeffery return false;
15048761c62SAndrew Jeffery }
15148761c62SAndrew Jeffery }
15248761c62SAndrew Jeffery
15348761c62SAndrew Jeffery /** @brief Check whether ComponentCompatibilityResponse is valid
15448761c62SAndrew Jeffery *
15548761c62SAndrew Jeffery * @return true if ComponentCompatibilityResponse is valid, false if not
15648761c62SAndrew Jeffery */
is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)15748761c62SAndrew Jeffery static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
15848761c62SAndrew Jeffery {
15948761c62SAndrew Jeffery switch (comp_compatibility_resp) {
16048761c62SAndrew Jeffery case PLDM_CCR_COMP_CAN_BE_UPDATED:
16148761c62SAndrew Jeffery case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
16248761c62SAndrew Jeffery return true;
16348761c62SAndrew Jeffery
16448761c62SAndrew Jeffery default:
16548761c62SAndrew Jeffery return false;
16648761c62SAndrew Jeffery }
16748761c62SAndrew Jeffery }
16848761c62SAndrew Jeffery
16948761c62SAndrew Jeffery /** @brief Check whether ComponentCompatibilityResponse Code is valid
17048761c62SAndrew Jeffery *
17148761c62SAndrew Jeffery * @return true if ComponentCompatibilityResponse Code is valid, false if not
17248761c62SAndrew Jeffery */
17348761c62SAndrew Jeffery static bool
is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)17448761c62SAndrew Jeffery is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
17548761c62SAndrew Jeffery {
17648761c62SAndrew Jeffery switch (comp_compatibility_resp_code) {
17748761c62SAndrew Jeffery case PLDM_CCRC_NO_RESPONSE_CODE:
17848761c62SAndrew Jeffery case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
17948761c62SAndrew Jeffery case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
18048761c62SAndrew Jeffery case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
18148761c62SAndrew Jeffery case PLDM_CCRC_COMP_CONFLICT:
18248761c62SAndrew Jeffery case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
18348761c62SAndrew Jeffery case PLDM_CCRC_COMP_NOT_SUPPORTED:
18448761c62SAndrew Jeffery case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
18548761c62SAndrew Jeffery case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
18648761c62SAndrew Jeffery case PLDM_CCRC_COMP_INFO_NO_MATCH:
18748761c62SAndrew Jeffery case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
18848761c62SAndrew Jeffery case PLDM_CCRC_COMP_VER_STR_LOWER:
18948761c62SAndrew Jeffery return true;
19048761c62SAndrew Jeffery
19148761c62SAndrew Jeffery default:
19248761c62SAndrew Jeffery if (comp_compatibility_resp_code >=
19348761c62SAndrew Jeffery PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
19448761c62SAndrew Jeffery comp_compatibility_resp_code <=
19548761c62SAndrew Jeffery PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
19648761c62SAndrew Jeffery return true;
19748761c62SAndrew Jeffery }
19848761c62SAndrew Jeffery return false;
19948761c62SAndrew Jeffery }
20048761c62SAndrew Jeffery }
20148761c62SAndrew Jeffery
20248761c62SAndrew Jeffery /** @brief Check whether SelfContainedActivationRequest is valid
20348761c62SAndrew Jeffery *
20448761c62SAndrew Jeffery * @return true if SelfContainedActivationRequest is valid, false if not
20548761c62SAndrew Jeffery */
20648761c62SAndrew Jeffery static bool
is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)20748761c62SAndrew Jeffery is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
20848761c62SAndrew Jeffery {
20948761c62SAndrew Jeffery switch (self_contained_activation_req) {
21048761c62SAndrew Jeffery case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
21148761c62SAndrew Jeffery case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
21248761c62SAndrew Jeffery return true;
21348761c62SAndrew Jeffery
21448761c62SAndrew Jeffery default:
21548761c62SAndrew Jeffery return false;
21648761c62SAndrew Jeffery }
21748761c62SAndrew Jeffery }
21848761c62SAndrew Jeffery
21948761c62SAndrew Jeffery /** @brief Check if current or previous status in GetStatus command response is
22048761c62SAndrew Jeffery * valid
22148761c62SAndrew Jeffery *
22248761c62SAndrew Jeffery * @param[in] state - current or previous different state machine state of
22348761c62SAndrew Jeffery * the FD
22448761c62SAndrew Jeffery * @return true if state is valid, false if not
22548761c62SAndrew Jeffery */
is_state_valid(uint8_t state)22648761c62SAndrew Jeffery static bool is_state_valid(uint8_t state)
22748761c62SAndrew Jeffery {
22848761c62SAndrew Jeffery switch (state) {
22948761c62SAndrew Jeffery case PLDM_FD_STATE_IDLE:
23048761c62SAndrew Jeffery case PLDM_FD_STATE_LEARN_COMPONENTS:
23148761c62SAndrew Jeffery case PLDM_FD_STATE_READY_XFER:
23248761c62SAndrew Jeffery case PLDM_FD_STATE_DOWNLOAD:
23348761c62SAndrew Jeffery case PLDM_FD_STATE_VERIFY:
23448761c62SAndrew Jeffery case PLDM_FD_STATE_APPLY:
23548761c62SAndrew Jeffery case PLDM_FD_STATE_ACTIVATE:
23648761c62SAndrew Jeffery return true;
23748761c62SAndrew Jeffery
23848761c62SAndrew Jeffery default:
23948761c62SAndrew Jeffery return false;
24048761c62SAndrew Jeffery }
24148761c62SAndrew Jeffery }
24248761c62SAndrew Jeffery
24348761c62SAndrew Jeffery /** @brief Check if aux state in GetStatus command response is valid
24448761c62SAndrew Jeffery *
24548761c62SAndrew Jeffery * @param[in] aux_state - provides additional information to the UA to describe
24648761c62SAndrew Jeffery * the current operation state of the FD/FDP
24748761c62SAndrew Jeffery *
24848761c62SAndrew Jeffery * @return true if aux state is valid, false if not
24948761c62SAndrew Jeffery */
is_aux_state_valid(uint8_t aux_state)25048761c62SAndrew Jeffery static bool is_aux_state_valid(uint8_t aux_state)
25148761c62SAndrew Jeffery {
25248761c62SAndrew Jeffery switch (aux_state) {
25348761c62SAndrew Jeffery case PLDM_FD_OPERATION_IN_PROGRESS:
25448761c62SAndrew Jeffery case PLDM_FD_OPERATION_SUCCESSFUL:
25548761c62SAndrew Jeffery case PLDM_FD_OPERATION_FAILED:
25648761c62SAndrew Jeffery case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
25748761c62SAndrew Jeffery return true;
25848761c62SAndrew Jeffery
25948761c62SAndrew Jeffery default:
26048761c62SAndrew Jeffery return false;
26148761c62SAndrew Jeffery }
26248761c62SAndrew Jeffery }
26348761c62SAndrew Jeffery
26448761c62SAndrew Jeffery /** @brief Check if aux state status in GetStatus command response is valid
26548761c62SAndrew Jeffery *
26648761c62SAndrew Jeffery * @param[in] aux_state_status - aux state status
26748761c62SAndrew Jeffery *
26848761c62SAndrew Jeffery * @return true if aux state status is valid, false if not
26948761c62SAndrew Jeffery */
is_aux_state_status_valid(uint8_t aux_state_status)27048761c62SAndrew Jeffery static bool is_aux_state_status_valid(uint8_t aux_state_status)
27148761c62SAndrew Jeffery {
27248761c62SAndrew Jeffery if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
27348761c62SAndrew Jeffery aux_state_status == PLDM_FD_TIMEOUT ||
27448761c62SAndrew Jeffery aux_state_status == PLDM_FD_GENERIC_ERROR ||
27548761c62SAndrew Jeffery (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
27648761c62SAndrew Jeffery aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
27748761c62SAndrew Jeffery return true;
27848761c62SAndrew Jeffery }
27948761c62SAndrew Jeffery
28048761c62SAndrew Jeffery return false;
28148761c62SAndrew Jeffery }
28248761c62SAndrew Jeffery
28348761c62SAndrew Jeffery /** @brief Check if reason code in GetStatus command response is valid
28448761c62SAndrew Jeffery *
28548761c62SAndrew Jeffery * @param[in] reason_code - provides the reason for why the current state
28648761c62SAndrew Jeffery * entered the IDLE state
28748761c62SAndrew Jeffery *
28848761c62SAndrew Jeffery * @return true if reason code is valid, false if not
28948761c62SAndrew Jeffery */
is_reason_code_valid(uint8_t reason_code)29048761c62SAndrew Jeffery static bool is_reason_code_valid(uint8_t reason_code)
29148761c62SAndrew Jeffery {
29248761c62SAndrew Jeffery switch (reason_code) {
29348761c62SAndrew Jeffery case PLDM_FD_INITIALIZATION:
29448761c62SAndrew Jeffery case PLDM_FD_ACTIVATE_FW:
29548761c62SAndrew Jeffery case PLDM_FD_CANCEL_UPDATE:
29648761c62SAndrew Jeffery case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
29748761c62SAndrew Jeffery case PLDM_FD_TIMEOUT_READY_XFER:
29848761c62SAndrew Jeffery case PLDM_FD_TIMEOUT_DOWNLOAD:
29948761c62SAndrew Jeffery case PLDM_FD_TIMEOUT_VERIFY:
30048761c62SAndrew Jeffery case PLDM_FD_TIMEOUT_APPLY:
30148761c62SAndrew Jeffery return true;
30248761c62SAndrew Jeffery
30348761c62SAndrew Jeffery default:
30448761c62SAndrew Jeffery if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
30548761c62SAndrew Jeffery return true;
30648761c62SAndrew Jeffery }
30748761c62SAndrew Jeffery return false;
30848761c62SAndrew Jeffery }
30948761c62SAndrew Jeffery }
31048761c62SAndrew Jeffery
31148761c62SAndrew Jeffery /** @brief Check if non functioning component indication in CancelUpdate
31248761c62SAndrew Jeffery * response is valid
31348761c62SAndrew Jeffery *
31448761c62SAndrew Jeffery * @return true if non functioning component indication is valid, false if not
31548761c62SAndrew Jeffery */
is_non_functioning_component_indication_valid(bool8_t non_functioning_component_indication)31648761c62SAndrew Jeffery static bool is_non_functioning_component_indication_valid(
31748761c62SAndrew Jeffery bool8_t non_functioning_component_indication)
31848761c62SAndrew Jeffery {
31948761c62SAndrew Jeffery switch (non_functioning_component_indication) {
32048761c62SAndrew Jeffery case PLDM_FWUP_COMPONENTS_FUNCTIONING:
32148761c62SAndrew Jeffery case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
32248761c62SAndrew Jeffery return true;
32348761c62SAndrew Jeffery
32448761c62SAndrew Jeffery default:
32548761c62SAndrew Jeffery return false;
32648761c62SAndrew Jeffery }
32748761c62SAndrew Jeffery }
32848761c62SAndrew Jeffery
decode_pldm_package_header_info_errno(const uint8_t * data,size_t length,struct pldm_package_header_information * package_header_info,struct variable_field * package_version_str)329779e9dbdSAndrew Jeffery static int decode_pldm_package_header_info_errno(
33048761c62SAndrew Jeffery const uint8_t *data, size_t length,
33148761c62SAndrew Jeffery struct pldm_package_header_information *package_header_info,
33248761c62SAndrew Jeffery struct variable_field *package_version_str)
33348761c62SAndrew Jeffery {
33448761c62SAndrew Jeffery if (data == NULL || package_header_info == NULL ||
33548761c62SAndrew Jeffery package_version_str == NULL) {
336779e9dbdSAndrew Jeffery return -EINVAL;
33748761c62SAndrew Jeffery }
33848761c62SAndrew Jeffery
33948761c62SAndrew Jeffery if (length < sizeof(struct pldm_package_header_information)) {
340779e9dbdSAndrew Jeffery return -EOVERFLOW;
34148761c62SAndrew Jeffery }
34248761c62SAndrew Jeffery
34348761c62SAndrew Jeffery struct pldm_package_header_information *data_header =
34448761c62SAndrew Jeffery (struct pldm_package_header_information *)(data);
34548761c62SAndrew Jeffery
34648761c62SAndrew Jeffery if (!is_string_type_valid(data_header->package_version_string_type) ||
34748761c62SAndrew Jeffery (data_header->package_version_string_length == 0)) {
348779e9dbdSAndrew Jeffery return -EBADMSG;
34948761c62SAndrew Jeffery }
35048761c62SAndrew Jeffery
35148761c62SAndrew Jeffery if (length < sizeof(struct pldm_package_header_information) +
35248761c62SAndrew Jeffery data_header->package_version_string_length) {
353779e9dbdSAndrew Jeffery return -EOVERFLOW;
35448761c62SAndrew Jeffery }
35548761c62SAndrew Jeffery
35648761c62SAndrew Jeffery if ((data_header->component_bitmap_bit_length %
35748761c62SAndrew Jeffery PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
358779e9dbdSAndrew Jeffery return -EBADMSG;
35948761c62SAndrew Jeffery }
36048761c62SAndrew Jeffery
36148761c62SAndrew Jeffery memcpy(package_header_info->uuid, data_header->uuid,
36248761c62SAndrew Jeffery sizeof(data_header->uuid));
36348761c62SAndrew Jeffery package_header_info->package_header_format_version =
36448761c62SAndrew Jeffery data_header->package_header_format_version;
36548761c62SAndrew Jeffery package_header_info->package_header_size =
36648761c62SAndrew Jeffery le16toh(data_header->package_header_size);
36748761c62SAndrew Jeffery memcpy(package_header_info->package_release_date_time,
36848761c62SAndrew Jeffery data_header->package_release_date_time,
36948761c62SAndrew Jeffery sizeof(data_header->package_release_date_time));
37048761c62SAndrew Jeffery package_header_info->component_bitmap_bit_length =
37148761c62SAndrew Jeffery le16toh(data_header->component_bitmap_bit_length);
37248761c62SAndrew Jeffery package_header_info->package_version_string_type =
37348761c62SAndrew Jeffery data_header->package_version_string_type;
37448761c62SAndrew Jeffery package_header_info->package_version_string_length =
37548761c62SAndrew Jeffery data_header->package_version_string_length;
37648761c62SAndrew Jeffery package_version_str->ptr =
37748761c62SAndrew Jeffery data + sizeof(struct pldm_package_header_information);
37848761c62SAndrew Jeffery package_version_str->length =
37948761c62SAndrew Jeffery package_header_info->package_version_string_length;
38048761c62SAndrew Jeffery
381779e9dbdSAndrew Jeffery return 0;
38248761c62SAndrew Jeffery }
38348761c62SAndrew Jeffery
38448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
decode_pldm_package_header_info(const uint8_t * data,size_t length,struct pldm_package_header_information * package_header_info,struct variable_field * package_version_str)385779e9dbdSAndrew Jeffery int decode_pldm_package_header_info(
386779e9dbdSAndrew Jeffery const uint8_t *data, size_t length,
387779e9dbdSAndrew Jeffery struct pldm_package_header_information *package_header_info,
388779e9dbdSAndrew Jeffery struct variable_field *package_version_str)
389779e9dbdSAndrew Jeffery {
390779e9dbdSAndrew Jeffery int rc;
391779e9dbdSAndrew Jeffery
392779e9dbdSAndrew Jeffery rc = decode_pldm_package_header_info_errno(
393779e9dbdSAndrew Jeffery data, length, package_header_info, package_version_str);
394779e9dbdSAndrew Jeffery if (rc < 0) {
395779e9dbdSAndrew Jeffery return pldm_xlate_errno(rc);
396779e9dbdSAndrew Jeffery }
397779e9dbdSAndrew Jeffery
398779e9dbdSAndrew Jeffery return PLDM_SUCCESS;
399779e9dbdSAndrew Jeffery }
400779e9dbdSAndrew Jeffery
decode_firmware_device_id_record_errno(const uint8_t * data,size_t length,uint16_t component_bitmap_bit_length,struct pldm_firmware_device_id_record * fw_device_id_record,struct variable_field * applicable_components,struct variable_field * comp_image_set_version_str,struct variable_field * record_descriptors,struct variable_field * fw_device_pkg_data)401779e9dbdSAndrew Jeffery static int decode_firmware_device_id_record_errno(
40248761c62SAndrew Jeffery const uint8_t *data, size_t length,
40348761c62SAndrew Jeffery uint16_t component_bitmap_bit_length,
40448761c62SAndrew Jeffery struct pldm_firmware_device_id_record *fw_device_id_record,
40548761c62SAndrew Jeffery struct variable_field *applicable_components,
40648761c62SAndrew Jeffery struct variable_field *comp_image_set_version_str,
40748761c62SAndrew Jeffery struct variable_field *record_descriptors,
40848761c62SAndrew Jeffery struct variable_field *fw_device_pkg_data)
40948761c62SAndrew Jeffery {
41048761c62SAndrew Jeffery if (data == NULL || fw_device_id_record == NULL ||
41148761c62SAndrew Jeffery applicable_components == NULL ||
41248761c62SAndrew Jeffery comp_image_set_version_str == NULL || record_descriptors == NULL ||
41348761c62SAndrew Jeffery fw_device_pkg_data == NULL) {
414779e9dbdSAndrew Jeffery return -EINVAL;
41548761c62SAndrew Jeffery }
41648761c62SAndrew Jeffery
41748761c62SAndrew Jeffery if (length < sizeof(struct pldm_firmware_device_id_record)) {
418779e9dbdSAndrew Jeffery return -EOVERFLOW;
41948761c62SAndrew Jeffery }
42048761c62SAndrew Jeffery
42148761c62SAndrew Jeffery if ((component_bitmap_bit_length %
42248761c62SAndrew Jeffery PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
423779e9dbdSAndrew Jeffery return -EBADMSG;
42448761c62SAndrew Jeffery }
42548761c62SAndrew Jeffery
42648761c62SAndrew Jeffery struct pldm_firmware_device_id_record *data_record =
42748761c62SAndrew Jeffery (struct pldm_firmware_device_id_record *)(data);
42848761c62SAndrew Jeffery
42948761c62SAndrew Jeffery if (!is_string_type_valid(
43048761c62SAndrew Jeffery data_record->comp_image_set_version_string_type) ||
43148761c62SAndrew Jeffery (data_record->comp_image_set_version_string_length == 0)) {
432779e9dbdSAndrew Jeffery return -EBADMSG;
43348761c62SAndrew Jeffery }
43448761c62SAndrew Jeffery
43548761c62SAndrew Jeffery fw_device_id_record->record_length =
43648761c62SAndrew Jeffery le16toh(data_record->record_length);
43748761c62SAndrew Jeffery fw_device_id_record->descriptor_count = data_record->descriptor_count;
43848761c62SAndrew Jeffery fw_device_id_record->device_update_option_flags.value =
43948761c62SAndrew Jeffery le32toh(data_record->device_update_option_flags.value);
44048761c62SAndrew Jeffery fw_device_id_record->comp_image_set_version_string_type =
44148761c62SAndrew Jeffery data_record->comp_image_set_version_string_type;
44248761c62SAndrew Jeffery fw_device_id_record->comp_image_set_version_string_length =
44348761c62SAndrew Jeffery data_record->comp_image_set_version_string_length;
44448761c62SAndrew Jeffery fw_device_id_record->fw_device_pkg_data_length =
44548761c62SAndrew Jeffery le16toh(data_record->fw_device_pkg_data_length);
44648761c62SAndrew Jeffery
44748761c62SAndrew Jeffery if (length < fw_device_id_record->record_length) {
448779e9dbdSAndrew Jeffery return -EOVERFLOW;
44948761c62SAndrew Jeffery }
45048761c62SAndrew Jeffery
45148761c62SAndrew Jeffery uint16_t applicable_components_length =
45248761c62SAndrew Jeffery component_bitmap_bit_length /
45348761c62SAndrew Jeffery PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
454c4d1c8bcSMatt Johnston size_t calc_min_record_length =
45548761c62SAndrew Jeffery sizeof(struct pldm_firmware_device_id_record) +
45648761c62SAndrew Jeffery applicable_components_length +
45748761c62SAndrew Jeffery data_record->comp_image_set_version_string_length +
45848761c62SAndrew Jeffery PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
45948761c62SAndrew Jeffery fw_device_id_record->fw_device_pkg_data_length;
46048761c62SAndrew Jeffery
46148761c62SAndrew Jeffery if (fw_device_id_record->record_length < calc_min_record_length) {
462779e9dbdSAndrew Jeffery return -EOVERFLOW;
46348761c62SAndrew Jeffery }
46448761c62SAndrew Jeffery
46548761c62SAndrew Jeffery applicable_components->ptr =
46648761c62SAndrew Jeffery data + sizeof(struct pldm_firmware_device_id_record);
46748761c62SAndrew Jeffery applicable_components->length = applicable_components_length;
46848761c62SAndrew Jeffery
46948761c62SAndrew Jeffery comp_image_set_version_str->ptr =
47048761c62SAndrew Jeffery applicable_components->ptr + applicable_components->length;
47148761c62SAndrew Jeffery comp_image_set_version_str->length =
47248761c62SAndrew Jeffery fw_device_id_record->comp_image_set_version_string_length;
47348761c62SAndrew Jeffery
47448761c62SAndrew Jeffery record_descriptors->ptr = comp_image_set_version_str->ptr +
47548761c62SAndrew Jeffery comp_image_set_version_str->length;
47648761c62SAndrew Jeffery record_descriptors->length =
47748761c62SAndrew Jeffery fw_device_id_record->record_length -
47848761c62SAndrew Jeffery sizeof(struct pldm_firmware_device_id_record) -
47948761c62SAndrew Jeffery applicable_components_length -
48048761c62SAndrew Jeffery fw_device_id_record->comp_image_set_version_string_length -
48148761c62SAndrew Jeffery fw_device_id_record->fw_device_pkg_data_length;
48248761c62SAndrew Jeffery
48348761c62SAndrew Jeffery if (fw_device_id_record->fw_device_pkg_data_length) {
48448761c62SAndrew Jeffery fw_device_pkg_data->ptr =
48548761c62SAndrew Jeffery record_descriptors->ptr + record_descriptors->length;
48648761c62SAndrew Jeffery fw_device_pkg_data->length =
48748761c62SAndrew Jeffery fw_device_id_record->fw_device_pkg_data_length;
48848761c62SAndrew Jeffery }
48948761c62SAndrew Jeffery
490779e9dbdSAndrew Jeffery return 0;
491779e9dbdSAndrew Jeffery }
492779e9dbdSAndrew Jeffery
493779e9dbdSAndrew Jeffery LIBPLDM_ABI_STABLE
decode_firmware_device_id_record(const uint8_t * data,size_t length,uint16_t component_bitmap_bit_length,struct pldm_firmware_device_id_record * fw_device_id_record,struct variable_field * applicable_components,struct variable_field * comp_image_set_version_str,struct variable_field * record_descriptors,struct variable_field * fw_device_pkg_data)494779e9dbdSAndrew Jeffery int decode_firmware_device_id_record(
495779e9dbdSAndrew Jeffery const uint8_t *data, size_t length,
496779e9dbdSAndrew Jeffery uint16_t component_bitmap_bit_length,
497779e9dbdSAndrew Jeffery struct pldm_firmware_device_id_record *fw_device_id_record,
498779e9dbdSAndrew Jeffery struct variable_field *applicable_components,
499779e9dbdSAndrew Jeffery struct variable_field *comp_image_set_version_str,
500779e9dbdSAndrew Jeffery struct variable_field *record_descriptors,
501779e9dbdSAndrew Jeffery struct variable_field *fw_device_pkg_data)
502779e9dbdSAndrew Jeffery {
503779e9dbdSAndrew Jeffery int rc;
504779e9dbdSAndrew Jeffery
505779e9dbdSAndrew Jeffery rc = decode_firmware_device_id_record_errno(
506779e9dbdSAndrew Jeffery data, length, component_bitmap_bit_length, fw_device_id_record,
507779e9dbdSAndrew Jeffery applicable_components, comp_image_set_version_str,
508779e9dbdSAndrew Jeffery record_descriptors, fw_device_pkg_data);
509779e9dbdSAndrew Jeffery if (rc < 0) {
510779e9dbdSAndrew Jeffery return pldm_xlate_errno(rc);
511779e9dbdSAndrew Jeffery }
512779e9dbdSAndrew Jeffery
51348761c62SAndrew Jeffery return PLDM_SUCCESS;
51448761c62SAndrew Jeffery }
51548761c62SAndrew Jeffery
516e5c3f148SUnive Tien LIBPLDM_ABI_STABLE
decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter * iter,struct pldm_descriptor * desc)5173a2c6589SAndrew Jeffery int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter,
5183a2c6589SAndrew Jeffery struct pldm_descriptor *desc)
5193a2c6589SAndrew Jeffery {
520*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
5213a2c6589SAndrew Jeffery int rc;
5223a2c6589SAndrew Jeffery
5233a2c6589SAndrew Jeffery if (!iter || !iter->field || !desc) {
5243a2c6589SAndrew Jeffery return -EINVAL;
5253a2c6589SAndrew Jeffery }
5263a2c6589SAndrew Jeffery
5273a2c6589SAndrew Jeffery rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN,
5283a2c6589SAndrew Jeffery iter->field->ptr, iter->field->length);
5293a2c6589SAndrew Jeffery if (rc) {
5303a2c6589SAndrew Jeffery return rc;
5313a2c6589SAndrew Jeffery }
5323a2c6589SAndrew Jeffery
5333a2c6589SAndrew Jeffery pldm_msgbuf_extract(buf, desc->descriptor_type);
5343a2c6589SAndrew Jeffery rc = pldm_msgbuf_extract(buf, desc->descriptor_length);
5353a2c6589SAndrew Jeffery if (rc) {
536*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
5373a2c6589SAndrew Jeffery }
5383a2c6589SAndrew Jeffery
5393a2c6589SAndrew Jeffery desc->descriptor_data = NULL;
5403a2c6589SAndrew Jeffery pldm_msgbuf_span_required(buf, desc->descriptor_length,
5413a2c6589SAndrew Jeffery (void **)&desc->descriptor_data);
5423a2c6589SAndrew Jeffery iter->field->ptr = NULL;
5433a2c6589SAndrew Jeffery pldm_msgbuf_span_remaining(buf, (void **)&iter->field->ptr,
5443a2c6589SAndrew Jeffery &iter->field->length);
5453a2c6589SAndrew Jeffery
54670d21c97SAndrew Jeffery return pldm_msgbuf_complete(buf);
5473a2c6589SAndrew Jeffery }
5483a2c6589SAndrew Jeffery
549779e9dbdSAndrew Jeffery static int decode_descriptor_type_length_value_errno(
decode_descriptor_type_length_value_errno(const uint8_t * data,size_t length,uint16_t * descriptor_type,struct variable_field * descriptor_data)550779e9dbdSAndrew Jeffery const uint8_t *data, size_t length, uint16_t *descriptor_type,
55148761c62SAndrew Jeffery struct variable_field *descriptor_data)
55248761c62SAndrew Jeffery {
55348761c62SAndrew Jeffery uint16_t descriptor_length = 0;
55448761c62SAndrew Jeffery
55548761c62SAndrew Jeffery if (data == NULL || descriptor_type == NULL ||
55648761c62SAndrew Jeffery descriptor_data == NULL) {
557779e9dbdSAndrew Jeffery return -EINVAL;
55848761c62SAndrew Jeffery }
55948761c62SAndrew Jeffery
56048761c62SAndrew Jeffery if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
561779e9dbdSAndrew Jeffery return -EOVERFLOW;
56248761c62SAndrew Jeffery }
56348761c62SAndrew Jeffery
56448761c62SAndrew Jeffery struct pldm_descriptor_tlv *entry =
56548761c62SAndrew Jeffery (struct pldm_descriptor_tlv *)(data);
56648761c62SAndrew Jeffery
56748761c62SAndrew Jeffery *descriptor_type = le16toh(entry->descriptor_type);
56848761c62SAndrew Jeffery descriptor_length = le16toh(entry->descriptor_length);
56948761c62SAndrew Jeffery if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
57048761c62SAndrew Jeffery if (descriptor_length !=
57148761c62SAndrew Jeffery get_descriptor_type_length(*descriptor_type)) {
572779e9dbdSAndrew Jeffery return -EBADMSG;
57348761c62SAndrew Jeffery }
57448761c62SAndrew Jeffery }
57548761c62SAndrew Jeffery
57648761c62SAndrew Jeffery if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
57748761c62SAndrew Jeffery descriptor_length)) {
578779e9dbdSAndrew Jeffery return -EOVERFLOW;
57948761c62SAndrew Jeffery }
58048761c62SAndrew Jeffery
58148761c62SAndrew Jeffery descriptor_data->ptr = entry->descriptor_data;
58248761c62SAndrew Jeffery descriptor_data->length = descriptor_length;
58348761c62SAndrew Jeffery
584779e9dbdSAndrew Jeffery return 0;
58548761c62SAndrew Jeffery }
58648761c62SAndrew Jeffery
58748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
588779e9dbdSAndrew Jeffery int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
decode_descriptor_type_length_value(const uint8_t * data,size_t length,uint16_t * descriptor_type,struct variable_field * descriptor_data)589779e9dbdSAndrew Jeffery uint16_t *descriptor_type,
590779e9dbdSAndrew Jeffery struct variable_field *descriptor_data)
591779e9dbdSAndrew Jeffery {
592779e9dbdSAndrew Jeffery int rc;
593779e9dbdSAndrew Jeffery
594779e9dbdSAndrew Jeffery rc = decode_descriptor_type_length_value_errno(
595779e9dbdSAndrew Jeffery data, length, descriptor_type, descriptor_data);
596779e9dbdSAndrew Jeffery if (rc < 0) {
597779e9dbdSAndrew Jeffery return pldm_xlate_errno(rc);
598779e9dbdSAndrew Jeffery }
599779e9dbdSAndrew Jeffery
600779e9dbdSAndrew Jeffery return PLDM_SUCCESS;
601779e9dbdSAndrew Jeffery }
602779e9dbdSAndrew Jeffery
603779e9dbdSAndrew Jeffery static int decode_vendor_defined_descriptor_value_errno(
decode_vendor_defined_descriptor_value_errno(const uint8_t * data,size_t length,uint8_t * descriptor_title_str_type,struct variable_field * descriptor_title_str,struct variable_field * descriptor_data)60448761c62SAndrew Jeffery const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
60548761c62SAndrew Jeffery struct variable_field *descriptor_title_str,
60648761c62SAndrew Jeffery struct variable_field *descriptor_data)
60748761c62SAndrew Jeffery {
60848761c62SAndrew Jeffery if (data == NULL || descriptor_title_str_type == NULL ||
60948761c62SAndrew Jeffery descriptor_title_str == NULL || descriptor_data == NULL) {
610779e9dbdSAndrew Jeffery return -EINVAL;
61148761c62SAndrew Jeffery }
61248761c62SAndrew Jeffery
61348761c62SAndrew Jeffery if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
614779e9dbdSAndrew Jeffery return -EOVERFLOW;
61548761c62SAndrew Jeffery }
61648761c62SAndrew Jeffery
61748761c62SAndrew Jeffery struct pldm_vendor_defined_descriptor_title_data *entry =
61848761c62SAndrew Jeffery (struct pldm_vendor_defined_descriptor_title_data *)(data);
61948761c62SAndrew Jeffery if (!is_string_type_valid(
62048761c62SAndrew Jeffery entry->vendor_defined_descriptor_title_str_type) ||
62148761c62SAndrew Jeffery (entry->vendor_defined_descriptor_title_str_len == 0)) {
622779e9dbdSAndrew Jeffery return -EBADMSG;
62348761c62SAndrew Jeffery }
62448761c62SAndrew Jeffery
62548761c62SAndrew Jeffery // Assuming at least 1 byte of VendorDefinedDescriptorData
62648761c62SAndrew Jeffery if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
62748761c62SAndrew Jeffery entry->vendor_defined_descriptor_title_str_len)) {
628779e9dbdSAndrew Jeffery return -EOVERFLOW;
62948761c62SAndrew Jeffery }
63048761c62SAndrew Jeffery
63148761c62SAndrew Jeffery *descriptor_title_str_type =
63248761c62SAndrew Jeffery entry->vendor_defined_descriptor_title_str_type;
63348761c62SAndrew Jeffery descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
63448761c62SAndrew Jeffery descriptor_title_str->length =
63548761c62SAndrew Jeffery entry->vendor_defined_descriptor_title_str_len;
63648761c62SAndrew Jeffery
63748761c62SAndrew Jeffery descriptor_data->ptr =
63848761c62SAndrew Jeffery descriptor_title_str->ptr + descriptor_title_str->length;
63948761c62SAndrew Jeffery descriptor_data->length =
64048761c62SAndrew Jeffery length -
64148761c62SAndrew Jeffery sizeof(entry->vendor_defined_descriptor_title_str_type) -
64248761c62SAndrew Jeffery sizeof(entry->vendor_defined_descriptor_title_str_len) -
64348761c62SAndrew Jeffery descriptor_title_str->length;
64448761c62SAndrew Jeffery
645779e9dbdSAndrew Jeffery return 0;
64648761c62SAndrew Jeffery }
64748761c62SAndrew Jeffery
64848761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
649779e9dbdSAndrew Jeffery int decode_vendor_defined_descriptor_value(
decode_vendor_defined_descriptor_value(const uint8_t * data,size_t length,uint8_t * descriptor_title_str_type,struct variable_field * descriptor_title_str,struct variable_field * descriptor_data)650779e9dbdSAndrew Jeffery const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
651779e9dbdSAndrew Jeffery struct variable_field *descriptor_title_str,
652779e9dbdSAndrew Jeffery struct variable_field *descriptor_data)
653779e9dbdSAndrew Jeffery {
654779e9dbdSAndrew Jeffery int rc;
655779e9dbdSAndrew Jeffery
656779e9dbdSAndrew Jeffery rc = decode_vendor_defined_descriptor_value_errno(
657779e9dbdSAndrew Jeffery data, length, descriptor_title_str_type, descriptor_title_str,
658779e9dbdSAndrew Jeffery descriptor_data);
659779e9dbdSAndrew Jeffery if (rc < 0) {
660779e9dbdSAndrew Jeffery return pldm_xlate_errno(rc);
661779e9dbdSAndrew Jeffery }
662779e9dbdSAndrew Jeffery
663779e9dbdSAndrew Jeffery return PLDM_SUCCESS;
664779e9dbdSAndrew Jeffery }
665779e9dbdSAndrew Jeffery
666779e9dbdSAndrew Jeffery static int decode_pldm_comp_image_info_errno(
decode_pldm_comp_image_info_errno(const uint8_t * data,size_t length,struct pldm_component_image_information * pldm_comp_image_info,struct variable_field * comp_version_str)66748761c62SAndrew Jeffery const uint8_t *data, size_t length,
66848761c62SAndrew Jeffery struct pldm_component_image_information *pldm_comp_image_info,
66948761c62SAndrew Jeffery struct variable_field *comp_version_str)
67048761c62SAndrew Jeffery {
67148761c62SAndrew Jeffery if (data == NULL || pldm_comp_image_info == NULL ||
67248761c62SAndrew Jeffery comp_version_str == NULL) {
673779e9dbdSAndrew Jeffery return -EINVAL;
67448761c62SAndrew Jeffery }
67548761c62SAndrew Jeffery
67648761c62SAndrew Jeffery if (length < sizeof(struct pldm_component_image_information)) {
677779e9dbdSAndrew Jeffery return -EOVERFLOW;
67848761c62SAndrew Jeffery }
67948761c62SAndrew Jeffery
68048761c62SAndrew Jeffery struct pldm_component_image_information *data_header =
68148761c62SAndrew Jeffery (struct pldm_component_image_information *)(data);
68248761c62SAndrew Jeffery
68348761c62SAndrew Jeffery if (!is_string_type_valid(data_header->comp_version_string_type) ||
68448761c62SAndrew Jeffery (data_header->comp_version_string_length == 0)) {
685779e9dbdSAndrew Jeffery return -EBADMSG;
68648761c62SAndrew Jeffery }
68748761c62SAndrew Jeffery
68848761c62SAndrew Jeffery if (length < sizeof(struct pldm_component_image_information) +
68948761c62SAndrew Jeffery data_header->comp_version_string_length) {
690779e9dbdSAndrew Jeffery return -EOVERFLOW;
69148761c62SAndrew Jeffery }
69248761c62SAndrew Jeffery
69348761c62SAndrew Jeffery pldm_comp_image_info->comp_classification =
69448761c62SAndrew Jeffery le16toh(data_header->comp_classification);
69548761c62SAndrew Jeffery pldm_comp_image_info->comp_identifier =
69648761c62SAndrew Jeffery le16toh(data_header->comp_identifier);
69748761c62SAndrew Jeffery pldm_comp_image_info->comp_comparison_stamp =
69848761c62SAndrew Jeffery le32toh(data_header->comp_comparison_stamp);
69948761c62SAndrew Jeffery pldm_comp_image_info->comp_options.value =
70048761c62SAndrew Jeffery le16toh(data_header->comp_options.value);
70148761c62SAndrew Jeffery pldm_comp_image_info->requested_comp_activation_method.value =
70248761c62SAndrew Jeffery le16toh(data_header->requested_comp_activation_method.value);
70348761c62SAndrew Jeffery pldm_comp_image_info->comp_location_offset =
70448761c62SAndrew Jeffery le32toh(data_header->comp_location_offset);
70548761c62SAndrew Jeffery pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
70648761c62SAndrew Jeffery pldm_comp_image_info->comp_version_string_type =
70748761c62SAndrew Jeffery data_header->comp_version_string_type;
70848761c62SAndrew Jeffery pldm_comp_image_info->comp_version_string_length =
70948761c62SAndrew Jeffery data_header->comp_version_string_length;
71048761c62SAndrew Jeffery
71148761c62SAndrew Jeffery if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
71248761c62SAndrew Jeffery pldm_comp_image_info->comp_comparison_stamp !=
71348761c62SAndrew Jeffery PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
714779e9dbdSAndrew Jeffery return -EBADMSG;
71548761c62SAndrew Jeffery }
71648761c62SAndrew Jeffery
71748761c62SAndrew Jeffery if (pldm_comp_image_info->comp_location_offset == 0 ||
71848761c62SAndrew Jeffery pldm_comp_image_info->comp_size == 0) {
719779e9dbdSAndrew Jeffery return -EBADMSG;
72048761c62SAndrew Jeffery }
72148761c62SAndrew Jeffery
72248761c62SAndrew Jeffery comp_version_str->ptr =
72348761c62SAndrew Jeffery data + sizeof(struct pldm_component_image_information);
72448761c62SAndrew Jeffery comp_version_str->length =
72548761c62SAndrew Jeffery pldm_comp_image_info->comp_version_string_length;
72648761c62SAndrew Jeffery
727779e9dbdSAndrew Jeffery return 0;
728779e9dbdSAndrew Jeffery }
729779e9dbdSAndrew Jeffery
730779e9dbdSAndrew Jeffery LIBPLDM_ABI_STABLE
731779e9dbdSAndrew Jeffery int decode_pldm_comp_image_info(
decode_pldm_comp_image_info(const uint8_t * data,size_t length,struct pldm_component_image_information * pldm_comp_image_info,struct variable_field * comp_version_str)732779e9dbdSAndrew Jeffery const uint8_t *data, size_t length,
733779e9dbdSAndrew Jeffery struct pldm_component_image_information *pldm_comp_image_info,
734779e9dbdSAndrew Jeffery struct variable_field *comp_version_str)
735779e9dbdSAndrew Jeffery {
736779e9dbdSAndrew Jeffery int rc;
737779e9dbdSAndrew Jeffery
738779e9dbdSAndrew Jeffery rc = decode_pldm_comp_image_info_errno(
739779e9dbdSAndrew Jeffery data, length, pldm_comp_image_info, comp_version_str);
740779e9dbdSAndrew Jeffery if (rc < 0) {
741779e9dbdSAndrew Jeffery return pldm_xlate_errno(rc);
742779e9dbdSAndrew Jeffery }
743779e9dbdSAndrew Jeffery
74448761c62SAndrew Jeffery return PLDM_SUCCESS;
74548761c62SAndrew Jeffery }
74648761c62SAndrew Jeffery
74748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
74848761c62SAndrew Jeffery int encode_query_device_identifiers_req(uint8_t instance_id,
encode_query_device_identifiers_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)74948761c62SAndrew Jeffery size_t payload_length,
75048761c62SAndrew Jeffery struct pldm_msg *msg)
75148761c62SAndrew Jeffery {
75248761c62SAndrew Jeffery if (msg == NULL) {
75348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
75448761c62SAndrew Jeffery }
75548761c62SAndrew Jeffery
75648761c62SAndrew Jeffery if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
75748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
75848761c62SAndrew Jeffery }
75948761c62SAndrew Jeffery
76048761c62SAndrew Jeffery return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
76148761c62SAndrew Jeffery PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
76248761c62SAndrew Jeffery }
76348761c62SAndrew Jeffery
76448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
76548761c62SAndrew Jeffery int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
decode_query_device_identifiers_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint32_t * device_identifiers_len,uint8_t * descriptor_count,uint8_t ** descriptor_data)76648761c62SAndrew Jeffery size_t payload_length,
76748761c62SAndrew Jeffery uint8_t *completion_code,
76848761c62SAndrew Jeffery uint32_t *device_identifiers_len,
76948761c62SAndrew Jeffery uint8_t *descriptor_count,
77048761c62SAndrew Jeffery uint8_t **descriptor_data)
77148761c62SAndrew Jeffery {
77248761c62SAndrew Jeffery if (msg == NULL || completion_code == NULL ||
77348761c62SAndrew Jeffery device_identifiers_len == NULL || descriptor_count == NULL ||
77448761c62SAndrew Jeffery descriptor_data == NULL) {
77548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
77648761c62SAndrew Jeffery }
77748761c62SAndrew Jeffery
77848761c62SAndrew Jeffery *completion_code = msg->payload[0];
77948761c62SAndrew Jeffery if (PLDM_SUCCESS != *completion_code) {
78048761c62SAndrew Jeffery return PLDM_SUCCESS;
78148761c62SAndrew Jeffery }
78248761c62SAndrew Jeffery
78348761c62SAndrew Jeffery if (payload_length <
78448761c62SAndrew Jeffery sizeof(struct pldm_query_device_identifiers_resp)) {
78548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
78648761c62SAndrew Jeffery }
78748761c62SAndrew Jeffery
78848761c62SAndrew Jeffery struct pldm_query_device_identifiers_resp *response =
78948761c62SAndrew Jeffery (struct pldm_query_device_identifiers_resp *)msg->payload;
79048761c62SAndrew Jeffery *device_identifiers_len = le32toh(response->device_identifiers_len);
79148761c62SAndrew Jeffery
79248761c62SAndrew Jeffery if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
79348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
79448761c62SAndrew Jeffery }
79548761c62SAndrew Jeffery
79648761c62SAndrew Jeffery if (payload_length !=
79748761c62SAndrew Jeffery sizeof(struct pldm_query_device_identifiers_resp) +
79848761c62SAndrew Jeffery *device_identifiers_len) {
79948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
80048761c62SAndrew Jeffery }
80148761c62SAndrew Jeffery *descriptor_count = response->descriptor_count;
80248761c62SAndrew Jeffery
80348761c62SAndrew Jeffery if (*descriptor_count == 0) {
80448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
80548761c62SAndrew Jeffery }
80648761c62SAndrew Jeffery *descriptor_data =
80748761c62SAndrew Jeffery (uint8_t *)(msg->payload +
80848761c62SAndrew Jeffery sizeof(struct pldm_query_device_identifiers_resp));
80948761c62SAndrew Jeffery return PLDM_SUCCESS;
81048761c62SAndrew Jeffery }
81148761c62SAndrew Jeffery
812cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
813cf9a2df3SMatt Johnston int encode_query_device_identifiers_resp(
encode_query_device_identifiers_resp(uint8_t instance_id,uint8_t descriptor_count,const struct pldm_descriptor * descriptors,struct pldm_msg * msg,size_t * payload_length)814cf9a2df3SMatt Johnston uint8_t instance_id, uint8_t descriptor_count,
815cf9a2df3SMatt Johnston const struct pldm_descriptor *descriptors, struct pldm_msg *msg,
816cf9a2df3SMatt Johnston size_t *payload_length)
817cf9a2df3SMatt Johnston {
818*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
819cf9a2df3SMatt Johnston int rc;
820cf9a2df3SMatt Johnston
821cf9a2df3SMatt Johnston if (descriptors == NULL || msg == NULL || payload_length == NULL) {
822cf9a2df3SMatt Johnston return -EINVAL;
823cf9a2df3SMatt Johnston }
824cf9a2df3SMatt Johnston
825cf9a2df3SMatt Johnston if (descriptor_count < 1) {
826cf9a2df3SMatt Johnston return -EINVAL;
827cf9a2df3SMatt Johnston }
828cf9a2df3SMatt Johnston
829cf9a2df3SMatt Johnston rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
830cf9a2df3SMatt Johnston PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
831cf9a2df3SMatt Johnston if (rc) {
832cf9a2df3SMatt Johnston return -EINVAL;
833cf9a2df3SMatt Johnston }
834cf9a2df3SMatt Johnston
835cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
836cf9a2df3SMatt Johnston if (rc) {
837cf9a2df3SMatt Johnston return rc;
838cf9a2df3SMatt Johnston }
839cf9a2df3SMatt Johnston
840cf9a2df3SMatt Johnston /* Determine total length */
841cf9a2df3SMatt Johnston uint32_t device_identifiers_len = 0;
842cf9a2df3SMatt Johnston for (uint8_t i = 0; i < descriptor_count; i++) {
843cf9a2df3SMatt Johnston const struct pldm_descriptor *d = &descriptors[i];
844cf9a2df3SMatt Johnston device_identifiers_len +=
845cf9a2df3SMatt Johnston 2 * sizeof(uint16_t) + d->descriptor_length;
846cf9a2df3SMatt Johnston }
847cf9a2df3SMatt Johnston
848cf9a2df3SMatt Johnston pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
849cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, device_identifiers_len);
850cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, descriptor_count);
851cf9a2df3SMatt Johnston
852cf9a2df3SMatt Johnston for (uint8_t i = 0; i < descriptor_count; i++) {
853cf9a2df3SMatt Johnston const struct pldm_descriptor *d = &descriptors[i];
854cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, d->descriptor_type);
855cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, d->descriptor_length);
856cf9a2df3SMatt Johnston if (d->descriptor_data == NULL) {
857*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, -EINVAL);
858cf9a2df3SMatt Johnston }
859cf9a2df3SMatt Johnston rc = pldm_msgbuf_insert_array(
860cf9a2df3SMatt Johnston buf, d->descriptor_length,
861cf9a2df3SMatt Johnston (const uint8_t *)d->descriptor_data,
862cf9a2df3SMatt Johnston d->descriptor_length);
863cf9a2df3SMatt Johnston if (rc) {
864*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
865cf9a2df3SMatt Johnston }
866cf9a2df3SMatt Johnston }
867cf9a2df3SMatt Johnston
86870d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
869cf9a2df3SMatt Johnston }
870cf9a2df3SMatt Johnston
87148761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
87248761c62SAndrew Jeffery int encode_get_firmware_parameters_req(uint8_t instance_id,
87348761c62SAndrew Jeffery size_t payload_length,
encode_get_firmware_parameters_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)87448761c62SAndrew Jeffery struct pldm_msg *msg)
87548761c62SAndrew Jeffery {
87648761c62SAndrew Jeffery if (msg == NULL) {
87748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
87848761c62SAndrew Jeffery }
87948761c62SAndrew Jeffery
88048761c62SAndrew Jeffery if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
88148761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
88248761c62SAndrew Jeffery }
88348761c62SAndrew Jeffery
88448761c62SAndrew Jeffery return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
88548761c62SAndrew Jeffery PLDM_GET_FIRMWARE_PARAMETERS, msg);
88648761c62SAndrew Jeffery }
88748761c62SAndrew Jeffery
88848761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
88948761c62SAndrew Jeffery int decode_get_firmware_parameters_resp(
89048761c62SAndrew Jeffery const struct pldm_msg *msg, size_t payload_length,
decode_get_firmware_parameters_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_get_firmware_parameters_resp * resp_data,struct variable_field * active_comp_image_set_ver_str,struct variable_field * pending_comp_image_set_ver_str,struct variable_field * comp_parameter_table)89148761c62SAndrew Jeffery struct pldm_get_firmware_parameters_resp *resp_data,
89248761c62SAndrew Jeffery struct variable_field *active_comp_image_set_ver_str,
89348761c62SAndrew Jeffery struct variable_field *pending_comp_image_set_ver_str,
89448761c62SAndrew Jeffery struct variable_field *comp_parameter_table)
89548761c62SAndrew Jeffery {
89648761c62SAndrew Jeffery if (msg == NULL || resp_data == NULL ||
89748761c62SAndrew Jeffery active_comp_image_set_ver_str == NULL ||
89848761c62SAndrew Jeffery pending_comp_image_set_ver_str == NULL ||
89948761c62SAndrew Jeffery comp_parameter_table == NULL || !payload_length) {
90048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
90148761c62SAndrew Jeffery }
90248761c62SAndrew Jeffery
90348761c62SAndrew Jeffery resp_data->completion_code = msg->payload[0];
90448761c62SAndrew Jeffery if (PLDM_SUCCESS != resp_data->completion_code) {
90548761c62SAndrew Jeffery return PLDM_SUCCESS;
90648761c62SAndrew Jeffery }
90748761c62SAndrew Jeffery
90848761c62SAndrew Jeffery if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
90948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
91048761c62SAndrew Jeffery }
91148761c62SAndrew Jeffery
91248761c62SAndrew Jeffery struct pldm_get_firmware_parameters_resp *response =
91348761c62SAndrew Jeffery (struct pldm_get_firmware_parameters_resp *)msg->payload;
91448761c62SAndrew Jeffery
91548761c62SAndrew Jeffery if (!is_string_type_valid(
91648761c62SAndrew Jeffery response->active_comp_image_set_ver_str_type) ||
91748761c62SAndrew Jeffery (response->active_comp_image_set_ver_str_len == 0)) {
91848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
91948761c62SAndrew Jeffery }
92048761c62SAndrew Jeffery
92148761c62SAndrew Jeffery if (response->pending_comp_image_set_ver_str_len == 0) {
92248761c62SAndrew Jeffery if (response->pending_comp_image_set_ver_str_type !=
92348761c62SAndrew Jeffery PLDM_STR_TYPE_UNKNOWN) {
92448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
92548761c62SAndrew Jeffery }
92648761c62SAndrew Jeffery } else {
92748761c62SAndrew Jeffery if (!is_string_type_valid(
92848761c62SAndrew Jeffery response->pending_comp_image_set_ver_str_type)) {
92948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
93048761c62SAndrew Jeffery }
93148761c62SAndrew Jeffery }
93248761c62SAndrew Jeffery
93348761c62SAndrew Jeffery size_t partial_response_length =
93448761c62SAndrew Jeffery sizeof(struct pldm_get_firmware_parameters_resp) +
93548761c62SAndrew Jeffery response->active_comp_image_set_ver_str_len +
93648761c62SAndrew Jeffery response->pending_comp_image_set_ver_str_len;
93748761c62SAndrew Jeffery
93848761c62SAndrew Jeffery if (payload_length < partial_response_length) {
93948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
94048761c62SAndrew Jeffery }
94148761c62SAndrew Jeffery
94248761c62SAndrew Jeffery resp_data->capabilities_during_update.value =
94348761c62SAndrew Jeffery le32toh(response->capabilities_during_update.value);
94448761c62SAndrew Jeffery resp_data->comp_count = le16toh(response->comp_count);
94548761c62SAndrew Jeffery resp_data->active_comp_image_set_ver_str_type =
94648761c62SAndrew Jeffery response->active_comp_image_set_ver_str_type;
94748761c62SAndrew Jeffery resp_data->active_comp_image_set_ver_str_len =
94848761c62SAndrew Jeffery response->active_comp_image_set_ver_str_len;
94948761c62SAndrew Jeffery resp_data->pending_comp_image_set_ver_str_type =
95048761c62SAndrew Jeffery response->pending_comp_image_set_ver_str_type;
95148761c62SAndrew Jeffery resp_data->pending_comp_image_set_ver_str_len =
95248761c62SAndrew Jeffery response->pending_comp_image_set_ver_str_len;
95348761c62SAndrew Jeffery
95448761c62SAndrew Jeffery active_comp_image_set_ver_str->ptr =
95548761c62SAndrew Jeffery msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
95648761c62SAndrew Jeffery active_comp_image_set_ver_str->length =
95748761c62SAndrew Jeffery resp_data->active_comp_image_set_ver_str_len;
95848761c62SAndrew Jeffery
95948761c62SAndrew Jeffery if (resp_data->pending_comp_image_set_ver_str_len != 0) {
96048761c62SAndrew Jeffery pending_comp_image_set_ver_str->ptr =
96148761c62SAndrew Jeffery msg->payload +
96248761c62SAndrew Jeffery sizeof(struct pldm_get_firmware_parameters_resp) +
96348761c62SAndrew Jeffery resp_data->active_comp_image_set_ver_str_len;
96448761c62SAndrew Jeffery pending_comp_image_set_ver_str->length =
96548761c62SAndrew Jeffery resp_data->pending_comp_image_set_ver_str_len;
96648761c62SAndrew Jeffery } else {
96748761c62SAndrew Jeffery pending_comp_image_set_ver_str->ptr = NULL;
96848761c62SAndrew Jeffery pending_comp_image_set_ver_str->length = 0;
96948761c62SAndrew Jeffery }
97048761c62SAndrew Jeffery
97148761c62SAndrew Jeffery if (payload_length > partial_response_length && resp_data->comp_count) {
97248761c62SAndrew Jeffery comp_parameter_table->ptr =
97348761c62SAndrew Jeffery msg->payload +
97448761c62SAndrew Jeffery sizeof(struct pldm_get_firmware_parameters_resp) +
97548761c62SAndrew Jeffery resp_data->active_comp_image_set_ver_str_len +
97648761c62SAndrew Jeffery resp_data->pending_comp_image_set_ver_str_len;
97748761c62SAndrew Jeffery comp_parameter_table->length =
97848761c62SAndrew Jeffery payload_length - partial_response_length;
97948761c62SAndrew Jeffery } else {
98048761c62SAndrew Jeffery comp_parameter_table->ptr = NULL;
98148761c62SAndrew Jeffery comp_parameter_table->length = 0;
98248761c62SAndrew Jeffery }
98348761c62SAndrew Jeffery
98448761c62SAndrew Jeffery return PLDM_SUCCESS;
98548761c62SAndrew Jeffery }
98648761c62SAndrew Jeffery
987cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
988cf9a2df3SMatt Johnston int encode_get_firmware_parameters_resp(
989cf9a2df3SMatt Johnston uint8_t instance_id,
encode_get_firmware_parameters_resp(uint8_t instance_id,const struct pldm_get_firmware_parameters_resp_full * resp_data,struct pldm_msg * msg,size_t * payload_length)990cf9a2df3SMatt Johnston const struct pldm_get_firmware_parameters_resp_full *resp_data,
991cf9a2df3SMatt Johnston struct pldm_msg *msg, size_t *payload_length)
992cf9a2df3SMatt Johnston {
993*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
994cf9a2df3SMatt Johnston int rc;
995cf9a2df3SMatt Johnston
996cf9a2df3SMatt Johnston if (resp_data == NULL || msg == NULL || payload_length == NULL) {
997cf9a2df3SMatt Johnston return -EINVAL;
998cf9a2df3SMatt Johnston }
999cf9a2df3SMatt Johnston
1000cf9a2df3SMatt Johnston rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
1001cf9a2df3SMatt Johnston PLDM_GET_FIRMWARE_PARAMETERS, msg);
1002cf9a2df3SMatt Johnston if (rc) {
1003cf9a2df3SMatt Johnston return -EINVAL;
1004cf9a2df3SMatt Johnston }
1005cf9a2df3SMatt Johnston
1006cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1007cf9a2df3SMatt Johnston if (rc) {
1008cf9a2df3SMatt Johnston return rc;
1009cf9a2df3SMatt Johnston }
1010cf9a2df3SMatt Johnston
1011cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->completion_code);
1012cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->capabilities_during_update.value);
1013cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->comp_count);
1014cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf,
1015cf9a2df3SMatt Johnston resp_data->active_comp_image_set_ver_str.str_type);
1016cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf,
1017cf9a2df3SMatt Johnston resp_data->active_comp_image_set_ver_str.str_len);
1018cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf,
1019cf9a2df3SMatt Johnston resp_data->pending_comp_image_set_ver_str.str_type);
1020cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf,
1021cf9a2df3SMatt Johnston resp_data->pending_comp_image_set_ver_str.str_len);
1022cf9a2df3SMatt Johnston /* String data appended */
1023cf9a2df3SMatt Johnston rc = pldm_msgbuf_insert_array(
1024cf9a2df3SMatt Johnston buf, resp_data->active_comp_image_set_ver_str.str_len,
1025cf9a2df3SMatt Johnston resp_data->active_comp_image_set_ver_str.str_data,
1026cf9a2df3SMatt Johnston resp_data->active_comp_image_set_ver_str.str_len);
1027cf9a2df3SMatt Johnston if (rc) {
1028*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1029cf9a2df3SMatt Johnston }
1030cf9a2df3SMatt Johnston rc = pldm_msgbuf_insert_array(
1031cf9a2df3SMatt Johnston buf, resp_data->pending_comp_image_set_ver_str.str_len,
1032cf9a2df3SMatt Johnston resp_data->pending_comp_image_set_ver_str.str_data,
1033cf9a2df3SMatt Johnston resp_data->pending_comp_image_set_ver_str.str_len);
1034cf9a2df3SMatt Johnston if (rc) {
1035*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1036cf9a2df3SMatt Johnston }
1037cf9a2df3SMatt Johnston
1038cf9a2df3SMatt Johnston /* Further calls to encode_get_firmware_parameters_resp_comp_entry
1039cf9a2df3SMatt Johnston * will populate the remainder */
1040cf9a2df3SMatt Johnston
104170d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1042cf9a2df3SMatt Johnston }
1043cf9a2df3SMatt Johnston
1044cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
1045cf9a2df3SMatt Johnston int encode_get_firmware_parameters_resp_comp_entry(
1046cf9a2df3SMatt Johnston const struct pldm_component_parameter_entry_full *comp,
1047cf9a2df3SMatt Johnston uint8_t *payload, size_t *payload_length)
encode_get_firmware_parameters_resp_comp_entry(const struct pldm_component_parameter_entry_full * comp,uint8_t * payload,size_t * payload_length)1048cf9a2df3SMatt Johnston {
1049*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
1050cf9a2df3SMatt Johnston int rc;
1051cf9a2df3SMatt Johnston
1052cf9a2df3SMatt Johnston if (comp == NULL || payload == NULL || payload_length == NULL) {
1053cf9a2df3SMatt Johnston return -EINVAL;
1054cf9a2df3SMatt Johnston }
1055cf9a2df3SMatt Johnston
1056cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, payload, *payload_length);
1057cf9a2df3SMatt Johnston if (rc) {
1058cf9a2df3SMatt Johnston return rc;
1059cf9a2df3SMatt Johnston }
1060cf9a2df3SMatt Johnston
1061cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, comp->comp_classification);
1062cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, comp->comp_identifier);
1063cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, comp->comp_classification_index);
1064cf9a2df3SMatt Johnston
1065cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, comp->active_ver.comparison_stamp);
1066cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, (uint8_t)comp->active_ver.str.str_type);
1067cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, comp->active_ver.str.str_len);
1068cf9a2df3SMatt Johnston rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1069cf9a2df3SMatt Johnston comp->active_ver.date,
1070cf9a2df3SMatt Johnston PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1071cf9a2df3SMatt Johnston if (rc) {
1072*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1073cf9a2df3SMatt Johnston }
1074cf9a2df3SMatt Johnston
1075cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, comp->pending_ver.comparison_stamp);
1076cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, (uint8_t)comp->pending_ver.str.str_type);
1077cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, comp->pending_ver.str.str_len);
1078cf9a2df3SMatt Johnston rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1079cf9a2df3SMatt Johnston comp->pending_ver.date,
1080cf9a2df3SMatt Johnston PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1081cf9a2df3SMatt Johnston if (rc) {
1082*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1083cf9a2df3SMatt Johnston }
1084cf9a2df3SMatt Johnston
1085cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, comp->comp_activation_methods.value);
1086cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, comp->capabilities_during_update.value);
1087cf9a2df3SMatt Johnston
1088cf9a2df3SMatt Johnston rc = pldm_msgbuf_insert_array(buf, comp->active_ver.str.str_len,
1089cf9a2df3SMatt Johnston comp->active_ver.str.str_data,
1090cf9a2df3SMatt Johnston comp->active_ver.str.str_len);
1091cf9a2df3SMatt Johnston if (rc) {
1092*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1093cf9a2df3SMatt Johnston }
1094cf9a2df3SMatt Johnston rc = pldm_msgbuf_insert_array(buf, comp->pending_ver.str.str_len,
1095cf9a2df3SMatt Johnston comp->pending_ver.str.str_data,
1096cf9a2df3SMatt Johnston comp->pending_ver.str.str_len);
1097cf9a2df3SMatt Johnston if (rc) {
1098*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1099cf9a2df3SMatt Johnston }
1100cf9a2df3SMatt Johnston
110170d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1102cf9a2df3SMatt Johnston }
1103cf9a2df3SMatt Johnston
110448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
110548761c62SAndrew Jeffery int decode_get_firmware_parameters_resp_comp_entry(
110648761c62SAndrew Jeffery const uint8_t *data, size_t length,
110748761c62SAndrew Jeffery struct pldm_component_parameter_entry *component_data,
110848761c62SAndrew Jeffery struct variable_field *active_comp_ver_str,
decode_get_firmware_parameters_resp_comp_entry(const uint8_t * data,size_t length,struct pldm_component_parameter_entry * component_data,struct variable_field * active_comp_ver_str,struct variable_field * pending_comp_ver_str)110948761c62SAndrew Jeffery struct variable_field *pending_comp_ver_str)
111048761c62SAndrew Jeffery {
111148761c62SAndrew Jeffery if (data == NULL || component_data == NULL ||
111248761c62SAndrew Jeffery active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
111348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
111448761c62SAndrew Jeffery }
111548761c62SAndrew Jeffery
111648761c62SAndrew Jeffery if (length < sizeof(struct pldm_component_parameter_entry)) {
111748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
111848761c62SAndrew Jeffery }
111948761c62SAndrew Jeffery
112048761c62SAndrew Jeffery struct pldm_component_parameter_entry *entry =
112148761c62SAndrew Jeffery (struct pldm_component_parameter_entry *)(data);
112248761c62SAndrew Jeffery
112348761c62SAndrew Jeffery size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
112448761c62SAndrew Jeffery entry->active_comp_ver_str_len +
112548761c62SAndrew Jeffery entry->pending_comp_ver_str_len;
112648761c62SAndrew Jeffery
112748761c62SAndrew Jeffery if (length < entry_length) {
112848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
112948761c62SAndrew Jeffery }
113048761c62SAndrew Jeffery
113148761c62SAndrew Jeffery component_data->comp_classification =
113248761c62SAndrew Jeffery le16toh(entry->comp_classification);
113348761c62SAndrew Jeffery component_data->comp_identifier = le16toh(entry->comp_identifier);
113448761c62SAndrew Jeffery component_data->comp_classification_index =
113548761c62SAndrew Jeffery entry->comp_classification_index;
113648761c62SAndrew Jeffery component_data->active_comp_comparison_stamp =
113748761c62SAndrew Jeffery le32toh(entry->active_comp_comparison_stamp);
113848761c62SAndrew Jeffery component_data->active_comp_ver_str_type =
113948761c62SAndrew Jeffery entry->active_comp_ver_str_type;
114048761c62SAndrew Jeffery component_data->active_comp_ver_str_len =
114148761c62SAndrew Jeffery entry->active_comp_ver_str_len;
114248761c62SAndrew Jeffery memcpy(component_data->active_comp_release_date,
114348761c62SAndrew Jeffery entry->active_comp_release_date,
114448761c62SAndrew Jeffery sizeof(entry->active_comp_release_date));
114548761c62SAndrew Jeffery component_data->pending_comp_comparison_stamp =
114648761c62SAndrew Jeffery le32toh(entry->pending_comp_comparison_stamp);
114748761c62SAndrew Jeffery component_data->pending_comp_ver_str_type =
114848761c62SAndrew Jeffery entry->pending_comp_ver_str_type;
114948761c62SAndrew Jeffery component_data->pending_comp_ver_str_len =
115048761c62SAndrew Jeffery entry->pending_comp_ver_str_len;
115148761c62SAndrew Jeffery memcpy(component_data->pending_comp_release_date,
115248761c62SAndrew Jeffery entry->pending_comp_release_date,
115348761c62SAndrew Jeffery sizeof(entry->pending_comp_release_date));
115448761c62SAndrew Jeffery component_data->comp_activation_methods.value =
115548761c62SAndrew Jeffery le16toh(entry->comp_activation_methods.value);
115648761c62SAndrew Jeffery component_data->capabilities_during_update.value =
115748761c62SAndrew Jeffery le32toh(entry->capabilities_during_update.value);
115848761c62SAndrew Jeffery
115948761c62SAndrew Jeffery if (entry->active_comp_ver_str_len != 0) {
116048761c62SAndrew Jeffery active_comp_ver_str->ptr =
116148761c62SAndrew Jeffery data + sizeof(struct pldm_component_parameter_entry);
116248761c62SAndrew Jeffery active_comp_ver_str->length = entry->active_comp_ver_str_len;
116348761c62SAndrew Jeffery } else {
116448761c62SAndrew Jeffery active_comp_ver_str->ptr = NULL;
116548761c62SAndrew Jeffery active_comp_ver_str->length = 0;
116648761c62SAndrew Jeffery }
116748761c62SAndrew Jeffery
116848761c62SAndrew Jeffery if (entry->pending_comp_ver_str_len != 0) {
116948761c62SAndrew Jeffery pending_comp_ver_str->ptr =
117048761c62SAndrew Jeffery data + sizeof(struct pldm_component_parameter_entry) +
117148761c62SAndrew Jeffery entry->active_comp_ver_str_len;
117248761c62SAndrew Jeffery pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
117348761c62SAndrew Jeffery } else {
117448761c62SAndrew Jeffery pending_comp_ver_str->ptr = NULL;
117548761c62SAndrew Jeffery pending_comp_ver_str->length = 0;
117648761c62SAndrew Jeffery }
117748761c62SAndrew Jeffery return PLDM_SUCCESS;
117848761c62SAndrew Jeffery }
117948761c62SAndrew Jeffery
1180e5c3f148SUnive Tien LIBPLDM_ABI_STABLE
118148761c62SAndrew Jeffery int encode_query_downstream_devices_req(uint8_t instance_id,
118248761c62SAndrew Jeffery struct pldm_msg *msg)
118348761c62SAndrew Jeffery {
118448761c62SAndrew Jeffery if (msg == NULL) {
encode_query_downstream_devices_req(uint8_t instance_id,struct pldm_msg * msg)118571e935cfSUnive Tien return -EINVAL;
118648761c62SAndrew Jeffery }
118748761c62SAndrew Jeffery
118871e935cfSUnive Tien return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id,
118971e935cfSUnive Tien PLDM_FWUP,
119071e935cfSUnive Tien PLDM_QUERY_DOWNSTREAM_DEVICES,
119171e935cfSUnive Tien msg);
119248761c62SAndrew Jeffery }
119348761c62SAndrew Jeffery
1194e5c3f148SUnive Tien LIBPLDM_ABI_STABLE
119548761c62SAndrew Jeffery int decode_query_downstream_devices_resp(
119648761c62SAndrew Jeffery const struct pldm_msg *msg, size_t payload_length,
119748761c62SAndrew Jeffery struct pldm_query_downstream_devices_resp *resp_data)
119848761c62SAndrew Jeffery {
decode_query_downstream_devices_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_query_downstream_devices_resp * resp_data)1199*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
120048761c62SAndrew Jeffery int rc;
120148761c62SAndrew Jeffery
120248761c62SAndrew Jeffery if (msg == NULL || resp_data == NULL || !payload_length) {
120371e935cfSUnive Tien return -EINVAL;
120448761c62SAndrew Jeffery }
120548761c62SAndrew Jeffery
1206830c1eb4SAndrew Jeffery rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
120748761c62SAndrew Jeffery msg->payload, payload_length);
120848761c62SAndrew Jeffery if (rc) {
120948761c62SAndrew Jeffery return rc;
121048761c62SAndrew Jeffery }
121148761c62SAndrew Jeffery
121248761c62SAndrew Jeffery rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
121348761c62SAndrew Jeffery if (rc) {
1214*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
121548761c62SAndrew Jeffery }
121648761c62SAndrew Jeffery if (PLDM_SUCCESS != resp_data->completion_code) {
121748761c62SAndrew Jeffery // Return the CC directly without decoding the rest of the payload
1218*a1896967SAndrew Jeffery return pldm_msgbuf_complete(buf);
121948761c62SAndrew Jeffery }
122048761c62SAndrew Jeffery
122148761c62SAndrew Jeffery if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
1222*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, -EBADMSG);
122348761c62SAndrew Jeffery }
122448761c62SAndrew Jeffery
122548761c62SAndrew Jeffery rc = pldm_msgbuf_extract(buf,
122648761c62SAndrew Jeffery resp_data->downstream_device_update_supported);
122748761c62SAndrew Jeffery if (rc) {
1228*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
122948761c62SAndrew Jeffery }
123048761c62SAndrew Jeffery
123148761c62SAndrew Jeffery if (!is_downstream_device_update_support_valid(
123248761c62SAndrew Jeffery resp_data->downstream_device_update_supported)) {
1233*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, -EINVAL);
123448761c62SAndrew Jeffery }
123548761c62SAndrew Jeffery
123648761c62SAndrew Jeffery pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
123748761c62SAndrew Jeffery pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
123848761c62SAndrew Jeffery pldm_msgbuf_extract(buf, resp_data->capabilities.value);
123948761c62SAndrew Jeffery
124070d21c97SAndrew Jeffery return pldm_msgbuf_complete_consumed(buf);
124148761c62SAndrew Jeffery }
124248761c62SAndrew Jeffery
1243e5c3f148SUnive Tien LIBPLDM_ABI_STABLE
124448761c62SAndrew Jeffery int encode_query_downstream_identifiers_req(
1245d2f8a7e3SUnive Tien uint8_t instance_id,
1246d2f8a7e3SUnive Tien const struct pldm_query_downstream_identifiers_req *params_req,
1247d2f8a7e3SUnive Tien struct pldm_msg *msg, size_t payload_length)
124848761c62SAndrew Jeffery {
encode_query_downstream_identifiers_req(uint8_t instance_id,const struct pldm_query_downstream_identifiers_req * params_req,struct pldm_msg * msg,size_t payload_length)1249*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
125048761c62SAndrew Jeffery int rc;
125148761c62SAndrew Jeffery
1252d2f8a7e3SUnive Tien if (!msg || !params_req) {
125371e935cfSUnive Tien return -EINVAL;
125448761c62SAndrew Jeffery }
125548761c62SAndrew Jeffery
1256d2f8a7e3SUnive Tien if (!is_transfer_operation_flag_valid(
1257d2f8a7e3SUnive Tien (enum transfer_op_flag)
1258d2f8a7e3SUnive Tien params_req->transfer_operation_flag)) {
125971e935cfSUnive Tien return -EINVAL;
126048761c62SAndrew Jeffery }
126148761c62SAndrew Jeffery
126248761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
126348761c62SAndrew Jeffery header.instance = instance_id;
126448761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
126548761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
126648761c62SAndrew Jeffery header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
126771e935cfSUnive Tien rc = pack_pldm_header_errno(&header, &(msg->hdr));
126848761c62SAndrew Jeffery if (rc) {
126948761c62SAndrew Jeffery return rc;
127048761c62SAndrew Jeffery }
127148761c62SAndrew Jeffery
1272830c1eb4SAndrew Jeffery rc = pldm_msgbuf_init_errno(buf,
127348761c62SAndrew Jeffery PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
127448761c62SAndrew Jeffery msg->payload, payload_length);
127548761c62SAndrew Jeffery if (rc) {
127671e935cfSUnive Tien return rc;
127748761c62SAndrew Jeffery }
127848761c62SAndrew Jeffery
1279d2f8a7e3SUnive Tien pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
128048761c62SAndrew Jeffery // Data correctness has been verified, cast it to 1-byte data directly.
1281d2f8a7e3SUnive Tien pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
128248761c62SAndrew Jeffery
128370d21c97SAndrew Jeffery return pldm_msgbuf_complete(buf);
128448761c62SAndrew Jeffery }
128548761c62SAndrew Jeffery
1286e5c3f148SUnive Tien LIBPLDM_ABI_STABLE
128748761c62SAndrew Jeffery int decode_query_downstream_identifiers_resp(
128848761c62SAndrew Jeffery const struct pldm_msg *msg, size_t payload_length,
128948761c62SAndrew Jeffery struct pldm_query_downstream_identifiers_resp *resp_data,
12903a2c6589SAndrew Jeffery struct pldm_downstream_device_iter *iter)
129148761c62SAndrew Jeffery {
1292*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
decode_query_downstream_identifiers_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_query_downstream_identifiers_resp * resp_data,struct pldm_downstream_device_iter * iter)12933a2c6589SAndrew Jeffery void *remaining = NULL;
129471e935cfSUnive Tien int rc = 0;
129548761c62SAndrew Jeffery
12963a2c6589SAndrew Jeffery if (msg == NULL || resp_data == NULL || iter == NULL ||
129748761c62SAndrew Jeffery !payload_length) {
129871e935cfSUnive Tien return -EINVAL;
129948761c62SAndrew Jeffery }
130048761c62SAndrew Jeffery
1301830c1eb4SAndrew Jeffery rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
130248761c62SAndrew Jeffery msg->payload, payload_length);
130348761c62SAndrew Jeffery if (rc) {
130471e935cfSUnive Tien return rc;
130548761c62SAndrew Jeffery }
130648761c62SAndrew Jeffery
130748761c62SAndrew Jeffery rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
130848761c62SAndrew Jeffery if (rc) {
1309*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
131048761c62SAndrew Jeffery }
131148761c62SAndrew Jeffery if (PLDM_SUCCESS != resp_data->completion_code) {
1312*a1896967SAndrew Jeffery return pldm_msgbuf_complete(buf);
131348761c62SAndrew Jeffery }
131448761c62SAndrew Jeffery
131548761c62SAndrew Jeffery if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
1316*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, -EBADMSG);
131748761c62SAndrew Jeffery }
131848761c62SAndrew Jeffery
131948761c62SAndrew Jeffery pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
132048761c62SAndrew Jeffery pldm_msgbuf_extract(buf, resp_data->transfer_flag);
132148761c62SAndrew Jeffery
132248761c62SAndrew Jeffery rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
132348761c62SAndrew Jeffery if (rc) {
1324*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
132548761c62SAndrew Jeffery }
132648761c62SAndrew Jeffery
132748761c62SAndrew Jeffery pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1328*a1896967SAndrew Jeffery pldm_msgbuf_span_required(buf, resp_data->downstream_devices_length,
1329*a1896967SAndrew Jeffery &remaining);
133048761c62SAndrew Jeffery
133170d21c97SAndrew Jeffery rc = pldm_msgbuf_complete(buf);
1332830c1eb4SAndrew Jeffery if (rc) {
133371e935cfSUnive Tien return rc;
1334830c1eb4SAndrew Jeffery }
1335830c1eb4SAndrew Jeffery
13363a2c6589SAndrew Jeffery iter->field.ptr = remaining;
13373a2c6589SAndrew Jeffery iter->field.length = resp_data->downstream_devices_length;
13383a2c6589SAndrew Jeffery iter->devs = resp_data->number_of_downstream_devices;
13393a2c6589SAndrew Jeffery
134071e935cfSUnive Tien return 0;
134148761c62SAndrew Jeffery }
134248761c62SAndrew Jeffery
1343e5c3f148SUnive Tien LIBPLDM_ABI_STABLE
13443a2c6589SAndrew Jeffery int decode_pldm_downstream_device_from_iter(
13453a2c6589SAndrew Jeffery struct pldm_downstream_device_iter *iter,
13463a2c6589SAndrew Jeffery struct pldm_downstream_device *dev)
13473a2c6589SAndrew Jeffery {
1348*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
13493a2c6589SAndrew Jeffery int rc;
13503a2c6589SAndrew Jeffery
1351*a1896967SAndrew Jeffery if (!iter || !iter->field.ptr || !dev) {
13523a2c6589SAndrew Jeffery return -EINVAL;
13533a2c6589SAndrew Jeffery }
decode_pldm_downstream_device_from_iter(struct pldm_downstream_device_iter * iter,struct pldm_downstream_device * dev)13543a2c6589SAndrew Jeffery
13553a2c6589SAndrew Jeffery rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr,
13563a2c6589SAndrew Jeffery iter->field.length);
13573a2c6589SAndrew Jeffery if (rc) {
13583a2c6589SAndrew Jeffery return rc;
13593a2c6589SAndrew Jeffery }
13603a2c6589SAndrew Jeffery
13613a2c6589SAndrew Jeffery pldm_msgbuf_extract(buf, dev->downstream_device_index);
13623a2c6589SAndrew Jeffery pldm_msgbuf_extract(buf, dev->downstream_descriptor_count);
13633a2c6589SAndrew Jeffery pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr,
13643a2c6589SAndrew Jeffery &iter->field.length);
13653a2c6589SAndrew Jeffery
136670d21c97SAndrew Jeffery return pldm_msgbuf_complete(buf);
13673a2c6589SAndrew Jeffery }
13683a2c6589SAndrew Jeffery
1369e5c3f148SUnive Tien LIBPLDM_ABI_STABLE
13706a97b79eSAndrew Jeffery int encode_get_downstream_firmware_parameters_req(
1371d2f8a7e3SUnive Tien uint8_t instance_id,
13726a97b79eSAndrew Jeffery const struct pldm_get_downstream_firmware_parameters_req *params_req,
1373d2f8a7e3SUnive Tien struct pldm_msg *msg, size_t payload_length)
1374b6ef35b4SChris Wang {
1375*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
1376b6ef35b4SChris Wang int rc;
1377b6ef35b4SChris Wang
1378d2f8a7e3SUnive Tien if (!msg || !params_req) {
1379b6ef35b4SChris Wang return -EINVAL;
1380b6ef35b4SChris Wang }
1381b6ef35b4SChris Wang
encode_get_downstream_firmware_parameters_req(uint8_t instance_id,const struct pldm_get_downstream_firmware_parameters_req * params_req,struct pldm_msg * msg,size_t payload_length)1382d2f8a7e3SUnive Tien if (!is_transfer_operation_flag_valid(
1383d2f8a7e3SUnive Tien (enum transfer_op_flag)
1384d2f8a7e3SUnive Tien params_req->transfer_operation_flag)) {
1385b6ef35b4SChris Wang return -EBADMSG;
1386b6ef35b4SChris Wang }
1387b6ef35b4SChris Wang
1388b6ef35b4SChris Wang struct pldm_header_info header = { 0 };
1389b6ef35b4SChris Wang header.instance = instance_id;
1390b6ef35b4SChris Wang header.msg_type = PLDM_REQUEST;
1391b6ef35b4SChris Wang header.pldm_type = PLDM_FWUP;
1392b6ef35b4SChris Wang header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1393b6ef35b4SChris Wang rc = pack_pldm_header_errno(&header, &msg->hdr);
1394b6ef35b4SChris Wang if (rc < 0) {
1395b6ef35b4SChris Wang return rc;
1396b6ef35b4SChris Wang }
1397b6ef35b4SChris Wang
139853b08675SAndrew Jeffery rc = pldm_msgbuf_init_errno(
139953b08675SAndrew Jeffery buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES,
140053b08675SAndrew Jeffery msg->payload, payload_length);
140153b08675SAndrew Jeffery if (rc < 0) {
140253b08675SAndrew Jeffery return rc;
140353b08675SAndrew Jeffery }
140453b08675SAndrew Jeffery
1405d2f8a7e3SUnive Tien pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
1406b6ef35b4SChris Wang // Data correctness has been verified, cast it to 1-byte data directly.
1407d2f8a7e3SUnive Tien pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
1408b6ef35b4SChris Wang
140970d21c97SAndrew Jeffery return pldm_msgbuf_complete(buf);
1410b6ef35b4SChris Wang }
1411b6ef35b4SChris Wang
1412e5c3f148SUnive Tien LIBPLDM_ABI_STABLE
14136a97b79eSAndrew Jeffery int decode_get_downstream_firmware_parameters_resp(
1414b6ef35b4SChris Wang const struct pldm_msg *msg, size_t payload_length,
14156a97b79eSAndrew Jeffery struct pldm_get_downstream_firmware_parameters_resp *resp_data,
14165a5129b0SAndrew Jeffery struct pldm_downstream_device_parameters_iter *iter)
1417b6ef35b4SChris Wang {
1418*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
14195a5129b0SAndrew Jeffery void *remaining = NULL;
14205a5129b0SAndrew Jeffery size_t length;
1421b6ef35b4SChris Wang int rc;
1422b6ef35b4SChris Wang
14235a5129b0SAndrew Jeffery if (msg == NULL || resp_data == NULL || iter == NULL) {
1424b6ef35b4SChris Wang return -EINVAL;
1425b6ef35b4SChris Wang }
decode_get_downstream_firmware_parameters_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_get_downstream_firmware_parameters_resp * resp_data,struct pldm_downstream_device_parameters_iter * iter)1426b6ef35b4SChris Wang
1427b6ef35b4SChris Wang rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1428b6ef35b4SChris Wang msg->payload, payload_length);
1429b6ef35b4SChris Wang if (rc < 0) {
1430b6ef35b4SChris Wang return rc;
1431b6ef35b4SChris Wang }
1432b6ef35b4SChris Wang
1433b6ef35b4SChris Wang rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1434b6ef35b4SChris Wang if (rc < 0) {
1435*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1436b6ef35b4SChris Wang }
1437b6ef35b4SChris Wang if (PLDM_SUCCESS != resp_data->completion_code) {
1438*a1896967SAndrew Jeffery return pldm_msgbuf_complete(buf);
1439b6ef35b4SChris Wang }
1440b6ef35b4SChris Wang
14416a97b79eSAndrew Jeffery if (payload_length <
14426a97b79eSAndrew Jeffery PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) {
1443*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, -EBADMSG);
1444b6ef35b4SChris Wang }
1445b6ef35b4SChris Wang
1446b6ef35b4SChris Wang pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1447b6ef35b4SChris Wang pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1448b6ef35b4SChris Wang pldm_msgbuf_extract(buf,
1449b6ef35b4SChris Wang resp_data->fdp_capabilities_during_update.value);
1450b6ef35b4SChris Wang pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1451b6ef35b4SChris Wang
14525a5129b0SAndrew Jeffery rc = pldm_msgbuf_span_remaining(buf, &remaining, &length);
14535a5129b0SAndrew Jeffery if (rc) {
1454*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
14555a5129b0SAndrew Jeffery }
14565a5129b0SAndrew Jeffery
145770d21c97SAndrew Jeffery rc = pldm_msgbuf_complete(buf);
14585a5129b0SAndrew Jeffery if (rc) {
14595a5129b0SAndrew Jeffery return rc;
14605a5129b0SAndrew Jeffery }
14615a5129b0SAndrew Jeffery
14625a5129b0SAndrew Jeffery iter->field.ptr = remaining;
14635a5129b0SAndrew Jeffery iter->field.length = length;
14645a5129b0SAndrew Jeffery iter->entries = resp_data->downstream_device_count;
14655a5129b0SAndrew Jeffery
14665a5129b0SAndrew Jeffery return 0;
1467b6ef35b4SChris Wang }
1468b6ef35b4SChris Wang
1469e5c3f148SUnive Tien LIBPLDM_ABI_STABLE
14705a5129b0SAndrew Jeffery int decode_pldm_downstream_device_parameters_entry_from_iter(
14715a5129b0SAndrew Jeffery struct pldm_downstream_device_parameters_iter *iter,
14725a5129b0SAndrew Jeffery struct pldm_downstream_device_parameters_entry *entry)
1473b6ef35b4SChris Wang {
1474*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
14755a5129b0SAndrew Jeffery void *comp_ver_str;
1476b6ef35b4SChris Wang size_t remaining;
14775a5129b0SAndrew Jeffery void *cursor;
1478b6ef35b4SChris Wang int rc;
1479b6ef35b4SChris Wang
1480*a1896967SAndrew Jeffery if (iter == NULL || iter->field.ptr == NULL || entry == NULL) {
1481b6ef35b4SChris Wang return -EINVAL;
1482b6ef35b4SChris Wang }
1483b6ef35b4SChris Wang
decode_pldm_downstream_device_parameters_entry_from_iter(struct pldm_downstream_device_parameters_iter * iter,struct pldm_downstream_device_parameters_entry * entry)1484b6ef35b4SChris Wang rc = pldm_msgbuf_init_errno(
14855a5129b0SAndrew Jeffery buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN,
14865a5129b0SAndrew Jeffery iter->field.ptr, iter->field.length);
1487b6ef35b4SChris Wang if (rc < 0) {
1488b6ef35b4SChris Wang return rc;
1489b6ef35b4SChris Wang }
1490b6ef35b4SChris Wang
1491b6ef35b4SChris Wang pldm_msgbuf_extract(buf, entry->downstream_device_index);
1492b6ef35b4SChris Wang pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1493b6ef35b4SChris Wang pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1494b6ef35b4SChris Wang rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1495b6ef35b4SChris Wang if (rc < 0) {
1496*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1497b6ef35b4SChris Wang }
14980a1be3cbSAndrew Jeffery rc = pldm_msgbuf_extract_array(buf,
14990a1be3cbSAndrew Jeffery PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
15000a1be3cbSAndrew Jeffery entry->active_comp_release_date,
15010a1be3cbSAndrew Jeffery sizeof(entry->active_comp_release_date));
15020a1be3cbSAndrew Jeffery if (rc < 0) {
1503*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
15040a1be3cbSAndrew Jeffery }
15050a1be3cbSAndrew Jeffery
1506b6ef35b4SChris Wang // Fill the last byte with NULL character
1507b6ef35b4SChris Wang entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1508b6ef35b4SChris Wang '\0';
1509b6ef35b4SChris Wang
1510b6ef35b4SChris Wang pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1511b6ef35b4SChris Wang pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1512b6ef35b4SChris Wang rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1513b6ef35b4SChris Wang if (rc < 0) {
1514*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1515b6ef35b4SChris Wang }
15160a1be3cbSAndrew Jeffery
15170a1be3cbSAndrew Jeffery rc = pldm_msgbuf_extract_array(
15180a1be3cbSAndrew Jeffery buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
15190a1be3cbSAndrew Jeffery entry->pending_comp_release_date,
15200a1be3cbSAndrew Jeffery sizeof(entry->pending_comp_release_date));
15210a1be3cbSAndrew Jeffery if (rc < 0) {
1522*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
15230a1be3cbSAndrew Jeffery }
15240a1be3cbSAndrew Jeffery
1525b6ef35b4SChris Wang // Fill the last byte with NULL character
1526b6ef35b4SChris Wang entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1527b6ef35b4SChris Wang '\0';
1528b6ef35b4SChris Wang
1529b6ef35b4SChris Wang pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1530b6ef35b4SChris Wang pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
1531b6ef35b4SChris Wang
1532*a1896967SAndrew Jeffery rc = pldm_msgbuf_span_required(buf, entry->active_comp_ver_str_len,
15335a5129b0SAndrew Jeffery &comp_ver_str);
1534*a1896967SAndrew Jeffery if (rc < 0) {
1535*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1536*a1896967SAndrew Jeffery }
15375a5129b0SAndrew Jeffery entry->active_comp_ver_str = comp_ver_str;
15385a5129b0SAndrew Jeffery
1539*a1896967SAndrew Jeffery rc = pldm_msgbuf_span_required(buf, entry->pending_comp_ver_str_len,
15405a5129b0SAndrew Jeffery &comp_ver_str);
1541*a1896967SAndrew Jeffery if (rc < 0) {
1542*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1543*a1896967SAndrew Jeffery }
15445a5129b0SAndrew Jeffery entry->pending_comp_ver_str = comp_ver_str;
15455a5129b0SAndrew Jeffery
1546b6ef35b4SChris Wang rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1547b6ef35b4SChris Wang if (rc < 0) {
1548*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1549b6ef35b4SChris Wang }
1550b6ef35b4SChris Wang
15515a5129b0SAndrew Jeffery iter->field.ptr = cursor;
15525a5129b0SAndrew Jeffery iter->field.length = remaining;
1553b6ef35b4SChris Wang
1554*a1896967SAndrew Jeffery return pldm_msgbuf_complete(buf);
1555b6ef35b4SChris Wang }
1556b6ef35b4SChris Wang
155748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
155848761c62SAndrew Jeffery int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
155948761c62SAndrew Jeffery uint16_t num_of_comp,
156048761c62SAndrew Jeffery uint8_t max_outstanding_transfer_req,
156148761c62SAndrew Jeffery uint16_t pkg_data_len,
156248761c62SAndrew Jeffery uint8_t comp_image_set_ver_str_type,
156348761c62SAndrew Jeffery uint8_t comp_image_set_ver_str_len,
156448761c62SAndrew Jeffery const struct variable_field *comp_img_set_ver_str,
156548761c62SAndrew Jeffery struct pldm_msg *msg, size_t payload_length)
156648761c62SAndrew Jeffery {
156748761c62SAndrew Jeffery if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
156848761c62SAndrew Jeffery msg == NULL) {
156948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
encode_request_update_req(uint8_t instance_id,uint32_t max_transfer_size,uint16_t num_of_comp,uint8_t max_outstanding_transfer_req,uint16_t pkg_data_len,uint8_t comp_image_set_ver_str_type,uint8_t comp_image_set_ver_str_len,const struct variable_field * comp_img_set_ver_str,struct pldm_msg * msg,size_t payload_length)157048761c62SAndrew Jeffery }
157148761c62SAndrew Jeffery
157248761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_request_update_req) +
157348761c62SAndrew Jeffery comp_img_set_ver_str->length) {
157448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
157548761c62SAndrew Jeffery }
157648761c62SAndrew Jeffery
157748761c62SAndrew Jeffery if ((comp_image_set_ver_str_len == 0) ||
157848761c62SAndrew Jeffery (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
157948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
158048761c62SAndrew Jeffery }
158148761c62SAndrew Jeffery
158248761c62SAndrew Jeffery if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
158348761c62SAndrew Jeffery (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
158448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
158548761c62SAndrew Jeffery }
158648761c62SAndrew Jeffery
158748761c62SAndrew Jeffery if (!is_string_type_valid(comp_image_set_ver_str_type)) {
158848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
158948761c62SAndrew Jeffery }
159048761c62SAndrew Jeffery
159148761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
159248761c62SAndrew Jeffery header.instance = instance_id;
159348761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
159448761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
159548761c62SAndrew Jeffery header.command = PLDM_REQUEST_UPDATE;
159648761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
159748761c62SAndrew Jeffery if (rc) {
159848761c62SAndrew Jeffery return rc;
159948761c62SAndrew Jeffery }
160048761c62SAndrew Jeffery
160148761c62SAndrew Jeffery struct pldm_request_update_req *request =
160248761c62SAndrew Jeffery (struct pldm_request_update_req *)msg->payload;
160348761c62SAndrew Jeffery
160448761c62SAndrew Jeffery request->max_transfer_size = htole32(max_transfer_size);
160548761c62SAndrew Jeffery request->num_of_comp = htole16(num_of_comp);
160648761c62SAndrew Jeffery request->max_outstanding_transfer_req = max_outstanding_transfer_req;
160748761c62SAndrew Jeffery request->pkg_data_len = htole16(pkg_data_len);
160848761c62SAndrew Jeffery request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
160948761c62SAndrew Jeffery request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
161048761c62SAndrew Jeffery
161148761c62SAndrew Jeffery memcpy(msg->payload + sizeof(struct pldm_request_update_req),
161248761c62SAndrew Jeffery comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
161348761c62SAndrew Jeffery
161448761c62SAndrew Jeffery return PLDM_SUCCESS;
161548761c62SAndrew Jeffery }
161648761c62SAndrew Jeffery
1617cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
1618cf9a2df3SMatt Johnston int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length,
1619cf9a2df3SMatt Johnston struct pldm_request_update_req_full *req)
1620cf9a2df3SMatt Johnston {
1621cf9a2df3SMatt Johnston int rc;
1622cf9a2df3SMatt Johnston uint8_t t;
1623*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
1624cf9a2df3SMatt Johnston
1625cf9a2df3SMatt Johnston if (msg == NULL || req == NULL) {
1626cf9a2df3SMatt Johnston return -EINVAL;
1627cf9a2df3SMatt Johnston }
1628cf9a2df3SMatt Johnston
1629cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
decode_request_update_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_request_update_req_full * req)1630cf9a2df3SMatt Johnston if (rc) {
1631cf9a2df3SMatt Johnston return rc;
1632cf9a2df3SMatt Johnston }
1633cf9a2df3SMatt Johnston
1634cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, req->max_transfer_size);
1635cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, req->num_of_comp);
1636cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, req->max_outstanding_transfer_req);
1637cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, req->pkg_data_len);
1638cf9a2df3SMatt Johnston rc = pldm_msgbuf_extract(buf, t);
1639cf9a2df3SMatt Johnston if (rc) {
1640*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1641cf9a2df3SMatt Johnston }
1642cf9a2df3SMatt Johnston if (t > PLDM_STR_TYPE_UTF_16BE) {
1643*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, -EBADMSG);
1644cf9a2df3SMatt Johnston }
1645cf9a2df3SMatt Johnston req->image_set_ver.str_type = (enum pldm_firmware_update_string_type)t;
1646cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, req->image_set_ver.str_len);
1647cf9a2df3SMatt Johnston if (rc) {
1648*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1649cf9a2df3SMatt Johnston }
1650cf9a2df3SMatt Johnston
1651cf9a2df3SMatt Johnston rc = pldm_msgbuf_extract_array(buf, req->image_set_ver.str_len,
1652cf9a2df3SMatt Johnston req->image_set_ver.str_data,
1653cf9a2df3SMatt Johnston PLDM_FIRMWARE_MAX_STRING);
1654cf9a2df3SMatt Johnston if (rc) {
1655*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1656cf9a2df3SMatt Johnston }
1657cf9a2df3SMatt Johnston
165870d21c97SAndrew Jeffery return pldm_msgbuf_complete_consumed(buf);
1659cf9a2df3SMatt Johnston }
1660cf9a2df3SMatt Johnston
166148761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
166248761c62SAndrew Jeffery int decode_request_update_resp(const struct pldm_msg *msg,
166348761c62SAndrew Jeffery size_t payload_length, uint8_t *completion_code,
166448761c62SAndrew Jeffery uint16_t *fd_meta_data_len,
166548761c62SAndrew Jeffery uint8_t *fd_will_send_pkg_data)
166648761c62SAndrew Jeffery {
166748761c62SAndrew Jeffery if (msg == NULL || completion_code == NULL ||
166848761c62SAndrew Jeffery fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
166948761c62SAndrew Jeffery !payload_length) {
167048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
167148761c62SAndrew Jeffery }
167248761c62SAndrew Jeffery
167348761c62SAndrew Jeffery *completion_code = msg->payload[0];
167448761c62SAndrew Jeffery if (*completion_code != PLDM_SUCCESS) {
decode_request_update_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint16_t * fd_meta_data_len,uint8_t * fd_will_send_pkg_data)167548761c62SAndrew Jeffery return PLDM_SUCCESS;
167648761c62SAndrew Jeffery }
167748761c62SAndrew Jeffery
167848761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_request_update_resp)) {
167948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
168048761c62SAndrew Jeffery }
168148761c62SAndrew Jeffery
168248761c62SAndrew Jeffery struct pldm_request_update_resp *response =
168348761c62SAndrew Jeffery (struct pldm_request_update_resp *)msg->payload;
168448761c62SAndrew Jeffery
168548761c62SAndrew Jeffery *fd_meta_data_len = le16toh(response->fd_meta_data_len);
168648761c62SAndrew Jeffery *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
168748761c62SAndrew Jeffery
168848761c62SAndrew Jeffery return PLDM_SUCCESS;
168948761c62SAndrew Jeffery }
169048761c62SAndrew Jeffery
1691cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
1692cf9a2df3SMatt Johnston int encode_request_update_resp(uint8_t instance_id,
1693cf9a2df3SMatt Johnston const struct pldm_request_update_resp *resp_data,
1694cf9a2df3SMatt Johnston struct pldm_msg *msg, size_t *payload_length)
1695cf9a2df3SMatt Johnston {
1696*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
1697cf9a2df3SMatt Johnston int rc;
1698cf9a2df3SMatt Johnston
1699cf9a2df3SMatt Johnston if (msg == NULL || payload_length == NULL) {
1700cf9a2df3SMatt Johnston return -EINVAL;
1701cf9a2df3SMatt Johnston }
1702cf9a2df3SMatt Johnston
1703cf9a2df3SMatt Johnston struct pldm_header_info header = {
1704cf9a2df3SMatt Johnston .instance = instance_id,
encode_request_update_resp(uint8_t instance_id,const struct pldm_request_update_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)1705cf9a2df3SMatt Johnston .msg_type = PLDM_RESPONSE,
1706cf9a2df3SMatt Johnston .pldm_type = PLDM_FWUP,
1707cf9a2df3SMatt Johnston .command = PLDM_REQUEST_UPDATE,
1708cf9a2df3SMatt Johnston };
1709cf9a2df3SMatt Johnston rc = pack_pldm_header(&header, &(msg->hdr));
1710cf9a2df3SMatt Johnston if (rc) {
1711cf9a2df3SMatt Johnston return -EINVAL;
1712cf9a2df3SMatt Johnston }
1713cf9a2df3SMatt Johnston
1714cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1715cf9a2df3SMatt Johnston if (rc) {
1716cf9a2df3SMatt Johnston return rc;
1717cf9a2df3SMatt Johnston }
1718cf9a2df3SMatt Johnston
1719cf9a2df3SMatt Johnston pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1720cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->fd_meta_data_len);
1721cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->fd_will_send_pkg_data);
1722cf9a2df3SMatt Johnston
1723cf9a2df3SMatt Johnston /* TODO: DSP0267 1.3.0 adds GetPackageDataMaximumTransferSize */
1724cf9a2df3SMatt Johnston
172570d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1726cf9a2df3SMatt Johnston }
1727cf9a2df3SMatt Johnston
172848761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
172948761c62SAndrew Jeffery int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
173048761c62SAndrew Jeffery uint16_t comp_classification,
173148761c62SAndrew Jeffery uint16_t comp_identifier,
173248761c62SAndrew Jeffery uint8_t comp_classification_index,
173348761c62SAndrew Jeffery uint32_t comp_comparison_stamp,
173448761c62SAndrew Jeffery uint8_t comp_ver_str_type,
173548761c62SAndrew Jeffery uint8_t comp_ver_str_len,
173648761c62SAndrew Jeffery const struct variable_field *comp_ver_str,
173748761c62SAndrew Jeffery struct pldm_msg *msg, size_t payload_length)
173848761c62SAndrew Jeffery {
173948761c62SAndrew Jeffery if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
174048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
174148761c62SAndrew Jeffery }
174248761c62SAndrew Jeffery
encode_pass_component_table_req(uint8_t instance_id,uint8_t transfer_flag,uint16_t comp_classification,uint16_t comp_identifier,uint8_t comp_classification_index,uint32_t comp_comparison_stamp,uint8_t comp_ver_str_type,uint8_t comp_ver_str_len,const struct variable_field * comp_ver_str,struct pldm_msg * msg,size_t payload_length)174348761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_pass_component_table_req) +
174448761c62SAndrew Jeffery comp_ver_str->length) {
174548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
174648761c62SAndrew Jeffery }
174748761c62SAndrew Jeffery
174848761c62SAndrew Jeffery if ((comp_ver_str_len == 0) ||
174948761c62SAndrew Jeffery (comp_ver_str_len != comp_ver_str->length)) {
175048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
175148761c62SAndrew Jeffery }
175248761c62SAndrew Jeffery
175348761c62SAndrew Jeffery if (!is_transfer_flag_valid(transfer_flag)) {
175448761c62SAndrew Jeffery return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
175548761c62SAndrew Jeffery }
175648761c62SAndrew Jeffery
175748761c62SAndrew Jeffery if (!is_string_type_valid(comp_ver_str_type)) {
175848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
175948761c62SAndrew Jeffery }
176048761c62SAndrew Jeffery
176148761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
176248761c62SAndrew Jeffery header.instance = instance_id;
176348761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
176448761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
176548761c62SAndrew Jeffery header.command = PLDM_PASS_COMPONENT_TABLE;
176648761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
176748761c62SAndrew Jeffery if (rc) {
176848761c62SAndrew Jeffery return rc;
176948761c62SAndrew Jeffery }
177048761c62SAndrew Jeffery
177148761c62SAndrew Jeffery struct pldm_pass_component_table_req *request =
177248761c62SAndrew Jeffery (struct pldm_pass_component_table_req *)msg->payload;
177348761c62SAndrew Jeffery
177448761c62SAndrew Jeffery request->transfer_flag = transfer_flag;
177548761c62SAndrew Jeffery request->comp_classification = htole16(comp_classification);
177648761c62SAndrew Jeffery request->comp_identifier = htole16(comp_identifier);
177748761c62SAndrew Jeffery request->comp_classification_index = comp_classification_index;
177848761c62SAndrew Jeffery request->comp_comparison_stamp = htole32(comp_comparison_stamp);
177948761c62SAndrew Jeffery request->comp_ver_str_type = comp_ver_str_type;
178048761c62SAndrew Jeffery request->comp_ver_str_len = comp_ver_str_len;
178148761c62SAndrew Jeffery
178248761c62SAndrew Jeffery memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
178348761c62SAndrew Jeffery comp_ver_str->ptr, comp_ver_str->length);
178448761c62SAndrew Jeffery
178548761c62SAndrew Jeffery return PLDM_SUCCESS;
178648761c62SAndrew Jeffery }
178748761c62SAndrew Jeffery
1788cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
1789cf9a2df3SMatt Johnston int decode_pass_component_table_req(
1790cf9a2df3SMatt Johnston const struct pldm_msg *msg, size_t payload_length,
1791cf9a2df3SMatt Johnston struct pldm_pass_component_table_req_full *pcomp)
1792cf9a2df3SMatt Johnston {
1793cf9a2df3SMatt Johnston int rc;
1794cf9a2df3SMatt Johnston uint8_t t;
1795*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
1796cf9a2df3SMatt Johnston
1797cf9a2df3SMatt Johnston if (msg == NULL || pcomp == NULL) {
1798cf9a2df3SMatt Johnston return -EINVAL;
1799cf9a2df3SMatt Johnston }
1800cf9a2df3SMatt Johnston
1801cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1802cf9a2df3SMatt Johnston if (rc) {
decode_pass_component_table_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_pass_component_table_req_full * pcomp)1803cf9a2df3SMatt Johnston return rc;
1804cf9a2df3SMatt Johnston }
1805cf9a2df3SMatt Johnston
1806cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, pcomp->transfer_flag);
1807cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, pcomp->comp_classification);
1808cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, pcomp->comp_identifier);
1809cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, pcomp->comp_classification_index);
1810cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, pcomp->comp_comparison_stamp);
1811cf9a2df3SMatt Johnston rc = pldm_msgbuf_extract(buf, t);
1812cf9a2df3SMatt Johnston if (rc) {
1813*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1814cf9a2df3SMatt Johnston }
1815cf9a2df3SMatt Johnston if (t > PLDM_STR_TYPE_UTF_16BE) {
1816*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, -EBADMSG);
1817cf9a2df3SMatt Johnston }
1818cf9a2df3SMatt Johnston pcomp->version.str_type = (enum pldm_firmware_update_string_type)t;
1819cf9a2df3SMatt Johnston rc = pldm_msgbuf_extract(buf, pcomp->version.str_len);
1820cf9a2df3SMatt Johnston if (rc) {
1821*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1822cf9a2df3SMatt Johnston }
1823cf9a2df3SMatt Johnston rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len,
1824cf9a2df3SMatt Johnston pcomp->version.str_data,
1825cf9a2df3SMatt Johnston PLDM_FIRMWARE_MAX_STRING);
1826cf9a2df3SMatt Johnston if (rc) {
1827*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1828cf9a2df3SMatt Johnston }
1829cf9a2df3SMatt Johnston
183070d21c97SAndrew Jeffery return pldm_msgbuf_complete_consumed(buf);
1831cf9a2df3SMatt Johnston }
1832cf9a2df3SMatt Johnston
183348761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
183448761c62SAndrew Jeffery int decode_pass_component_table_resp(const struct pldm_msg *msg,
183548761c62SAndrew Jeffery const size_t payload_length,
183648761c62SAndrew Jeffery uint8_t *completion_code,
183748761c62SAndrew Jeffery uint8_t *comp_resp,
183848761c62SAndrew Jeffery uint8_t *comp_resp_code)
183948761c62SAndrew Jeffery {
184048761c62SAndrew Jeffery if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
184148761c62SAndrew Jeffery comp_resp_code == NULL || !payload_length) {
184248761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
184348761c62SAndrew Jeffery }
184448761c62SAndrew Jeffery
184548761c62SAndrew Jeffery *completion_code = msg->payload[0];
184648761c62SAndrew Jeffery if (*completion_code != PLDM_SUCCESS) {
184748761c62SAndrew Jeffery return PLDM_SUCCESS;
184848761c62SAndrew Jeffery }
decode_pass_component_table_resp(const struct pldm_msg * msg,const size_t payload_length,uint8_t * completion_code,uint8_t * comp_resp,uint8_t * comp_resp_code)184948761c62SAndrew Jeffery
185048761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
185148761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
185248761c62SAndrew Jeffery }
185348761c62SAndrew Jeffery
185448761c62SAndrew Jeffery struct pldm_pass_component_table_resp *response =
185548761c62SAndrew Jeffery (struct pldm_pass_component_table_resp *)msg->payload;
185648761c62SAndrew Jeffery
185748761c62SAndrew Jeffery if (!is_comp_resp_valid(response->comp_resp)) {
185848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
185948761c62SAndrew Jeffery }
186048761c62SAndrew Jeffery
186148761c62SAndrew Jeffery if (!is_comp_resp_code_valid(response->comp_resp_code)) {
186248761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
186348761c62SAndrew Jeffery }
186448761c62SAndrew Jeffery
186548761c62SAndrew Jeffery *comp_resp = response->comp_resp;
186648761c62SAndrew Jeffery *comp_resp_code = response->comp_resp_code;
186748761c62SAndrew Jeffery
186848761c62SAndrew Jeffery return PLDM_SUCCESS;
186948761c62SAndrew Jeffery }
187048761c62SAndrew Jeffery
1871cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
1872cf9a2df3SMatt Johnston int encode_pass_component_table_resp(
1873cf9a2df3SMatt Johnston uint8_t instance_id,
1874cf9a2df3SMatt Johnston const struct pldm_pass_component_table_resp *resp_data,
1875cf9a2df3SMatt Johnston struct pldm_msg *msg, size_t *payload_length)
1876cf9a2df3SMatt Johnston {
1877*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
1878cf9a2df3SMatt Johnston int rc;
1879cf9a2df3SMatt Johnston
1880cf9a2df3SMatt Johnston if (msg == NULL || payload_length == NULL) {
1881cf9a2df3SMatt Johnston return -EINVAL;
1882cf9a2df3SMatt Johnston }
1883cf9a2df3SMatt Johnston
1884cf9a2df3SMatt Johnston rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
1885cf9a2df3SMatt Johnston PLDM_PASS_COMPONENT_TABLE, msg);
1886cf9a2df3SMatt Johnston if (rc) {
encode_pass_component_table_resp(uint8_t instance_id,const struct pldm_pass_component_table_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)1887cf9a2df3SMatt Johnston return -EINVAL;
1888cf9a2df3SMatt Johnston }
1889cf9a2df3SMatt Johnston
1890cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1891cf9a2df3SMatt Johnston if (rc) {
1892cf9a2df3SMatt Johnston return rc;
1893cf9a2df3SMatt Johnston }
1894cf9a2df3SMatt Johnston
1895cf9a2df3SMatt Johnston pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1896cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->comp_resp);
1897cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->comp_resp_code);
1898cf9a2df3SMatt Johnston
189970d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1900cf9a2df3SMatt Johnston }
1901cf9a2df3SMatt Johnston
190248761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
190348761c62SAndrew Jeffery int encode_update_component_req(
190448761c62SAndrew Jeffery uint8_t instance_id, uint16_t comp_classification,
190548761c62SAndrew Jeffery uint16_t comp_identifier, uint8_t comp_classification_index,
190648761c62SAndrew Jeffery uint32_t comp_comparison_stamp, uint32_t comp_image_size,
190748761c62SAndrew Jeffery bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
190848761c62SAndrew Jeffery uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
190948761c62SAndrew Jeffery struct pldm_msg *msg, size_t payload_length)
191048761c62SAndrew Jeffery {
191148761c62SAndrew Jeffery if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
191248761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
191348761c62SAndrew Jeffery }
191448761c62SAndrew Jeffery
191548761c62SAndrew Jeffery if (payload_length !=
191648761c62SAndrew Jeffery sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
191748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
191848761c62SAndrew Jeffery }
encode_update_component_req(uint8_t instance_id,uint16_t comp_classification,uint16_t comp_identifier,uint8_t comp_classification_index,uint32_t comp_comparison_stamp,uint32_t comp_image_size,bitfield32_t update_option_flags,uint8_t comp_ver_str_type,uint8_t comp_ver_str_len,const struct variable_field * comp_ver_str,struct pldm_msg * msg,size_t payload_length)191948761c62SAndrew Jeffery
192048761c62SAndrew Jeffery if (!comp_image_size) {
192148761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
192248761c62SAndrew Jeffery }
192348761c62SAndrew Jeffery
192448761c62SAndrew Jeffery if ((comp_ver_str_len == 0) ||
192548761c62SAndrew Jeffery (comp_ver_str_len != comp_ver_str->length)) {
192648761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
192748761c62SAndrew Jeffery }
192848761c62SAndrew Jeffery
192948761c62SAndrew Jeffery if (!is_string_type_valid(comp_ver_str_type)) {
193048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
193148761c62SAndrew Jeffery }
193248761c62SAndrew Jeffery
193348761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
193448761c62SAndrew Jeffery header.instance = instance_id;
193548761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
193648761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
193748761c62SAndrew Jeffery header.command = PLDM_UPDATE_COMPONENT;
193848761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
193948761c62SAndrew Jeffery if (rc) {
194048761c62SAndrew Jeffery return rc;
194148761c62SAndrew Jeffery }
194248761c62SAndrew Jeffery
194348761c62SAndrew Jeffery struct pldm_update_component_req *request =
194448761c62SAndrew Jeffery (struct pldm_update_component_req *)msg->payload;
194548761c62SAndrew Jeffery
194648761c62SAndrew Jeffery request->comp_classification = htole16(comp_classification);
194748761c62SAndrew Jeffery request->comp_identifier = htole16(comp_identifier);
194848761c62SAndrew Jeffery request->comp_classification_index = comp_classification_index;
194948761c62SAndrew Jeffery request->comp_comparison_stamp = htole32(comp_comparison_stamp);
195048761c62SAndrew Jeffery request->comp_image_size = htole32(comp_image_size);
195148761c62SAndrew Jeffery request->update_option_flags.value = htole32(update_option_flags.value);
195248761c62SAndrew Jeffery request->comp_ver_str_type = comp_ver_str_type;
195348761c62SAndrew Jeffery request->comp_ver_str_len = comp_ver_str_len;
195448761c62SAndrew Jeffery
195548761c62SAndrew Jeffery memcpy(msg->payload + sizeof(struct pldm_update_component_req),
195648761c62SAndrew Jeffery comp_ver_str->ptr, comp_ver_str->length);
195748761c62SAndrew Jeffery
195848761c62SAndrew Jeffery return PLDM_SUCCESS;
195948761c62SAndrew Jeffery }
196048761c62SAndrew Jeffery
1961cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
1962cf9a2df3SMatt Johnston int decode_update_component_req(const struct pldm_msg *msg,
1963cf9a2df3SMatt Johnston size_t payload_length,
1964cf9a2df3SMatt Johnston struct pldm_update_component_req_full *up)
1965cf9a2df3SMatt Johnston {
1966cf9a2df3SMatt Johnston int rc;
1967cf9a2df3SMatt Johnston uint8_t t;
1968*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
1969cf9a2df3SMatt Johnston
1970cf9a2df3SMatt Johnston if (msg == NULL || up == NULL) {
1971cf9a2df3SMatt Johnston return -EINVAL;
1972cf9a2df3SMatt Johnston }
1973cf9a2df3SMatt Johnston
1974cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1975cf9a2df3SMatt Johnston if (rc) {
1976cf9a2df3SMatt Johnston return rc;
1977cf9a2df3SMatt Johnston }
decode_update_component_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_update_component_req_full * up)1978cf9a2df3SMatt Johnston
1979cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, up->comp_classification);
1980cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, up->comp_identifier);
1981cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, up->comp_classification_index);
1982cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, up->comp_comparison_stamp);
1983cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, up->comp_image_size);
1984cf9a2df3SMatt Johnston pldm_msgbuf_extract(buf, up->update_option_flags.value);
1985cf9a2df3SMatt Johnston rc = pldm_msgbuf_extract(buf, t);
1986cf9a2df3SMatt Johnston if (rc) {
1987*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1988cf9a2df3SMatt Johnston }
1989cf9a2df3SMatt Johnston if (t > PLDM_STR_TYPE_UTF_16BE) {
1990*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, -EBADMSG);
1991cf9a2df3SMatt Johnston }
1992cf9a2df3SMatt Johnston up->version.str_type = (enum pldm_firmware_update_string_type)t;
1993cf9a2df3SMatt Johnston rc = pldm_msgbuf_extract(buf, up->version.str_len);
1994cf9a2df3SMatt Johnston if (rc) {
1995*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
1996cf9a2df3SMatt Johnston }
1997cf9a2df3SMatt Johnston rc = pldm_msgbuf_extract_array(buf, up->version.str_len,
1998cf9a2df3SMatt Johnston up->version.str_data,
1999cf9a2df3SMatt Johnston PLDM_FIRMWARE_MAX_STRING);
2000cf9a2df3SMatt Johnston if (rc) {
2001*a1896967SAndrew Jeffery return pldm_msgbuf_discard(buf, rc);
2002cf9a2df3SMatt Johnston }
2003cf9a2df3SMatt Johnston
2004*a1896967SAndrew Jeffery return pldm_msgbuf_complete_consumed(buf);
2005cf9a2df3SMatt Johnston }
2006cf9a2df3SMatt Johnston
200748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
200848761c62SAndrew Jeffery int decode_update_component_resp(const struct pldm_msg *msg,
200948761c62SAndrew Jeffery size_t payload_length,
201048761c62SAndrew Jeffery uint8_t *completion_code,
201148761c62SAndrew Jeffery uint8_t *comp_compatibility_resp,
201248761c62SAndrew Jeffery uint8_t *comp_compatibility_resp_code,
201348761c62SAndrew Jeffery bitfield32_t *update_option_flags_enabled,
201448761c62SAndrew Jeffery uint16_t *time_before_req_fw_data)
201548761c62SAndrew Jeffery {
201648761c62SAndrew Jeffery if (msg == NULL || completion_code == NULL ||
201748761c62SAndrew Jeffery comp_compatibility_resp == NULL ||
201848761c62SAndrew Jeffery comp_compatibility_resp_code == NULL ||
201948761c62SAndrew Jeffery update_option_flags_enabled == NULL ||
202048761c62SAndrew Jeffery time_before_req_fw_data == NULL || !payload_length) {
202148761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
202248761c62SAndrew Jeffery }
202348761c62SAndrew Jeffery
202448761c62SAndrew Jeffery *completion_code = msg->payload[0];
202548761c62SAndrew Jeffery if (*completion_code != PLDM_SUCCESS) {
202648761c62SAndrew Jeffery return PLDM_SUCCESS;
202748761c62SAndrew Jeffery }
202848761c62SAndrew Jeffery
decode_update_component_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * comp_compatibility_resp,uint8_t * comp_compatibility_resp_code,bitfield32_t * update_option_flags_enabled,uint16_t * time_before_req_fw_data)202948761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_update_component_resp)) {
203048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
203148761c62SAndrew Jeffery }
203248761c62SAndrew Jeffery
203348761c62SAndrew Jeffery struct pldm_update_component_resp *response =
203448761c62SAndrew Jeffery (struct pldm_update_component_resp *)msg->payload;
203548761c62SAndrew Jeffery
203648761c62SAndrew Jeffery if (!is_comp_compatibility_resp_valid(
203748761c62SAndrew Jeffery response->comp_compatibility_resp)) {
203848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
203948761c62SAndrew Jeffery }
204048761c62SAndrew Jeffery
204148761c62SAndrew Jeffery if (!is_comp_compatibility_resp_code_valid(
204248761c62SAndrew Jeffery response->comp_compatibility_resp_code)) {
204348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
204448761c62SAndrew Jeffery }
204548761c62SAndrew Jeffery
204648761c62SAndrew Jeffery *comp_compatibility_resp = response->comp_compatibility_resp;
204748761c62SAndrew Jeffery *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
204848761c62SAndrew Jeffery update_option_flags_enabled->value =
204948761c62SAndrew Jeffery le32toh(response->update_option_flags_enabled.value);
205048761c62SAndrew Jeffery *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
205148761c62SAndrew Jeffery
205248761c62SAndrew Jeffery return PLDM_SUCCESS;
205348761c62SAndrew Jeffery }
205448761c62SAndrew Jeffery
2055cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
2056cf9a2df3SMatt Johnston int encode_update_component_resp(
2057cf9a2df3SMatt Johnston uint8_t instance_id, const struct pldm_update_component_resp *resp_data,
2058cf9a2df3SMatt Johnston struct pldm_msg *msg, size_t *payload_length)
2059cf9a2df3SMatt Johnston {
2060*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
2061cf9a2df3SMatt Johnston int rc;
2062cf9a2df3SMatt Johnston
2063cf9a2df3SMatt Johnston if (msg == NULL || payload_length == NULL) {
2064cf9a2df3SMatt Johnston return -EINVAL;
2065cf9a2df3SMatt Johnston }
2066cf9a2df3SMatt Johnston
2067cf9a2df3SMatt Johnston rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2068cf9a2df3SMatt Johnston PLDM_UPDATE_COMPONENT, msg);
2069cf9a2df3SMatt Johnston if (rc) {
2070cf9a2df3SMatt Johnston return -EINVAL;
2071cf9a2df3SMatt Johnston }
2072cf9a2df3SMatt Johnston
2073cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2074cf9a2df3SMatt Johnston if (rc) {
2075cf9a2df3SMatt Johnston return rc;
2076cf9a2df3SMatt Johnston }
encode_update_component_resp(uint8_t instance_id,const struct pldm_update_component_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)2077cf9a2df3SMatt Johnston
2078cf9a2df3SMatt Johnston pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2079cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp);
2080cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp_code);
2081cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->update_option_flags_enabled.value);
2082cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->time_before_req_fw_data);
2083cf9a2df3SMatt Johnston
208470d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2085cf9a2df3SMatt Johnston }
2086cf9a2df3SMatt Johnston
208748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
208848761c62SAndrew Jeffery int decode_request_firmware_data_req(const struct pldm_msg *msg,
208948761c62SAndrew Jeffery size_t payload_length, uint32_t *offset,
209048761c62SAndrew Jeffery uint32_t *length)
209148761c62SAndrew Jeffery {
209248761c62SAndrew Jeffery if (msg == NULL || offset == NULL || length == NULL) {
209348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
209448761c62SAndrew Jeffery }
209548761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
209648761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
209748761c62SAndrew Jeffery }
209848761c62SAndrew Jeffery struct pldm_request_firmware_data_req *request =
209948761c62SAndrew Jeffery (struct pldm_request_firmware_data_req *)msg->payload;
210048761c62SAndrew Jeffery *offset = le32toh(request->offset);
210148761c62SAndrew Jeffery *length = le32toh(request->length);
210248761c62SAndrew Jeffery
210348761c62SAndrew Jeffery if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
210448761c62SAndrew Jeffery return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
210548761c62SAndrew Jeffery }
210648761c62SAndrew Jeffery
210748761c62SAndrew Jeffery return PLDM_SUCCESS;
210848761c62SAndrew Jeffery }
210948761c62SAndrew Jeffery
decode_request_firmware_data_req(const struct pldm_msg * msg,size_t payload_length,uint32_t * offset,uint32_t * length)2110cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
2111cf9a2df3SMatt Johnston int encode_request_firmware_data_req(
2112cf9a2df3SMatt Johnston uint8_t instance_id,
2113cf9a2df3SMatt Johnston const struct pldm_request_firmware_data_req *req_params,
2114cf9a2df3SMatt Johnston struct pldm_msg *msg, size_t *payload_length)
2115cf9a2df3SMatt Johnston {
2116*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
2117cf9a2df3SMatt Johnston int rc;
2118cf9a2df3SMatt Johnston
2119cf9a2df3SMatt Johnston if (msg == NULL || payload_length == NULL) {
2120cf9a2df3SMatt Johnston return -EINVAL;
2121cf9a2df3SMatt Johnston }
2122cf9a2df3SMatt Johnston
2123cf9a2df3SMatt Johnston rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2124cf9a2df3SMatt Johnston PLDM_REQUEST_FIRMWARE_DATA, msg);
2125cf9a2df3SMatt Johnston if (rc) {
2126cf9a2df3SMatt Johnston return -EINVAL;
2127cf9a2df3SMatt Johnston }
2128cf9a2df3SMatt Johnston
2129cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2130cf9a2df3SMatt Johnston if (rc) {
2131cf9a2df3SMatt Johnston return rc;
2132cf9a2df3SMatt Johnston }
2133cf9a2df3SMatt Johnston
2134cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, req_params->offset);
2135cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, req_params->length);
2136cf9a2df3SMatt Johnston
213770d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2138cf9a2df3SMatt Johnston }
2139cf9a2df3SMatt Johnston
214048761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
214148761c62SAndrew Jeffery int encode_request_firmware_data_resp(uint8_t instance_id,
214248761c62SAndrew Jeffery uint8_t completion_code,
214348761c62SAndrew Jeffery struct pldm_msg *msg,
214448761c62SAndrew Jeffery size_t payload_length)
214548761c62SAndrew Jeffery {
214648761c62SAndrew Jeffery if (msg == NULL || !payload_length) {
214748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
214848761c62SAndrew Jeffery }
214948761c62SAndrew Jeffery
215048761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
215148761c62SAndrew Jeffery header.instance = instance_id;
215248761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
215348761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
215448761c62SAndrew Jeffery header.command = PLDM_REQUEST_FIRMWARE_DATA;
215548761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
215648761c62SAndrew Jeffery if (rc) {
215748761c62SAndrew Jeffery return rc;
215848761c62SAndrew Jeffery }
215948761c62SAndrew Jeffery
216048761c62SAndrew Jeffery msg->payload[0] = completion_code;
216148761c62SAndrew Jeffery
216248761c62SAndrew Jeffery return PLDM_SUCCESS;
216348761c62SAndrew Jeffery }
encode_request_firmware_data_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)216448761c62SAndrew Jeffery
216548761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
216648761c62SAndrew Jeffery int decode_transfer_complete_req(const struct pldm_msg *msg,
216748761c62SAndrew Jeffery size_t payload_length,
216848761c62SAndrew Jeffery uint8_t *transfer_result)
216948761c62SAndrew Jeffery {
217048761c62SAndrew Jeffery if (msg == NULL || transfer_result == NULL) {
217148761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
217248761c62SAndrew Jeffery }
217348761c62SAndrew Jeffery
217448761c62SAndrew Jeffery if (payload_length != sizeof(*transfer_result)) {
217548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
217648761c62SAndrew Jeffery }
217748761c62SAndrew Jeffery
217848761c62SAndrew Jeffery *transfer_result = msg->payload[0];
217948761c62SAndrew Jeffery return PLDM_SUCCESS;
218048761c62SAndrew Jeffery }
218148761c62SAndrew Jeffery
2182cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
2183cf9a2df3SMatt Johnston int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
2184cf9a2df3SMatt Johnston struct pldm_msg *msg, size_t *payload_length)
2185cf9a2df3SMatt Johnston {
2186*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
2187cf9a2df3SMatt Johnston int rc;
2188cf9a2df3SMatt Johnston
decode_transfer_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * transfer_result)2189cf9a2df3SMatt Johnston if (msg == NULL || payload_length == NULL) {
2190cf9a2df3SMatt Johnston return -EINVAL;
2191cf9a2df3SMatt Johnston }
2192cf9a2df3SMatt Johnston
2193cf9a2df3SMatt Johnston rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2194cf9a2df3SMatt Johnston PLDM_TRANSFER_COMPLETE, msg);
2195cf9a2df3SMatt Johnston if (rc) {
2196cf9a2df3SMatt Johnston return -EINVAL;
2197cf9a2df3SMatt Johnston }
2198cf9a2df3SMatt Johnston
2199cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2200cf9a2df3SMatt Johnston if (rc) {
2201cf9a2df3SMatt Johnston return rc;
2202cf9a2df3SMatt Johnston }
2203cf9a2df3SMatt Johnston
2204*a1896967SAndrew Jeffery pldm_msgbuf_insert(buf, transfer_result);
2205cf9a2df3SMatt Johnston
encode_transfer_complete_req(uint8_t instance_id,uint8_t transfer_result,struct pldm_msg * msg,size_t * payload_length)220670d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2207cf9a2df3SMatt Johnston }
2208cf9a2df3SMatt Johnston
220948761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
221048761c62SAndrew Jeffery int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
221148761c62SAndrew Jeffery struct pldm_msg *msg, size_t payload_length)
221248761c62SAndrew Jeffery {
221348761c62SAndrew Jeffery if (msg == NULL) {
221448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
221548761c62SAndrew Jeffery }
221648761c62SAndrew Jeffery
221748761c62SAndrew Jeffery if (payload_length != sizeof(completion_code)) {
221848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
221948761c62SAndrew Jeffery }
222048761c62SAndrew Jeffery
222148761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
222248761c62SAndrew Jeffery header.instance = instance_id;
222348761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
222448761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
222548761c62SAndrew Jeffery header.command = PLDM_TRANSFER_COMPLETE;
222648761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
222748761c62SAndrew Jeffery if (rc) {
222848761c62SAndrew Jeffery return rc;
222948761c62SAndrew Jeffery }
223048761c62SAndrew Jeffery
223148761c62SAndrew Jeffery msg->payload[0] = completion_code;
223248761c62SAndrew Jeffery
223348761c62SAndrew Jeffery return PLDM_SUCCESS;
223448761c62SAndrew Jeffery }
223548761c62SAndrew Jeffery
223648761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_transfer_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)223748761c62SAndrew Jeffery int decode_verify_complete_req(const struct pldm_msg *msg,
223848761c62SAndrew Jeffery size_t payload_length, uint8_t *verify_result)
223948761c62SAndrew Jeffery {
224048761c62SAndrew Jeffery if (msg == NULL || verify_result == NULL) {
224148761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
224248761c62SAndrew Jeffery }
224348761c62SAndrew Jeffery
224448761c62SAndrew Jeffery if (payload_length != sizeof(*verify_result)) {
224548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
224648761c62SAndrew Jeffery }
224748761c62SAndrew Jeffery
224848761c62SAndrew Jeffery *verify_result = msg->payload[0];
224948761c62SAndrew Jeffery return PLDM_SUCCESS;
225048761c62SAndrew Jeffery }
225148761c62SAndrew Jeffery
2252cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
2253cf9a2df3SMatt Johnston int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
2254cf9a2df3SMatt Johnston struct pldm_msg *msg, size_t *payload_length)
2255cf9a2df3SMatt Johnston {
2256*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
2257cf9a2df3SMatt Johnston int rc;
2258cf9a2df3SMatt Johnston
2259cf9a2df3SMatt Johnston if (msg == NULL || payload_length == NULL) {
2260cf9a2df3SMatt Johnston return -EINVAL;
2261cf9a2df3SMatt Johnston }
2262cf9a2df3SMatt Johnston
2263cf9a2df3SMatt Johnston rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
decode_verify_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * verify_result)2264cf9a2df3SMatt Johnston PLDM_VERIFY_COMPLETE, msg);
2265cf9a2df3SMatt Johnston if (rc) {
2266cf9a2df3SMatt Johnston return EINVAL;
2267cf9a2df3SMatt Johnston }
2268cf9a2df3SMatt Johnston
2269cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2270cf9a2df3SMatt Johnston if (rc) {
2271cf9a2df3SMatt Johnston return rc;
2272cf9a2df3SMatt Johnston }
2273cf9a2df3SMatt Johnston
2274*a1896967SAndrew Jeffery pldm_msgbuf_insert(buf, verify_result);
2275cf9a2df3SMatt Johnston
227670d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2277cf9a2df3SMatt Johnston }
2278cf9a2df3SMatt Johnston
227948761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_verify_complete_req(uint8_t instance_id,uint8_t verify_result,struct pldm_msg * msg,size_t * payload_length)228048761c62SAndrew Jeffery int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
228148761c62SAndrew Jeffery struct pldm_msg *msg, size_t payload_length)
228248761c62SAndrew Jeffery {
228348761c62SAndrew Jeffery if (msg == NULL) {
228448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
228548761c62SAndrew Jeffery }
228648761c62SAndrew Jeffery
228748761c62SAndrew Jeffery if (payload_length != sizeof(completion_code)) {
228848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
228948761c62SAndrew Jeffery }
229048761c62SAndrew Jeffery
229148761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
229248761c62SAndrew Jeffery header.instance = instance_id;
229348761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
229448761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
229548761c62SAndrew Jeffery header.command = PLDM_VERIFY_COMPLETE;
229648761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
229748761c62SAndrew Jeffery if (rc) {
229848761c62SAndrew Jeffery return rc;
229948761c62SAndrew Jeffery }
230048761c62SAndrew Jeffery
230148761c62SAndrew Jeffery msg->payload[0] = completion_code;
230248761c62SAndrew Jeffery
230348761c62SAndrew Jeffery return PLDM_SUCCESS;
230448761c62SAndrew Jeffery }
230548761c62SAndrew Jeffery
230648761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
230748761c62SAndrew Jeffery int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
230848761c62SAndrew Jeffery uint8_t *apply_result,
230948761c62SAndrew Jeffery bitfield16_t *comp_activation_methods_modification)
231048761c62SAndrew Jeffery {
encode_verify_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)231148761c62SAndrew Jeffery if (msg == NULL || apply_result == NULL ||
231248761c62SAndrew Jeffery comp_activation_methods_modification == NULL) {
231348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
231448761c62SAndrew Jeffery }
231548761c62SAndrew Jeffery
231648761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_apply_complete_req)) {
231748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
231848761c62SAndrew Jeffery }
231948761c62SAndrew Jeffery
232048761c62SAndrew Jeffery struct pldm_apply_complete_req *request =
232148761c62SAndrew Jeffery (struct pldm_apply_complete_req *)msg->payload;
232248761c62SAndrew Jeffery
232348761c62SAndrew Jeffery *apply_result = request->apply_result;
232448761c62SAndrew Jeffery comp_activation_methods_modification->value =
232548761c62SAndrew Jeffery le16toh(request->comp_activation_methods_modification.value);
232648761c62SAndrew Jeffery
232748761c62SAndrew Jeffery if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
232848761c62SAndrew Jeffery comp_activation_methods_modification->value) {
232948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
233048761c62SAndrew Jeffery }
233148761c62SAndrew Jeffery
233248761c62SAndrew Jeffery return PLDM_SUCCESS;
233348761c62SAndrew Jeffery }
233448761c62SAndrew Jeffery
2335cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
2336cf9a2df3SMatt Johnston int encode_apply_complete_req(uint8_t instance_id,
2337cf9a2df3SMatt Johnston const struct pldm_apply_complete_req *req_data,
decode_apply_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * apply_result,bitfield16_t * comp_activation_methods_modification)2338cf9a2df3SMatt Johnston struct pldm_msg *msg, size_t *payload_length)
2339cf9a2df3SMatt Johnston {
2340*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
2341cf9a2df3SMatt Johnston int rc;
2342cf9a2df3SMatt Johnston
2343cf9a2df3SMatt Johnston if (msg == NULL || payload_length == NULL) {
2344cf9a2df3SMatt Johnston return -EINVAL;
2345cf9a2df3SMatt Johnston }
2346cf9a2df3SMatt Johnston
2347cf9a2df3SMatt Johnston rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2348cf9a2df3SMatt Johnston PLDM_APPLY_COMPLETE, msg);
2349cf9a2df3SMatt Johnston if (rc) {
2350cf9a2df3SMatt Johnston return -EINVAL;
2351cf9a2df3SMatt Johnston }
2352cf9a2df3SMatt Johnston
2353cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2354cf9a2df3SMatt Johnston if (rc) {
2355cf9a2df3SMatt Johnston return rc;
2356cf9a2df3SMatt Johnston }
2357cf9a2df3SMatt Johnston
2358cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, req_data->apply_result);
2359cf9a2df3SMatt Johnston pldm_msgbuf_insert(
2360cf9a2df3SMatt Johnston buf, req_data->comp_activation_methods_modification.value);
2361cf9a2df3SMatt Johnston
236270d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2363cf9a2df3SMatt Johnston }
2364cf9a2df3SMatt Johnston
236548761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
236648761c62SAndrew Jeffery int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
encode_apply_complete_req(uint8_t instance_id,const struct pldm_apply_complete_req * req_data,struct pldm_msg * msg,size_t * payload_length)236748761c62SAndrew Jeffery struct pldm_msg *msg, size_t payload_length)
236848761c62SAndrew Jeffery {
236948761c62SAndrew Jeffery if (msg == NULL) {
237048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
237148761c62SAndrew Jeffery }
237248761c62SAndrew Jeffery
237348761c62SAndrew Jeffery if (payload_length != sizeof(completion_code)) {
237448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
237548761c62SAndrew Jeffery }
237648761c62SAndrew Jeffery
237748761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
237848761c62SAndrew Jeffery header.instance = instance_id;
237948761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
238048761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
238148761c62SAndrew Jeffery header.command = PLDM_APPLY_COMPLETE;
238248761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
238348761c62SAndrew Jeffery if (rc) {
238448761c62SAndrew Jeffery return rc;
238548761c62SAndrew Jeffery }
238648761c62SAndrew Jeffery
238748761c62SAndrew Jeffery msg->payload[0] = completion_code;
238848761c62SAndrew Jeffery
238948761c62SAndrew Jeffery return PLDM_SUCCESS;
239048761c62SAndrew Jeffery }
239148761c62SAndrew Jeffery
2392cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
2393cf9a2df3SMatt Johnston int decode_activate_firmware_req(const struct pldm_msg *msg,
2394cf9a2df3SMatt Johnston size_t payload_length, bool *self_contained)
2395cf9a2df3SMatt Johnston {
2396*a1896967SAndrew Jeffery uint8_t self_contained_u8 = 0;
2397*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
encode_apply_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2398cf9a2df3SMatt Johnston int rc;
2399cf9a2df3SMatt Johnston
2400cf9a2df3SMatt Johnston if (msg == NULL || self_contained == NULL) {
2401cf9a2df3SMatt Johnston return -EINVAL;
2402cf9a2df3SMatt Johnston }
2403cf9a2df3SMatt Johnston
2404cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
2405cf9a2df3SMatt Johnston if (rc) {
2406cf9a2df3SMatt Johnston return 0;
2407cf9a2df3SMatt Johnston }
2408cf9a2df3SMatt Johnston
2409*a1896967SAndrew Jeffery pldm_msgbuf_extract(buf, self_contained_u8);
2410*a1896967SAndrew Jeffery
2411*a1896967SAndrew Jeffery rc = pldm_msgbuf_complete_consumed(buf);
2412cf9a2df3SMatt Johnston if (rc) {
2413cf9a2df3SMatt Johnston return rc;
2414cf9a2df3SMatt Johnston }
2415*a1896967SAndrew Jeffery
2416cf9a2df3SMatt Johnston *self_contained = (bool)self_contained_u8;
2417cf9a2df3SMatt Johnston return 0;
2418cf9a2df3SMatt Johnston }
2419cf9a2df3SMatt Johnston
242048761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
242148761c62SAndrew Jeffery int encode_activate_firmware_req(uint8_t instance_id,
242248761c62SAndrew Jeffery bool8_t self_contained_activation_req,
242348761c62SAndrew Jeffery struct pldm_msg *msg, size_t payload_length)
242448761c62SAndrew Jeffery {
decode_activate_firmware_req(const struct pldm_msg * msg,size_t payload_length,bool * self_contained)242548761c62SAndrew Jeffery if (msg == NULL) {
242648761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
242748761c62SAndrew Jeffery }
242848761c62SAndrew Jeffery
242948761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
243048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
243148761c62SAndrew Jeffery }
243248761c62SAndrew Jeffery
243348761c62SAndrew Jeffery if (!is_self_contained_activation_req_valid(
243448761c62SAndrew Jeffery self_contained_activation_req)) {
243548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
243648761c62SAndrew Jeffery }
243748761c62SAndrew Jeffery
243848761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
243948761c62SAndrew Jeffery header.instance = instance_id;
244048761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
244148761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
244248761c62SAndrew Jeffery header.command = PLDM_ACTIVATE_FIRMWARE;
244348761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
244448761c62SAndrew Jeffery if (rc) {
244548761c62SAndrew Jeffery return rc;
244648761c62SAndrew Jeffery }
244748761c62SAndrew Jeffery
244848761c62SAndrew Jeffery struct pldm_activate_firmware_req *request =
244948761c62SAndrew Jeffery (struct pldm_activate_firmware_req *)msg->payload;
245048761c62SAndrew Jeffery
245148761c62SAndrew Jeffery request->self_contained_activation_req = self_contained_activation_req;
245248761c62SAndrew Jeffery
245348761c62SAndrew Jeffery return PLDM_SUCCESS;
encode_activate_firmware_req(uint8_t instance_id,bool8_t self_contained_activation_req,struct pldm_msg * msg,size_t payload_length)245448761c62SAndrew Jeffery }
245548761c62SAndrew Jeffery
245648761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
245748761c62SAndrew Jeffery int decode_activate_firmware_resp(const struct pldm_msg *msg,
245848761c62SAndrew Jeffery size_t payload_length,
245948761c62SAndrew Jeffery uint8_t *completion_code,
246048761c62SAndrew Jeffery uint16_t *estimated_time_activation)
246148761c62SAndrew Jeffery {
246248761c62SAndrew Jeffery if (msg == NULL || completion_code == NULL ||
246348761c62SAndrew Jeffery estimated_time_activation == NULL || !payload_length) {
246448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
246548761c62SAndrew Jeffery }
246648761c62SAndrew Jeffery
246748761c62SAndrew Jeffery *completion_code = msg->payload[0];
246848761c62SAndrew Jeffery if (*completion_code != PLDM_SUCCESS) {
246948761c62SAndrew Jeffery return PLDM_SUCCESS;
247048761c62SAndrew Jeffery }
247148761c62SAndrew Jeffery
247248761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
247348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
247448761c62SAndrew Jeffery }
247548761c62SAndrew Jeffery
247648761c62SAndrew Jeffery struct pldm_activate_firmware_resp *response =
247748761c62SAndrew Jeffery (struct pldm_activate_firmware_resp *)msg->payload;
247848761c62SAndrew Jeffery
247948761c62SAndrew Jeffery *estimated_time_activation =
248048761c62SAndrew Jeffery le16toh(response->estimated_time_activation);
248148761c62SAndrew Jeffery
248248761c62SAndrew Jeffery return PLDM_SUCCESS;
248348761c62SAndrew Jeffery }
248448761c62SAndrew Jeffery
2485cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
2486cf9a2df3SMatt Johnston int encode_activate_firmware_resp(
2487cf9a2df3SMatt Johnston uint8_t instance_id,
2488cf9a2df3SMatt Johnston const struct pldm_activate_firmware_resp *resp_data,
2489cf9a2df3SMatt Johnston struct pldm_msg *msg, size_t *payload_length)
decode_activate_firmware_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint16_t * estimated_time_activation)2490cf9a2df3SMatt Johnston {
2491*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
2492cf9a2df3SMatt Johnston int rc;
2493cf9a2df3SMatt Johnston
2494cf9a2df3SMatt Johnston if (msg == NULL || payload_length == NULL) {
2495cf9a2df3SMatt Johnston return -EINVAL;
2496cf9a2df3SMatt Johnston }
2497cf9a2df3SMatt Johnston
2498cf9a2df3SMatt Johnston rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2499cf9a2df3SMatt Johnston PLDM_ACTIVATE_FIRMWARE, msg);
2500cf9a2df3SMatt Johnston if (rc) {
2501cf9a2df3SMatt Johnston return -EINVAL;
2502cf9a2df3SMatt Johnston }
2503cf9a2df3SMatt Johnston
2504cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2505cf9a2df3SMatt Johnston if (rc) {
2506cf9a2df3SMatt Johnston return rc;
2507cf9a2df3SMatt Johnston }
2508cf9a2df3SMatt Johnston
2509cf9a2df3SMatt Johnston pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2510cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->estimated_time_activation);
2511cf9a2df3SMatt Johnston
251270d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2513cf9a2df3SMatt Johnston }
2514cf9a2df3SMatt Johnston
251548761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
251648761c62SAndrew Jeffery int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
251748761c62SAndrew Jeffery size_t payload_length)
251848761c62SAndrew Jeffery {
encode_activate_firmware_resp(uint8_t instance_id,const struct pldm_activate_firmware_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)251948761c62SAndrew Jeffery if (msg == NULL) {
252048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
252148761c62SAndrew Jeffery }
252248761c62SAndrew Jeffery
252348761c62SAndrew Jeffery if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
252448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
252548761c62SAndrew Jeffery }
252648761c62SAndrew Jeffery
252748761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
252848761c62SAndrew Jeffery header.instance = instance_id;
252948761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
253048761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
253148761c62SAndrew Jeffery header.command = PLDM_GET_STATUS;
253248761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
253348761c62SAndrew Jeffery if (rc) {
253448761c62SAndrew Jeffery return rc;
253548761c62SAndrew Jeffery }
253648761c62SAndrew Jeffery
253748761c62SAndrew Jeffery return PLDM_SUCCESS;
253848761c62SAndrew Jeffery }
253948761c62SAndrew Jeffery
254048761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
254148761c62SAndrew Jeffery int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
254248761c62SAndrew Jeffery uint8_t *completion_code, uint8_t *current_state,
254348761c62SAndrew Jeffery uint8_t *previous_state, uint8_t *aux_state,
254448761c62SAndrew Jeffery uint8_t *aux_state_status, uint8_t *progress_percent,
254548761c62SAndrew Jeffery uint8_t *reason_code,
254648761c62SAndrew Jeffery bitfield32_t *update_option_flags_enabled)
254748761c62SAndrew Jeffery {
254848761c62SAndrew Jeffery if (msg == NULL || completion_code == NULL || current_state == NULL ||
254948761c62SAndrew Jeffery previous_state == NULL || aux_state == NULL ||
encode_get_status_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)255048761c62SAndrew Jeffery aux_state_status == NULL || progress_percent == NULL ||
255148761c62SAndrew Jeffery reason_code == NULL || update_option_flags_enabled == NULL ||
255248761c62SAndrew Jeffery !payload_length) {
255348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
255448761c62SAndrew Jeffery }
255548761c62SAndrew Jeffery
255648761c62SAndrew Jeffery *completion_code = msg->payload[0];
255748761c62SAndrew Jeffery if (*completion_code != PLDM_SUCCESS) {
255848761c62SAndrew Jeffery return PLDM_SUCCESS;
255948761c62SAndrew Jeffery }
256048761c62SAndrew Jeffery
256148761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_get_status_resp)) {
256248761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
256348761c62SAndrew Jeffery }
256448761c62SAndrew Jeffery struct pldm_get_status_resp *response =
256548761c62SAndrew Jeffery (struct pldm_get_status_resp *)msg->payload;
256648761c62SAndrew Jeffery
256748761c62SAndrew Jeffery if (!is_state_valid(response->current_state)) {
256848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
256948761c62SAndrew Jeffery }
257048761c62SAndrew Jeffery if (!is_state_valid(response->previous_state)) {
257148761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
257248761c62SAndrew Jeffery }
257348761c62SAndrew Jeffery if (!is_aux_state_valid(response->aux_state)) {
257448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
decode_get_status_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * current_state,uint8_t * previous_state,uint8_t * aux_state,uint8_t * aux_state_status,uint8_t * progress_percent,uint8_t * reason_code,bitfield32_t * update_option_flags_enabled)257548761c62SAndrew Jeffery }
257648761c62SAndrew Jeffery if (!is_aux_state_status_valid(response->aux_state_status)) {
257748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
257848761c62SAndrew Jeffery }
257948761c62SAndrew Jeffery if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
258048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
258148761c62SAndrew Jeffery }
258248761c62SAndrew Jeffery if (!is_reason_code_valid(response->reason_code)) {
258348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
258448761c62SAndrew Jeffery }
258548761c62SAndrew Jeffery
258648761c62SAndrew Jeffery if ((response->current_state == PLDM_FD_STATE_IDLE) ||
258748761c62SAndrew Jeffery (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
258848761c62SAndrew Jeffery (response->current_state == PLDM_FD_STATE_READY_XFER)) {
258948761c62SAndrew Jeffery if (response->aux_state !=
259048761c62SAndrew Jeffery PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
259148761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
259248761c62SAndrew Jeffery }
259348761c62SAndrew Jeffery }
259448761c62SAndrew Jeffery
259548761c62SAndrew Jeffery *current_state = response->current_state;
259648761c62SAndrew Jeffery *previous_state = response->previous_state;
259748761c62SAndrew Jeffery *aux_state = response->aux_state;
259848761c62SAndrew Jeffery *aux_state_status = response->aux_state_status;
259948761c62SAndrew Jeffery *progress_percent = response->progress_percent;
260048761c62SAndrew Jeffery *reason_code = response->reason_code;
260148761c62SAndrew Jeffery update_option_flags_enabled->value =
260248761c62SAndrew Jeffery le32toh(response->update_option_flags_enabled.value);
260348761c62SAndrew Jeffery
260448761c62SAndrew Jeffery return PLDM_SUCCESS;
260548761c62SAndrew Jeffery }
260648761c62SAndrew Jeffery
2607cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
2608cf9a2df3SMatt Johnston int encode_get_status_resp(uint8_t instance_id,
2609cf9a2df3SMatt Johnston const struct pldm_get_status_resp *status,
2610cf9a2df3SMatt Johnston struct pldm_msg *msg, size_t *payload_length)
2611cf9a2df3SMatt Johnston {
2612*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
2613cf9a2df3SMatt Johnston int rc;
2614cf9a2df3SMatt Johnston
2615cf9a2df3SMatt Johnston if (status == NULL || msg == NULL || payload_length == NULL) {
2616cf9a2df3SMatt Johnston return -EINVAL;
2617cf9a2df3SMatt Johnston }
2618cf9a2df3SMatt Johnston
2619cf9a2df3SMatt Johnston if (status->completion_code != PLDM_SUCCESS) {
2620cf9a2df3SMatt Johnston return -EINVAL;
2621cf9a2df3SMatt Johnston }
2622cf9a2df3SMatt Johnston
2623cf9a2df3SMatt Johnston rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2624cf9a2df3SMatt Johnston PLDM_GET_STATUS, msg);
2625cf9a2df3SMatt Johnston if (rc) {
2626cf9a2df3SMatt Johnston return -EINVAL;
2627cf9a2df3SMatt Johnston }
2628cf9a2df3SMatt Johnston
2629cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2630cf9a2df3SMatt Johnston if (rc) {
2631cf9a2df3SMatt Johnston return rc;
2632cf9a2df3SMatt Johnston }
2633cf9a2df3SMatt Johnston
2634cf9a2df3SMatt Johnston pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2635cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, status->current_state);
2636cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, status->previous_state);
2637cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, status->aux_state);
2638cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, status->aux_state_status);
2639cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, status->progress_percent);
2640cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, status->reason_code);
2641cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, status->update_option_flags_enabled.value);
encode_get_status_resp(uint8_t instance_id,const struct pldm_get_status_resp * status,struct pldm_msg * msg,size_t * payload_length)2642cf9a2df3SMatt Johnston
264370d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2644cf9a2df3SMatt Johnston }
2645cf9a2df3SMatt Johnston
264648761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
264748761c62SAndrew Jeffery int encode_cancel_update_component_req(uint8_t instance_id,
264848761c62SAndrew Jeffery struct pldm_msg *msg,
264948761c62SAndrew Jeffery size_t payload_length)
265048761c62SAndrew Jeffery {
265148761c62SAndrew Jeffery if (msg == NULL) {
265248761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
265348761c62SAndrew Jeffery }
265448761c62SAndrew Jeffery
265548761c62SAndrew Jeffery if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
265648761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
265748761c62SAndrew Jeffery }
265848761c62SAndrew Jeffery
265948761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
266048761c62SAndrew Jeffery header.instance = instance_id;
266148761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
266248761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
266348761c62SAndrew Jeffery header.command = PLDM_CANCEL_UPDATE_COMPONENT;
266448761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
266548761c62SAndrew Jeffery if (rc) {
266648761c62SAndrew Jeffery return rc;
266748761c62SAndrew Jeffery }
266848761c62SAndrew Jeffery
266948761c62SAndrew Jeffery return PLDM_SUCCESS;
267048761c62SAndrew Jeffery }
267148761c62SAndrew Jeffery
267248761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
267348761c62SAndrew Jeffery int decode_cancel_update_component_resp(const struct pldm_msg *msg,
267448761c62SAndrew Jeffery size_t payload_length,
267548761c62SAndrew Jeffery uint8_t *completion_code)
267648761c62SAndrew Jeffery {
267748761c62SAndrew Jeffery if (msg == NULL || completion_code == NULL) {
267848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
267948761c62SAndrew Jeffery }
268048761c62SAndrew Jeffery
268148761c62SAndrew Jeffery if (payload_length != sizeof(*completion_code)) {
encode_cancel_update_component_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)268248761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
268348761c62SAndrew Jeffery }
268448761c62SAndrew Jeffery
268548761c62SAndrew Jeffery *completion_code = msg->payload[0];
268648761c62SAndrew Jeffery return PLDM_SUCCESS;
268748761c62SAndrew Jeffery }
268848761c62SAndrew Jeffery
268948761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
269048761c62SAndrew Jeffery int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
269148761c62SAndrew Jeffery size_t payload_length)
269248761c62SAndrew Jeffery {
269348761c62SAndrew Jeffery if (msg == NULL) {
269448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
269548761c62SAndrew Jeffery }
269648761c62SAndrew Jeffery
269748761c62SAndrew Jeffery if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
269848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
269948761c62SAndrew Jeffery }
270048761c62SAndrew Jeffery
270148761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
270248761c62SAndrew Jeffery header.instance = instance_id;
270348761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
270448761c62SAndrew Jeffery header.pldm_type = PLDM_FWUP;
270548761c62SAndrew Jeffery header.command = PLDM_CANCEL_UPDATE;
270648761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
270748761c62SAndrew Jeffery if (rc) {
decode_cancel_update_component_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code)270848761c62SAndrew Jeffery return rc;
270948761c62SAndrew Jeffery }
271048761c62SAndrew Jeffery
271148761c62SAndrew Jeffery return PLDM_SUCCESS;
271248761c62SAndrew Jeffery }
271348761c62SAndrew Jeffery
271448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
271548761c62SAndrew Jeffery int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
271648761c62SAndrew Jeffery uint8_t *completion_code,
271748761c62SAndrew Jeffery bool8_t *non_functioning_component_indication,
271848761c62SAndrew Jeffery bitfield64_t *non_functioning_component_bitmap)
271948761c62SAndrew Jeffery {
272048761c62SAndrew Jeffery if (msg == NULL || completion_code == NULL ||
272148761c62SAndrew Jeffery non_functioning_component_indication == NULL ||
272248761c62SAndrew Jeffery non_functioning_component_bitmap == NULL || !payload_length) {
272348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
272448761c62SAndrew Jeffery }
encode_cancel_update_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)272548761c62SAndrew Jeffery
272648761c62SAndrew Jeffery *completion_code = msg->payload[0];
272748761c62SAndrew Jeffery if (*completion_code != PLDM_SUCCESS) {
272848761c62SAndrew Jeffery return PLDM_SUCCESS;
272948761c62SAndrew Jeffery }
273048761c62SAndrew Jeffery
273148761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
273248761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
273348761c62SAndrew Jeffery }
273448761c62SAndrew Jeffery struct pldm_cancel_update_resp *response =
273548761c62SAndrew Jeffery (struct pldm_cancel_update_resp *)msg->payload;
273648761c62SAndrew Jeffery
273748761c62SAndrew Jeffery if (!is_non_functioning_component_indication_valid(
273848761c62SAndrew Jeffery response->non_functioning_component_indication)) {
273948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
274048761c62SAndrew Jeffery }
274148761c62SAndrew Jeffery
274248761c62SAndrew Jeffery *non_functioning_component_indication =
274348761c62SAndrew Jeffery response->non_functioning_component_indication;
274448761c62SAndrew Jeffery
274548761c62SAndrew Jeffery if (*non_functioning_component_indication) {
274648761c62SAndrew Jeffery non_functioning_component_bitmap->value =
274748761c62SAndrew Jeffery le64toh(response->non_functioning_component_bitmap);
274848761c62SAndrew Jeffery }
274948761c62SAndrew Jeffery
decode_cancel_update_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,bool8_t * non_functioning_component_indication,bitfield64_t * non_functioning_component_bitmap)275048761c62SAndrew Jeffery return PLDM_SUCCESS;
275148761c62SAndrew Jeffery }
2752cf9a2df3SMatt Johnston
2753cf9a2df3SMatt Johnston LIBPLDM_ABI_TESTING
2754cf9a2df3SMatt Johnston int encode_cancel_update_resp(uint8_t instance_id,
2755cf9a2df3SMatt Johnston const struct pldm_cancel_update_resp *resp_data,
2756cf9a2df3SMatt Johnston struct pldm_msg *msg, size_t *payload_length)
2757cf9a2df3SMatt Johnston {
2758*a1896967SAndrew Jeffery PLDM_MSGBUF_DEFINE_P(buf);
2759cf9a2df3SMatt Johnston int rc;
2760cf9a2df3SMatt Johnston
2761cf9a2df3SMatt Johnston if (msg == NULL || payload_length == NULL) {
2762cf9a2df3SMatt Johnston return -EINVAL;
2763cf9a2df3SMatt Johnston }
2764cf9a2df3SMatt Johnston
2765cf9a2df3SMatt Johnston rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2766cf9a2df3SMatt Johnston PLDM_CANCEL_UPDATE, msg);
2767cf9a2df3SMatt Johnston if (rc) {
2768cf9a2df3SMatt Johnston return -EINVAL;
2769cf9a2df3SMatt Johnston }
2770cf9a2df3SMatt Johnston
2771cf9a2df3SMatt Johnston rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2772cf9a2df3SMatt Johnston if (rc) {
2773cf9a2df3SMatt Johnston return rc;
2774cf9a2df3SMatt Johnston }
2775cf9a2df3SMatt Johnston
2776cf9a2df3SMatt Johnston pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2777cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf,
2778cf9a2df3SMatt Johnston resp_data->non_functioning_component_indication);
2779cf9a2df3SMatt Johnston pldm_msgbuf_insert(buf, resp_data->non_functioning_component_bitmap);
2780cf9a2df3SMatt Johnston
278170d21c97SAndrew Jeffery return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2782cf9a2df3SMatt Johnston }
2783