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 /** @brief Check whether string type value is valid
13 *
14 * @return true if string type value is valid, false if not
15 */
is_string_type_valid(uint8_t string_type)16 static bool is_string_type_valid(uint8_t string_type)
17 {
18 switch (string_type) {
19 case PLDM_STR_TYPE_UNKNOWN:
20 return false;
21 case PLDM_STR_TYPE_ASCII:
22 case PLDM_STR_TYPE_UTF_8:
23 case PLDM_STR_TYPE_UTF_16:
24 case PLDM_STR_TYPE_UTF_16LE:
25 case PLDM_STR_TYPE_UTF_16BE:
26 return true;
27 default:
28 return false;
29 }
30 }
31
32 /** @brief Return the length of the descriptor type described in firmware update
33 * specification
34 *
35 * @return length of the descriptor type if descriptor type is valid else
36 * return 0
37 */
get_descriptor_type_length(uint16_t descriptor_type)38 static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
39 {
40 switch (descriptor_type) {
41 case PLDM_FWUP_PCI_VENDOR_ID:
42 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
43 case PLDM_FWUP_IANA_ENTERPRISE_ID:
44 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
45 case PLDM_FWUP_UUID:
46 return PLDM_FWUP_UUID_LENGTH;
47 case PLDM_FWUP_PNP_VENDOR_ID:
48 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
49 case PLDM_FWUP_ACPI_VENDOR_ID:
50 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
51 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
52 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
53 case PLDM_FWUP_SCSI_VENDOR_ID:
54 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
55 case PLDM_FWUP_PCI_DEVICE_ID:
56 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
57 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
58 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
59 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
60 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
61 case PLDM_FWUP_PCI_REVISION_ID:
62 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
63 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
64 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
65 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
66 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
67 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
68 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
69 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
70 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
71 case PLDM_FWUP_SCSI_PRODUCT_ID:
72 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
73 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
74 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
75 default:
76 return 0;
77 }
78 }
79
is_downstream_device_update_support_valid(uint8_t resp)80 static bool is_downstream_device_update_support_valid(uint8_t resp)
81 {
82 switch (resp) {
83 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
84 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
85 return true;
86 default:
87 return false;
88 }
89 }
90
91 static bool
is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)92 is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)
93 {
94 switch (transfer_op_flag) {
95 case PLDM_GET_NEXTPART:
96 case PLDM_GET_FIRSTPART:
97 return true;
98 default:
99 return false;
100 }
101 }
102
103 /** @brief Check whether ComponentResponse is valid
104 *
105 * @return true if ComponentResponse is valid, false if not
106 */
is_comp_resp_valid(uint8_t comp_resp)107 static bool is_comp_resp_valid(uint8_t comp_resp)
108 {
109 switch (comp_resp) {
110 case PLDM_CR_COMP_CAN_BE_UPDATED:
111 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
112 return true;
113
114 default:
115 return false;
116 }
117 }
118
119 /** @brief Check whether ComponentResponseCode is valid
120 *
121 * @return true if ComponentResponseCode is valid, false if not
122 */
is_comp_resp_code_valid(uint8_t comp_resp_code)123 static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
124 {
125 switch (comp_resp_code) {
126 case PLDM_CRC_COMP_CAN_BE_UPDATED:
127 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
128 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
129 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
130 case PLDM_CRC_COMP_CONFLICT:
131 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
132 case PLDM_CRC_COMP_NOT_SUPPORTED:
133 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
134 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
135 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
136 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
137 case PLDM_CRC_COMP_VER_STR_LOWER:
138 return true;
139
140 default:
141 if (comp_resp_code >=
142 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
143 comp_resp_code <=
144 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
145 return true;
146 }
147 return false;
148 }
149 }
150
151 /** @brief Check whether ComponentCompatibilityResponse is valid
152 *
153 * @return true if ComponentCompatibilityResponse is valid, false if not
154 */
is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)155 static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
156 {
157 switch (comp_compatibility_resp) {
158 case PLDM_CCR_COMP_CAN_BE_UPDATED:
159 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
160 return true;
161
162 default:
163 return false;
164 }
165 }
166
167 /** @brief Check whether ComponentCompatibilityResponse Code is valid
168 *
169 * @return true if ComponentCompatibilityResponse Code is valid, false if not
170 */
171 static bool
is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)172 is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
173 {
174 switch (comp_compatibility_resp_code) {
175 case PLDM_CCRC_NO_RESPONSE_CODE:
176 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
177 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
178 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
179 case PLDM_CCRC_COMP_CONFLICT:
180 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
181 case PLDM_CCRC_COMP_NOT_SUPPORTED:
182 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
183 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
184 case PLDM_CCRC_COMP_INFO_NO_MATCH:
185 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
186 case PLDM_CCRC_COMP_VER_STR_LOWER:
187 return true;
188
189 default:
190 if (comp_compatibility_resp_code >=
191 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
192 comp_compatibility_resp_code <=
193 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
194 return true;
195 }
196 return false;
197 }
198 }
199
200 /** @brief Check whether SelfContainedActivationRequest is valid
201 *
202 * @return true if SelfContainedActivationRequest is valid, false if not
203 */
204 static bool
is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)205 is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
206 {
207 switch (self_contained_activation_req) {
208 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
209 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
210 return true;
211
212 default:
213 return false;
214 }
215 }
216
217 /** @brief Check if current or previous status in GetStatus command response is
218 * valid
219 *
220 * @param[in] state - current or previous different state machine state of
221 * the FD
222 * @return true if state is valid, false if not
223 */
is_state_valid(uint8_t state)224 static bool is_state_valid(uint8_t state)
225 {
226 switch (state) {
227 case PLDM_FD_STATE_IDLE:
228 case PLDM_FD_STATE_LEARN_COMPONENTS:
229 case PLDM_FD_STATE_READY_XFER:
230 case PLDM_FD_STATE_DOWNLOAD:
231 case PLDM_FD_STATE_VERIFY:
232 case PLDM_FD_STATE_APPLY:
233 case PLDM_FD_STATE_ACTIVATE:
234 return true;
235
236 default:
237 return false;
238 }
239 }
240
241 /** @brief Check if aux state in GetStatus command response is valid
242 *
243 * @param[in] aux_state - provides additional information to the UA to describe
244 * the current operation state of the FD/FDP
245 *
246 * @return true if aux state is valid, false if not
247 */
is_aux_state_valid(uint8_t aux_state)248 static bool is_aux_state_valid(uint8_t aux_state)
249 {
250 switch (aux_state) {
251 case PLDM_FD_OPERATION_IN_PROGRESS:
252 case PLDM_FD_OPERATION_SUCCESSFUL:
253 case PLDM_FD_OPERATION_FAILED:
254 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
255 return true;
256
257 default:
258 return false;
259 }
260 }
261
262 /** @brief Check if aux state status in GetStatus command response is valid
263 *
264 * @param[in] aux_state_status - aux state status
265 *
266 * @return true if aux state status is valid, false if not
267 */
is_aux_state_status_valid(uint8_t aux_state_status)268 static bool is_aux_state_status_valid(uint8_t aux_state_status)
269 {
270 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
271 aux_state_status == PLDM_FD_TIMEOUT ||
272 aux_state_status == PLDM_FD_GENERIC_ERROR ||
273 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
274 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
275 return true;
276 }
277
278 return false;
279 }
280
281 /** @brief Check if reason code in GetStatus command response is valid
282 *
283 * @param[in] reason_code - provides the reason for why the current state
284 * entered the IDLE state
285 *
286 * @return true if reason code is valid, false if not
287 */
is_reason_code_valid(uint8_t reason_code)288 static bool is_reason_code_valid(uint8_t reason_code)
289 {
290 switch (reason_code) {
291 case PLDM_FD_INITIALIZATION:
292 case PLDM_FD_ACTIVATE_FW:
293 case PLDM_FD_CANCEL_UPDATE:
294 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
295 case PLDM_FD_TIMEOUT_READY_XFER:
296 case PLDM_FD_TIMEOUT_DOWNLOAD:
297 case PLDM_FD_TIMEOUT_VERIFY:
298 case PLDM_FD_TIMEOUT_APPLY:
299 return true;
300
301 default:
302 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
303 return true;
304 }
305 return false;
306 }
307 }
308
309 /** @brief Check if non functioning component indication in CancelUpdate
310 * response is valid
311 *
312 * @return true if non functioning component indication is valid, false if not
313 */
is_non_functioning_component_indication_valid(bool8_t non_functioning_component_indication)314 static bool is_non_functioning_component_indication_valid(
315 bool8_t non_functioning_component_indication)
316 {
317 switch (non_functioning_component_indication) {
318 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
319 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
320 return true;
321
322 default:
323 return false;
324 }
325 }
326
327 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)328 int decode_pldm_package_header_info(
329 const uint8_t *data, size_t length,
330 struct pldm_package_header_information *package_header_info,
331 struct variable_field *package_version_str)
332 {
333 if (data == NULL || package_header_info == NULL ||
334 package_version_str == NULL) {
335 return PLDM_ERROR_INVALID_DATA;
336 }
337
338 if (length < sizeof(struct pldm_package_header_information)) {
339 return PLDM_ERROR_INVALID_LENGTH;
340 }
341
342 struct pldm_package_header_information *data_header =
343 (struct pldm_package_header_information *)(data);
344
345 if (!is_string_type_valid(data_header->package_version_string_type) ||
346 (data_header->package_version_string_length == 0)) {
347 return PLDM_ERROR_INVALID_DATA;
348 }
349
350 if (length < sizeof(struct pldm_package_header_information) +
351 data_header->package_version_string_length) {
352 return PLDM_ERROR_INVALID_LENGTH;
353 }
354
355 if ((data_header->component_bitmap_bit_length %
356 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
357 return PLDM_ERROR_INVALID_DATA;
358 }
359
360 memcpy(package_header_info->uuid, data_header->uuid,
361 sizeof(data_header->uuid));
362 package_header_info->package_header_format_version =
363 data_header->package_header_format_version;
364 package_header_info->package_header_size =
365 le16toh(data_header->package_header_size);
366 memcpy(package_header_info->package_release_date_time,
367 data_header->package_release_date_time,
368 sizeof(data_header->package_release_date_time));
369 package_header_info->component_bitmap_bit_length =
370 le16toh(data_header->component_bitmap_bit_length);
371 package_header_info->package_version_string_type =
372 data_header->package_version_string_type;
373 package_header_info->package_version_string_length =
374 data_header->package_version_string_length;
375 package_version_str->ptr =
376 data + sizeof(struct pldm_package_header_information);
377 package_version_str->length =
378 package_header_info->package_version_string_length;
379
380 return PLDM_SUCCESS;
381 }
382
383 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)384 int decode_firmware_device_id_record(
385 const uint8_t *data, size_t length,
386 uint16_t component_bitmap_bit_length,
387 struct pldm_firmware_device_id_record *fw_device_id_record,
388 struct variable_field *applicable_components,
389 struct variable_field *comp_image_set_version_str,
390 struct variable_field *record_descriptors,
391 struct variable_field *fw_device_pkg_data)
392 {
393 if (data == NULL || fw_device_id_record == NULL ||
394 applicable_components == NULL ||
395 comp_image_set_version_str == NULL || record_descriptors == NULL ||
396 fw_device_pkg_data == NULL) {
397 return PLDM_ERROR_INVALID_DATA;
398 }
399
400 if (length < sizeof(struct pldm_firmware_device_id_record)) {
401 return PLDM_ERROR_INVALID_LENGTH;
402 }
403
404 if ((component_bitmap_bit_length %
405 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
406 return PLDM_ERROR_INVALID_DATA;
407 }
408
409 struct pldm_firmware_device_id_record *data_record =
410 (struct pldm_firmware_device_id_record *)(data);
411
412 if (!is_string_type_valid(
413 data_record->comp_image_set_version_string_type) ||
414 (data_record->comp_image_set_version_string_length == 0)) {
415 return PLDM_ERROR_INVALID_DATA;
416 }
417
418 fw_device_id_record->record_length =
419 le16toh(data_record->record_length);
420 fw_device_id_record->descriptor_count = data_record->descriptor_count;
421 fw_device_id_record->device_update_option_flags.value =
422 le32toh(data_record->device_update_option_flags.value);
423 fw_device_id_record->comp_image_set_version_string_type =
424 data_record->comp_image_set_version_string_type;
425 fw_device_id_record->comp_image_set_version_string_length =
426 data_record->comp_image_set_version_string_length;
427 fw_device_id_record->fw_device_pkg_data_length =
428 le16toh(data_record->fw_device_pkg_data_length);
429
430 if (length < fw_device_id_record->record_length) {
431 return PLDM_ERROR_INVALID_LENGTH;
432 }
433
434 uint16_t applicable_components_length =
435 component_bitmap_bit_length /
436 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
437 uint16_t calc_min_record_length =
438 sizeof(struct pldm_firmware_device_id_record) +
439 applicable_components_length +
440 data_record->comp_image_set_version_string_length +
441 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
442 fw_device_id_record->fw_device_pkg_data_length;
443
444 if (fw_device_id_record->record_length < calc_min_record_length) {
445 return PLDM_ERROR_INVALID_LENGTH;
446 }
447
448 applicable_components->ptr =
449 data + sizeof(struct pldm_firmware_device_id_record);
450 applicable_components->length = applicable_components_length;
451
452 comp_image_set_version_str->ptr =
453 applicable_components->ptr + applicable_components->length;
454 comp_image_set_version_str->length =
455 fw_device_id_record->comp_image_set_version_string_length;
456
457 record_descriptors->ptr = comp_image_set_version_str->ptr +
458 comp_image_set_version_str->length;
459 record_descriptors->length =
460 fw_device_id_record->record_length -
461 sizeof(struct pldm_firmware_device_id_record) -
462 applicable_components_length -
463 fw_device_id_record->comp_image_set_version_string_length -
464 fw_device_id_record->fw_device_pkg_data_length;
465
466 if (fw_device_id_record->fw_device_pkg_data_length) {
467 fw_device_pkg_data->ptr =
468 record_descriptors->ptr + record_descriptors->length;
469 fw_device_pkg_data->length =
470 fw_device_id_record->fw_device_pkg_data_length;
471 }
472
473 return PLDM_SUCCESS;
474 }
475
476 LIBPLDM_ABI_TESTING
decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter * iter,struct pldm_descriptor * desc)477 int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter,
478 struct pldm_descriptor *desc)
479 {
480 struct pldm_msgbuf _buf;
481 struct pldm_msgbuf *buf = &_buf;
482 int rc;
483
484 if (!iter || !iter->field || !desc) {
485 return -EINVAL;
486 }
487
488 rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN,
489 iter->field->ptr, iter->field->length);
490 if (rc) {
491 return rc;
492 }
493
494 pldm_msgbuf_extract(buf, desc->descriptor_type);
495 rc = pldm_msgbuf_extract(buf, desc->descriptor_length);
496 if (rc) {
497 return rc;
498 }
499
500 desc->descriptor_data = NULL;
501 pldm_msgbuf_span_required(buf, desc->descriptor_length,
502 (void **)&desc->descriptor_data);
503 iter->field->ptr = NULL;
504 pldm_msgbuf_span_remaining(buf, (void **)&iter->field->ptr,
505 &iter->field->length);
506
507 return pldm_msgbuf_destroy(buf);
508 }
509
510 LIBPLDM_ABI_STABLE
decode_descriptor_type_length_value(const uint8_t * data,size_t length,uint16_t * descriptor_type,struct variable_field * descriptor_data)511 int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
512 uint16_t *descriptor_type,
513 struct variable_field *descriptor_data)
514 {
515 uint16_t descriptor_length = 0;
516
517 if (data == NULL || descriptor_type == NULL ||
518 descriptor_data == NULL) {
519 return PLDM_ERROR_INVALID_DATA;
520 }
521
522 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
523 return PLDM_ERROR_INVALID_LENGTH;
524 }
525
526 struct pldm_descriptor_tlv *entry =
527 (struct pldm_descriptor_tlv *)(data);
528
529 *descriptor_type = le16toh(entry->descriptor_type);
530 descriptor_length = le16toh(entry->descriptor_length);
531 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
532 if (descriptor_length !=
533 get_descriptor_type_length(*descriptor_type)) {
534 return PLDM_ERROR_INVALID_LENGTH;
535 }
536 }
537
538 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
539 descriptor_length)) {
540 return PLDM_ERROR_INVALID_LENGTH;
541 }
542
543 descriptor_data->ptr = entry->descriptor_data;
544 descriptor_data->length = descriptor_length;
545
546 return PLDM_SUCCESS;
547 }
548
549 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)550 int decode_vendor_defined_descriptor_value(
551 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
552 struct variable_field *descriptor_title_str,
553 struct variable_field *descriptor_data)
554 {
555 if (data == NULL || descriptor_title_str_type == NULL ||
556 descriptor_title_str == NULL || descriptor_data == NULL) {
557 return PLDM_ERROR_INVALID_DATA;
558 }
559
560 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
561 return PLDM_ERROR_INVALID_LENGTH;
562 }
563
564 struct pldm_vendor_defined_descriptor_title_data *entry =
565 (struct pldm_vendor_defined_descriptor_title_data *)(data);
566 if (!is_string_type_valid(
567 entry->vendor_defined_descriptor_title_str_type) ||
568 (entry->vendor_defined_descriptor_title_str_len == 0)) {
569 return PLDM_ERROR_INVALID_DATA;
570 }
571
572 // Assuming at least 1 byte of VendorDefinedDescriptorData
573 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
574 entry->vendor_defined_descriptor_title_str_len)) {
575 return PLDM_ERROR_INVALID_LENGTH;
576 }
577
578 *descriptor_title_str_type =
579 entry->vendor_defined_descriptor_title_str_type;
580 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
581 descriptor_title_str->length =
582 entry->vendor_defined_descriptor_title_str_len;
583
584 descriptor_data->ptr =
585 descriptor_title_str->ptr + descriptor_title_str->length;
586 descriptor_data->length =
587 length -
588 sizeof(entry->vendor_defined_descriptor_title_str_type) -
589 sizeof(entry->vendor_defined_descriptor_title_str_len) -
590 descriptor_title_str->length;
591
592 return PLDM_SUCCESS;
593 }
594
595 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)596 int decode_pldm_comp_image_info(
597 const uint8_t *data, size_t length,
598 struct pldm_component_image_information *pldm_comp_image_info,
599 struct variable_field *comp_version_str)
600 {
601 if (data == NULL || pldm_comp_image_info == NULL ||
602 comp_version_str == NULL) {
603 return PLDM_ERROR_INVALID_DATA;
604 }
605
606 if (length < sizeof(struct pldm_component_image_information)) {
607 return PLDM_ERROR_INVALID_LENGTH;
608 }
609
610 struct pldm_component_image_information *data_header =
611 (struct pldm_component_image_information *)(data);
612
613 if (!is_string_type_valid(data_header->comp_version_string_type) ||
614 (data_header->comp_version_string_length == 0)) {
615 return PLDM_ERROR_INVALID_DATA;
616 }
617
618 if (length < sizeof(struct pldm_component_image_information) +
619 data_header->comp_version_string_length) {
620 return PLDM_ERROR_INVALID_LENGTH;
621 }
622
623 pldm_comp_image_info->comp_classification =
624 le16toh(data_header->comp_classification);
625 pldm_comp_image_info->comp_identifier =
626 le16toh(data_header->comp_identifier);
627 pldm_comp_image_info->comp_comparison_stamp =
628 le32toh(data_header->comp_comparison_stamp);
629 pldm_comp_image_info->comp_options.value =
630 le16toh(data_header->comp_options.value);
631 pldm_comp_image_info->requested_comp_activation_method.value =
632 le16toh(data_header->requested_comp_activation_method.value);
633 pldm_comp_image_info->comp_location_offset =
634 le32toh(data_header->comp_location_offset);
635 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
636 pldm_comp_image_info->comp_version_string_type =
637 data_header->comp_version_string_type;
638 pldm_comp_image_info->comp_version_string_length =
639 data_header->comp_version_string_length;
640
641 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
642 pldm_comp_image_info->comp_comparison_stamp !=
643 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
644 return PLDM_ERROR_INVALID_DATA;
645 }
646
647 if (pldm_comp_image_info->comp_location_offset == 0 ||
648 pldm_comp_image_info->comp_size == 0) {
649 return PLDM_ERROR_INVALID_DATA;
650 }
651
652 comp_version_str->ptr =
653 data + sizeof(struct pldm_component_image_information);
654 comp_version_str->length =
655 pldm_comp_image_info->comp_version_string_length;
656
657 return PLDM_SUCCESS;
658 }
659
660 LIBPLDM_ABI_STABLE
encode_query_device_identifiers_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)661 int encode_query_device_identifiers_req(uint8_t instance_id,
662 size_t payload_length,
663 struct pldm_msg *msg)
664 {
665 if (msg == NULL) {
666 return PLDM_ERROR_INVALID_DATA;
667 }
668
669 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
670 return PLDM_ERROR_INVALID_LENGTH;
671 }
672
673 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
674 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
675 }
676
677 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)678 int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
679 size_t payload_length,
680 uint8_t *completion_code,
681 uint32_t *device_identifiers_len,
682 uint8_t *descriptor_count,
683 uint8_t **descriptor_data)
684 {
685 if (msg == NULL || completion_code == NULL ||
686 device_identifiers_len == NULL || descriptor_count == NULL ||
687 descriptor_data == NULL) {
688 return PLDM_ERROR_INVALID_DATA;
689 }
690
691 *completion_code = msg->payload[0];
692 if (PLDM_SUCCESS != *completion_code) {
693 return PLDM_SUCCESS;
694 }
695
696 if (payload_length <
697 sizeof(struct pldm_query_device_identifiers_resp)) {
698 return PLDM_ERROR_INVALID_LENGTH;
699 }
700
701 struct pldm_query_device_identifiers_resp *response =
702 (struct pldm_query_device_identifiers_resp *)msg->payload;
703 *device_identifiers_len = le32toh(response->device_identifiers_len);
704
705 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
706 return PLDM_ERROR_INVALID_LENGTH;
707 }
708
709 if (payload_length !=
710 sizeof(struct pldm_query_device_identifiers_resp) +
711 *device_identifiers_len) {
712 return PLDM_ERROR_INVALID_LENGTH;
713 }
714 *descriptor_count = response->descriptor_count;
715
716 if (*descriptor_count == 0) {
717 return PLDM_ERROR_INVALID_DATA;
718 }
719 *descriptor_data =
720 (uint8_t *)(msg->payload +
721 sizeof(struct pldm_query_device_identifiers_resp));
722 return PLDM_SUCCESS;
723 }
724
725 LIBPLDM_ABI_STABLE
encode_get_firmware_parameters_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)726 int encode_get_firmware_parameters_req(uint8_t instance_id,
727 size_t payload_length,
728 struct pldm_msg *msg)
729 {
730 if (msg == NULL) {
731 return PLDM_ERROR_INVALID_DATA;
732 }
733
734 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
735 return PLDM_ERROR_INVALID_LENGTH;
736 }
737
738 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
739 PLDM_GET_FIRMWARE_PARAMETERS, msg);
740 }
741
742 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)743 int decode_get_firmware_parameters_resp(
744 const struct pldm_msg *msg, size_t payload_length,
745 struct pldm_get_firmware_parameters_resp *resp_data,
746 struct variable_field *active_comp_image_set_ver_str,
747 struct variable_field *pending_comp_image_set_ver_str,
748 struct variable_field *comp_parameter_table)
749 {
750 if (msg == NULL || resp_data == NULL ||
751 active_comp_image_set_ver_str == NULL ||
752 pending_comp_image_set_ver_str == NULL ||
753 comp_parameter_table == NULL || !payload_length) {
754 return PLDM_ERROR_INVALID_DATA;
755 }
756
757 resp_data->completion_code = msg->payload[0];
758 if (PLDM_SUCCESS != resp_data->completion_code) {
759 return PLDM_SUCCESS;
760 }
761
762 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
763 return PLDM_ERROR_INVALID_LENGTH;
764 }
765
766 struct pldm_get_firmware_parameters_resp *response =
767 (struct pldm_get_firmware_parameters_resp *)msg->payload;
768
769 if (!is_string_type_valid(
770 response->active_comp_image_set_ver_str_type) ||
771 (response->active_comp_image_set_ver_str_len == 0)) {
772 return PLDM_ERROR_INVALID_DATA;
773 }
774
775 if (response->pending_comp_image_set_ver_str_len == 0) {
776 if (response->pending_comp_image_set_ver_str_type !=
777 PLDM_STR_TYPE_UNKNOWN) {
778 return PLDM_ERROR_INVALID_DATA;
779 }
780 } else {
781 if (!is_string_type_valid(
782 response->pending_comp_image_set_ver_str_type)) {
783 return PLDM_ERROR_INVALID_DATA;
784 }
785 }
786
787 size_t partial_response_length =
788 sizeof(struct pldm_get_firmware_parameters_resp) +
789 response->active_comp_image_set_ver_str_len +
790 response->pending_comp_image_set_ver_str_len;
791
792 if (payload_length < partial_response_length) {
793 return PLDM_ERROR_INVALID_LENGTH;
794 }
795
796 resp_data->capabilities_during_update.value =
797 le32toh(response->capabilities_during_update.value);
798 resp_data->comp_count = le16toh(response->comp_count);
799 resp_data->active_comp_image_set_ver_str_type =
800 response->active_comp_image_set_ver_str_type;
801 resp_data->active_comp_image_set_ver_str_len =
802 response->active_comp_image_set_ver_str_len;
803 resp_data->pending_comp_image_set_ver_str_type =
804 response->pending_comp_image_set_ver_str_type;
805 resp_data->pending_comp_image_set_ver_str_len =
806 response->pending_comp_image_set_ver_str_len;
807
808 active_comp_image_set_ver_str->ptr =
809 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
810 active_comp_image_set_ver_str->length =
811 resp_data->active_comp_image_set_ver_str_len;
812
813 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
814 pending_comp_image_set_ver_str->ptr =
815 msg->payload +
816 sizeof(struct pldm_get_firmware_parameters_resp) +
817 resp_data->active_comp_image_set_ver_str_len;
818 pending_comp_image_set_ver_str->length =
819 resp_data->pending_comp_image_set_ver_str_len;
820 } else {
821 pending_comp_image_set_ver_str->ptr = NULL;
822 pending_comp_image_set_ver_str->length = 0;
823 }
824
825 if (payload_length > partial_response_length && resp_data->comp_count) {
826 comp_parameter_table->ptr =
827 msg->payload +
828 sizeof(struct pldm_get_firmware_parameters_resp) +
829 resp_data->active_comp_image_set_ver_str_len +
830 resp_data->pending_comp_image_set_ver_str_len;
831 comp_parameter_table->length =
832 payload_length - partial_response_length;
833 } else {
834 comp_parameter_table->ptr = NULL;
835 comp_parameter_table->length = 0;
836 }
837
838 return PLDM_SUCCESS;
839 }
840
841 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)842 int decode_get_firmware_parameters_resp_comp_entry(
843 const uint8_t *data, size_t length,
844 struct pldm_component_parameter_entry *component_data,
845 struct variable_field *active_comp_ver_str,
846 struct variable_field *pending_comp_ver_str)
847 {
848 if (data == NULL || component_data == NULL ||
849 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
850 return PLDM_ERROR_INVALID_DATA;
851 }
852
853 if (length < sizeof(struct pldm_component_parameter_entry)) {
854 return PLDM_ERROR_INVALID_LENGTH;
855 }
856
857 struct pldm_component_parameter_entry *entry =
858 (struct pldm_component_parameter_entry *)(data);
859
860 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
861 entry->active_comp_ver_str_len +
862 entry->pending_comp_ver_str_len;
863
864 if (length < entry_length) {
865 return PLDM_ERROR_INVALID_LENGTH;
866 }
867
868 component_data->comp_classification =
869 le16toh(entry->comp_classification);
870 component_data->comp_identifier = le16toh(entry->comp_identifier);
871 component_data->comp_classification_index =
872 entry->comp_classification_index;
873 component_data->active_comp_comparison_stamp =
874 le32toh(entry->active_comp_comparison_stamp);
875 component_data->active_comp_ver_str_type =
876 entry->active_comp_ver_str_type;
877 component_data->active_comp_ver_str_len =
878 entry->active_comp_ver_str_len;
879 memcpy(component_data->active_comp_release_date,
880 entry->active_comp_release_date,
881 sizeof(entry->active_comp_release_date));
882 component_data->pending_comp_comparison_stamp =
883 le32toh(entry->pending_comp_comparison_stamp);
884 component_data->pending_comp_ver_str_type =
885 entry->pending_comp_ver_str_type;
886 component_data->pending_comp_ver_str_len =
887 entry->pending_comp_ver_str_len;
888 memcpy(component_data->pending_comp_release_date,
889 entry->pending_comp_release_date,
890 sizeof(entry->pending_comp_release_date));
891 component_data->comp_activation_methods.value =
892 le16toh(entry->comp_activation_methods.value);
893 component_data->capabilities_during_update.value =
894 le32toh(entry->capabilities_during_update.value);
895
896 if (entry->active_comp_ver_str_len != 0) {
897 active_comp_ver_str->ptr =
898 data + sizeof(struct pldm_component_parameter_entry);
899 active_comp_ver_str->length = entry->active_comp_ver_str_len;
900 } else {
901 active_comp_ver_str->ptr = NULL;
902 active_comp_ver_str->length = 0;
903 }
904
905 if (entry->pending_comp_ver_str_len != 0) {
906 pending_comp_ver_str->ptr =
907 data + sizeof(struct pldm_component_parameter_entry) +
908 entry->active_comp_ver_str_len;
909 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
910 } else {
911 pending_comp_ver_str->ptr = NULL;
912 pending_comp_ver_str->length = 0;
913 }
914 return PLDM_SUCCESS;
915 }
916
917 LIBPLDM_ABI_TESTING
encode_query_downstream_devices_req(uint8_t instance_id,struct pldm_msg * msg)918 int encode_query_downstream_devices_req(uint8_t instance_id,
919 struct pldm_msg *msg)
920 {
921 if (msg == NULL) {
922 return PLDM_ERROR_INVALID_DATA;
923 }
924
925 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
926 PLDM_QUERY_DOWNSTREAM_DEVICES, msg);
927 }
928
929 LIBPLDM_ABI_TESTING
decode_query_downstream_devices_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_query_downstream_devices_resp * resp_data)930 int decode_query_downstream_devices_resp(
931 const struct pldm_msg *msg, size_t payload_length,
932 struct pldm_query_downstream_devices_resp *resp_data)
933 {
934 struct pldm_msgbuf _buf;
935 struct pldm_msgbuf *buf = &_buf;
936 int rc;
937
938 if (msg == NULL || resp_data == NULL || !payload_length) {
939 return PLDM_ERROR_INVALID_DATA;
940 }
941
942 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
943 msg->payload, payload_length);
944 if (rc) {
945 return rc;
946 }
947
948 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
949 if (rc) {
950 return pldm_xlate_errno(rc);
951 }
952 if (PLDM_SUCCESS != resp_data->completion_code) {
953 // Return the CC directly without decoding the rest of the payload
954 return PLDM_SUCCESS;
955 }
956
957 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
958 return PLDM_ERROR_INVALID_LENGTH;
959 }
960
961 rc = pldm_msgbuf_extract(buf,
962 resp_data->downstream_device_update_supported);
963 if (rc) {
964 return pldm_xlate_errno(rc);
965 }
966
967 if (!is_downstream_device_update_support_valid(
968 resp_data->downstream_device_update_supported)) {
969 return PLDM_ERROR_INVALID_DATA;
970 }
971
972 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
973 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
974 pldm_msgbuf_extract(buf, resp_data->capabilities.value);
975
976 rc = pldm_msgbuf_destroy_consumed(buf);
977 if (rc) {
978 pldm_xlate_errno(rc);
979 }
980
981 return PLDM_SUCCESS;
982 }
983
984 LIBPLDM_ABI_TESTING
encode_query_downstream_identifiers_req(uint8_t instance_id,uint32_t data_transfer_handle,enum transfer_op_flag transfer_operation_flag,struct pldm_msg * msg,size_t payload_length)985 int encode_query_downstream_identifiers_req(
986 uint8_t instance_id, uint32_t data_transfer_handle,
987 enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg,
988 size_t payload_length)
989 {
990 struct pldm_msgbuf _buf;
991 struct pldm_msgbuf *buf = &_buf;
992 int rc;
993
994 if (msg == NULL) {
995 return PLDM_ERROR_INVALID_DATA;
996 }
997
998 if (!is_transfer_operation_flag_valid(transfer_operation_flag)) {
999 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1000 }
1001
1002 struct pldm_header_info header = { 0 };
1003 header.instance = instance_id;
1004 header.msg_type = PLDM_REQUEST;
1005 header.pldm_type = PLDM_FWUP;
1006 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
1007 rc = pack_pldm_header(&header, &(msg->hdr));
1008 if (rc) {
1009 return rc;
1010 }
1011
1012 rc = pldm_msgbuf_init_errno(buf,
1013 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
1014 msg->payload, payload_length);
1015 if (rc) {
1016 return pldm_xlate_errno(rc);
1017 }
1018
1019 pldm_msgbuf_insert(buf, data_transfer_handle);
1020 // Data correctness has been verified, cast it to 1-byte data directly.
1021 pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag);
1022
1023 rc = pldm_msgbuf_destroy(buf);
1024 if (rc) {
1025 return pldm_xlate_errno(rc);
1026 }
1027
1028 return PLDM_SUCCESS;
1029 }
1030
1031 LIBPLDM_ABI_TESTING
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)1032 int decode_query_downstream_identifiers_resp(
1033 const struct pldm_msg *msg, size_t payload_length,
1034 struct pldm_query_downstream_identifiers_resp *resp_data,
1035 struct pldm_downstream_device_iter *iter)
1036 {
1037 struct pldm_msgbuf _buf;
1038 struct pldm_msgbuf *buf = &_buf;
1039 void *remaining = NULL;
1040 int rc = PLDM_ERROR;
1041
1042 if (msg == NULL || resp_data == NULL || iter == NULL ||
1043 !payload_length) {
1044 return PLDM_ERROR_INVALID_DATA;
1045 }
1046
1047 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1048 msg->payload, payload_length);
1049 if (rc) {
1050 return pldm_xlate_errno(rc);
1051 }
1052
1053 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1054 if (rc) {
1055 return pldm_xlate_errno(rc);
1056 }
1057 if (PLDM_SUCCESS != resp_data->completion_code) {
1058 return PLDM_SUCCESS;
1059 }
1060
1061 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
1062 return PLDM_ERROR_INVALID_LENGTH;
1063 }
1064
1065 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1066 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1067
1068 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
1069 if (rc) {
1070 return pldm_xlate_errno(rc);
1071 }
1072
1073 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1074 rc = pldm_msgbuf_span_required(
1075 buf, resp_data->downstream_devices_length, &remaining);
1076 if (rc) {
1077 return pldm_xlate_errno(rc);
1078 }
1079
1080 rc = pldm_msgbuf_destroy(buf);
1081 if (rc) {
1082 return pldm_xlate_errno(rc);
1083 }
1084
1085 iter->field.ptr = remaining;
1086 iter->field.length = resp_data->downstream_devices_length;
1087 iter->devs = resp_data->number_of_downstream_devices;
1088
1089 return PLDM_SUCCESS;
1090 }
1091
1092 LIBPLDM_ABI_TESTING
decode_pldm_downstream_device_from_iter(struct pldm_downstream_device_iter * iter,struct pldm_downstream_device * dev)1093 int decode_pldm_downstream_device_from_iter(
1094 struct pldm_downstream_device_iter *iter,
1095 struct pldm_downstream_device *dev)
1096 {
1097 struct pldm_msgbuf _buf;
1098 struct pldm_msgbuf *buf = &_buf;
1099 int rc;
1100
1101 if (!iter || !dev) {
1102 return -EINVAL;
1103 }
1104
1105 rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr,
1106 iter->field.length);
1107 if (rc) {
1108 return rc;
1109 }
1110
1111 pldm_msgbuf_extract(buf, dev->downstream_device_index);
1112 pldm_msgbuf_extract(buf, dev->downstream_descriptor_count);
1113 iter->field.ptr = NULL;
1114 pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr,
1115 &iter->field.length);
1116
1117 return pldm_msgbuf_destroy(buf);
1118 }
1119
1120 LIBPLDM_ABI_TESTING
encode_get_downstream_firmware_params_req(uint8_t instance_id,uint32_t data_transfer_handle,enum transfer_op_flag transfer_operation_flag,struct pldm_msg * msg,size_t payload_length)1121 int encode_get_downstream_firmware_params_req(
1122 uint8_t instance_id, uint32_t data_transfer_handle,
1123 enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg,
1124 size_t payload_length)
1125 {
1126 struct pldm_msgbuf _buf;
1127 struct pldm_msgbuf *buf = &_buf;
1128 int rc;
1129
1130 if (msg == NULL) {
1131 return -EINVAL;
1132 }
1133
1134 rc = pldm_msgbuf_init_errno(
1135 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_REQ_BYTES,
1136 msg->payload, payload_length);
1137 if (rc < 0) {
1138 return rc;
1139 }
1140
1141 if (!is_transfer_operation_flag_valid(transfer_operation_flag)) {
1142 return -EBADMSG;
1143 }
1144
1145 struct pldm_header_info header = { 0 };
1146 header.instance = instance_id;
1147 header.msg_type = PLDM_REQUEST;
1148 header.pldm_type = PLDM_FWUP;
1149 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1150 rc = pack_pldm_header_errno(&header, &msg->hdr);
1151 if (rc < 0) {
1152 return rc;
1153 }
1154
1155 pldm_msgbuf_insert(buf, data_transfer_handle);
1156 // Data correctness has been verified, cast it to 1-byte data directly.
1157 pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag);
1158
1159 return pldm_msgbuf_destroy(buf);
1160 }
1161
1162 LIBPLDM_ABI_TESTING
decode_get_downstream_firmware_params_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_get_downstream_firmware_params_resp * resp_data,struct variable_field * downstream_device_param_table)1163 int decode_get_downstream_firmware_params_resp(
1164 const struct pldm_msg *msg, size_t payload_length,
1165 struct pldm_get_downstream_firmware_params_resp *resp_data,
1166 struct variable_field *downstream_device_param_table)
1167 {
1168 struct pldm_msgbuf _buf;
1169 struct pldm_msgbuf *buf = &_buf;
1170 int rc;
1171
1172 if (msg == NULL || resp_data == NULL ||
1173 downstream_device_param_table == NULL) {
1174 return -EINVAL;
1175 }
1176
1177 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1178 msg->payload, payload_length);
1179 if (rc < 0) {
1180 return rc;
1181 }
1182
1183 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1184 if (rc < 0) {
1185 return rc;
1186 }
1187 if (PLDM_SUCCESS != resp_data->completion_code) {
1188 return 0;
1189 }
1190
1191 if (payload_length < PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_RESP_MIN_LEN) {
1192 return -EBADMSG;
1193 }
1194
1195 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1196 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1197 pldm_msgbuf_extract(buf,
1198 resp_data->fdp_capabilities_during_update.value);
1199 pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1200
1201 return pldm_msgbuf_span_remaining(
1202 buf, (void **)&downstream_device_param_table->ptr,
1203 &downstream_device_param_table->length);
1204 }
1205
1206 LIBPLDM_ABI_TESTING
decode_downstream_device_parameter_table_entry(struct variable_field * data,struct pldm_downstream_device_parameter_entry * entry,struct variable_field * versions)1207 int decode_downstream_device_parameter_table_entry(
1208 struct variable_field *data,
1209 struct pldm_downstream_device_parameter_entry *entry,
1210 struct variable_field *versions)
1211 {
1212 struct pldm_msgbuf _buf;
1213 struct pldm_msgbuf *buf = &_buf;
1214 void *cursor = NULL;
1215 size_t remaining;
1216 int rc;
1217
1218 if (data == NULL || entry == NULL || versions == NULL) {
1219 return -EINVAL;
1220 }
1221
1222 rc = pldm_msgbuf_init_errno(
1223 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETER_ENTRY_MIN_LEN, data->ptr,
1224 data->length);
1225 if (rc < 0) {
1226 return rc;
1227 }
1228
1229 pldm_msgbuf_extract(buf, entry->downstream_device_index);
1230 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1231 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1232 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1233 if (rc < 0) {
1234 return rc;
1235 }
1236 rc = pldm_msgbuf_extract_array(buf,
1237 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1238 entry->active_comp_release_date,
1239 sizeof(entry->active_comp_release_date));
1240 if (rc < 0) {
1241 return rc;
1242 }
1243
1244 // Fill the last byte with NULL character
1245 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1246 '\0';
1247
1248 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1249 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1250 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1251 if (rc < 0) {
1252 return rc;
1253 }
1254
1255 rc = pldm_msgbuf_extract_array(
1256 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1257 entry->pending_comp_release_date,
1258 sizeof(entry->pending_comp_release_date));
1259 if (rc < 0) {
1260 return rc;
1261 }
1262
1263 // Fill the last byte with NULL character
1264 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1265 '\0';
1266
1267 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1268 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
1269 const size_t versions_len = entry->active_comp_ver_str_len +
1270 entry->pending_comp_ver_str_len;
1271 rc = pldm_msgbuf_span_required(buf, versions_len,
1272 (void **)&versions->ptr);
1273 if (rc < 0) {
1274 return rc;
1275 }
1276 versions->length = versions_len;
1277
1278 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1279 if (rc < 0) {
1280 return rc;
1281 }
1282
1283 data->ptr = cursor;
1284 data->length = remaining;
1285
1286 return 0;
1287 }
1288
1289 LIBPLDM_ABI_TESTING
decode_downstream_device_parameter_table_entry_versions(const struct variable_field * versions,struct pldm_downstream_device_parameter_entry * entry,char * active,size_t active_len,char * pending,size_t pending_len)1290 int decode_downstream_device_parameter_table_entry_versions(
1291 const struct variable_field *versions,
1292 struct pldm_downstream_device_parameter_entry *entry, char *active,
1293 size_t active_len, char *pending, size_t pending_len)
1294 {
1295 struct pldm_msgbuf _buf;
1296 struct pldm_msgbuf *buf = &_buf;
1297 int rc;
1298
1299 if (versions == NULL || versions->ptr == NULL || !versions->length ||
1300 entry == NULL || active == NULL || pending == NULL) {
1301 return -EINVAL;
1302 }
1303
1304 if (!active_len || active_len - 1 < entry->active_comp_ver_str_len) {
1305 return -EOVERFLOW;
1306 }
1307
1308 if (!pending_len || pending_len - 1 < entry->pending_comp_ver_str_len) {
1309 return -EOVERFLOW;
1310 }
1311
1312 /* This API should be called after decode_downstream_device_parameter_table_entry
1313 * has successfully decoded the entry, assume the entry data is valid here.
1314 */
1315 const size_t versions_len = entry->active_comp_ver_str_len +
1316 entry->pending_comp_ver_str_len;
1317 rc = pldm_msgbuf_init_errno(buf, versions_len, versions->ptr,
1318 versions->length);
1319 if (rc < 0) {
1320 return rc;
1321 }
1322
1323 rc = pldm_msgbuf_extract_array(buf, entry->active_comp_ver_str_len,
1324 active, active_len);
1325 if (rc < 0) {
1326 return rc;
1327 }
1328
1329 active[entry->active_comp_ver_str_len] = '\0';
1330 rc = pldm_msgbuf_extract_array(buf, entry->pending_comp_ver_str_len,
1331 pending, pending_len);
1332 if (rc < 0) {
1333 return rc;
1334 }
1335
1336 pending[entry->pending_comp_ver_str_len] = '\0';
1337
1338 entry->active_comp_ver_str = active;
1339 entry->pending_comp_ver_str = pending;
1340
1341 return pldm_msgbuf_destroy_consumed(buf);
1342 }
1343
1344 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)1345 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1346 uint16_t num_of_comp,
1347 uint8_t max_outstanding_transfer_req,
1348 uint16_t pkg_data_len,
1349 uint8_t comp_image_set_ver_str_type,
1350 uint8_t comp_image_set_ver_str_len,
1351 const struct variable_field *comp_img_set_ver_str,
1352 struct pldm_msg *msg, size_t payload_length)
1353 {
1354 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
1355 msg == NULL) {
1356 return PLDM_ERROR_INVALID_DATA;
1357 }
1358
1359 if (payload_length != sizeof(struct pldm_request_update_req) +
1360 comp_img_set_ver_str->length) {
1361 return PLDM_ERROR_INVALID_LENGTH;
1362 }
1363
1364 if ((comp_image_set_ver_str_len == 0) ||
1365 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
1366 return PLDM_ERROR_INVALID_DATA;
1367 }
1368
1369 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
1370 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
1371 return PLDM_ERROR_INVALID_DATA;
1372 }
1373
1374 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
1375 return PLDM_ERROR_INVALID_DATA;
1376 }
1377
1378 struct pldm_header_info header = { 0 };
1379 header.instance = instance_id;
1380 header.msg_type = PLDM_REQUEST;
1381 header.pldm_type = PLDM_FWUP;
1382 header.command = PLDM_REQUEST_UPDATE;
1383 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1384 if (rc) {
1385 return rc;
1386 }
1387
1388 struct pldm_request_update_req *request =
1389 (struct pldm_request_update_req *)msg->payload;
1390
1391 request->max_transfer_size = htole32(max_transfer_size);
1392 request->num_of_comp = htole16(num_of_comp);
1393 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
1394 request->pkg_data_len = htole16(pkg_data_len);
1395 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
1396 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
1397
1398 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
1399 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
1400
1401 return PLDM_SUCCESS;
1402 }
1403
1404 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)1405 int decode_request_update_resp(const struct pldm_msg *msg,
1406 size_t payload_length, uint8_t *completion_code,
1407 uint16_t *fd_meta_data_len,
1408 uint8_t *fd_will_send_pkg_data)
1409 {
1410 if (msg == NULL || completion_code == NULL ||
1411 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
1412 !payload_length) {
1413 return PLDM_ERROR_INVALID_DATA;
1414 }
1415
1416 *completion_code = msg->payload[0];
1417 if (*completion_code != PLDM_SUCCESS) {
1418 return PLDM_SUCCESS;
1419 }
1420
1421 if (payload_length != sizeof(struct pldm_request_update_resp)) {
1422 return PLDM_ERROR_INVALID_LENGTH;
1423 }
1424
1425 struct pldm_request_update_resp *response =
1426 (struct pldm_request_update_resp *)msg->payload;
1427
1428 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
1429 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1430
1431 return PLDM_SUCCESS;
1432 }
1433
1434 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)1435 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1436 uint16_t comp_classification,
1437 uint16_t comp_identifier,
1438 uint8_t comp_classification_index,
1439 uint32_t comp_comparison_stamp,
1440 uint8_t comp_ver_str_type,
1441 uint8_t comp_ver_str_len,
1442 const struct variable_field *comp_ver_str,
1443 struct pldm_msg *msg, size_t payload_length)
1444 {
1445 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1446 return PLDM_ERROR_INVALID_DATA;
1447 }
1448
1449 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
1450 comp_ver_str->length) {
1451 return PLDM_ERROR_INVALID_LENGTH;
1452 }
1453
1454 if ((comp_ver_str_len == 0) ||
1455 (comp_ver_str_len != comp_ver_str->length)) {
1456 return PLDM_ERROR_INVALID_DATA;
1457 }
1458
1459 if (!is_transfer_flag_valid(transfer_flag)) {
1460 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1461 }
1462
1463 if (!is_string_type_valid(comp_ver_str_type)) {
1464 return PLDM_ERROR_INVALID_DATA;
1465 }
1466
1467 struct pldm_header_info header = { 0 };
1468 header.instance = instance_id;
1469 header.msg_type = PLDM_REQUEST;
1470 header.pldm_type = PLDM_FWUP;
1471 header.command = PLDM_PASS_COMPONENT_TABLE;
1472 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1473 if (rc) {
1474 return rc;
1475 }
1476
1477 struct pldm_pass_component_table_req *request =
1478 (struct pldm_pass_component_table_req *)msg->payload;
1479
1480 request->transfer_flag = transfer_flag;
1481 request->comp_classification = htole16(comp_classification);
1482 request->comp_identifier = htole16(comp_identifier);
1483 request->comp_classification_index = comp_classification_index;
1484 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1485 request->comp_ver_str_type = comp_ver_str_type;
1486 request->comp_ver_str_len = comp_ver_str_len;
1487
1488 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1489 comp_ver_str->ptr, comp_ver_str->length);
1490
1491 return PLDM_SUCCESS;
1492 }
1493
1494 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)1495 int decode_pass_component_table_resp(const struct pldm_msg *msg,
1496 const size_t payload_length,
1497 uint8_t *completion_code,
1498 uint8_t *comp_resp,
1499 uint8_t *comp_resp_code)
1500 {
1501 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1502 comp_resp_code == NULL || !payload_length) {
1503 return PLDM_ERROR_INVALID_DATA;
1504 }
1505
1506 *completion_code = msg->payload[0];
1507 if (*completion_code != PLDM_SUCCESS) {
1508 return PLDM_SUCCESS;
1509 }
1510
1511 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1512 return PLDM_ERROR_INVALID_LENGTH;
1513 }
1514
1515 struct pldm_pass_component_table_resp *response =
1516 (struct pldm_pass_component_table_resp *)msg->payload;
1517
1518 if (!is_comp_resp_valid(response->comp_resp)) {
1519 return PLDM_ERROR_INVALID_DATA;
1520 }
1521
1522 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1523 return PLDM_ERROR_INVALID_DATA;
1524 }
1525
1526 *comp_resp = response->comp_resp;
1527 *comp_resp_code = response->comp_resp_code;
1528
1529 return PLDM_SUCCESS;
1530 }
1531
1532 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)1533 int encode_update_component_req(
1534 uint8_t instance_id, uint16_t comp_classification,
1535 uint16_t comp_identifier, uint8_t comp_classification_index,
1536 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1537 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1538 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1539 struct pldm_msg *msg, size_t payload_length)
1540 {
1541 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1542 return PLDM_ERROR_INVALID_DATA;
1543 }
1544
1545 if (payload_length !=
1546 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1547 return PLDM_ERROR_INVALID_LENGTH;
1548 }
1549
1550 if (!comp_image_size) {
1551 return PLDM_ERROR_INVALID_DATA;
1552 }
1553
1554 if ((comp_ver_str_len == 0) ||
1555 (comp_ver_str_len != comp_ver_str->length)) {
1556 return PLDM_ERROR_INVALID_DATA;
1557 }
1558
1559 if (!is_string_type_valid(comp_ver_str_type)) {
1560 return PLDM_ERROR_INVALID_DATA;
1561 }
1562
1563 struct pldm_header_info header = { 0 };
1564 header.instance = instance_id;
1565 header.msg_type = PLDM_REQUEST;
1566 header.pldm_type = PLDM_FWUP;
1567 header.command = PLDM_UPDATE_COMPONENT;
1568 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1569 if (rc) {
1570 return rc;
1571 }
1572
1573 struct pldm_update_component_req *request =
1574 (struct pldm_update_component_req *)msg->payload;
1575
1576 request->comp_classification = htole16(comp_classification);
1577 request->comp_identifier = htole16(comp_identifier);
1578 request->comp_classification_index = comp_classification_index;
1579 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1580 request->comp_image_size = htole32(comp_image_size);
1581 request->update_option_flags.value = htole32(update_option_flags.value);
1582 request->comp_ver_str_type = comp_ver_str_type;
1583 request->comp_ver_str_len = comp_ver_str_len;
1584
1585 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1586 comp_ver_str->ptr, comp_ver_str->length);
1587
1588 return PLDM_SUCCESS;
1589 }
1590
1591 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)1592 int decode_update_component_resp(const struct pldm_msg *msg,
1593 size_t payload_length,
1594 uint8_t *completion_code,
1595 uint8_t *comp_compatibility_resp,
1596 uint8_t *comp_compatibility_resp_code,
1597 bitfield32_t *update_option_flags_enabled,
1598 uint16_t *time_before_req_fw_data)
1599 {
1600 if (msg == NULL || completion_code == NULL ||
1601 comp_compatibility_resp == NULL ||
1602 comp_compatibility_resp_code == NULL ||
1603 update_option_flags_enabled == NULL ||
1604 time_before_req_fw_data == NULL || !payload_length) {
1605 return PLDM_ERROR_INVALID_DATA;
1606 }
1607
1608 *completion_code = msg->payload[0];
1609 if (*completion_code != PLDM_SUCCESS) {
1610 return PLDM_SUCCESS;
1611 }
1612
1613 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1614 return PLDM_ERROR_INVALID_LENGTH;
1615 }
1616
1617 struct pldm_update_component_resp *response =
1618 (struct pldm_update_component_resp *)msg->payload;
1619
1620 if (!is_comp_compatibility_resp_valid(
1621 response->comp_compatibility_resp)) {
1622 return PLDM_ERROR_INVALID_DATA;
1623 }
1624
1625 if (!is_comp_compatibility_resp_code_valid(
1626 response->comp_compatibility_resp_code)) {
1627 return PLDM_ERROR_INVALID_DATA;
1628 }
1629
1630 *comp_compatibility_resp = response->comp_compatibility_resp;
1631 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1632 update_option_flags_enabled->value =
1633 le32toh(response->update_option_flags_enabled.value);
1634 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1635
1636 return PLDM_SUCCESS;
1637 }
1638
1639 LIBPLDM_ABI_STABLE
decode_request_firmware_data_req(const struct pldm_msg * msg,size_t payload_length,uint32_t * offset,uint32_t * length)1640 int decode_request_firmware_data_req(const struct pldm_msg *msg,
1641 size_t payload_length, uint32_t *offset,
1642 uint32_t *length)
1643 {
1644 if (msg == NULL || offset == NULL || length == NULL) {
1645 return PLDM_ERROR_INVALID_DATA;
1646 }
1647 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1648 return PLDM_ERROR_INVALID_LENGTH;
1649 }
1650 struct pldm_request_firmware_data_req *request =
1651 (struct pldm_request_firmware_data_req *)msg->payload;
1652 *offset = le32toh(request->offset);
1653 *length = le32toh(request->length);
1654
1655 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1656 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1657 }
1658
1659 return PLDM_SUCCESS;
1660 }
1661
1662 LIBPLDM_ABI_STABLE
encode_request_firmware_data_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)1663 int encode_request_firmware_data_resp(uint8_t instance_id,
1664 uint8_t completion_code,
1665 struct pldm_msg *msg,
1666 size_t payload_length)
1667 {
1668 if (msg == NULL || !payload_length) {
1669 return PLDM_ERROR_INVALID_DATA;
1670 }
1671
1672 struct pldm_header_info header = { 0 };
1673 header.instance = instance_id;
1674 header.msg_type = PLDM_RESPONSE;
1675 header.pldm_type = PLDM_FWUP;
1676 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1677 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1678 if (rc) {
1679 return rc;
1680 }
1681
1682 msg->payload[0] = completion_code;
1683
1684 return PLDM_SUCCESS;
1685 }
1686
1687 LIBPLDM_ABI_STABLE
decode_transfer_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * transfer_result)1688 int decode_transfer_complete_req(const struct pldm_msg *msg,
1689 size_t payload_length,
1690 uint8_t *transfer_result)
1691 {
1692 if (msg == NULL || transfer_result == NULL) {
1693 return PLDM_ERROR_INVALID_DATA;
1694 }
1695
1696 if (payload_length != sizeof(*transfer_result)) {
1697 return PLDM_ERROR_INVALID_LENGTH;
1698 }
1699
1700 *transfer_result = msg->payload[0];
1701 return PLDM_SUCCESS;
1702 }
1703
1704 LIBPLDM_ABI_STABLE
encode_transfer_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)1705 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1706 struct pldm_msg *msg, size_t payload_length)
1707 {
1708 if (msg == NULL) {
1709 return PLDM_ERROR_INVALID_DATA;
1710 }
1711
1712 if (payload_length != sizeof(completion_code)) {
1713 return PLDM_ERROR_INVALID_LENGTH;
1714 }
1715
1716 struct pldm_header_info header = { 0 };
1717 header.instance = instance_id;
1718 header.msg_type = PLDM_RESPONSE;
1719 header.pldm_type = PLDM_FWUP;
1720 header.command = PLDM_TRANSFER_COMPLETE;
1721 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1722 if (rc) {
1723 return rc;
1724 }
1725
1726 msg->payload[0] = completion_code;
1727
1728 return PLDM_SUCCESS;
1729 }
1730
1731 LIBPLDM_ABI_STABLE
decode_verify_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * verify_result)1732 int decode_verify_complete_req(const struct pldm_msg *msg,
1733 size_t payload_length, uint8_t *verify_result)
1734 {
1735 if (msg == NULL || verify_result == NULL) {
1736 return PLDM_ERROR_INVALID_DATA;
1737 }
1738
1739 if (payload_length != sizeof(*verify_result)) {
1740 return PLDM_ERROR_INVALID_LENGTH;
1741 }
1742
1743 *verify_result = msg->payload[0];
1744 return PLDM_SUCCESS;
1745 }
1746
1747 LIBPLDM_ABI_STABLE
encode_verify_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)1748 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1749 struct pldm_msg *msg, size_t payload_length)
1750 {
1751 if (msg == NULL) {
1752 return PLDM_ERROR_INVALID_DATA;
1753 }
1754
1755 if (payload_length != sizeof(completion_code)) {
1756 return PLDM_ERROR_INVALID_LENGTH;
1757 }
1758
1759 struct pldm_header_info header = { 0 };
1760 header.instance = instance_id;
1761 header.msg_type = PLDM_RESPONSE;
1762 header.pldm_type = PLDM_FWUP;
1763 header.command = PLDM_VERIFY_COMPLETE;
1764 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1765 if (rc) {
1766 return rc;
1767 }
1768
1769 msg->payload[0] = completion_code;
1770
1771 return PLDM_SUCCESS;
1772 }
1773
1774 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)1775 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
1776 uint8_t *apply_result,
1777 bitfield16_t *comp_activation_methods_modification)
1778 {
1779 if (msg == NULL || apply_result == NULL ||
1780 comp_activation_methods_modification == NULL) {
1781 return PLDM_ERROR_INVALID_DATA;
1782 }
1783
1784 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1785 return PLDM_ERROR_INVALID_LENGTH;
1786 }
1787
1788 struct pldm_apply_complete_req *request =
1789 (struct pldm_apply_complete_req *)msg->payload;
1790
1791 *apply_result = request->apply_result;
1792 comp_activation_methods_modification->value =
1793 le16toh(request->comp_activation_methods_modification.value);
1794
1795 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1796 comp_activation_methods_modification->value) {
1797 return PLDM_ERROR_INVALID_DATA;
1798 }
1799
1800 return PLDM_SUCCESS;
1801 }
1802
1803 LIBPLDM_ABI_STABLE
encode_apply_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)1804 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1805 struct pldm_msg *msg, size_t payload_length)
1806 {
1807 if (msg == NULL) {
1808 return PLDM_ERROR_INVALID_DATA;
1809 }
1810
1811 if (payload_length != sizeof(completion_code)) {
1812 return PLDM_ERROR_INVALID_LENGTH;
1813 }
1814
1815 struct pldm_header_info header = { 0 };
1816 header.instance = instance_id;
1817 header.msg_type = PLDM_RESPONSE;
1818 header.pldm_type = PLDM_FWUP;
1819 header.command = PLDM_APPLY_COMPLETE;
1820 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1821 if (rc) {
1822 return rc;
1823 }
1824
1825 msg->payload[0] = completion_code;
1826
1827 return PLDM_SUCCESS;
1828 }
1829
1830 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)1831 int encode_activate_firmware_req(uint8_t instance_id,
1832 bool8_t self_contained_activation_req,
1833 struct pldm_msg *msg, size_t payload_length)
1834 {
1835 if (msg == NULL) {
1836 return PLDM_ERROR_INVALID_DATA;
1837 }
1838
1839 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1840 return PLDM_ERROR_INVALID_LENGTH;
1841 }
1842
1843 if (!is_self_contained_activation_req_valid(
1844 self_contained_activation_req)) {
1845 return PLDM_ERROR_INVALID_DATA;
1846 }
1847
1848 struct pldm_header_info header = { 0 };
1849 header.instance = instance_id;
1850 header.msg_type = PLDM_REQUEST;
1851 header.pldm_type = PLDM_FWUP;
1852 header.command = PLDM_ACTIVATE_FIRMWARE;
1853 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1854 if (rc) {
1855 return rc;
1856 }
1857
1858 struct pldm_activate_firmware_req *request =
1859 (struct pldm_activate_firmware_req *)msg->payload;
1860
1861 request->self_contained_activation_req = self_contained_activation_req;
1862
1863 return PLDM_SUCCESS;
1864 }
1865
1866 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)1867 int decode_activate_firmware_resp(const struct pldm_msg *msg,
1868 size_t payload_length,
1869 uint8_t *completion_code,
1870 uint16_t *estimated_time_activation)
1871 {
1872 if (msg == NULL || completion_code == NULL ||
1873 estimated_time_activation == NULL || !payload_length) {
1874 return PLDM_ERROR_INVALID_DATA;
1875 }
1876
1877 *completion_code = msg->payload[0];
1878 if (*completion_code != PLDM_SUCCESS) {
1879 return PLDM_SUCCESS;
1880 }
1881
1882 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1883 return PLDM_ERROR_INVALID_LENGTH;
1884 }
1885
1886 struct pldm_activate_firmware_resp *response =
1887 (struct pldm_activate_firmware_resp *)msg->payload;
1888
1889 *estimated_time_activation =
1890 le16toh(response->estimated_time_activation);
1891
1892 return PLDM_SUCCESS;
1893 }
1894
1895 LIBPLDM_ABI_STABLE
encode_get_status_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)1896 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1897 size_t payload_length)
1898 {
1899 if (msg == NULL) {
1900 return PLDM_ERROR_INVALID_DATA;
1901 }
1902
1903 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1904 return PLDM_ERROR_INVALID_LENGTH;
1905 }
1906
1907 struct pldm_header_info header = { 0 };
1908 header.instance = instance_id;
1909 header.msg_type = PLDM_REQUEST;
1910 header.pldm_type = PLDM_FWUP;
1911 header.command = PLDM_GET_STATUS;
1912 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1913 if (rc) {
1914 return rc;
1915 }
1916
1917 return PLDM_SUCCESS;
1918 }
1919
1920 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)1921 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1922 uint8_t *completion_code, uint8_t *current_state,
1923 uint8_t *previous_state, uint8_t *aux_state,
1924 uint8_t *aux_state_status, uint8_t *progress_percent,
1925 uint8_t *reason_code,
1926 bitfield32_t *update_option_flags_enabled)
1927 {
1928 if (msg == NULL || completion_code == NULL || current_state == NULL ||
1929 previous_state == NULL || aux_state == NULL ||
1930 aux_state_status == NULL || progress_percent == NULL ||
1931 reason_code == NULL || update_option_flags_enabled == NULL ||
1932 !payload_length) {
1933 return PLDM_ERROR_INVALID_DATA;
1934 }
1935
1936 *completion_code = msg->payload[0];
1937 if (*completion_code != PLDM_SUCCESS) {
1938 return PLDM_SUCCESS;
1939 }
1940
1941 if (payload_length != sizeof(struct pldm_get_status_resp)) {
1942 return PLDM_ERROR_INVALID_LENGTH;
1943 }
1944 struct pldm_get_status_resp *response =
1945 (struct pldm_get_status_resp *)msg->payload;
1946
1947 if (!is_state_valid(response->current_state)) {
1948 return PLDM_ERROR_INVALID_DATA;
1949 }
1950 if (!is_state_valid(response->previous_state)) {
1951 return PLDM_ERROR_INVALID_DATA;
1952 }
1953 if (!is_aux_state_valid(response->aux_state)) {
1954 return PLDM_ERROR_INVALID_DATA;
1955 }
1956 if (!is_aux_state_status_valid(response->aux_state_status)) {
1957 return PLDM_ERROR_INVALID_DATA;
1958 }
1959 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1960 return PLDM_ERROR_INVALID_DATA;
1961 }
1962 if (!is_reason_code_valid(response->reason_code)) {
1963 return PLDM_ERROR_INVALID_DATA;
1964 }
1965
1966 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1967 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1968 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1969 if (response->aux_state !=
1970 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1971 return PLDM_ERROR_INVALID_DATA;
1972 }
1973 }
1974
1975 *current_state = response->current_state;
1976 *previous_state = response->previous_state;
1977 *aux_state = response->aux_state;
1978 *aux_state_status = response->aux_state_status;
1979 *progress_percent = response->progress_percent;
1980 *reason_code = response->reason_code;
1981 update_option_flags_enabled->value =
1982 le32toh(response->update_option_flags_enabled.value);
1983
1984 return PLDM_SUCCESS;
1985 }
1986
1987 LIBPLDM_ABI_STABLE
encode_cancel_update_component_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)1988 int encode_cancel_update_component_req(uint8_t instance_id,
1989 struct pldm_msg *msg,
1990 size_t payload_length)
1991 {
1992 if (msg == NULL) {
1993 return PLDM_ERROR_INVALID_DATA;
1994 }
1995
1996 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1997 return PLDM_ERROR_INVALID_LENGTH;
1998 }
1999
2000 struct pldm_header_info header = { 0 };
2001 header.instance = instance_id;
2002 header.msg_type = PLDM_REQUEST;
2003 header.pldm_type = PLDM_FWUP;
2004 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
2005 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2006 if (rc) {
2007 return rc;
2008 }
2009
2010 return PLDM_SUCCESS;
2011 }
2012
2013 LIBPLDM_ABI_STABLE
decode_cancel_update_component_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code)2014 int decode_cancel_update_component_resp(const struct pldm_msg *msg,
2015 size_t payload_length,
2016 uint8_t *completion_code)
2017 {
2018 if (msg == NULL || completion_code == NULL) {
2019 return PLDM_ERROR_INVALID_DATA;
2020 }
2021
2022 if (payload_length != sizeof(*completion_code)) {
2023 return PLDM_ERROR_INVALID_LENGTH;
2024 }
2025
2026 *completion_code = msg->payload[0];
2027 return PLDM_SUCCESS;
2028 }
2029
2030 LIBPLDM_ABI_STABLE
encode_cancel_update_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)2031 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
2032 size_t payload_length)
2033 {
2034 if (msg == NULL) {
2035 return PLDM_ERROR_INVALID_DATA;
2036 }
2037
2038 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
2039 return PLDM_ERROR_INVALID_LENGTH;
2040 }
2041
2042 struct pldm_header_info header = { 0 };
2043 header.instance = instance_id;
2044 header.msg_type = PLDM_REQUEST;
2045 header.pldm_type = PLDM_FWUP;
2046 header.command = PLDM_CANCEL_UPDATE;
2047 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2048 if (rc) {
2049 return rc;
2050 }
2051
2052 return PLDM_SUCCESS;
2053 }
2054
2055 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)2056 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
2057 uint8_t *completion_code,
2058 bool8_t *non_functioning_component_indication,
2059 bitfield64_t *non_functioning_component_bitmap)
2060 {
2061 if (msg == NULL || completion_code == NULL ||
2062 non_functioning_component_indication == NULL ||
2063 non_functioning_component_bitmap == NULL || !payload_length) {
2064 return PLDM_ERROR_INVALID_DATA;
2065 }
2066
2067 *completion_code = msg->payload[0];
2068 if (*completion_code != PLDM_SUCCESS) {
2069 return PLDM_SUCCESS;
2070 }
2071
2072 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
2073 return PLDM_ERROR_INVALID_LENGTH;
2074 }
2075 struct pldm_cancel_update_resp *response =
2076 (struct pldm_cancel_update_resp *)msg->payload;
2077
2078 if (!is_non_functioning_component_indication_valid(
2079 response->non_functioning_component_indication)) {
2080 return PLDM_ERROR_INVALID_DATA;
2081 }
2082
2083 *non_functioning_component_indication =
2084 response->non_functioning_component_indication;
2085
2086 if (*non_functioning_component_indication) {
2087 non_functioning_component_bitmap->value =
2088 le64toh(response->non_functioning_component_bitmap);
2089 }
2090
2091 return PLDM_SUCCESS;
2092 }
2093