blob: 955fe1c85e0f142ccbdc6b0f330fa8d230de24d1 [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09302#include "api.h"
Chris Wangb6ef35b2024-07-03 09:35:42 +08003#include "dsp/base.h"
Chris Wang4c1f2c72024-03-21 17:09:44 +08004#include "msgbuf.h"
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10305#include <libpldm/firmware_update.h>
6#include <libpldm/utils.h>
7
Andrew Jeffery9c766792022-08-10 23:12:49 +09308#include <endian.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05309#include <stdbool.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +093010#include <string.h>
11
Matt Johnstoncf9a2df2024-11-07 15:29:29 +080012static_assert(PLDM_FIRMWARE_MAX_STRING <= UINT8_MAX, "too large");
13
Andrew Jeffery9c766792022-08-10 23:12:49 +093014/** @brief Check whether string type value is valid
15 *
16 * @return true if string type value is valid, false if not
17 */
18static bool is_string_type_valid(uint8_t string_type)
19{
20 switch (string_type) {
21 case PLDM_STR_TYPE_UNKNOWN:
22 return false;
23 case PLDM_STR_TYPE_ASCII:
24 case PLDM_STR_TYPE_UTF_8:
25 case PLDM_STR_TYPE_UTF_16:
26 case PLDM_STR_TYPE_UTF_16LE:
27 case PLDM_STR_TYPE_UTF_16BE:
28 return true;
29 default:
30 return false;
31 }
32}
33
34/** @brief Return the length of the descriptor type described in firmware update
35 * specification
36 *
37 * @return length of the descriptor type if descriptor type is valid else
38 * return 0
39 */
40static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
41{
42 switch (descriptor_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093043 case PLDM_FWUP_PCI_VENDOR_ID:
44 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
45 case PLDM_FWUP_IANA_ENTERPRISE_ID:
46 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
47 case PLDM_FWUP_UUID:
48 return PLDM_FWUP_UUID_LENGTH;
49 case PLDM_FWUP_PNP_VENDOR_ID:
50 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
51 case PLDM_FWUP_ACPI_VENDOR_ID:
52 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
53 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
54 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
55 case PLDM_FWUP_SCSI_VENDOR_ID:
56 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
57 case PLDM_FWUP_PCI_DEVICE_ID:
58 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
59 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
60 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
61 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
62 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
63 case PLDM_FWUP_PCI_REVISION_ID:
64 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
65 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
66 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
67 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
68 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
69 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
70 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
71 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
72 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
73 case PLDM_FWUP_SCSI_PRODUCT_ID:
74 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
75 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
76 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
77 default:
78 return 0;
79 }
80}
81
Chris Wang4c1f2c72024-03-21 17:09:44 +080082static bool is_downstream_device_update_support_valid(uint8_t resp)
83{
84 switch (resp) {
85 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
86 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
87 return true;
88 default:
89 return false;
90 }
91}
92
Chris Wang458475a2024-03-26 17:59:19 +080093static bool
94is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)
95{
96 switch (transfer_op_flag) {
97 case PLDM_GET_NEXTPART:
98 case PLDM_GET_FIRSTPART:
99 return true;
100 default:
101 return false;
102 }
103}
104
Andrew Jeffery9c766792022-08-10 23:12:49 +0930105/** @brief Check whether ComponentResponse is valid
106 *
107 * @return true if ComponentResponse is valid, false if not
108 */
109static bool is_comp_resp_valid(uint8_t comp_resp)
110{
111 switch (comp_resp) {
112 case PLDM_CR_COMP_CAN_BE_UPDATED:
113 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
114 return true;
115
116 default:
117 return false;
118 }
119}
120
121/** @brief Check whether ComponentResponseCode is valid
122 *
123 * @return true if ComponentResponseCode is valid, false if not
124 */
125static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
126{
127 switch (comp_resp_code) {
128 case PLDM_CRC_COMP_CAN_BE_UPDATED:
129 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
130 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
131 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
132 case PLDM_CRC_COMP_CONFLICT:
133 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
134 case PLDM_CRC_COMP_NOT_SUPPORTED:
135 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
136 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
137 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
138 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
139 case PLDM_CRC_COMP_VER_STR_LOWER:
140 return true;
141
142 default:
143 if (comp_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930144 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930145 comp_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930146 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930147 return true;
148 }
149 return false;
150 }
151}
152
153/** @brief Check whether ComponentCompatibilityResponse is valid
154 *
155 * @return true if ComponentCompatibilityResponse is valid, false if not
156 */
157static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
158{
159 switch (comp_compatibility_resp) {
160 case PLDM_CCR_COMP_CAN_BE_UPDATED:
161 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
162 return true;
163
164 default:
165 return false;
166 }
167}
168
169/** @brief Check whether ComponentCompatibilityResponse Code is valid
170 *
171 * @return true if ComponentCompatibilityResponse Code is valid, false if not
172 */
173static bool
174is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
175{
176 switch (comp_compatibility_resp_code) {
177 case PLDM_CCRC_NO_RESPONSE_CODE:
178 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
179 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
180 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
181 case PLDM_CCRC_COMP_CONFLICT:
182 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
183 case PLDM_CCRC_COMP_NOT_SUPPORTED:
184 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
185 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
186 case PLDM_CCRC_COMP_INFO_NO_MATCH:
187 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
188 case PLDM_CCRC_COMP_VER_STR_LOWER:
189 return true;
190
191 default:
192 if (comp_compatibility_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930193 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930194 comp_compatibility_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930195 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930196 return true;
197 }
198 return false;
199 }
200}
201
202/** @brief Check whether SelfContainedActivationRequest is valid
203 *
204 * @return true if SelfContainedActivationRequest is valid, false if not
205 */
206static bool
207is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
208{
209 switch (self_contained_activation_req) {
210 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
211 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
212 return true;
213
214 default:
215 return false;
216 }
217}
218
219/** @brief Check if current or previous status in GetStatus command response is
220 * valid
221 *
222 * @param[in] state - current or previous different state machine state of
223 * the FD
224 * @return true if state is valid, false if not
225 */
226static bool is_state_valid(uint8_t state)
227{
228 switch (state) {
229 case PLDM_FD_STATE_IDLE:
230 case PLDM_FD_STATE_LEARN_COMPONENTS:
231 case PLDM_FD_STATE_READY_XFER:
232 case PLDM_FD_STATE_DOWNLOAD:
233 case PLDM_FD_STATE_VERIFY:
234 case PLDM_FD_STATE_APPLY:
235 case PLDM_FD_STATE_ACTIVATE:
236 return true;
237
238 default:
239 return false;
240 }
241}
242
243/** @brief Check if aux state in GetStatus command response is valid
244 *
245 * @param[in] aux_state - provides additional information to the UA to describe
246 * the current operation state of the FD/FDP
247 *
248 * @return true if aux state is valid, false if not
249 */
250static bool is_aux_state_valid(uint8_t aux_state)
251{
252 switch (aux_state) {
253 case PLDM_FD_OPERATION_IN_PROGRESS:
254 case PLDM_FD_OPERATION_SUCCESSFUL:
255 case PLDM_FD_OPERATION_FAILED:
256 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
257 return true;
258
259 default:
260 return false;
261 }
262}
263
264/** @brief Check if aux state status in GetStatus command response is valid
265 *
266 * @param[in] aux_state_status - aux state status
267 *
268 * @return true if aux state status is valid, false if not
269 */
270static bool is_aux_state_status_valid(uint8_t aux_state_status)
271{
272 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
273 aux_state_status == PLDM_FD_TIMEOUT ||
Andrew Jeffery67f7ed92023-04-05 14:00:00 +0930274 aux_state_status == PLDM_FD_GENERIC_ERROR ||
275 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
276 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930277 return true;
278 }
279
280 return false;
281}
282
283/** @brief Check if reason code in GetStatus command response is valid
284 *
285 * @param[in] reason_code - provides the reason for why the current state
286 * entered the IDLE state
287 *
288 * @return true if reason code is valid, false if not
289 */
290static bool is_reason_code_valid(uint8_t reason_code)
291{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930292 switch (reason_code) {
293 case PLDM_FD_INITIALIZATION:
294 case PLDM_FD_ACTIVATE_FW:
295 case PLDM_FD_CANCEL_UPDATE:
296 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
297 case PLDM_FD_TIMEOUT_READY_XFER:
298 case PLDM_FD_TIMEOUT_DOWNLOAD:
299 case PLDM_FD_TIMEOUT_VERIFY:
300 case PLDM_FD_TIMEOUT_APPLY:
301 return true;
302
303 default:
304 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
305 return true;
306 }
307 return false;
308 }
309}
310
311/** @brief Check if non functioning component indication in CancelUpdate
312 * response is valid
313 *
314 * @return true if non functioning component indication is valid, false if not
315 */
316static bool is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930317 bool8_t non_functioning_component_indication)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930318{
319 switch (non_functioning_component_indication) {
320 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
321 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
322 return true;
323
324 default:
325 return false;
326 }
327}
328
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030329static int decode_pldm_package_header_info_errno(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930330 const uint8_t *data, size_t length,
331 struct pldm_package_header_information *package_header_info,
332 struct variable_field *package_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930333{
334 if (data == NULL || package_header_info == NULL ||
335 package_version_str == NULL) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030336 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930337 }
338
339 if (length < sizeof(struct pldm_package_header_information)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030340 return -EOVERFLOW;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930341 }
342
343 struct pldm_package_header_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930344 (struct pldm_package_header_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930345
346 if (!is_string_type_valid(data_header->package_version_string_type) ||
347 (data_header->package_version_string_length == 0)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030348 return -EBADMSG;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930349 }
350
351 if (length < sizeof(struct pldm_package_header_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930352 data_header->package_version_string_length) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030353 return -EOVERFLOW;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930354 }
355
356 if ((data_header->component_bitmap_bit_length %
357 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030358 return -EBADMSG;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930359 }
360
361 memcpy(package_header_info->uuid, data_header->uuid,
362 sizeof(data_header->uuid));
363 package_header_info->package_header_format_version =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930364 data_header->package_header_format_version;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930365 package_header_info->package_header_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930366 le16toh(data_header->package_header_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930367 memcpy(package_header_info->package_release_date_time,
368 data_header->package_release_date_time,
369 sizeof(data_header->package_release_date_time));
370 package_header_info->component_bitmap_bit_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930371 le16toh(data_header->component_bitmap_bit_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930372 package_header_info->package_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930373 data_header->package_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930374 package_header_info->package_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930375 data_header->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930376 package_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930377 data + sizeof(struct pldm_package_header_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930378 package_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930379 package_header_info->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930380
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030381 return 0;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930382}
383
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930384LIBPLDM_ABI_STABLE
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030385int decode_pldm_package_header_info(
386 const uint8_t *data, size_t length,
387 struct pldm_package_header_information *package_header_info,
388 struct variable_field *package_version_str)
389{
390 int rc;
391
392 rc = decode_pldm_package_header_info_errno(
393 data, length, package_header_info, package_version_str);
394 if (rc < 0) {
395 return pldm_xlate_errno(rc);
396 }
397
398 return PLDM_SUCCESS;
399}
400
401static int decode_firmware_device_id_record_errno(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930402 const uint8_t *data, size_t length,
403 uint16_t component_bitmap_bit_length,
404 struct pldm_firmware_device_id_record *fw_device_id_record,
405 struct variable_field *applicable_components,
406 struct variable_field *comp_image_set_version_str,
407 struct variable_field *record_descriptors,
408 struct variable_field *fw_device_pkg_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930409{
410 if (data == NULL || fw_device_id_record == NULL ||
411 applicable_components == NULL ||
412 comp_image_set_version_str == NULL || record_descriptors == NULL ||
413 fw_device_pkg_data == NULL) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030414 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930415 }
416
417 if (length < sizeof(struct pldm_firmware_device_id_record)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030418 return -EOVERFLOW;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930419 }
420
421 if ((component_bitmap_bit_length %
422 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030423 return -EBADMSG;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930424 }
425
426 struct pldm_firmware_device_id_record *data_record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930427 (struct pldm_firmware_device_id_record *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930428
429 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930430 data_record->comp_image_set_version_string_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930431 (data_record->comp_image_set_version_string_length == 0)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030432 return -EBADMSG;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930433 }
434
435 fw_device_id_record->record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930436 le16toh(data_record->record_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930437 fw_device_id_record->descriptor_count = data_record->descriptor_count;
438 fw_device_id_record->device_update_option_flags.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930439 le32toh(data_record->device_update_option_flags.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930440 fw_device_id_record->comp_image_set_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930441 data_record->comp_image_set_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930442 fw_device_id_record->comp_image_set_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930443 data_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930444 fw_device_id_record->fw_device_pkg_data_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930445 le16toh(data_record->fw_device_pkg_data_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930446
447 if (length < fw_device_id_record->record_length) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030448 return -EOVERFLOW;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930449 }
450
451 uint16_t applicable_components_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930452 component_bitmap_bit_length /
453 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
Matt Johnstonc4d1c8b2024-12-18 11:16:55 +0800454 size_t calc_min_record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930455 sizeof(struct pldm_firmware_device_id_record) +
456 applicable_components_length +
457 data_record->comp_image_set_version_string_length +
458 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
459 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930460
461 if (fw_device_id_record->record_length < calc_min_record_length) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030462 return -EOVERFLOW;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930463 }
464
465 applicable_components->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930466 data + sizeof(struct pldm_firmware_device_id_record);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930467 applicable_components->length = applicable_components_length;
468
469 comp_image_set_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930470 applicable_components->ptr + applicable_components->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930471 comp_image_set_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930472 fw_device_id_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930473
474 record_descriptors->ptr = comp_image_set_version_str->ptr +
475 comp_image_set_version_str->length;
476 record_descriptors->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930477 fw_device_id_record->record_length -
478 sizeof(struct pldm_firmware_device_id_record) -
479 applicable_components_length -
480 fw_device_id_record->comp_image_set_version_string_length -
481 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930482
483 if (fw_device_id_record->fw_device_pkg_data_length) {
484 fw_device_pkg_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930485 record_descriptors->ptr + record_descriptors->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930486 fw_device_pkg_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930487 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930488 }
489
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030490 return 0;
491}
492
493LIBPLDM_ABI_STABLE
494int decode_firmware_device_id_record(
495 const uint8_t *data, size_t length,
496 uint16_t component_bitmap_bit_length,
497 struct pldm_firmware_device_id_record *fw_device_id_record,
498 struct variable_field *applicable_components,
499 struct variable_field *comp_image_set_version_str,
500 struct variable_field *record_descriptors,
501 struct variable_field *fw_device_pkg_data)
502{
503 int rc;
504
505 rc = decode_firmware_device_id_record_errno(
506 data, length, component_bitmap_bit_length, fw_device_id_record,
507 applicable_components, comp_image_set_version_str,
508 record_descriptors, fw_device_pkg_data);
509 if (rc < 0) {
510 return pldm_xlate_errno(rc);
511 }
512
Andrew Jeffery9c766792022-08-10 23:12:49 +0930513 return PLDM_SUCCESS;
514}
515
Unive Tiene5c3f142024-12-13 14:14:19 +0800516LIBPLDM_ABI_STABLE
Andrew Jeffery3a2c6582024-11-07 16:30:36 +1030517int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter,
518 struct pldm_descriptor *desc)
519{
Andrew Jefferya1896962025-03-03 21:41:25 +1030520 PLDM_MSGBUF_DEFINE_P(buf);
Andrew Jeffery3a2c6582024-11-07 16:30:36 +1030521 int rc;
522
523 if (!iter || !iter->field || !desc) {
524 return -EINVAL;
525 }
526
527 rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN,
528 iter->field->ptr, iter->field->length);
529 if (rc) {
530 return rc;
531 }
532
533 pldm_msgbuf_extract(buf, desc->descriptor_type);
534 rc = pldm_msgbuf_extract(buf, desc->descriptor_length);
535 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030536 return pldm_msgbuf_discard(buf, rc);
Andrew Jeffery3a2c6582024-11-07 16:30:36 +1030537 }
538
539 desc->descriptor_data = NULL;
540 pldm_msgbuf_span_required(buf, desc->descriptor_length,
541 (void **)&desc->descriptor_data);
542 iter->field->ptr = NULL;
543 pldm_msgbuf_span_remaining(buf, (void **)&iter->field->ptr,
544 &iter->field->length);
545
Andrew Jeffery70d21c92025-03-05 12:59:42 +1030546 return pldm_msgbuf_complete(buf);
Andrew Jeffery3a2c6582024-11-07 16:30:36 +1030547}
548
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030549static int decode_descriptor_type_length_value_errno(
550 const uint8_t *data, size_t length, uint16_t *descriptor_type,
551 struct variable_field *descriptor_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930552{
553 uint16_t descriptor_length = 0;
554
555 if (data == NULL || descriptor_type == NULL ||
556 descriptor_data == NULL) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030557 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930558 }
559
560 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030561 return -EOVERFLOW;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930562 }
563
564 struct pldm_descriptor_tlv *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930565 (struct pldm_descriptor_tlv *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930566
567 *descriptor_type = le16toh(entry->descriptor_type);
568 descriptor_length = le16toh(entry->descriptor_length);
569 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
570 if (descriptor_length !=
571 get_descriptor_type_length(*descriptor_type)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030572 return -EBADMSG;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930573 }
574 }
575
576 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
577 descriptor_length)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030578 return -EOVERFLOW;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930579 }
580
581 descriptor_data->ptr = entry->descriptor_data;
582 descriptor_data->length = descriptor_length;
583
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030584 return 0;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930585}
586
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930587LIBPLDM_ABI_STABLE
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030588int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
589 uint16_t *descriptor_type,
590 struct variable_field *descriptor_data)
591{
592 int rc;
593
594 rc = decode_descriptor_type_length_value_errno(
595 data, length, descriptor_type, descriptor_data);
596 if (rc < 0) {
597 return pldm_xlate_errno(rc);
598 }
599
600 return PLDM_SUCCESS;
601}
602
603static int decode_vendor_defined_descriptor_value_errno(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930604 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
605 struct variable_field *descriptor_title_str,
606 struct variable_field *descriptor_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930607{
608 if (data == NULL || descriptor_title_str_type == NULL ||
609 descriptor_title_str == NULL || descriptor_data == NULL) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030610 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930611 }
612
613 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030614 return -EOVERFLOW;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930615 }
616
617 struct pldm_vendor_defined_descriptor_title_data *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930618 (struct pldm_vendor_defined_descriptor_title_data *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930619 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930620 entry->vendor_defined_descriptor_title_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930621 (entry->vendor_defined_descriptor_title_str_len == 0)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030622 return -EBADMSG;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930623 }
624
Manojkiran Eda9e3a5d42024-06-17 16:06:42 +0530625 // Assuming at least 1 byte of VendorDefinedDescriptorData
Andrew Jeffery9c766792022-08-10 23:12:49 +0930626 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
627 entry->vendor_defined_descriptor_title_str_len)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030628 return -EOVERFLOW;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930629 }
630
631 *descriptor_title_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930632 entry->vendor_defined_descriptor_title_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930633 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
634 descriptor_title_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930635 entry->vendor_defined_descriptor_title_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930636
637 descriptor_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930638 descriptor_title_str->ptr + descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930639 descriptor_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930640 length -
641 sizeof(entry->vendor_defined_descriptor_title_str_type) -
642 sizeof(entry->vendor_defined_descriptor_title_str_len) -
643 descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930644
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030645 return 0;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930646}
647
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930648LIBPLDM_ABI_STABLE
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030649int decode_vendor_defined_descriptor_value(
650 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
651 struct variable_field *descriptor_title_str,
652 struct variable_field *descriptor_data)
653{
654 int rc;
655
656 rc = decode_vendor_defined_descriptor_value_errno(
657 data, length, descriptor_title_str_type, descriptor_title_str,
658 descriptor_data);
659 if (rc < 0) {
660 return pldm_xlate_errno(rc);
661 }
662
663 return PLDM_SUCCESS;
664}
665
666static int decode_pldm_comp_image_info_errno(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930667 const uint8_t *data, size_t length,
668 struct pldm_component_image_information *pldm_comp_image_info,
669 struct variable_field *comp_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930670{
671 if (data == NULL || pldm_comp_image_info == NULL ||
672 comp_version_str == NULL) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030673 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930674 }
675
676 if (length < sizeof(struct pldm_component_image_information)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030677 return -EOVERFLOW;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930678 }
679
680 struct pldm_component_image_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930681 (struct pldm_component_image_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930682
683 if (!is_string_type_valid(data_header->comp_version_string_type) ||
684 (data_header->comp_version_string_length == 0)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030685 return -EBADMSG;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930686 }
687
688 if (length < sizeof(struct pldm_component_image_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930689 data_header->comp_version_string_length) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030690 return -EOVERFLOW;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930691 }
692
693 pldm_comp_image_info->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930694 le16toh(data_header->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930695 pldm_comp_image_info->comp_identifier =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930696 le16toh(data_header->comp_identifier);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930697 pldm_comp_image_info->comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930698 le32toh(data_header->comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930699 pldm_comp_image_info->comp_options.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930700 le16toh(data_header->comp_options.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930701 pldm_comp_image_info->requested_comp_activation_method.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930702 le16toh(data_header->requested_comp_activation_method.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930703 pldm_comp_image_info->comp_location_offset =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930704 le32toh(data_header->comp_location_offset);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930705 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
706 pldm_comp_image_info->comp_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930707 data_header->comp_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930708 pldm_comp_image_info->comp_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930709 data_header->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930710
711 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
712 pldm_comp_image_info->comp_comparison_stamp !=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930713 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030714 return -EBADMSG;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930715 }
716
717 if (pldm_comp_image_info->comp_location_offset == 0 ||
718 pldm_comp_image_info->comp_size == 0) {
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030719 return -EBADMSG;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930720 }
721
722 comp_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930723 data + sizeof(struct pldm_component_image_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930724 comp_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930725 pldm_comp_image_info->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930726
Andrew Jeffery779e9db2025-02-21 12:14:28 +1030727 return 0;
728}
729
730LIBPLDM_ABI_STABLE
731int decode_pldm_comp_image_info(
732 const uint8_t *data, size_t length,
733 struct pldm_component_image_information *pldm_comp_image_info,
734 struct variable_field *comp_version_str)
735{
736 int rc;
737
738 rc = decode_pldm_comp_image_info_errno(
739 data, length, pldm_comp_image_info, comp_version_str);
740 if (rc < 0) {
741 return pldm_xlate_errno(rc);
742 }
743
Andrew Jeffery9c766792022-08-10 23:12:49 +0930744 return PLDM_SUCCESS;
745}
746
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930747LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930748int encode_query_device_identifiers_req(uint8_t instance_id,
749 size_t payload_length,
750 struct pldm_msg *msg)
751{
752 if (msg == NULL) {
753 return PLDM_ERROR_INVALID_DATA;
754 }
755
756 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
757 return PLDM_ERROR_INVALID_LENGTH;
758 }
759
760 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
761 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
762}
763
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930764LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930765int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
766 size_t payload_length,
767 uint8_t *completion_code,
768 uint32_t *device_identifiers_len,
769 uint8_t *descriptor_count,
770 uint8_t **descriptor_data)
771{
772 if (msg == NULL || completion_code == NULL ||
773 device_identifiers_len == NULL || descriptor_count == NULL ||
774 descriptor_data == NULL) {
775 return PLDM_ERROR_INVALID_DATA;
776 }
777
778 *completion_code = msg->payload[0];
779 if (PLDM_SUCCESS != *completion_code) {
780 return PLDM_SUCCESS;
781 }
782
783 if (payload_length <
784 sizeof(struct pldm_query_device_identifiers_resp)) {
785 return PLDM_ERROR_INVALID_LENGTH;
786 }
787
788 struct pldm_query_device_identifiers_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930789 (struct pldm_query_device_identifiers_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930790 *device_identifiers_len = le32toh(response->device_identifiers_len);
791
792 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
793 return PLDM_ERROR_INVALID_LENGTH;
794 }
795
796 if (payload_length !=
797 sizeof(struct pldm_query_device_identifiers_resp) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930798 *device_identifiers_len) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930799 return PLDM_ERROR_INVALID_LENGTH;
800 }
801 *descriptor_count = response->descriptor_count;
802
803 if (*descriptor_count == 0) {
804 return PLDM_ERROR_INVALID_DATA;
805 }
806 *descriptor_data =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930807 (uint8_t *)(msg->payload +
808 sizeof(struct pldm_query_device_identifiers_resp));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930809 return PLDM_SUCCESS;
810}
811
Matt Johnstoncf9a2df2024-11-07 15:29:29 +0800812LIBPLDM_ABI_TESTING
813int encode_query_device_identifiers_resp(
814 uint8_t instance_id, uint8_t descriptor_count,
815 const struct pldm_descriptor *descriptors, struct pldm_msg *msg,
816 size_t *payload_length)
817{
Andrew Jefferya1896962025-03-03 21:41:25 +1030818 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +0800819 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +0800820
821 if (descriptors == NULL || msg == NULL || payload_length == NULL) {
822 return -EINVAL;
823 }
824
825 if (descriptor_count < 1) {
826 return -EINVAL;
827 }
828
829 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
830 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
831 if (rc) {
832 return -EINVAL;
833 }
834
835 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
836 if (rc) {
837 return rc;
838 }
839
840 /* Determine total length */
841 uint32_t device_identifiers_len = 0;
842 for (uint8_t i = 0; i < descriptor_count; i++) {
843 const struct pldm_descriptor *d = &descriptors[i];
844 device_identifiers_len +=
845 2 * sizeof(uint16_t) + d->descriptor_length;
846 }
847
848 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
849 pldm_msgbuf_insert(buf, device_identifiers_len);
850 pldm_msgbuf_insert(buf, descriptor_count);
851
852 for (uint8_t i = 0; i < descriptor_count; i++) {
853 const struct pldm_descriptor *d = &descriptors[i];
854 pldm_msgbuf_insert(buf, d->descriptor_type);
855 pldm_msgbuf_insert(buf, d->descriptor_length);
856 if (d->descriptor_data == NULL) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030857 return pldm_msgbuf_discard(buf, -EINVAL);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +0800858 }
859 rc = pldm_msgbuf_insert_array(
860 buf, d->descriptor_length,
861 (const uint8_t *)d->descriptor_data,
862 d->descriptor_length);
863 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030864 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +0800865 }
866 }
867
Andrew Jeffery70d21c92025-03-05 12:59:42 +1030868 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +0800869}
870
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930871LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930872int encode_get_firmware_parameters_req(uint8_t instance_id,
873 size_t payload_length,
874 struct pldm_msg *msg)
875{
876 if (msg == NULL) {
877 return PLDM_ERROR_INVALID_DATA;
878 }
879
880 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
881 return PLDM_ERROR_INVALID_LENGTH;
882 }
883
884 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
885 PLDM_GET_FIRMWARE_PARAMETERS, msg);
886}
887
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930888LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930889int decode_get_firmware_parameters_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930890 const struct pldm_msg *msg, size_t payload_length,
891 struct pldm_get_firmware_parameters_resp *resp_data,
892 struct variable_field *active_comp_image_set_ver_str,
893 struct variable_field *pending_comp_image_set_ver_str,
894 struct variable_field *comp_parameter_table)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930895{
896 if (msg == NULL || resp_data == NULL ||
897 active_comp_image_set_ver_str == NULL ||
898 pending_comp_image_set_ver_str == NULL ||
899 comp_parameter_table == NULL || !payload_length) {
900 return PLDM_ERROR_INVALID_DATA;
901 }
902
903 resp_data->completion_code = msg->payload[0];
904 if (PLDM_SUCCESS != resp_data->completion_code) {
905 return PLDM_SUCCESS;
906 }
907
908 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
909 return PLDM_ERROR_INVALID_LENGTH;
910 }
911
912 struct pldm_get_firmware_parameters_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930913 (struct pldm_get_firmware_parameters_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930914
915 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930916 response->active_comp_image_set_ver_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930917 (response->active_comp_image_set_ver_str_len == 0)) {
918 return PLDM_ERROR_INVALID_DATA;
919 }
920
921 if (response->pending_comp_image_set_ver_str_len == 0) {
922 if (response->pending_comp_image_set_ver_str_type !=
923 PLDM_STR_TYPE_UNKNOWN) {
924 return PLDM_ERROR_INVALID_DATA;
925 }
926 } else {
927 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930928 response->pending_comp_image_set_ver_str_type)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930929 return PLDM_ERROR_INVALID_DATA;
930 }
931 }
932
933 size_t partial_response_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930934 sizeof(struct pldm_get_firmware_parameters_resp) +
935 response->active_comp_image_set_ver_str_len +
936 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930937
938 if (payload_length < partial_response_length) {
939 return PLDM_ERROR_INVALID_LENGTH;
940 }
941
942 resp_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930943 le32toh(response->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930944 resp_data->comp_count = le16toh(response->comp_count);
945 resp_data->active_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930946 response->active_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930947 resp_data->active_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930948 response->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930949 resp_data->pending_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930950 response->pending_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930951 resp_data->pending_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930952 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930953
954 active_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930955 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930956 active_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930957 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930958
959 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
960 pending_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930961 msg->payload +
962 sizeof(struct pldm_get_firmware_parameters_resp) +
963 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930964 pending_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930965 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930966 } else {
967 pending_comp_image_set_ver_str->ptr = NULL;
968 pending_comp_image_set_ver_str->length = 0;
969 }
970
971 if (payload_length > partial_response_length && resp_data->comp_count) {
972 comp_parameter_table->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930973 msg->payload +
974 sizeof(struct pldm_get_firmware_parameters_resp) +
975 resp_data->active_comp_image_set_ver_str_len +
976 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930977 comp_parameter_table->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930978 payload_length - partial_response_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930979 } else {
980 comp_parameter_table->ptr = NULL;
981 comp_parameter_table->length = 0;
982 }
983
984 return PLDM_SUCCESS;
985}
986
Matt Johnstoncf9a2df2024-11-07 15:29:29 +0800987LIBPLDM_ABI_TESTING
988int encode_get_firmware_parameters_resp(
989 uint8_t instance_id,
990 const struct pldm_get_firmware_parameters_resp_full *resp_data,
991 struct pldm_msg *msg, size_t *payload_length)
992{
Andrew Jefferya1896962025-03-03 21:41:25 +1030993 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +0800994 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +0800995
996 if (resp_data == NULL || msg == NULL || payload_length == NULL) {
997 return -EINVAL;
998 }
999
1000 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
1001 PLDM_GET_FIRMWARE_PARAMETERS, msg);
1002 if (rc) {
1003 return -EINVAL;
1004 }
1005
1006 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1007 if (rc) {
1008 return rc;
1009 }
1010
1011 pldm_msgbuf_insert(buf, resp_data->completion_code);
1012 pldm_msgbuf_insert(buf, resp_data->capabilities_during_update.value);
1013 pldm_msgbuf_insert(buf, resp_data->comp_count);
1014 pldm_msgbuf_insert(buf,
1015 resp_data->active_comp_image_set_ver_str.str_type);
1016 pldm_msgbuf_insert(buf,
1017 resp_data->active_comp_image_set_ver_str.str_len);
1018 pldm_msgbuf_insert(buf,
1019 resp_data->pending_comp_image_set_ver_str.str_type);
1020 pldm_msgbuf_insert(buf,
1021 resp_data->pending_comp_image_set_ver_str.str_len);
1022 /* String data appended */
1023 rc = pldm_msgbuf_insert_array(
1024 buf, resp_data->active_comp_image_set_ver_str.str_len,
1025 resp_data->active_comp_image_set_ver_str.str_data,
1026 resp_data->active_comp_image_set_ver_str.str_len);
1027 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301028 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001029 }
1030 rc = pldm_msgbuf_insert_array(
1031 buf, resp_data->pending_comp_image_set_ver_str.str_len,
1032 resp_data->pending_comp_image_set_ver_str.str_data,
1033 resp_data->pending_comp_image_set_ver_str.str_len);
1034 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301035 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001036 }
1037
1038 /* Further calls to encode_get_firmware_parameters_resp_comp_entry
1039 * will populate the remainder */
1040
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301041 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001042}
1043
1044LIBPLDM_ABI_TESTING
1045int encode_get_firmware_parameters_resp_comp_entry(
1046 const struct pldm_component_parameter_entry_full *comp,
1047 uint8_t *payload, size_t *payload_length)
1048{
Andrew Jefferya1896962025-03-03 21:41:25 +10301049 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001050 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001051
1052 if (comp == NULL || payload == NULL || payload_length == NULL) {
1053 return -EINVAL;
1054 }
1055
1056 rc = pldm_msgbuf_init_errno(buf, 0, payload, *payload_length);
1057 if (rc) {
1058 return rc;
1059 }
1060
1061 pldm_msgbuf_insert(buf, comp->comp_classification);
1062 pldm_msgbuf_insert(buf, comp->comp_identifier);
1063 pldm_msgbuf_insert(buf, comp->comp_classification_index);
1064
1065 pldm_msgbuf_insert(buf, comp->active_ver.comparison_stamp);
1066 pldm_msgbuf_insert(buf, (uint8_t)comp->active_ver.str.str_type);
1067 pldm_msgbuf_insert(buf, comp->active_ver.str.str_len);
1068 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1069 comp->active_ver.date,
1070 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1071 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301072 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001073 }
1074
1075 pldm_msgbuf_insert(buf, comp->pending_ver.comparison_stamp);
1076 pldm_msgbuf_insert(buf, (uint8_t)comp->pending_ver.str.str_type);
1077 pldm_msgbuf_insert(buf, comp->pending_ver.str.str_len);
1078 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1079 comp->pending_ver.date,
1080 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1081 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301082 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001083 }
1084
1085 pldm_msgbuf_insert(buf, comp->comp_activation_methods.value);
1086 pldm_msgbuf_insert(buf, comp->capabilities_during_update.value);
1087
1088 rc = pldm_msgbuf_insert_array(buf, comp->active_ver.str.str_len,
1089 comp->active_ver.str.str_data,
1090 comp->active_ver.str.str_len);
1091 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301092 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001093 }
1094 rc = pldm_msgbuf_insert_array(buf, comp->pending_ver.str.str_len,
1095 comp->pending_ver.str.str_data,
1096 comp->pending_ver.str.str_len);
1097 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301098 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001099 }
1100
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301101 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001102}
1103
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301104LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301105int decode_get_firmware_parameters_resp_comp_entry(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301106 const uint8_t *data, size_t length,
1107 struct pldm_component_parameter_entry *component_data,
1108 struct variable_field *active_comp_ver_str,
1109 struct variable_field *pending_comp_ver_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301110{
1111 if (data == NULL || component_data == NULL ||
1112 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
1113 return PLDM_ERROR_INVALID_DATA;
1114 }
1115
1116 if (length < sizeof(struct pldm_component_parameter_entry)) {
1117 return PLDM_ERROR_INVALID_LENGTH;
1118 }
1119
1120 struct pldm_component_parameter_entry *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301121 (struct pldm_component_parameter_entry *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301122
1123 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
1124 entry->active_comp_ver_str_len +
1125 entry->pending_comp_ver_str_len;
1126
1127 if (length < entry_length) {
1128 return PLDM_ERROR_INVALID_LENGTH;
1129 }
1130
1131 component_data->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301132 le16toh(entry->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301133 component_data->comp_identifier = le16toh(entry->comp_identifier);
1134 component_data->comp_classification_index =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301135 entry->comp_classification_index;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301136 component_data->active_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301137 le32toh(entry->active_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301138 component_data->active_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301139 entry->active_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301140 component_data->active_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301141 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301142 memcpy(component_data->active_comp_release_date,
1143 entry->active_comp_release_date,
1144 sizeof(entry->active_comp_release_date));
1145 component_data->pending_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301146 le32toh(entry->pending_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301147 component_data->pending_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301148 entry->pending_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301149 component_data->pending_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301150 entry->pending_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301151 memcpy(component_data->pending_comp_release_date,
1152 entry->pending_comp_release_date,
1153 sizeof(entry->pending_comp_release_date));
1154 component_data->comp_activation_methods.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301155 le16toh(entry->comp_activation_methods.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301156 component_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301157 le32toh(entry->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301158
1159 if (entry->active_comp_ver_str_len != 0) {
1160 active_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301161 data + sizeof(struct pldm_component_parameter_entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301162 active_comp_ver_str->length = entry->active_comp_ver_str_len;
1163 } else {
1164 active_comp_ver_str->ptr = NULL;
1165 active_comp_ver_str->length = 0;
1166 }
1167
1168 if (entry->pending_comp_ver_str_len != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301169 pending_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301170 data + sizeof(struct pldm_component_parameter_entry) +
1171 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301172 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
1173 } else {
1174 pending_comp_ver_str->ptr = NULL;
1175 pending_comp_ver_str->length = 0;
1176 }
1177 return PLDM_SUCCESS;
1178}
1179
Unive Tiene5c3f142024-12-13 14:14:19 +08001180LIBPLDM_ABI_STABLE
Chris Wang4c1f2c72024-03-21 17:09:44 +08001181int encode_query_downstream_devices_req(uint8_t instance_id,
1182 struct pldm_msg *msg)
1183{
1184 if (msg == NULL) {
Unive Tien71e935c2024-11-25 17:21:43 +08001185 return -EINVAL;
Chris Wang4c1f2c72024-03-21 17:09:44 +08001186 }
1187
Unive Tien71e935c2024-11-25 17:21:43 +08001188 return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id,
1189 PLDM_FWUP,
1190 PLDM_QUERY_DOWNSTREAM_DEVICES,
1191 msg);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001192}
1193
Unive Tiene5c3f142024-12-13 14:14:19 +08001194LIBPLDM_ABI_STABLE
Chris Wang4c1f2c72024-03-21 17:09:44 +08001195int decode_query_downstream_devices_resp(
1196 const struct pldm_msg *msg, size_t payload_length,
1197 struct pldm_query_downstream_devices_resp *resp_data)
1198{
Andrew Jefferya1896962025-03-03 21:41:25 +10301199 PLDM_MSGBUF_DEFINE_P(buf);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001200 int rc;
1201
1202 if (msg == NULL || resp_data == NULL || !payload_length) {
Unive Tien71e935c2024-11-25 17:21:43 +08001203 return -EINVAL;
Chris Wang4c1f2c72024-03-21 17:09:44 +08001204 }
1205
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301206 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1207 msg->payload, payload_length);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001208 if (rc) {
1209 return rc;
1210 }
1211
1212 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1213 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301214 return pldm_msgbuf_discard(buf, rc);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001215 }
1216 if (PLDM_SUCCESS != resp_data->completion_code) {
1217 // Return the CC directly without decoding the rest of the payload
Andrew Jefferya1896962025-03-03 21:41:25 +10301218 return pldm_msgbuf_complete(buf);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001219 }
1220
1221 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301222 return pldm_msgbuf_discard(buf, -EBADMSG);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001223 }
1224
1225 rc = pldm_msgbuf_extract(buf,
1226 resp_data->downstream_device_update_supported);
1227 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301228 return pldm_msgbuf_discard(buf, rc);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001229 }
1230
1231 if (!is_downstream_device_update_support_valid(
1232 resp_data->downstream_device_update_supported)) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301233 return pldm_msgbuf_discard(buf, -EINVAL);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001234 }
1235
1236 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1237 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
1238 pldm_msgbuf_extract(buf, resp_data->capabilities.value);
1239
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301240 return pldm_msgbuf_complete_consumed(buf);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001241}
1242
Unive Tiene5c3f142024-12-13 14:14:19 +08001243LIBPLDM_ABI_STABLE
Chris Wang458475a2024-03-26 17:59:19 +08001244int encode_query_downstream_identifiers_req(
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001245 uint8_t instance_id,
1246 const struct pldm_query_downstream_identifiers_req *params_req,
1247 struct pldm_msg *msg, size_t payload_length)
Chris Wang458475a2024-03-26 17:59:19 +08001248{
Andrew Jefferya1896962025-03-03 21:41:25 +10301249 PLDM_MSGBUF_DEFINE_P(buf);
Chris Wang458475a2024-03-26 17:59:19 +08001250 int rc;
1251
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001252 if (!msg || !params_req) {
Unive Tien71e935c2024-11-25 17:21:43 +08001253 return -EINVAL;
Chris Wang458475a2024-03-26 17:59:19 +08001254 }
1255
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001256 if (!is_transfer_operation_flag_valid(
1257 (enum transfer_op_flag)
1258 params_req->transfer_operation_flag)) {
Unive Tien71e935c2024-11-25 17:21:43 +08001259 return -EINVAL;
Chris Wang458475a2024-03-26 17:59:19 +08001260 }
1261
1262 struct pldm_header_info header = { 0 };
1263 header.instance = instance_id;
1264 header.msg_type = PLDM_REQUEST;
1265 header.pldm_type = PLDM_FWUP;
1266 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
Unive Tien71e935c2024-11-25 17:21:43 +08001267 rc = pack_pldm_header_errno(&header, &(msg->hdr));
Chris Wang458475a2024-03-26 17:59:19 +08001268 if (rc) {
1269 return rc;
1270 }
1271
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301272 rc = pldm_msgbuf_init_errno(buf,
1273 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
1274 msg->payload, payload_length);
Chris Wang458475a2024-03-26 17:59:19 +08001275 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001276 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001277 }
1278
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001279 pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
Chris Wang458475a2024-03-26 17:59:19 +08001280 // Data correctness has been verified, cast it to 1-byte data directly.
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001281 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
Chris Wang458475a2024-03-26 17:59:19 +08001282
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301283 return pldm_msgbuf_complete(buf);
Chris Wang458475a2024-03-26 17:59:19 +08001284}
1285
Unive Tiene5c3f142024-12-13 14:14:19 +08001286LIBPLDM_ABI_STABLE
Chris Wang458475a2024-03-26 17:59:19 +08001287int decode_query_downstream_identifiers_resp(
1288 const struct pldm_msg *msg, size_t payload_length,
1289 struct pldm_query_downstream_identifiers_resp *resp_data,
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301290 struct pldm_downstream_device_iter *iter)
Chris Wang458475a2024-03-26 17:59:19 +08001291{
Andrew Jefferya1896962025-03-03 21:41:25 +10301292 PLDM_MSGBUF_DEFINE_P(buf);
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301293 void *remaining = NULL;
Unive Tien71e935c2024-11-25 17:21:43 +08001294 int rc = 0;
Chris Wang458475a2024-03-26 17:59:19 +08001295
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301296 if (msg == NULL || resp_data == NULL || iter == NULL ||
Chris Wang458475a2024-03-26 17:59:19 +08001297 !payload_length) {
Unive Tien71e935c2024-11-25 17:21:43 +08001298 return -EINVAL;
Chris Wang458475a2024-03-26 17:59:19 +08001299 }
1300
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301301 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1302 msg->payload, payload_length);
Chris Wang458475a2024-03-26 17:59:19 +08001303 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001304 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001305 }
1306
1307 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1308 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301309 return pldm_msgbuf_discard(buf, rc);
Chris Wang458475a2024-03-26 17:59:19 +08001310 }
1311 if (PLDM_SUCCESS != resp_data->completion_code) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301312 return pldm_msgbuf_complete(buf);
Chris Wang458475a2024-03-26 17:59:19 +08001313 }
1314
1315 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301316 return pldm_msgbuf_discard(buf, -EBADMSG);
Chris Wang458475a2024-03-26 17:59:19 +08001317 }
1318
1319 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1320 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1321
1322 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
1323 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301324 return pldm_msgbuf_discard(buf, rc);
Chris Wang458475a2024-03-26 17:59:19 +08001325 }
1326
1327 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
Andrew Jefferya1896962025-03-03 21:41:25 +10301328 pldm_msgbuf_span_required(buf, resp_data->downstream_devices_length,
1329 &remaining);
Chris Wang458475a2024-03-26 17:59:19 +08001330
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301331 rc = pldm_msgbuf_complete(buf);
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301332 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001333 return rc;
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301334 }
1335
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301336 iter->field.ptr = remaining;
1337 iter->field.length = resp_data->downstream_devices_length;
1338 iter->devs = resp_data->number_of_downstream_devices;
1339
Unive Tien71e935c2024-11-25 17:21:43 +08001340 return 0;
Chris Wang458475a2024-03-26 17:59:19 +08001341}
1342
Unive Tiene5c3f142024-12-13 14:14:19 +08001343LIBPLDM_ABI_STABLE
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301344int decode_pldm_downstream_device_from_iter(
1345 struct pldm_downstream_device_iter *iter,
1346 struct pldm_downstream_device *dev)
1347{
Andrew Jefferya1896962025-03-03 21:41:25 +10301348 PLDM_MSGBUF_DEFINE_P(buf);
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301349 int rc;
1350
Andrew Jefferya1896962025-03-03 21:41:25 +10301351 if (!iter || !iter->field.ptr || !dev) {
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301352 return -EINVAL;
1353 }
1354
1355 rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr,
1356 iter->field.length);
1357 if (rc) {
1358 return rc;
1359 }
1360
1361 pldm_msgbuf_extract(buf, dev->downstream_device_index);
1362 pldm_msgbuf_extract(buf, dev->downstream_descriptor_count);
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301363 pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr,
1364 &iter->field.length);
1365
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301366 return pldm_msgbuf_complete(buf);
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301367}
1368
Unive Tiene5c3f142024-12-13 14:14:19 +08001369LIBPLDM_ABI_STABLE
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301370int encode_get_downstream_firmware_parameters_req(
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001371 uint8_t instance_id,
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301372 const struct pldm_get_downstream_firmware_parameters_req *params_req,
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001373 struct pldm_msg *msg, size_t payload_length)
Chris Wangb6ef35b2024-07-03 09:35:42 +08001374{
Andrew Jefferya1896962025-03-03 21:41:25 +10301375 PLDM_MSGBUF_DEFINE_P(buf);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001376 int rc;
1377
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001378 if (!msg || !params_req) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001379 return -EINVAL;
1380 }
1381
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001382 if (!is_transfer_operation_flag_valid(
1383 (enum transfer_op_flag)
1384 params_req->transfer_operation_flag)) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001385 return -EBADMSG;
1386 }
1387
1388 struct pldm_header_info header = { 0 };
1389 header.instance = instance_id;
1390 header.msg_type = PLDM_REQUEST;
1391 header.pldm_type = PLDM_FWUP;
1392 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1393 rc = pack_pldm_header_errno(&header, &msg->hdr);
1394 if (rc < 0) {
1395 return rc;
1396 }
1397
Andrew Jeffery53b08672025-03-04 12:26:18 +10301398 rc = pldm_msgbuf_init_errno(
1399 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES,
1400 msg->payload, payload_length);
1401 if (rc < 0) {
1402 return rc;
1403 }
1404
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001405 pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001406 // Data correctness has been verified, cast it to 1-byte data directly.
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001407 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001408
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301409 return pldm_msgbuf_complete(buf);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001410}
1411
Unive Tiene5c3f142024-12-13 14:14:19 +08001412LIBPLDM_ABI_STABLE
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301413int decode_get_downstream_firmware_parameters_resp(
Chris Wangb6ef35b2024-07-03 09:35:42 +08001414 const struct pldm_msg *msg, size_t payload_length,
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301415 struct pldm_get_downstream_firmware_parameters_resp *resp_data,
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301416 struct pldm_downstream_device_parameters_iter *iter)
Chris Wangb6ef35b2024-07-03 09:35:42 +08001417{
Andrew Jefferya1896962025-03-03 21:41:25 +10301418 PLDM_MSGBUF_DEFINE_P(buf);
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301419 void *remaining = NULL;
1420 size_t length;
Chris Wangb6ef35b2024-07-03 09:35:42 +08001421 int rc;
1422
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301423 if (msg == NULL || resp_data == NULL || iter == NULL) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001424 return -EINVAL;
1425 }
1426
1427 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1428 msg->payload, payload_length);
1429 if (rc < 0) {
1430 return rc;
1431 }
1432
1433 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1434 if (rc < 0) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301435 return pldm_msgbuf_discard(buf, rc);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001436 }
1437 if (PLDM_SUCCESS != resp_data->completion_code) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301438 return pldm_msgbuf_complete(buf);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001439 }
1440
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301441 if (payload_length <
1442 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301443 return pldm_msgbuf_discard(buf, -EBADMSG);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001444 }
1445
1446 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1447 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1448 pldm_msgbuf_extract(buf,
1449 resp_data->fdp_capabilities_during_update.value);
1450 pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1451
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301452 rc = pldm_msgbuf_span_remaining(buf, &remaining, &length);
1453 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301454 return pldm_msgbuf_discard(buf, rc);
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301455 }
1456
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301457 rc = pldm_msgbuf_complete(buf);
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301458 if (rc) {
1459 return rc;
1460 }
1461
1462 iter->field.ptr = remaining;
1463 iter->field.length = length;
1464 iter->entries = resp_data->downstream_device_count;
1465
1466 return 0;
Chris Wangb6ef35b2024-07-03 09:35:42 +08001467}
1468
Unive Tiene5c3f142024-12-13 14:14:19 +08001469LIBPLDM_ABI_STABLE
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301470int decode_pldm_downstream_device_parameters_entry_from_iter(
1471 struct pldm_downstream_device_parameters_iter *iter,
1472 struct pldm_downstream_device_parameters_entry *entry)
Chris Wangb6ef35b2024-07-03 09:35:42 +08001473{
Andrew Jefferya1896962025-03-03 21:41:25 +10301474 PLDM_MSGBUF_DEFINE_P(buf);
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301475 void *comp_ver_str;
Chris Wangb6ef35b2024-07-03 09:35:42 +08001476 size_t remaining;
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301477 void *cursor;
Chris Wangb6ef35b2024-07-03 09:35:42 +08001478 int rc;
1479
Andrew Jefferya1896962025-03-03 21:41:25 +10301480 if (iter == NULL || iter->field.ptr == NULL || entry == NULL) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001481 return -EINVAL;
1482 }
1483
1484 rc = pldm_msgbuf_init_errno(
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301485 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN,
1486 iter->field.ptr, iter->field.length);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001487 if (rc < 0) {
1488 return rc;
1489 }
1490
1491 pldm_msgbuf_extract(buf, entry->downstream_device_index);
1492 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1493 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1494 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1495 if (rc < 0) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301496 return pldm_msgbuf_discard(buf, rc);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001497 }
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001498 rc = pldm_msgbuf_extract_array(buf,
1499 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1500 entry->active_comp_release_date,
1501 sizeof(entry->active_comp_release_date));
1502 if (rc < 0) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301503 return pldm_msgbuf_discard(buf, rc);
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001504 }
1505
Chris Wangb6ef35b2024-07-03 09:35:42 +08001506 // Fill the last byte with NULL character
1507 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1508 '\0';
1509
1510 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1511 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1512 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1513 if (rc < 0) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301514 return pldm_msgbuf_discard(buf, rc);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001515 }
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001516
1517 rc = pldm_msgbuf_extract_array(
1518 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1519 entry->pending_comp_release_date,
1520 sizeof(entry->pending_comp_release_date));
1521 if (rc < 0) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301522 return pldm_msgbuf_discard(buf, rc);
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001523 }
1524
Chris Wangb6ef35b2024-07-03 09:35:42 +08001525 // Fill the last byte with NULL character
1526 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1527 '\0';
1528
1529 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1530 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001531
Andrew Jefferya1896962025-03-03 21:41:25 +10301532 rc = pldm_msgbuf_span_required(buf, entry->active_comp_ver_str_len,
1533 &comp_ver_str);
1534 if (rc < 0) {
1535 return pldm_msgbuf_discard(buf, rc);
1536 }
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301537 entry->active_comp_ver_str = comp_ver_str;
1538
Andrew Jefferya1896962025-03-03 21:41:25 +10301539 rc = pldm_msgbuf_span_required(buf, entry->pending_comp_ver_str_len,
1540 &comp_ver_str);
1541 if (rc < 0) {
1542 return pldm_msgbuf_discard(buf, rc);
1543 }
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301544 entry->pending_comp_ver_str = comp_ver_str;
1545
Chris Wangb6ef35b2024-07-03 09:35:42 +08001546 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1547 if (rc < 0) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301548 return pldm_msgbuf_discard(buf, rc);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001549 }
1550
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301551 iter->field.ptr = cursor;
1552 iter->field.length = remaining;
Chris Wangb6ef35b2024-07-03 09:35:42 +08001553
Andrew Jefferya1896962025-03-03 21:41:25 +10301554 return pldm_msgbuf_complete(buf);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001555}
1556
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301557LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301558int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1559 uint16_t num_of_comp,
1560 uint8_t max_outstanding_transfer_req,
1561 uint16_t pkg_data_len,
1562 uint8_t comp_image_set_ver_str_type,
1563 uint8_t comp_image_set_ver_str_len,
1564 const struct variable_field *comp_img_set_ver_str,
1565 struct pldm_msg *msg, size_t payload_length)
1566{
1567 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
1568 msg == NULL) {
1569 return PLDM_ERROR_INVALID_DATA;
1570 }
1571
1572 if (payload_length != sizeof(struct pldm_request_update_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301573 comp_img_set_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301574 return PLDM_ERROR_INVALID_LENGTH;
1575 }
1576
1577 if ((comp_image_set_ver_str_len == 0) ||
1578 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
1579 return PLDM_ERROR_INVALID_DATA;
1580 }
1581
1582 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
1583 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
1584 return PLDM_ERROR_INVALID_DATA;
1585 }
1586
1587 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
1588 return PLDM_ERROR_INVALID_DATA;
1589 }
1590
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301591 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301592 header.instance = instance_id;
1593 header.msg_type = PLDM_REQUEST;
1594 header.pldm_type = PLDM_FWUP;
1595 header.command = PLDM_REQUEST_UPDATE;
1596 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1597 if (rc) {
1598 return rc;
1599 }
1600
1601 struct pldm_request_update_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301602 (struct pldm_request_update_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301603
1604 request->max_transfer_size = htole32(max_transfer_size);
1605 request->num_of_comp = htole16(num_of_comp);
1606 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
1607 request->pkg_data_len = htole16(pkg_data_len);
1608 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
1609 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
1610
1611 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
1612 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
1613
1614 return PLDM_SUCCESS;
1615}
1616
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001617LIBPLDM_ABI_TESTING
1618int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length,
1619 struct pldm_request_update_req_full *req)
1620{
1621 int rc;
1622 uint8_t t;
Andrew Jefferya1896962025-03-03 21:41:25 +10301623 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001624
1625 if (msg == NULL || req == NULL) {
1626 return -EINVAL;
1627 }
1628
1629 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1630 if (rc) {
1631 return rc;
1632 }
1633
1634 pldm_msgbuf_extract(buf, req->max_transfer_size);
1635 pldm_msgbuf_extract(buf, req->num_of_comp);
1636 pldm_msgbuf_extract(buf, req->max_outstanding_transfer_req);
1637 pldm_msgbuf_extract(buf, req->pkg_data_len);
1638 rc = pldm_msgbuf_extract(buf, t);
1639 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301640 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001641 }
1642 if (t > PLDM_STR_TYPE_UTF_16BE) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301643 return pldm_msgbuf_discard(buf, -EBADMSG);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001644 }
1645 req->image_set_ver.str_type = (enum pldm_firmware_update_string_type)t;
1646 pldm_msgbuf_extract(buf, req->image_set_ver.str_len);
1647 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301648 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001649 }
1650
1651 rc = pldm_msgbuf_extract_array(buf, req->image_set_ver.str_len,
1652 req->image_set_ver.str_data,
1653 PLDM_FIRMWARE_MAX_STRING);
1654 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301655 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001656 }
1657
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301658 return pldm_msgbuf_complete_consumed(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001659}
1660
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301661LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301662int decode_request_update_resp(const struct pldm_msg *msg,
1663 size_t payload_length, uint8_t *completion_code,
1664 uint16_t *fd_meta_data_len,
1665 uint8_t *fd_will_send_pkg_data)
1666{
1667 if (msg == NULL || completion_code == NULL ||
1668 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
1669 !payload_length) {
1670 return PLDM_ERROR_INVALID_DATA;
1671 }
1672
1673 *completion_code = msg->payload[0];
1674 if (*completion_code != PLDM_SUCCESS) {
1675 return PLDM_SUCCESS;
1676 }
1677
1678 if (payload_length != sizeof(struct pldm_request_update_resp)) {
1679 return PLDM_ERROR_INVALID_LENGTH;
1680 }
1681
1682 struct pldm_request_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301683 (struct pldm_request_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301684
1685 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
1686 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1687
1688 return PLDM_SUCCESS;
1689}
1690
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001691LIBPLDM_ABI_TESTING
1692int encode_request_update_resp(uint8_t instance_id,
1693 const struct pldm_request_update_resp *resp_data,
1694 struct pldm_msg *msg, size_t *payload_length)
1695{
Andrew Jefferya1896962025-03-03 21:41:25 +10301696 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001697 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001698
1699 if (msg == NULL || payload_length == NULL) {
1700 return -EINVAL;
1701 }
1702
1703 struct pldm_header_info header = {
1704 .instance = instance_id,
1705 .msg_type = PLDM_RESPONSE,
1706 .pldm_type = PLDM_FWUP,
1707 .command = PLDM_REQUEST_UPDATE,
1708 };
1709 rc = pack_pldm_header(&header, &(msg->hdr));
1710 if (rc) {
1711 return -EINVAL;
1712 }
1713
1714 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1715 if (rc) {
1716 return rc;
1717 }
1718
1719 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1720 pldm_msgbuf_insert(buf, resp_data->fd_meta_data_len);
1721 pldm_msgbuf_insert(buf, resp_data->fd_will_send_pkg_data);
1722
1723 /* TODO: DSP0267 1.3.0 adds GetPackageDataMaximumTransferSize */
1724
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301725 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001726}
1727
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301728LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301729int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1730 uint16_t comp_classification,
1731 uint16_t comp_identifier,
1732 uint8_t comp_classification_index,
1733 uint32_t comp_comparison_stamp,
1734 uint8_t comp_ver_str_type,
1735 uint8_t comp_ver_str_len,
1736 const struct variable_field *comp_ver_str,
1737 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301738{
1739 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1740 return PLDM_ERROR_INVALID_DATA;
1741 }
1742
1743 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301744 comp_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301745 return PLDM_ERROR_INVALID_LENGTH;
1746 }
1747
1748 if ((comp_ver_str_len == 0) ||
1749 (comp_ver_str_len != comp_ver_str->length)) {
1750 return PLDM_ERROR_INVALID_DATA;
1751 }
1752
1753 if (!is_transfer_flag_valid(transfer_flag)) {
1754 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1755 }
1756
1757 if (!is_string_type_valid(comp_ver_str_type)) {
1758 return PLDM_ERROR_INVALID_DATA;
1759 }
1760
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301761 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301762 header.instance = instance_id;
1763 header.msg_type = PLDM_REQUEST;
1764 header.pldm_type = PLDM_FWUP;
1765 header.command = PLDM_PASS_COMPONENT_TABLE;
1766 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1767 if (rc) {
1768 return rc;
1769 }
1770
1771 struct pldm_pass_component_table_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301772 (struct pldm_pass_component_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301773
1774 request->transfer_flag = transfer_flag;
1775 request->comp_classification = htole16(comp_classification);
1776 request->comp_identifier = htole16(comp_identifier);
1777 request->comp_classification_index = comp_classification_index;
1778 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1779 request->comp_ver_str_type = comp_ver_str_type;
1780 request->comp_ver_str_len = comp_ver_str_len;
1781
1782 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1783 comp_ver_str->ptr, comp_ver_str->length);
1784
1785 return PLDM_SUCCESS;
1786}
1787
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001788LIBPLDM_ABI_TESTING
1789int decode_pass_component_table_req(
1790 const struct pldm_msg *msg, size_t payload_length,
1791 struct pldm_pass_component_table_req_full *pcomp)
1792{
1793 int rc;
1794 uint8_t t;
Andrew Jefferya1896962025-03-03 21:41:25 +10301795 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001796
1797 if (msg == NULL || pcomp == NULL) {
1798 return -EINVAL;
1799 }
1800
1801 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1802 if (rc) {
1803 return rc;
1804 }
1805
1806 pldm_msgbuf_extract(buf, pcomp->transfer_flag);
1807 pldm_msgbuf_extract(buf, pcomp->comp_classification);
1808 pldm_msgbuf_extract(buf, pcomp->comp_identifier);
1809 pldm_msgbuf_extract(buf, pcomp->comp_classification_index);
1810 pldm_msgbuf_extract(buf, pcomp->comp_comparison_stamp);
1811 rc = pldm_msgbuf_extract(buf, t);
1812 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301813 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001814 }
1815 if (t > PLDM_STR_TYPE_UTF_16BE) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301816 return pldm_msgbuf_discard(buf, -EBADMSG);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001817 }
1818 pcomp->version.str_type = (enum pldm_firmware_update_string_type)t;
1819 rc = pldm_msgbuf_extract(buf, pcomp->version.str_len);
1820 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301821 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001822 }
1823 rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len,
1824 pcomp->version.str_data,
1825 PLDM_FIRMWARE_MAX_STRING);
1826 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301827 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001828 }
1829
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301830 return pldm_msgbuf_complete_consumed(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001831}
1832
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301833LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301834int decode_pass_component_table_resp(const struct pldm_msg *msg,
1835 const size_t payload_length,
1836 uint8_t *completion_code,
1837 uint8_t *comp_resp,
1838 uint8_t *comp_resp_code)
1839{
1840 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1841 comp_resp_code == NULL || !payload_length) {
1842 return PLDM_ERROR_INVALID_DATA;
1843 }
1844
1845 *completion_code = msg->payload[0];
1846 if (*completion_code != PLDM_SUCCESS) {
1847 return PLDM_SUCCESS;
1848 }
1849
1850 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1851 return PLDM_ERROR_INVALID_LENGTH;
1852 }
1853
1854 struct pldm_pass_component_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301855 (struct pldm_pass_component_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301856
1857 if (!is_comp_resp_valid(response->comp_resp)) {
1858 return PLDM_ERROR_INVALID_DATA;
1859 }
1860
1861 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1862 return PLDM_ERROR_INVALID_DATA;
1863 }
1864
1865 *comp_resp = response->comp_resp;
1866 *comp_resp_code = response->comp_resp_code;
1867
1868 return PLDM_SUCCESS;
1869}
1870
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001871LIBPLDM_ABI_TESTING
1872int encode_pass_component_table_resp(
1873 uint8_t instance_id,
1874 const struct pldm_pass_component_table_resp *resp_data,
1875 struct pldm_msg *msg, size_t *payload_length)
1876{
Andrew Jefferya1896962025-03-03 21:41:25 +10301877 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001878 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001879
1880 if (msg == NULL || payload_length == NULL) {
1881 return -EINVAL;
1882 }
1883
1884 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
1885 PLDM_PASS_COMPONENT_TABLE, msg);
1886 if (rc) {
1887 return -EINVAL;
1888 }
1889
1890 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1891 if (rc) {
1892 return rc;
1893 }
1894
1895 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1896 pldm_msgbuf_insert(buf, resp_data->comp_resp);
1897 pldm_msgbuf_insert(buf, resp_data->comp_resp_code);
1898
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301899 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001900}
1901
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301902LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301903int encode_update_component_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301904 uint8_t instance_id, uint16_t comp_classification,
1905 uint16_t comp_identifier, uint8_t comp_classification_index,
1906 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1907 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1908 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1909 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301910{
1911 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1912 return PLDM_ERROR_INVALID_DATA;
1913 }
1914
1915 if (payload_length !=
1916 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1917 return PLDM_ERROR_INVALID_LENGTH;
1918 }
1919
1920 if (!comp_image_size) {
1921 return PLDM_ERROR_INVALID_DATA;
1922 }
1923
1924 if ((comp_ver_str_len == 0) ||
1925 (comp_ver_str_len != comp_ver_str->length)) {
1926 return PLDM_ERROR_INVALID_DATA;
1927 }
1928
1929 if (!is_string_type_valid(comp_ver_str_type)) {
1930 return PLDM_ERROR_INVALID_DATA;
1931 }
1932
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301933 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301934 header.instance = instance_id;
1935 header.msg_type = PLDM_REQUEST;
1936 header.pldm_type = PLDM_FWUP;
1937 header.command = PLDM_UPDATE_COMPONENT;
1938 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1939 if (rc) {
1940 return rc;
1941 }
1942
1943 struct pldm_update_component_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301944 (struct pldm_update_component_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301945
1946 request->comp_classification = htole16(comp_classification);
1947 request->comp_identifier = htole16(comp_identifier);
1948 request->comp_classification_index = comp_classification_index;
1949 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1950 request->comp_image_size = htole32(comp_image_size);
1951 request->update_option_flags.value = htole32(update_option_flags.value);
1952 request->comp_ver_str_type = comp_ver_str_type;
1953 request->comp_ver_str_len = comp_ver_str_len;
1954
1955 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1956 comp_ver_str->ptr, comp_ver_str->length);
1957
1958 return PLDM_SUCCESS;
1959}
1960
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001961LIBPLDM_ABI_TESTING
1962int decode_update_component_req(const struct pldm_msg *msg,
1963 size_t payload_length,
1964 struct pldm_update_component_req_full *up)
1965{
1966 int rc;
1967 uint8_t t;
Andrew Jefferya1896962025-03-03 21:41:25 +10301968 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001969
1970 if (msg == NULL || up == NULL) {
1971 return -EINVAL;
1972 }
1973
1974 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1975 if (rc) {
1976 return rc;
1977 }
1978
1979 pldm_msgbuf_extract(buf, up->comp_classification);
1980 pldm_msgbuf_extract(buf, up->comp_identifier);
1981 pldm_msgbuf_extract(buf, up->comp_classification_index);
1982 pldm_msgbuf_extract(buf, up->comp_comparison_stamp);
1983 pldm_msgbuf_extract(buf, up->comp_image_size);
1984 pldm_msgbuf_extract(buf, up->update_option_flags.value);
1985 rc = pldm_msgbuf_extract(buf, t);
1986 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301987 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001988 }
1989 if (t > PLDM_STR_TYPE_UTF_16BE) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301990 return pldm_msgbuf_discard(buf, -EBADMSG);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001991 }
1992 up->version.str_type = (enum pldm_firmware_update_string_type)t;
1993 rc = pldm_msgbuf_extract(buf, up->version.str_len);
1994 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301995 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001996 }
1997 rc = pldm_msgbuf_extract_array(buf, up->version.str_len,
1998 up->version.str_data,
1999 PLDM_FIRMWARE_MAX_STRING);
2000 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10302001 return pldm_msgbuf_discard(buf, rc);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002002 }
2003
Andrew Jefferya1896962025-03-03 21:41:25 +10302004 return pldm_msgbuf_complete_consumed(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002005}
2006
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302007LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302008int decode_update_component_resp(const struct pldm_msg *msg,
2009 size_t payload_length,
2010 uint8_t *completion_code,
2011 uint8_t *comp_compatibility_resp,
2012 uint8_t *comp_compatibility_resp_code,
2013 bitfield32_t *update_option_flags_enabled,
2014 uint16_t *time_before_req_fw_data)
2015{
2016 if (msg == NULL || completion_code == NULL ||
2017 comp_compatibility_resp == NULL ||
2018 comp_compatibility_resp_code == NULL ||
2019 update_option_flags_enabled == NULL ||
2020 time_before_req_fw_data == NULL || !payload_length) {
2021 return PLDM_ERROR_INVALID_DATA;
2022 }
2023
2024 *completion_code = msg->payload[0];
2025 if (*completion_code != PLDM_SUCCESS) {
2026 return PLDM_SUCCESS;
2027 }
2028
2029 if (payload_length != sizeof(struct pldm_update_component_resp)) {
2030 return PLDM_ERROR_INVALID_LENGTH;
2031 }
2032
2033 struct pldm_update_component_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302034 (struct pldm_update_component_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302035
2036 if (!is_comp_compatibility_resp_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302037 response->comp_compatibility_resp)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09302038 return PLDM_ERROR_INVALID_DATA;
2039 }
2040
2041 if (!is_comp_compatibility_resp_code_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302042 response->comp_compatibility_resp_code)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09302043 return PLDM_ERROR_INVALID_DATA;
2044 }
2045
2046 *comp_compatibility_resp = response->comp_compatibility_resp;
2047 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
2048 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302049 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302050 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
2051
2052 return PLDM_SUCCESS;
2053}
2054
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002055LIBPLDM_ABI_TESTING
2056int encode_update_component_resp(
2057 uint8_t instance_id, const struct pldm_update_component_resp *resp_data,
2058 struct pldm_msg *msg, size_t *payload_length)
2059{
Andrew Jefferya1896962025-03-03 21:41:25 +10302060 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002061 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002062
2063 if (msg == NULL || payload_length == NULL) {
2064 return -EINVAL;
2065 }
2066
2067 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2068 PLDM_UPDATE_COMPONENT, msg);
2069 if (rc) {
2070 return -EINVAL;
2071 }
2072
2073 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2074 if (rc) {
2075 return rc;
2076 }
2077
2078 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2079 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp);
2080 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp_code);
2081 pldm_msgbuf_insert(buf, resp_data->update_option_flags_enabled.value);
2082 pldm_msgbuf_insert(buf, resp_data->time_before_req_fw_data);
2083
Andrew Jeffery70d21c92025-03-05 12:59:42 +10302084 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002085}
2086
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302087LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302088int decode_request_firmware_data_req(const struct pldm_msg *msg,
2089 size_t payload_length, uint32_t *offset,
2090 uint32_t *length)
2091{
2092 if (msg == NULL || offset == NULL || length == NULL) {
2093 return PLDM_ERROR_INVALID_DATA;
2094 }
2095 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
2096 return PLDM_ERROR_INVALID_LENGTH;
2097 }
2098 struct pldm_request_firmware_data_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302099 (struct pldm_request_firmware_data_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302100 *offset = le32toh(request->offset);
2101 *length = le32toh(request->length);
2102
2103 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
2104 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
2105 }
2106
2107 return PLDM_SUCCESS;
2108}
2109
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002110LIBPLDM_ABI_TESTING
2111int encode_request_firmware_data_req(
2112 uint8_t instance_id,
2113 const struct pldm_request_firmware_data_req *req_params,
2114 struct pldm_msg *msg, size_t *payload_length)
2115{
Andrew Jefferya1896962025-03-03 21:41:25 +10302116 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002117 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002118
2119 if (msg == NULL || payload_length == NULL) {
2120 return -EINVAL;
2121 }
2122
2123 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2124 PLDM_REQUEST_FIRMWARE_DATA, msg);
2125 if (rc) {
2126 return -EINVAL;
2127 }
2128
2129 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2130 if (rc) {
2131 return rc;
2132 }
2133
2134 pldm_msgbuf_insert(buf, req_params->offset);
2135 pldm_msgbuf_insert(buf, req_params->length);
2136
Andrew Jeffery70d21c92025-03-05 12:59:42 +10302137 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002138}
2139
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302140LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302141int encode_request_firmware_data_resp(uint8_t instance_id,
2142 uint8_t completion_code,
2143 struct pldm_msg *msg,
2144 size_t payload_length)
2145{
2146 if (msg == NULL || !payload_length) {
2147 return PLDM_ERROR_INVALID_DATA;
2148 }
2149
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302150 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302151 header.instance = instance_id;
2152 header.msg_type = PLDM_RESPONSE;
2153 header.pldm_type = PLDM_FWUP;
2154 header.command = PLDM_REQUEST_FIRMWARE_DATA;
2155 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2156 if (rc) {
2157 return rc;
2158 }
2159
2160 msg->payload[0] = completion_code;
2161
2162 return PLDM_SUCCESS;
2163}
2164
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302165LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302166int decode_transfer_complete_req(const struct pldm_msg *msg,
2167 size_t payload_length,
2168 uint8_t *transfer_result)
2169{
2170 if (msg == NULL || transfer_result == NULL) {
2171 return PLDM_ERROR_INVALID_DATA;
2172 }
2173
2174 if (payload_length != sizeof(*transfer_result)) {
2175 return PLDM_ERROR_INVALID_LENGTH;
2176 }
2177
2178 *transfer_result = msg->payload[0];
2179 return PLDM_SUCCESS;
2180}
2181
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002182LIBPLDM_ABI_TESTING
2183int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
2184 struct pldm_msg *msg, size_t *payload_length)
2185{
Andrew Jefferya1896962025-03-03 21:41:25 +10302186 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002187 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002188
2189 if (msg == NULL || payload_length == NULL) {
2190 return -EINVAL;
2191 }
2192
2193 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2194 PLDM_TRANSFER_COMPLETE, msg);
2195 if (rc) {
2196 return -EINVAL;
2197 }
2198
2199 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2200 if (rc) {
2201 return rc;
2202 }
2203
Andrew Jefferya1896962025-03-03 21:41:25 +10302204 pldm_msgbuf_insert(buf, transfer_result);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002205
Andrew Jeffery70d21c92025-03-05 12:59:42 +10302206 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002207}
2208
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302209LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302210int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
2211 struct pldm_msg *msg, size_t payload_length)
2212{
2213 if (msg == NULL) {
2214 return PLDM_ERROR_INVALID_DATA;
2215 }
2216
2217 if (payload_length != sizeof(completion_code)) {
2218 return PLDM_ERROR_INVALID_LENGTH;
2219 }
2220
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302221 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302222 header.instance = instance_id;
2223 header.msg_type = PLDM_RESPONSE;
2224 header.pldm_type = PLDM_FWUP;
2225 header.command = PLDM_TRANSFER_COMPLETE;
2226 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2227 if (rc) {
2228 return rc;
2229 }
2230
2231 msg->payload[0] = completion_code;
2232
2233 return PLDM_SUCCESS;
2234}
2235
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302236LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302237int decode_verify_complete_req(const struct pldm_msg *msg,
2238 size_t payload_length, uint8_t *verify_result)
2239{
2240 if (msg == NULL || verify_result == NULL) {
2241 return PLDM_ERROR_INVALID_DATA;
2242 }
2243
2244 if (payload_length != sizeof(*verify_result)) {
2245 return PLDM_ERROR_INVALID_LENGTH;
2246 }
2247
2248 *verify_result = msg->payload[0];
2249 return PLDM_SUCCESS;
2250}
2251
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002252LIBPLDM_ABI_TESTING
2253int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
2254 struct pldm_msg *msg, size_t *payload_length)
2255{
Andrew Jefferya1896962025-03-03 21:41:25 +10302256 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002257 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002258
2259 if (msg == NULL || payload_length == NULL) {
2260 return -EINVAL;
2261 }
2262
2263 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2264 PLDM_VERIFY_COMPLETE, msg);
2265 if (rc) {
2266 return EINVAL;
2267 }
2268
2269 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2270 if (rc) {
2271 return rc;
2272 }
2273
Andrew Jefferya1896962025-03-03 21:41:25 +10302274 pldm_msgbuf_insert(buf, verify_result);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002275
Andrew Jeffery70d21c92025-03-05 12:59:42 +10302276 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002277}
2278
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302279LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302280int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
2281 struct pldm_msg *msg, size_t payload_length)
2282{
2283 if (msg == NULL) {
2284 return PLDM_ERROR_INVALID_DATA;
2285 }
2286
2287 if (payload_length != sizeof(completion_code)) {
2288 return PLDM_ERROR_INVALID_LENGTH;
2289 }
2290
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302291 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302292 header.instance = instance_id;
2293 header.msg_type = PLDM_RESPONSE;
2294 header.pldm_type = PLDM_FWUP;
2295 header.command = PLDM_VERIFY_COMPLETE;
2296 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2297 if (rc) {
2298 return rc;
2299 }
2300
2301 msg->payload[0] = completion_code;
2302
2303 return PLDM_SUCCESS;
2304}
2305
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302306LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302307int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
2308 uint8_t *apply_result,
2309 bitfield16_t *comp_activation_methods_modification)
Andrew Jeffery9c766792022-08-10 23:12:49 +09302310{
2311 if (msg == NULL || apply_result == NULL ||
2312 comp_activation_methods_modification == NULL) {
2313 return PLDM_ERROR_INVALID_DATA;
2314 }
2315
2316 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
2317 return PLDM_ERROR_INVALID_LENGTH;
2318 }
2319
2320 struct pldm_apply_complete_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302321 (struct pldm_apply_complete_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302322
2323 *apply_result = request->apply_result;
2324 comp_activation_methods_modification->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302325 le16toh(request->comp_activation_methods_modification.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302326
2327 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
2328 comp_activation_methods_modification->value) {
2329 return PLDM_ERROR_INVALID_DATA;
2330 }
2331
2332 return PLDM_SUCCESS;
2333}
2334
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002335LIBPLDM_ABI_TESTING
2336int encode_apply_complete_req(uint8_t instance_id,
2337 const struct pldm_apply_complete_req *req_data,
2338 struct pldm_msg *msg, size_t *payload_length)
2339{
Andrew Jefferya1896962025-03-03 21:41:25 +10302340 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002341 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002342
2343 if (msg == NULL || payload_length == NULL) {
2344 return -EINVAL;
2345 }
2346
2347 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2348 PLDM_APPLY_COMPLETE, msg);
2349 if (rc) {
2350 return -EINVAL;
2351 }
2352
2353 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2354 if (rc) {
2355 return rc;
2356 }
2357
2358 pldm_msgbuf_insert(buf, req_data->apply_result);
2359 pldm_msgbuf_insert(
2360 buf, req_data->comp_activation_methods_modification.value);
2361
Andrew Jeffery70d21c92025-03-05 12:59:42 +10302362 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002363}
2364
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302365LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302366int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
2367 struct pldm_msg *msg, size_t payload_length)
2368{
2369 if (msg == NULL) {
2370 return PLDM_ERROR_INVALID_DATA;
2371 }
2372
2373 if (payload_length != sizeof(completion_code)) {
2374 return PLDM_ERROR_INVALID_LENGTH;
2375 }
2376
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302377 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302378 header.instance = instance_id;
2379 header.msg_type = PLDM_RESPONSE;
2380 header.pldm_type = PLDM_FWUP;
2381 header.command = PLDM_APPLY_COMPLETE;
2382 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2383 if (rc) {
2384 return rc;
2385 }
2386
2387 msg->payload[0] = completion_code;
2388
2389 return PLDM_SUCCESS;
2390}
2391
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002392LIBPLDM_ABI_TESTING
2393int decode_activate_firmware_req(const struct pldm_msg *msg,
2394 size_t payload_length, bool *self_contained)
2395{
Andrew Jefferya1896962025-03-03 21:41:25 +10302396 uint8_t self_contained_u8 = 0;
2397 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002398 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002399
2400 if (msg == NULL || self_contained == NULL) {
2401 return -EINVAL;
2402 }
2403
2404 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
2405 if (rc) {
2406 return 0;
2407 }
2408
Andrew Jefferya1896962025-03-03 21:41:25 +10302409 pldm_msgbuf_extract(buf, self_contained_u8);
2410
2411 rc = pldm_msgbuf_complete_consumed(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002412 if (rc) {
2413 return rc;
2414 }
Andrew Jefferya1896962025-03-03 21:41:25 +10302415
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002416 *self_contained = (bool)self_contained_u8;
2417 return 0;
2418}
2419
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302420LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302421int encode_activate_firmware_req(uint8_t instance_id,
2422 bool8_t self_contained_activation_req,
2423 struct pldm_msg *msg, size_t payload_length)
2424{
2425 if (msg == NULL) {
2426 return PLDM_ERROR_INVALID_DATA;
2427 }
2428
2429 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
2430 return PLDM_ERROR_INVALID_LENGTH;
2431 }
2432
2433 if (!is_self_contained_activation_req_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302434 self_contained_activation_req)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09302435 return PLDM_ERROR_INVALID_DATA;
2436 }
2437
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302438 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302439 header.instance = instance_id;
2440 header.msg_type = PLDM_REQUEST;
2441 header.pldm_type = PLDM_FWUP;
2442 header.command = PLDM_ACTIVATE_FIRMWARE;
2443 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2444 if (rc) {
2445 return rc;
2446 }
2447
2448 struct pldm_activate_firmware_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302449 (struct pldm_activate_firmware_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302450
2451 request->self_contained_activation_req = self_contained_activation_req;
2452
2453 return PLDM_SUCCESS;
2454}
2455
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302456LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302457int decode_activate_firmware_resp(const struct pldm_msg *msg,
2458 size_t payload_length,
2459 uint8_t *completion_code,
2460 uint16_t *estimated_time_activation)
2461{
2462 if (msg == NULL || completion_code == NULL ||
2463 estimated_time_activation == NULL || !payload_length) {
2464 return PLDM_ERROR_INVALID_DATA;
2465 }
2466
2467 *completion_code = msg->payload[0];
2468 if (*completion_code != PLDM_SUCCESS) {
2469 return PLDM_SUCCESS;
2470 }
2471
2472 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
2473 return PLDM_ERROR_INVALID_LENGTH;
2474 }
2475
2476 struct pldm_activate_firmware_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302477 (struct pldm_activate_firmware_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302478
2479 *estimated_time_activation =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302480 le16toh(response->estimated_time_activation);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302481
2482 return PLDM_SUCCESS;
2483}
2484
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002485LIBPLDM_ABI_TESTING
2486int encode_activate_firmware_resp(
2487 uint8_t instance_id,
2488 const struct pldm_activate_firmware_resp *resp_data,
2489 struct pldm_msg *msg, size_t *payload_length)
2490{
Andrew Jefferya1896962025-03-03 21:41:25 +10302491 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002492 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002493
2494 if (msg == NULL || payload_length == NULL) {
2495 return -EINVAL;
2496 }
2497
2498 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2499 PLDM_ACTIVATE_FIRMWARE, msg);
2500 if (rc) {
2501 return -EINVAL;
2502 }
2503
2504 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2505 if (rc) {
2506 return rc;
2507 }
2508
2509 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2510 pldm_msgbuf_insert(buf, resp_data->estimated_time_activation);
2511
Andrew Jeffery70d21c92025-03-05 12:59:42 +10302512 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002513}
2514
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302515LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302516int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
2517 size_t payload_length)
2518{
2519 if (msg == NULL) {
2520 return PLDM_ERROR_INVALID_DATA;
2521 }
2522
2523 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
2524 return PLDM_ERROR_INVALID_LENGTH;
2525 }
2526
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302527 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302528 header.instance = instance_id;
2529 header.msg_type = PLDM_REQUEST;
2530 header.pldm_type = PLDM_FWUP;
2531 header.command = PLDM_GET_STATUS;
2532 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2533 if (rc) {
2534 return rc;
2535 }
2536
2537 return PLDM_SUCCESS;
2538}
2539
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302540LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302541int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
2542 uint8_t *completion_code, uint8_t *current_state,
2543 uint8_t *previous_state, uint8_t *aux_state,
2544 uint8_t *aux_state_status, uint8_t *progress_percent,
2545 uint8_t *reason_code,
2546 bitfield32_t *update_option_flags_enabled)
2547{
2548 if (msg == NULL || completion_code == NULL || current_state == NULL ||
2549 previous_state == NULL || aux_state == NULL ||
2550 aux_state_status == NULL || progress_percent == NULL ||
2551 reason_code == NULL || update_option_flags_enabled == NULL ||
2552 !payload_length) {
2553 return PLDM_ERROR_INVALID_DATA;
2554 }
2555
2556 *completion_code = msg->payload[0];
2557 if (*completion_code != PLDM_SUCCESS) {
2558 return PLDM_SUCCESS;
2559 }
2560
2561 if (payload_length != sizeof(struct pldm_get_status_resp)) {
2562 return PLDM_ERROR_INVALID_LENGTH;
2563 }
2564 struct pldm_get_status_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302565 (struct pldm_get_status_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302566
2567 if (!is_state_valid(response->current_state)) {
2568 return PLDM_ERROR_INVALID_DATA;
2569 }
2570 if (!is_state_valid(response->previous_state)) {
2571 return PLDM_ERROR_INVALID_DATA;
2572 }
2573 if (!is_aux_state_valid(response->aux_state)) {
2574 return PLDM_ERROR_INVALID_DATA;
2575 }
2576 if (!is_aux_state_status_valid(response->aux_state_status)) {
2577 return PLDM_ERROR_INVALID_DATA;
2578 }
2579 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
2580 return PLDM_ERROR_INVALID_DATA;
2581 }
2582 if (!is_reason_code_valid(response->reason_code)) {
2583 return PLDM_ERROR_INVALID_DATA;
2584 }
2585
2586 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
2587 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
2588 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
2589 if (response->aux_state !=
2590 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
2591 return PLDM_ERROR_INVALID_DATA;
2592 }
2593 }
2594
2595 *current_state = response->current_state;
2596 *previous_state = response->previous_state;
2597 *aux_state = response->aux_state;
2598 *aux_state_status = response->aux_state_status;
2599 *progress_percent = response->progress_percent;
2600 *reason_code = response->reason_code;
2601 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302602 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302603
2604 return PLDM_SUCCESS;
2605}
2606
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002607LIBPLDM_ABI_TESTING
2608int encode_get_status_resp(uint8_t instance_id,
2609 const struct pldm_get_status_resp *status,
2610 struct pldm_msg *msg, size_t *payload_length)
2611{
Andrew Jefferya1896962025-03-03 21:41:25 +10302612 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002613 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002614
2615 if (status == NULL || msg == NULL || payload_length == NULL) {
2616 return -EINVAL;
2617 }
2618
2619 if (status->completion_code != PLDM_SUCCESS) {
2620 return -EINVAL;
2621 }
2622
2623 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2624 PLDM_GET_STATUS, msg);
2625 if (rc) {
2626 return -EINVAL;
2627 }
2628
2629 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2630 if (rc) {
2631 return rc;
2632 }
2633
2634 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2635 pldm_msgbuf_insert(buf, status->current_state);
2636 pldm_msgbuf_insert(buf, status->previous_state);
2637 pldm_msgbuf_insert(buf, status->aux_state);
2638 pldm_msgbuf_insert(buf, status->aux_state_status);
2639 pldm_msgbuf_insert(buf, status->progress_percent);
2640 pldm_msgbuf_insert(buf, status->reason_code);
2641 pldm_msgbuf_insert(buf, status->update_option_flags_enabled.value);
2642
Andrew Jeffery70d21c92025-03-05 12:59:42 +10302643 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002644}
2645
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302646LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302647int encode_cancel_update_component_req(uint8_t instance_id,
2648 struct pldm_msg *msg,
2649 size_t payload_length)
2650{
2651 if (msg == NULL) {
2652 return PLDM_ERROR_INVALID_DATA;
2653 }
2654
2655 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
2656 return PLDM_ERROR_INVALID_LENGTH;
2657 }
2658
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302659 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302660 header.instance = instance_id;
2661 header.msg_type = PLDM_REQUEST;
2662 header.pldm_type = PLDM_FWUP;
2663 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
2664 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2665 if (rc) {
2666 return rc;
2667 }
2668
2669 return PLDM_SUCCESS;
2670}
2671
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302672LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302673int decode_cancel_update_component_resp(const struct pldm_msg *msg,
2674 size_t payload_length,
2675 uint8_t *completion_code)
2676{
2677 if (msg == NULL || completion_code == NULL) {
2678 return PLDM_ERROR_INVALID_DATA;
2679 }
2680
2681 if (payload_length != sizeof(*completion_code)) {
2682 return PLDM_ERROR_INVALID_LENGTH;
2683 }
2684
2685 *completion_code = msg->payload[0];
2686 return PLDM_SUCCESS;
2687}
2688
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302689LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302690int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
2691 size_t payload_length)
2692{
2693 if (msg == NULL) {
2694 return PLDM_ERROR_INVALID_DATA;
2695 }
2696
2697 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
2698 return PLDM_ERROR_INVALID_LENGTH;
2699 }
2700
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302701 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302702 header.instance = instance_id;
2703 header.msg_type = PLDM_REQUEST;
2704 header.pldm_type = PLDM_FWUP;
2705 header.command = PLDM_CANCEL_UPDATE;
2706 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2707 if (rc) {
2708 return rc;
2709 }
2710
2711 return PLDM_SUCCESS;
2712}
2713
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302714LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302715int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
2716 uint8_t *completion_code,
2717 bool8_t *non_functioning_component_indication,
2718 bitfield64_t *non_functioning_component_bitmap)
2719{
2720 if (msg == NULL || completion_code == NULL ||
2721 non_functioning_component_indication == NULL ||
2722 non_functioning_component_bitmap == NULL || !payload_length) {
2723 return PLDM_ERROR_INVALID_DATA;
2724 }
2725
2726 *completion_code = msg->payload[0];
2727 if (*completion_code != PLDM_SUCCESS) {
2728 return PLDM_SUCCESS;
2729 }
2730
2731 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
2732 return PLDM_ERROR_INVALID_LENGTH;
2733 }
2734 struct pldm_cancel_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302735 (struct pldm_cancel_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302736
2737 if (!is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302738 response->non_functioning_component_indication)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09302739 return PLDM_ERROR_INVALID_DATA;
2740 }
2741
2742 *non_functioning_component_indication =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302743 response->non_functioning_component_indication;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302744
2745 if (*non_functioning_component_indication) {
2746 non_functioning_component_bitmap->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302747 le64toh(response->non_functioning_component_bitmap);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302748 }
2749
2750 return PLDM_SUCCESS;
2751}
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002752
2753LIBPLDM_ABI_TESTING
2754int encode_cancel_update_resp(uint8_t instance_id,
2755 const struct pldm_cancel_update_resp *resp_data,
2756 struct pldm_msg *msg, size_t *payload_length)
2757{
Andrew Jefferya1896962025-03-03 21:41:25 +10302758 PLDM_MSGBUF_DEFINE_P(buf);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002759 int rc;
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002760
2761 if (msg == NULL || payload_length == NULL) {
2762 return -EINVAL;
2763 }
2764
2765 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2766 PLDM_CANCEL_UPDATE, msg);
2767 if (rc) {
2768 return -EINVAL;
2769 }
2770
2771 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2772 if (rc) {
2773 return rc;
2774 }
2775
2776 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2777 pldm_msgbuf_insert(buf,
2778 resp_data->non_functioning_component_indication);
2779 pldm_msgbuf_insert(buf, resp_data->non_functioning_component_bitmap);
2780
Andrew Jeffery70d21c92025-03-05 12:59:42 +10302781 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002782}