1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #include "api.h"
3 #include "dsp/base.h"
4 #include "msgbuf.h"
5 #include <libpldm/firmware_update.h>
6 #include <libpldm/utils.h>
7
8 #include <endian.h>
9 #include <stdbool.h>
10 #include <string.h>
11
12 static_assert(PLDM_FIRMWARE_MAX_STRING <= UINT8_MAX, "too large");
13
14 /** @brief Check whether string type value is valid
15 *
16 * @return true if string type value is valid, false if not
17 */
is_string_type_valid(uint8_t string_type)18 static 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 */
get_descriptor_type_length(uint16_t descriptor_type)40 static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
41 {
42 switch (descriptor_type) {
43 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
is_downstream_device_update_support_valid(uint8_t resp)82 static 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
93 static bool
is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)94 is_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
105 /** @brief Check whether ComponentResponse is valid
106 *
107 * @return true if ComponentResponse is valid, false if not
108 */
is_comp_resp_valid(uint8_t comp_resp)109 static 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 */
is_comp_resp_code_valid(uint8_t comp_resp_code)125 static 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 >=
144 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
145 comp_resp_code <=
146 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
147 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 */
is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)157 static 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 */
173 static bool
is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)174 is_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 >=
193 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
194 comp_compatibility_resp_code <=
195 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
196 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 */
206 static bool
is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)207 is_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 */
is_state_valid(uint8_t state)226 static 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 */
is_aux_state_valid(uint8_t aux_state)250 static 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 */
is_aux_state_status_valid(uint8_t aux_state_status)270 static 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 ||
274 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)) {
277 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 */
is_reason_code_valid(uint8_t reason_code)290 static bool is_reason_code_valid(uint8_t reason_code)
291 {
292 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 */
is_non_functioning_component_indication_valid(bool8_t non_functioning_component_indication)316 static bool is_non_functioning_component_indication_valid(
317 bool8_t non_functioning_component_indication)
318 {
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
decode_pldm_package_header_info_errno(const uint8_t * data,size_t length,struct pldm_package_header_information * package_header_info,struct variable_field * package_version_str)329 static int decode_pldm_package_header_info_errno(
330 const uint8_t *data, size_t length,
331 struct pldm_package_header_information *package_header_info,
332 struct variable_field *package_version_str)
333 {
334 if (data == NULL || package_header_info == NULL ||
335 package_version_str == NULL) {
336 return -EINVAL;
337 }
338
339 if (length < sizeof(struct pldm_package_header_information)) {
340 return -EOVERFLOW;
341 }
342
343 struct pldm_package_header_information *data_header =
344 (struct pldm_package_header_information *)(data);
345
346 if (!is_string_type_valid(data_header->package_version_string_type) ||
347 (data_header->package_version_string_length == 0)) {
348 return -EBADMSG;
349 }
350
351 if (length < sizeof(struct pldm_package_header_information) +
352 data_header->package_version_string_length) {
353 return -EOVERFLOW;
354 }
355
356 if ((data_header->component_bitmap_bit_length %
357 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
358 return -EBADMSG;
359 }
360
361 memcpy(package_header_info->uuid, data_header->uuid,
362 sizeof(data_header->uuid));
363 package_header_info->package_header_format_version =
364 data_header->package_header_format_version;
365 package_header_info->package_header_size =
366 le16toh(data_header->package_header_size);
367 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 =
371 le16toh(data_header->component_bitmap_bit_length);
372 package_header_info->package_version_string_type =
373 data_header->package_version_string_type;
374 package_header_info->package_version_string_length =
375 data_header->package_version_string_length;
376 package_version_str->ptr =
377 data + sizeof(struct pldm_package_header_information);
378 package_version_str->length =
379 package_header_info->package_version_string_length;
380
381 return 0;
382 }
383
384 LIBPLDM_ABI_STABLE
decode_pldm_package_header_info(const uint8_t * data,size_t length,struct pldm_package_header_information * package_header_info,struct variable_field * package_version_str)385 int 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
decode_firmware_device_id_record_errno(const uint8_t * data,size_t length,uint16_t component_bitmap_bit_length,struct pldm_firmware_device_id_record * fw_device_id_record,struct variable_field * applicable_components,struct variable_field * comp_image_set_version_str,struct variable_field * record_descriptors,struct variable_field * fw_device_pkg_data)401 static int decode_firmware_device_id_record_errno(
402 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)
409 {
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) {
414 return -EINVAL;
415 }
416
417 if (length < sizeof(struct pldm_firmware_device_id_record)) {
418 return -EOVERFLOW;
419 }
420
421 if ((component_bitmap_bit_length %
422 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
423 return -EBADMSG;
424 }
425
426 struct pldm_firmware_device_id_record *data_record =
427 (struct pldm_firmware_device_id_record *)(data);
428
429 if (!is_string_type_valid(
430 data_record->comp_image_set_version_string_type) ||
431 (data_record->comp_image_set_version_string_length == 0)) {
432 return -EBADMSG;
433 }
434
435 fw_device_id_record->record_length =
436 le16toh(data_record->record_length);
437 fw_device_id_record->descriptor_count = data_record->descriptor_count;
438 fw_device_id_record->device_update_option_flags.value =
439 le32toh(data_record->device_update_option_flags.value);
440 fw_device_id_record->comp_image_set_version_string_type =
441 data_record->comp_image_set_version_string_type;
442 fw_device_id_record->comp_image_set_version_string_length =
443 data_record->comp_image_set_version_string_length;
444 fw_device_id_record->fw_device_pkg_data_length =
445 le16toh(data_record->fw_device_pkg_data_length);
446
447 if (length < fw_device_id_record->record_length) {
448 return -EOVERFLOW;
449 }
450
451 uint16_t applicable_components_length =
452 component_bitmap_bit_length /
453 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
454 size_t calc_min_record_length =
455 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;
460
461 if (fw_device_id_record->record_length < calc_min_record_length) {
462 return -EOVERFLOW;
463 }
464
465 applicable_components->ptr =
466 data + sizeof(struct pldm_firmware_device_id_record);
467 applicable_components->length = applicable_components_length;
468
469 comp_image_set_version_str->ptr =
470 applicable_components->ptr + applicable_components->length;
471 comp_image_set_version_str->length =
472 fw_device_id_record->comp_image_set_version_string_length;
473
474 record_descriptors->ptr = comp_image_set_version_str->ptr +
475 comp_image_set_version_str->length;
476 record_descriptors->length =
477 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;
482
483 if (fw_device_id_record->fw_device_pkg_data_length) {
484 fw_device_pkg_data->ptr =
485 record_descriptors->ptr + record_descriptors->length;
486 fw_device_pkg_data->length =
487 fw_device_id_record->fw_device_pkg_data_length;
488 }
489
490 return 0;
491 }
492
493 LIBPLDM_ABI_STABLE
decode_firmware_device_id_record(const uint8_t * data,size_t length,uint16_t component_bitmap_bit_length,struct pldm_firmware_device_id_record * fw_device_id_record,struct variable_field * applicable_components,struct variable_field * comp_image_set_version_str,struct variable_field * record_descriptors,struct variable_field * fw_device_pkg_data)494 int 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
513 return PLDM_SUCCESS;
514 }
515
516 LIBPLDM_ABI_STABLE
decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter * iter,struct pldm_descriptor * desc)517 int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter,
518 struct pldm_descriptor *desc)
519 {
520 PLDM_MSGBUF_DEFINE_P(buf);
521 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) {
536 return pldm_msgbuf_discard(buf, rc);
537 }
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
546 return pldm_msgbuf_complete(buf);
547 }
548
decode_descriptor_type_length_value_errno(const uint8_t * data,size_t length,uint16_t * descriptor_type,struct variable_field * descriptor_data)549 static 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)
552 {
553 uint16_t descriptor_length = 0;
554
555 if (data == NULL || descriptor_type == NULL ||
556 descriptor_data == NULL) {
557 return -EINVAL;
558 }
559
560 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
561 return -EOVERFLOW;
562 }
563
564 struct pldm_descriptor_tlv *entry =
565 (struct pldm_descriptor_tlv *)(data);
566
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)) {
572 return -EBADMSG;
573 }
574 }
575
576 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
577 descriptor_length)) {
578 return -EOVERFLOW;
579 }
580
581 descriptor_data->ptr = entry->descriptor_data;
582 descriptor_data->length = descriptor_length;
583
584 return 0;
585 }
586
587 LIBPLDM_ABI_STABLE
decode_descriptor_type_length_value(const uint8_t * data,size_t length,uint16_t * descriptor_type,struct variable_field * descriptor_data)588 int 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
decode_vendor_defined_descriptor_value_errno(const uint8_t * data,size_t length,uint8_t * descriptor_title_str_type,struct variable_field * descriptor_title_str,struct variable_field * descriptor_data)603 static int decode_vendor_defined_descriptor_value_errno(
604 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)
607 {
608 if (data == NULL || descriptor_title_str_type == NULL ||
609 descriptor_title_str == NULL || descriptor_data == NULL) {
610 return -EINVAL;
611 }
612
613 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
614 return -EOVERFLOW;
615 }
616
617 struct pldm_vendor_defined_descriptor_title_data *entry =
618 (struct pldm_vendor_defined_descriptor_title_data *)(data);
619 if (!is_string_type_valid(
620 entry->vendor_defined_descriptor_title_str_type) ||
621 (entry->vendor_defined_descriptor_title_str_len == 0)) {
622 return -EBADMSG;
623 }
624
625 // Assuming at least 1 byte of VendorDefinedDescriptorData
626 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
627 entry->vendor_defined_descriptor_title_str_len)) {
628 return -EOVERFLOW;
629 }
630
631 *descriptor_title_str_type =
632 entry->vendor_defined_descriptor_title_str_type;
633 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
634 descriptor_title_str->length =
635 entry->vendor_defined_descriptor_title_str_len;
636
637 descriptor_data->ptr =
638 descriptor_title_str->ptr + descriptor_title_str->length;
639 descriptor_data->length =
640 length -
641 sizeof(entry->vendor_defined_descriptor_title_str_type) -
642 sizeof(entry->vendor_defined_descriptor_title_str_len) -
643 descriptor_title_str->length;
644
645 return 0;
646 }
647
648 LIBPLDM_ABI_STABLE
decode_vendor_defined_descriptor_value(const uint8_t * data,size_t length,uint8_t * descriptor_title_str_type,struct variable_field * descriptor_title_str,struct variable_field * descriptor_data)649 int 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
decode_pldm_comp_image_info_errno(const uint8_t * data,size_t length,struct pldm_component_image_information * pldm_comp_image_info,struct variable_field * comp_version_str)666 static int decode_pldm_comp_image_info_errno(
667 const uint8_t *data, size_t length,
668 struct pldm_component_image_information *pldm_comp_image_info,
669 struct variable_field *comp_version_str)
670 {
671 if (data == NULL || pldm_comp_image_info == NULL ||
672 comp_version_str == NULL) {
673 return -EINVAL;
674 }
675
676 if (length < sizeof(struct pldm_component_image_information)) {
677 return -EOVERFLOW;
678 }
679
680 struct pldm_component_image_information *data_header =
681 (struct pldm_component_image_information *)(data);
682
683 if (!is_string_type_valid(data_header->comp_version_string_type) ||
684 (data_header->comp_version_string_length == 0)) {
685 return -EBADMSG;
686 }
687
688 if (length < sizeof(struct pldm_component_image_information) +
689 data_header->comp_version_string_length) {
690 return -EOVERFLOW;
691 }
692
693 pldm_comp_image_info->comp_classification =
694 le16toh(data_header->comp_classification);
695 pldm_comp_image_info->comp_identifier =
696 le16toh(data_header->comp_identifier);
697 pldm_comp_image_info->comp_comparison_stamp =
698 le32toh(data_header->comp_comparison_stamp);
699 pldm_comp_image_info->comp_options.value =
700 le16toh(data_header->comp_options.value);
701 pldm_comp_image_info->requested_comp_activation_method.value =
702 le16toh(data_header->requested_comp_activation_method.value);
703 pldm_comp_image_info->comp_location_offset =
704 le32toh(data_header->comp_location_offset);
705 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
706 pldm_comp_image_info->comp_version_string_type =
707 data_header->comp_version_string_type;
708 pldm_comp_image_info->comp_version_string_length =
709 data_header->comp_version_string_length;
710
711 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
712 pldm_comp_image_info->comp_comparison_stamp !=
713 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
714 return -EBADMSG;
715 }
716
717 if (pldm_comp_image_info->comp_location_offset == 0 ||
718 pldm_comp_image_info->comp_size == 0) {
719 return -EBADMSG;
720 }
721
722 comp_version_str->ptr =
723 data + sizeof(struct pldm_component_image_information);
724 comp_version_str->length =
725 pldm_comp_image_info->comp_version_string_length;
726
727 return 0;
728 }
729
730 LIBPLDM_ABI_STABLE
decode_pldm_comp_image_info(const uint8_t * data,size_t length,struct pldm_component_image_information * pldm_comp_image_info,struct variable_field * comp_version_str)731 int 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
744 return PLDM_SUCCESS;
745 }
746
747 LIBPLDM_ABI_STABLE
encode_query_device_identifiers_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)748 int 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
764 LIBPLDM_ABI_STABLE
decode_query_device_identifiers_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint32_t * device_identifiers_len,uint8_t * descriptor_count,uint8_t ** descriptor_data)765 int 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 =
789 (struct pldm_query_device_identifiers_resp *)msg->payload;
790 *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) +
798 *device_identifiers_len) {
799 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 =
807 (uint8_t *)(msg->payload +
808 sizeof(struct pldm_query_device_identifiers_resp));
809 return PLDM_SUCCESS;
810 }
811
812 LIBPLDM_ABI_TESTING
encode_query_device_identifiers_resp(uint8_t instance_id,uint8_t descriptor_count,const struct pldm_descriptor * descriptors,struct pldm_msg * msg,size_t * payload_length)813 int 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 {
818 PLDM_MSGBUF_DEFINE_P(buf);
819 int rc;
820
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) {
857 return pldm_msgbuf_discard(buf, -EINVAL);
858 }
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) {
864 return pldm_msgbuf_discard(buf, rc);
865 }
866 }
867
868 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
869 }
870
871 LIBPLDM_ABI_STABLE
encode_get_firmware_parameters_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)872 int 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
888 LIBPLDM_ABI_STABLE
decode_get_firmware_parameters_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_get_firmware_parameters_resp * resp_data,struct variable_field * active_comp_image_set_ver_str,struct variable_field * pending_comp_image_set_ver_str,struct variable_field * comp_parameter_table)889 int decode_get_firmware_parameters_resp(
890 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)
895 {
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 =
913 (struct pldm_get_firmware_parameters_resp *)msg->payload;
914
915 if (!is_string_type_valid(
916 response->active_comp_image_set_ver_str_type) ||
917 (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(
928 response->pending_comp_image_set_ver_str_type)) {
929 return PLDM_ERROR_INVALID_DATA;
930 }
931 }
932
933 size_t partial_response_length =
934 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;
937
938 if (payload_length < partial_response_length) {
939 return PLDM_ERROR_INVALID_LENGTH;
940 }
941
942 resp_data->capabilities_during_update.value =
943 le32toh(response->capabilities_during_update.value);
944 resp_data->comp_count = le16toh(response->comp_count);
945 resp_data->active_comp_image_set_ver_str_type =
946 response->active_comp_image_set_ver_str_type;
947 resp_data->active_comp_image_set_ver_str_len =
948 response->active_comp_image_set_ver_str_len;
949 resp_data->pending_comp_image_set_ver_str_type =
950 response->pending_comp_image_set_ver_str_type;
951 resp_data->pending_comp_image_set_ver_str_len =
952 response->pending_comp_image_set_ver_str_len;
953
954 active_comp_image_set_ver_str->ptr =
955 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
956 active_comp_image_set_ver_str->length =
957 resp_data->active_comp_image_set_ver_str_len;
958
959 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
960 pending_comp_image_set_ver_str->ptr =
961 msg->payload +
962 sizeof(struct pldm_get_firmware_parameters_resp) +
963 resp_data->active_comp_image_set_ver_str_len;
964 pending_comp_image_set_ver_str->length =
965 resp_data->pending_comp_image_set_ver_str_len;
966 } 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 =
973 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;
977 comp_parameter_table->length =
978 payload_length - partial_response_length;
979 } else {
980 comp_parameter_table->ptr = NULL;
981 comp_parameter_table->length = 0;
982 }
983
984 return PLDM_SUCCESS;
985 }
986
987 LIBPLDM_ABI_TESTING
encode_get_firmware_parameters_resp(uint8_t instance_id,const struct pldm_get_firmware_parameters_resp_full * resp_data,struct pldm_msg * msg,size_t * payload_length)988 int 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 {
993 PLDM_MSGBUF_DEFINE_P(buf);
994 int rc;
995
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) {
1028 return pldm_msgbuf_discard(buf, rc);
1029 }
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) {
1035 return pldm_msgbuf_discard(buf, rc);
1036 }
1037
1038 /* Further calls to encode_get_firmware_parameters_resp_comp_entry
1039 * will populate the remainder */
1040
1041 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1042 }
1043
1044 LIBPLDM_ABI_TESTING
encode_get_firmware_parameters_resp_comp_entry(const struct pldm_component_parameter_entry_full * comp,uint8_t * payload,size_t * payload_length)1045 int 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 {
1049 PLDM_MSGBUF_DEFINE_P(buf);
1050 int rc;
1051
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) {
1072 return pldm_msgbuf_discard(buf, rc);
1073 }
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) {
1082 return pldm_msgbuf_discard(buf, rc);
1083 }
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) {
1092 return pldm_msgbuf_discard(buf, rc);
1093 }
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) {
1098 return pldm_msgbuf_discard(buf, rc);
1099 }
1100
1101 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1102 }
1103
1104 LIBPLDM_ABI_STABLE
decode_get_firmware_parameters_resp_comp_entry(const uint8_t * data,size_t length,struct pldm_component_parameter_entry * component_data,struct variable_field * active_comp_ver_str,struct variable_field * pending_comp_ver_str)1105 int decode_get_firmware_parameters_resp_comp_entry(
1106 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)
1110 {
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 =
1121 (struct pldm_component_parameter_entry *)(data);
1122
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 =
1132 le16toh(entry->comp_classification);
1133 component_data->comp_identifier = le16toh(entry->comp_identifier);
1134 component_data->comp_classification_index =
1135 entry->comp_classification_index;
1136 component_data->active_comp_comparison_stamp =
1137 le32toh(entry->active_comp_comparison_stamp);
1138 component_data->active_comp_ver_str_type =
1139 entry->active_comp_ver_str_type;
1140 component_data->active_comp_ver_str_len =
1141 entry->active_comp_ver_str_len;
1142 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 =
1146 le32toh(entry->pending_comp_comparison_stamp);
1147 component_data->pending_comp_ver_str_type =
1148 entry->pending_comp_ver_str_type;
1149 component_data->pending_comp_ver_str_len =
1150 entry->pending_comp_ver_str_len;
1151 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 =
1155 le16toh(entry->comp_activation_methods.value);
1156 component_data->capabilities_during_update.value =
1157 le32toh(entry->capabilities_during_update.value);
1158
1159 if (entry->active_comp_ver_str_len != 0) {
1160 active_comp_ver_str->ptr =
1161 data + sizeof(struct pldm_component_parameter_entry);
1162 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) {
1169 pending_comp_ver_str->ptr =
1170 data + sizeof(struct pldm_component_parameter_entry) +
1171 entry->active_comp_ver_str_len;
1172 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
1180 LIBPLDM_ABI_STABLE
encode_query_downstream_devices_req(uint8_t instance_id,struct pldm_msg * msg)1181 int encode_query_downstream_devices_req(uint8_t instance_id,
1182 struct pldm_msg *msg)
1183 {
1184 if (msg == NULL) {
1185 return -EINVAL;
1186 }
1187
1188 return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id,
1189 PLDM_FWUP,
1190 PLDM_QUERY_DOWNSTREAM_DEVICES,
1191 msg);
1192 }
1193
1194 LIBPLDM_ABI_STABLE
decode_query_downstream_devices_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_query_downstream_devices_resp * resp_data)1195 int 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 {
1199 PLDM_MSGBUF_DEFINE_P(buf);
1200 int rc;
1201
1202 if (msg == NULL || resp_data == NULL || !payload_length) {
1203 return -EINVAL;
1204 }
1205
1206 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1207 msg->payload, payload_length);
1208 if (rc) {
1209 return rc;
1210 }
1211
1212 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1213 if (rc) {
1214 return pldm_msgbuf_discard(buf, rc);
1215 }
1216 if (PLDM_SUCCESS != resp_data->completion_code) {
1217 // Return the CC directly without decoding the rest of the payload
1218 return pldm_msgbuf_complete(buf);
1219 }
1220
1221 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
1222 return pldm_msgbuf_discard(buf, -EBADMSG);
1223 }
1224
1225 rc = pldm_msgbuf_extract(buf,
1226 resp_data->downstream_device_update_supported);
1227 if (rc) {
1228 return pldm_msgbuf_discard(buf, rc);
1229 }
1230
1231 if (!is_downstream_device_update_support_valid(
1232 resp_data->downstream_device_update_supported)) {
1233 return pldm_msgbuf_discard(buf, -EINVAL);
1234 }
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
1240 return pldm_msgbuf_complete_consumed(buf);
1241 }
1242
1243 LIBPLDM_ABI_STABLE
encode_query_downstream_identifiers_req(uint8_t instance_id,const struct pldm_query_downstream_identifiers_req * params_req,struct pldm_msg * msg,size_t payload_length)1244 int encode_query_downstream_identifiers_req(
1245 uint8_t instance_id,
1246 const struct pldm_query_downstream_identifiers_req *params_req,
1247 struct pldm_msg *msg, size_t payload_length)
1248 {
1249 PLDM_MSGBUF_DEFINE_P(buf);
1250 int rc;
1251
1252 if (!msg || !params_req) {
1253 return -EINVAL;
1254 }
1255
1256 if (!is_transfer_operation_flag_valid(
1257 (enum transfer_op_flag)
1258 params_req->transfer_operation_flag)) {
1259 return -EINVAL;
1260 }
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;
1267 rc = pack_pldm_header_errno(&header, &(msg->hdr));
1268 if (rc) {
1269 return rc;
1270 }
1271
1272 rc = pldm_msgbuf_init_errno(buf,
1273 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
1274 msg->payload, payload_length);
1275 if (rc) {
1276 return rc;
1277 }
1278
1279 pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
1280 // Data correctness has been verified, cast it to 1-byte data directly.
1281 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
1282
1283 return pldm_msgbuf_complete(buf);
1284 }
1285
1286 LIBPLDM_ABI_STABLE
decode_query_downstream_identifiers_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_query_downstream_identifiers_resp * resp_data,struct pldm_downstream_device_iter * iter)1287 int decode_query_downstream_identifiers_resp(
1288 const struct pldm_msg *msg, size_t payload_length,
1289 struct pldm_query_downstream_identifiers_resp *resp_data,
1290 struct pldm_downstream_device_iter *iter)
1291 {
1292 PLDM_MSGBUF_DEFINE_P(buf);
1293 void *remaining = NULL;
1294 int rc = 0;
1295
1296 if (msg == NULL || resp_data == NULL || iter == NULL ||
1297 !payload_length) {
1298 return -EINVAL;
1299 }
1300
1301 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1302 msg->payload, payload_length);
1303 if (rc) {
1304 return rc;
1305 }
1306
1307 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1308 if (rc) {
1309 return pldm_msgbuf_discard(buf, rc);
1310 }
1311 if (PLDM_SUCCESS != resp_data->completion_code) {
1312 return pldm_msgbuf_complete(buf);
1313 }
1314
1315 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
1316 return pldm_msgbuf_discard(buf, -EBADMSG);
1317 }
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) {
1324 return pldm_msgbuf_discard(buf, rc);
1325 }
1326
1327 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1328 pldm_msgbuf_span_required(buf, resp_data->downstream_devices_length,
1329 &remaining);
1330
1331 rc = pldm_msgbuf_complete(buf);
1332 if (rc) {
1333 return rc;
1334 }
1335
1336 iter->field.ptr = remaining;
1337 iter->field.length = resp_data->downstream_devices_length;
1338 iter->devs = resp_data->number_of_downstream_devices;
1339
1340 return 0;
1341 }
1342
1343 LIBPLDM_ABI_STABLE
decode_pldm_downstream_device_from_iter(struct pldm_downstream_device_iter * iter,struct pldm_downstream_device * dev)1344 int decode_pldm_downstream_device_from_iter(
1345 struct pldm_downstream_device_iter *iter,
1346 struct pldm_downstream_device *dev)
1347 {
1348 PLDM_MSGBUF_DEFINE_P(buf);
1349 int rc;
1350
1351 if (!iter || !iter->field.ptr || !dev) {
1352 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);
1363 pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr,
1364 &iter->field.length);
1365
1366 return pldm_msgbuf_complete(buf);
1367 }
1368
1369 LIBPLDM_ABI_STABLE
encode_get_downstream_firmware_parameters_req(uint8_t instance_id,const struct pldm_get_downstream_firmware_parameters_req * params_req,struct pldm_msg * msg,size_t payload_length)1370 int encode_get_downstream_firmware_parameters_req(
1371 uint8_t instance_id,
1372 const struct pldm_get_downstream_firmware_parameters_req *params_req,
1373 struct pldm_msg *msg, size_t payload_length)
1374 {
1375 PLDM_MSGBUF_DEFINE_P(buf);
1376 int rc;
1377
1378 if (!msg || !params_req) {
1379 return -EINVAL;
1380 }
1381
1382 if (!is_transfer_operation_flag_valid(
1383 (enum transfer_op_flag)
1384 params_req->transfer_operation_flag)) {
1385 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
1398 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
1405 pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
1406 // Data correctness has been verified, cast it to 1-byte data directly.
1407 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
1408
1409 return pldm_msgbuf_complete(buf);
1410 }
1411
1412 LIBPLDM_ABI_STABLE
decode_get_downstream_firmware_parameters_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_get_downstream_firmware_parameters_resp * resp_data,struct pldm_downstream_device_parameters_iter * iter)1413 int decode_get_downstream_firmware_parameters_resp(
1414 const struct pldm_msg *msg, size_t payload_length,
1415 struct pldm_get_downstream_firmware_parameters_resp *resp_data,
1416 struct pldm_downstream_device_parameters_iter *iter)
1417 {
1418 PLDM_MSGBUF_DEFINE_P(buf);
1419 void *remaining = NULL;
1420 size_t length;
1421 int rc;
1422
1423 if (msg == NULL || resp_data == NULL || iter == NULL) {
1424 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) {
1435 return pldm_msgbuf_discard(buf, rc);
1436 }
1437 if (PLDM_SUCCESS != resp_data->completion_code) {
1438 return pldm_msgbuf_complete(buf);
1439 }
1440
1441 if (payload_length <
1442 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) {
1443 return pldm_msgbuf_discard(buf, -EBADMSG);
1444 }
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
1452 rc = pldm_msgbuf_span_remaining(buf, &remaining, &length);
1453 if (rc) {
1454 return pldm_msgbuf_discard(buf, rc);
1455 }
1456
1457 rc = pldm_msgbuf_complete(buf);
1458 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;
1467 }
1468
1469 LIBPLDM_ABI_STABLE
decode_pldm_downstream_device_parameters_entry_from_iter(struct pldm_downstream_device_parameters_iter * iter,struct pldm_downstream_device_parameters_entry * entry)1470 int decode_pldm_downstream_device_parameters_entry_from_iter(
1471 struct pldm_downstream_device_parameters_iter *iter,
1472 struct pldm_downstream_device_parameters_entry *entry)
1473 {
1474 PLDM_MSGBUF_DEFINE_P(buf);
1475 void *comp_ver_str;
1476 size_t remaining;
1477 void *cursor;
1478 int rc;
1479
1480 if (iter == NULL || iter->field.ptr == NULL || entry == NULL) {
1481 return -EINVAL;
1482 }
1483
1484 rc = pldm_msgbuf_init_errno(
1485 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN,
1486 iter->field.ptr, iter->field.length);
1487 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) {
1496 return pldm_msgbuf_discard(buf, rc);
1497 }
1498 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) {
1503 return pldm_msgbuf_discard(buf, rc);
1504 }
1505
1506 // 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) {
1514 return pldm_msgbuf_discard(buf, rc);
1515 }
1516
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) {
1522 return pldm_msgbuf_discard(buf, rc);
1523 }
1524
1525 // 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);
1531
1532 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 }
1537 entry->active_comp_ver_str = comp_ver_str;
1538
1539 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 }
1544 entry->pending_comp_ver_str = comp_ver_str;
1545
1546 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1547 if (rc < 0) {
1548 return pldm_msgbuf_discard(buf, rc);
1549 }
1550
1551 iter->field.ptr = cursor;
1552 iter->field.length = remaining;
1553
1554 return pldm_msgbuf_complete(buf);
1555 }
1556
1557 LIBPLDM_ABI_STABLE
encode_request_update_req(uint8_t instance_id,uint32_t max_transfer_size,uint16_t num_of_comp,uint8_t max_outstanding_transfer_req,uint16_t pkg_data_len,uint8_t comp_image_set_ver_str_type,uint8_t comp_image_set_ver_str_len,const struct variable_field * comp_img_set_ver_str,struct pldm_msg * msg,size_t payload_length)1558 int 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) +
1573 comp_img_set_ver_str->length) {
1574 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
1591 struct pldm_header_info header = { 0 };
1592 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 =
1602 (struct pldm_request_update_req *)msg->payload;
1603
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
1617 LIBPLDM_ABI_TESTING
decode_request_update_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_request_update_req_full * req)1618 int 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;
1623 PLDM_MSGBUF_DEFINE_P(buf);
1624
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) {
1640 return pldm_msgbuf_discard(buf, rc);
1641 }
1642 if (t > PLDM_STR_TYPE_UTF_16BE) {
1643 return pldm_msgbuf_discard(buf, -EBADMSG);
1644 }
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) {
1648 return pldm_msgbuf_discard(buf, rc);
1649 }
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) {
1655 return pldm_msgbuf_discard(buf, rc);
1656 }
1657
1658 return pldm_msgbuf_complete_consumed(buf);
1659 }
1660
1661 LIBPLDM_ABI_STABLE
decode_request_update_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint16_t * fd_meta_data_len,uint8_t * fd_will_send_pkg_data)1662 int 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 =
1683 (struct pldm_request_update_resp *)msg->payload;
1684
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
1691 LIBPLDM_ABI_TESTING
encode_request_update_resp(uint8_t instance_id,const struct pldm_request_update_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)1692 int 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 {
1696 PLDM_MSGBUF_DEFINE_P(buf);
1697 int rc;
1698
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
1725 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1726 }
1727
1728 LIBPLDM_ABI_STABLE
encode_pass_component_table_req(uint8_t instance_id,uint8_t transfer_flag,uint16_t comp_classification,uint16_t comp_identifier,uint8_t comp_classification_index,uint32_t comp_comparison_stamp,uint8_t comp_ver_str_type,uint8_t comp_ver_str_len,const struct variable_field * comp_ver_str,struct pldm_msg * msg,size_t payload_length)1729 int 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)
1738 {
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) +
1744 comp_ver_str->length) {
1745 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
1761 struct pldm_header_info header = { 0 };
1762 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 =
1772 (struct pldm_pass_component_table_req *)msg->payload;
1773
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
1788 LIBPLDM_ABI_TESTING
decode_pass_component_table_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_pass_component_table_req_full * pcomp)1789 int 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;
1795 PLDM_MSGBUF_DEFINE_P(buf);
1796
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) {
1813 return pldm_msgbuf_discard(buf, rc);
1814 }
1815 if (t > PLDM_STR_TYPE_UTF_16BE) {
1816 return pldm_msgbuf_discard(buf, -EBADMSG);
1817 }
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) {
1821 return pldm_msgbuf_discard(buf, rc);
1822 }
1823 rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len,
1824 pcomp->version.str_data,
1825 PLDM_FIRMWARE_MAX_STRING);
1826 if (rc) {
1827 return pldm_msgbuf_discard(buf, rc);
1828 }
1829
1830 return pldm_msgbuf_complete_consumed(buf);
1831 }
1832
1833 LIBPLDM_ABI_STABLE
decode_pass_component_table_resp(const struct pldm_msg * msg,const size_t payload_length,uint8_t * completion_code,uint8_t * comp_resp,uint8_t * comp_resp_code)1834 int 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 =
1855 (struct pldm_pass_component_table_resp *)msg->payload;
1856
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
1871 LIBPLDM_ABI_TESTING
encode_pass_component_table_resp(uint8_t instance_id,const struct pldm_pass_component_table_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)1872 int 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 {
1877 PLDM_MSGBUF_DEFINE_P(buf);
1878 int rc;
1879
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
1899 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1900 }
1901
1902 LIBPLDM_ABI_STABLE
encode_update_component_req(uint8_t instance_id,uint16_t comp_classification,uint16_t comp_identifier,uint8_t comp_classification_index,uint32_t comp_comparison_stamp,uint32_t comp_image_size,bitfield32_t update_option_flags,uint8_t comp_ver_str_type,uint8_t comp_ver_str_len,const struct variable_field * comp_ver_str,struct pldm_msg * msg,size_t payload_length)1903 int encode_update_component_req(
1904 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)
1910 {
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
1933 struct pldm_header_info header = { 0 };
1934 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 =
1944 (struct pldm_update_component_req *)msg->payload;
1945
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
1961 LIBPLDM_ABI_TESTING
decode_update_component_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_update_component_req_full * up)1962 int 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;
1968 PLDM_MSGBUF_DEFINE_P(buf);
1969
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) {
1987 return pldm_msgbuf_discard(buf, rc);
1988 }
1989 if (t > PLDM_STR_TYPE_UTF_16BE) {
1990 return pldm_msgbuf_discard(buf, -EBADMSG);
1991 }
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) {
1995 return pldm_msgbuf_discard(buf, rc);
1996 }
1997 rc = pldm_msgbuf_extract_array(buf, up->version.str_len,
1998 up->version.str_data,
1999 PLDM_FIRMWARE_MAX_STRING);
2000 if (rc) {
2001 return pldm_msgbuf_discard(buf, rc);
2002 }
2003
2004 return pldm_msgbuf_complete_consumed(buf);
2005 }
2006
2007 LIBPLDM_ABI_STABLE
decode_update_component_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * comp_compatibility_resp,uint8_t * comp_compatibility_resp_code,bitfield32_t * update_option_flags_enabled,uint16_t * time_before_req_fw_data)2008 int 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 =
2034 (struct pldm_update_component_resp *)msg->payload;
2035
2036 if (!is_comp_compatibility_resp_valid(
2037 response->comp_compatibility_resp)) {
2038 return PLDM_ERROR_INVALID_DATA;
2039 }
2040
2041 if (!is_comp_compatibility_resp_code_valid(
2042 response->comp_compatibility_resp_code)) {
2043 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 =
2049 le32toh(response->update_option_flags_enabled.value);
2050 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
2051
2052 return PLDM_SUCCESS;
2053 }
2054
2055 LIBPLDM_ABI_TESTING
encode_update_component_resp(uint8_t instance_id,const struct pldm_update_component_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)2056 int 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 {
2060 PLDM_MSGBUF_DEFINE_P(buf);
2061 int rc;
2062
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
2084 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2085 }
2086
2087 LIBPLDM_ABI_STABLE
decode_request_firmware_data_req(const struct pldm_msg * msg,size_t payload_length,uint32_t * offset,uint32_t * length)2088 int 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 =
2099 (struct pldm_request_firmware_data_req *)msg->payload;
2100 *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
2110 LIBPLDM_ABI_TESTING
encode_request_firmware_data_req(uint8_t instance_id,const struct pldm_request_firmware_data_req * req_params,struct pldm_msg * msg,size_t * payload_length)2111 int 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 {
2116 PLDM_MSGBUF_DEFINE_P(buf);
2117 int rc;
2118
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
2137 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2138 }
2139
2140 LIBPLDM_ABI_STABLE
encode_request_firmware_data_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2141 int 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
2150 struct pldm_header_info header = { 0 };
2151 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
2165 LIBPLDM_ABI_STABLE
decode_transfer_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * transfer_result)2166 int 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
2182 LIBPLDM_ABI_TESTING
encode_transfer_complete_req(uint8_t instance_id,uint8_t transfer_result,struct pldm_msg * msg,size_t * payload_length)2183 int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
2184 struct pldm_msg *msg, size_t *payload_length)
2185 {
2186 PLDM_MSGBUF_DEFINE_P(buf);
2187 int rc;
2188
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
2204 pldm_msgbuf_insert(buf, transfer_result);
2205
2206 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2207 }
2208
2209 LIBPLDM_ABI_STABLE
encode_transfer_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2210 int 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
2221 struct pldm_header_info header = { 0 };
2222 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
2236 LIBPLDM_ABI_STABLE
decode_verify_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * verify_result)2237 int 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
2252 LIBPLDM_ABI_TESTING
encode_verify_complete_req(uint8_t instance_id,uint8_t verify_result,struct pldm_msg * msg,size_t * payload_length)2253 int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
2254 struct pldm_msg *msg, size_t *payload_length)
2255 {
2256 PLDM_MSGBUF_DEFINE_P(buf);
2257 int rc;
2258
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
2274 pldm_msgbuf_insert(buf, verify_result);
2275
2276 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2277 }
2278
2279 LIBPLDM_ABI_STABLE
encode_verify_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2280 int 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
2291 struct pldm_header_info header = { 0 };
2292 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
2306 LIBPLDM_ABI_STABLE
decode_apply_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * apply_result,bitfield16_t * comp_activation_methods_modification)2307 int 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)
2310 {
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 =
2321 (struct pldm_apply_complete_req *)msg->payload;
2322
2323 *apply_result = request->apply_result;
2324 comp_activation_methods_modification->value =
2325 le16toh(request->comp_activation_methods_modification.value);
2326
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
2335 LIBPLDM_ABI_TESTING
encode_apply_complete_req(uint8_t instance_id,const struct pldm_apply_complete_req * req_data,struct pldm_msg * msg,size_t * payload_length)2336 int 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 {
2340 PLDM_MSGBUF_DEFINE_P(buf);
2341 int rc;
2342
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
2362 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2363 }
2364
2365 LIBPLDM_ABI_STABLE
encode_apply_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2366 int 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
2377 struct pldm_header_info header = { 0 };
2378 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
2392 LIBPLDM_ABI_TESTING
decode_activate_firmware_req(const struct pldm_msg * msg,size_t payload_length,bool * self_contained)2393 int decode_activate_firmware_req(const struct pldm_msg *msg,
2394 size_t payload_length, bool *self_contained)
2395 {
2396 uint8_t self_contained_u8 = 0;
2397 PLDM_MSGBUF_DEFINE_P(buf);
2398 int rc;
2399
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
2409 pldm_msgbuf_extract(buf, self_contained_u8);
2410
2411 rc = pldm_msgbuf_complete_consumed(buf);
2412 if (rc) {
2413 return rc;
2414 }
2415
2416 *self_contained = (bool)self_contained_u8;
2417 return 0;
2418 }
2419
2420 LIBPLDM_ABI_STABLE
encode_activate_firmware_req(uint8_t instance_id,bool8_t self_contained_activation_req,struct pldm_msg * msg,size_t payload_length)2421 int 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(
2434 self_contained_activation_req)) {
2435 return PLDM_ERROR_INVALID_DATA;
2436 }
2437
2438 struct pldm_header_info header = { 0 };
2439 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 =
2449 (struct pldm_activate_firmware_req *)msg->payload;
2450
2451 request->self_contained_activation_req = self_contained_activation_req;
2452
2453 return PLDM_SUCCESS;
2454 }
2455
2456 LIBPLDM_ABI_STABLE
decode_activate_firmware_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint16_t * estimated_time_activation)2457 int 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 =
2477 (struct pldm_activate_firmware_resp *)msg->payload;
2478
2479 *estimated_time_activation =
2480 le16toh(response->estimated_time_activation);
2481
2482 return PLDM_SUCCESS;
2483 }
2484
2485 LIBPLDM_ABI_TESTING
encode_activate_firmware_resp(uint8_t instance_id,const struct pldm_activate_firmware_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)2486 int 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 {
2491 PLDM_MSGBUF_DEFINE_P(buf);
2492 int rc;
2493
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
2512 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2513 }
2514
2515 LIBPLDM_ABI_STABLE
encode_get_status_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)2516 int 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
2527 struct pldm_header_info header = { 0 };
2528 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
2540 LIBPLDM_ABI_STABLE
decode_get_status_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * current_state,uint8_t * previous_state,uint8_t * aux_state,uint8_t * aux_state_status,uint8_t * progress_percent,uint8_t * reason_code,bitfield32_t * update_option_flags_enabled)2541 int 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 =
2565 (struct pldm_get_status_resp *)msg->payload;
2566
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 =
2602 le32toh(response->update_option_flags_enabled.value);
2603
2604 return PLDM_SUCCESS;
2605 }
2606
2607 LIBPLDM_ABI_TESTING
encode_get_status_resp(uint8_t instance_id,const struct pldm_get_status_resp * status,struct pldm_msg * msg,size_t * payload_length)2608 int 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 {
2612 PLDM_MSGBUF_DEFINE_P(buf);
2613 int rc;
2614
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
2643 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2644 }
2645
2646 LIBPLDM_ABI_STABLE
encode_cancel_update_component_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)2647 int 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
2659 struct pldm_header_info header = { 0 };
2660 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
2672 LIBPLDM_ABI_STABLE
decode_cancel_update_component_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code)2673 int 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
2689 LIBPLDM_ABI_STABLE
encode_cancel_update_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)2690 int 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
2701 struct pldm_header_info header = { 0 };
2702 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
2714 LIBPLDM_ABI_STABLE
decode_cancel_update_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,bool8_t * non_functioning_component_indication,bitfield64_t * non_functioning_component_bitmap)2715 int 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 =
2735 (struct pldm_cancel_update_resp *)msg->payload;
2736
2737 if (!is_non_functioning_component_indication_valid(
2738 response->non_functioning_component_indication)) {
2739 return PLDM_ERROR_INVALID_DATA;
2740 }
2741
2742 *non_functioning_component_indication =
2743 response->non_functioning_component_indication;
2744
2745 if (*non_functioning_component_indication) {
2746 non_functioning_component_bitmap->value =
2747 le64toh(response->non_functioning_component_bitmap);
2748 }
2749
2750 return PLDM_SUCCESS;
2751 }
2752
2753 LIBPLDM_ABI_TESTING
encode_cancel_update_resp(uint8_t instance_id,const struct pldm_cancel_update_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)2754 int 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 {
2758 PLDM_MSGBUF_DEFINE_P(buf);
2759 int rc;
2760
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
2781 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2782 }
2783