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 struct pldm_msgbuf _buf;
521 struct pldm_msgbuf *buf = &_buf;
522 int rc;
523
524 if (!iter || !iter->field || !desc) {
525 return -EINVAL;
526 }
527
528 rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN,
529 iter->field->ptr, iter->field->length);
530 if (rc) {
531 return rc;
532 }
533
534 pldm_msgbuf_extract(buf, desc->descriptor_type);
535 rc = pldm_msgbuf_extract(buf, desc->descriptor_length);
536 if (rc) {
537 return rc;
538 }
539
540 desc->descriptor_data = NULL;
541 pldm_msgbuf_span_required(buf, desc->descriptor_length,
542 (void **)&desc->descriptor_data);
543 iter->field->ptr = NULL;
544 pldm_msgbuf_span_remaining(buf, (void **)&iter->field->ptr,
545 &iter->field->length);
546
547 return pldm_msgbuf_destroy(buf);
548 }
549
decode_descriptor_type_length_value_errno(const uint8_t * data,size_t length,uint16_t * descriptor_type,struct variable_field * descriptor_data)550 static int decode_descriptor_type_length_value_errno(
551 const uint8_t *data, size_t length, uint16_t *descriptor_type,
552 struct variable_field *descriptor_data)
553 {
554 uint16_t descriptor_length = 0;
555
556 if (data == NULL || descriptor_type == NULL ||
557 descriptor_data == NULL) {
558 return -EINVAL;
559 }
560
561 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
562 return -EOVERFLOW;
563 }
564
565 struct pldm_descriptor_tlv *entry =
566 (struct pldm_descriptor_tlv *)(data);
567
568 *descriptor_type = le16toh(entry->descriptor_type);
569 descriptor_length = le16toh(entry->descriptor_length);
570 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
571 if (descriptor_length !=
572 get_descriptor_type_length(*descriptor_type)) {
573 return -EBADMSG;
574 }
575 }
576
577 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
578 descriptor_length)) {
579 return -EOVERFLOW;
580 }
581
582 descriptor_data->ptr = entry->descriptor_data;
583 descriptor_data->length = descriptor_length;
584
585 return 0;
586 }
587
588 LIBPLDM_ABI_STABLE
decode_descriptor_type_length_value(const uint8_t * data,size_t length,uint16_t * descriptor_type,struct variable_field * descriptor_data)589 int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
590 uint16_t *descriptor_type,
591 struct variable_field *descriptor_data)
592 {
593 int rc;
594
595 rc = decode_descriptor_type_length_value_errno(
596 data, length, descriptor_type, descriptor_data);
597 if (rc < 0) {
598 return pldm_xlate_errno(rc);
599 }
600
601 return PLDM_SUCCESS;
602 }
603
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)604 static int decode_vendor_defined_descriptor_value_errno(
605 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
606 struct variable_field *descriptor_title_str,
607 struct variable_field *descriptor_data)
608 {
609 if (data == NULL || descriptor_title_str_type == NULL ||
610 descriptor_title_str == NULL || descriptor_data == NULL) {
611 return -EINVAL;
612 }
613
614 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
615 return -EOVERFLOW;
616 }
617
618 struct pldm_vendor_defined_descriptor_title_data *entry =
619 (struct pldm_vendor_defined_descriptor_title_data *)(data);
620 if (!is_string_type_valid(
621 entry->vendor_defined_descriptor_title_str_type) ||
622 (entry->vendor_defined_descriptor_title_str_len == 0)) {
623 return -EBADMSG;
624 }
625
626 // Assuming at least 1 byte of VendorDefinedDescriptorData
627 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
628 entry->vendor_defined_descriptor_title_str_len)) {
629 return -EOVERFLOW;
630 }
631
632 *descriptor_title_str_type =
633 entry->vendor_defined_descriptor_title_str_type;
634 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
635 descriptor_title_str->length =
636 entry->vendor_defined_descriptor_title_str_len;
637
638 descriptor_data->ptr =
639 descriptor_title_str->ptr + descriptor_title_str->length;
640 descriptor_data->length =
641 length -
642 sizeof(entry->vendor_defined_descriptor_title_str_type) -
643 sizeof(entry->vendor_defined_descriptor_title_str_len) -
644 descriptor_title_str->length;
645
646 return 0;
647 }
648
649 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)650 int decode_vendor_defined_descriptor_value(
651 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
652 struct variable_field *descriptor_title_str,
653 struct variable_field *descriptor_data)
654 {
655 int rc;
656
657 rc = decode_vendor_defined_descriptor_value_errno(
658 data, length, descriptor_title_str_type, descriptor_title_str,
659 descriptor_data);
660 if (rc < 0) {
661 return pldm_xlate_errno(rc);
662 }
663
664 return PLDM_SUCCESS;
665 }
666
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)667 static int decode_pldm_comp_image_info_errno(
668 const uint8_t *data, size_t length,
669 struct pldm_component_image_information *pldm_comp_image_info,
670 struct variable_field *comp_version_str)
671 {
672 if (data == NULL || pldm_comp_image_info == NULL ||
673 comp_version_str == NULL) {
674 return -EINVAL;
675 }
676
677 if (length < sizeof(struct pldm_component_image_information)) {
678 return -EOVERFLOW;
679 }
680
681 struct pldm_component_image_information *data_header =
682 (struct pldm_component_image_information *)(data);
683
684 if (!is_string_type_valid(data_header->comp_version_string_type) ||
685 (data_header->comp_version_string_length == 0)) {
686 return -EBADMSG;
687 }
688
689 if (length < sizeof(struct pldm_component_image_information) +
690 data_header->comp_version_string_length) {
691 return -EOVERFLOW;
692 }
693
694 pldm_comp_image_info->comp_classification =
695 le16toh(data_header->comp_classification);
696 pldm_comp_image_info->comp_identifier =
697 le16toh(data_header->comp_identifier);
698 pldm_comp_image_info->comp_comparison_stamp =
699 le32toh(data_header->comp_comparison_stamp);
700 pldm_comp_image_info->comp_options.value =
701 le16toh(data_header->comp_options.value);
702 pldm_comp_image_info->requested_comp_activation_method.value =
703 le16toh(data_header->requested_comp_activation_method.value);
704 pldm_comp_image_info->comp_location_offset =
705 le32toh(data_header->comp_location_offset);
706 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
707 pldm_comp_image_info->comp_version_string_type =
708 data_header->comp_version_string_type;
709 pldm_comp_image_info->comp_version_string_length =
710 data_header->comp_version_string_length;
711
712 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
713 pldm_comp_image_info->comp_comparison_stamp !=
714 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
715 return -EBADMSG;
716 }
717
718 if (pldm_comp_image_info->comp_location_offset == 0 ||
719 pldm_comp_image_info->comp_size == 0) {
720 return -EBADMSG;
721 }
722
723 comp_version_str->ptr =
724 data + sizeof(struct pldm_component_image_information);
725 comp_version_str->length =
726 pldm_comp_image_info->comp_version_string_length;
727
728 return 0;
729 }
730
731 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)732 int decode_pldm_comp_image_info(
733 const uint8_t *data, size_t length,
734 struct pldm_component_image_information *pldm_comp_image_info,
735 struct variable_field *comp_version_str)
736 {
737 int rc;
738
739 rc = decode_pldm_comp_image_info_errno(
740 data, length, pldm_comp_image_info, comp_version_str);
741 if (rc < 0) {
742 return pldm_xlate_errno(rc);
743 }
744
745 return PLDM_SUCCESS;
746 }
747
748 LIBPLDM_ABI_STABLE
encode_query_device_identifiers_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)749 int encode_query_device_identifiers_req(uint8_t instance_id,
750 size_t payload_length,
751 struct pldm_msg *msg)
752 {
753 if (msg == NULL) {
754 return PLDM_ERROR_INVALID_DATA;
755 }
756
757 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
758 return PLDM_ERROR_INVALID_LENGTH;
759 }
760
761 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
762 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
763 }
764
765 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)766 int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
767 size_t payload_length,
768 uint8_t *completion_code,
769 uint32_t *device_identifiers_len,
770 uint8_t *descriptor_count,
771 uint8_t **descriptor_data)
772 {
773 if (msg == NULL || completion_code == NULL ||
774 device_identifiers_len == NULL || descriptor_count == NULL ||
775 descriptor_data == NULL) {
776 return PLDM_ERROR_INVALID_DATA;
777 }
778
779 *completion_code = msg->payload[0];
780 if (PLDM_SUCCESS != *completion_code) {
781 return PLDM_SUCCESS;
782 }
783
784 if (payload_length <
785 sizeof(struct pldm_query_device_identifiers_resp)) {
786 return PLDM_ERROR_INVALID_LENGTH;
787 }
788
789 struct pldm_query_device_identifiers_resp *response =
790 (struct pldm_query_device_identifiers_resp *)msg->payload;
791 *device_identifiers_len = le32toh(response->device_identifiers_len);
792
793 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
794 return PLDM_ERROR_INVALID_LENGTH;
795 }
796
797 if (payload_length !=
798 sizeof(struct pldm_query_device_identifiers_resp) +
799 *device_identifiers_len) {
800 return PLDM_ERROR_INVALID_LENGTH;
801 }
802 *descriptor_count = response->descriptor_count;
803
804 if (*descriptor_count == 0) {
805 return PLDM_ERROR_INVALID_DATA;
806 }
807 *descriptor_data =
808 (uint8_t *)(msg->payload +
809 sizeof(struct pldm_query_device_identifiers_resp));
810 return PLDM_SUCCESS;
811 }
812
813 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)814 int encode_query_device_identifiers_resp(
815 uint8_t instance_id, uint8_t descriptor_count,
816 const struct pldm_descriptor *descriptors, struct pldm_msg *msg,
817 size_t *payload_length)
818 {
819 int rc;
820 struct pldm_msgbuf _buf;
821 struct pldm_msgbuf *buf = &_buf;
822
823 if (descriptors == NULL || msg == NULL || payload_length == NULL) {
824 return -EINVAL;
825 }
826
827 if (descriptor_count < 1) {
828 return -EINVAL;
829 }
830
831 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
832 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
833 if (rc) {
834 return -EINVAL;
835 }
836
837 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
838 if (rc) {
839 return rc;
840 }
841
842 /* Determine total length */
843 uint32_t device_identifiers_len = 0;
844 for (uint8_t i = 0; i < descriptor_count; i++) {
845 const struct pldm_descriptor *d = &descriptors[i];
846 device_identifiers_len +=
847 2 * sizeof(uint16_t) + d->descriptor_length;
848 }
849
850 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
851 pldm_msgbuf_insert(buf, device_identifiers_len);
852 pldm_msgbuf_insert(buf, descriptor_count);
853
854 for (uint8_t i = 0; i < descriptor_count; i++) {
855 const struct pldm_descriptor *d = &descriptors[i];
856 pldm_msgbuf_insert(buf, d->descriptor_type);
857 pldm_msgbuf_insert(buf, d->descriptor_length);
858 if (d->descriptor_data == NULL) {
859 return -EINVAL;
860 }
861 rc = pldm_msgbuf_insert_array(
862 buf, d->descriptor_length,
863 (const uint8_t *)d->descriptor_data,
864 d->descriptor_length);
865 if (rc) {
866 return rc;
867 }
868 }
869
870 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
871 }
872
873 LIBPLDM_ABI_STABLE
encode_get_firmware_parameters_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)874 int encode_get_firmware_parameters_req(uint8_t instance_id,
875 size_t payload_length,
876 struct pldm_msg *msg)
877 {
878 if (msg == NULL) {
879 return PLDM_ERROR_INVALID_DATA;
880 }
881
882 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
883 return PLDM_ERROR_INVALID_LENGTH;
884 }
885
886 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
887 PLDM_GET_FIRMWARE_PARAMETERS, msg);
888 }
889
890 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)891 int decode_get_firmware_parameters_resp(
892 const struct pldm_msg *msg, size_t payload_length,
893 struct pldm_get_firmware_parameters_resp *resp_data,
894 struct variable_field *active_comp_image_set_ver_str,
895 struct variable_field *pending_comp_image_set_ver_str,
896 struct variable_field *comp_parameter_table)
897 {
898 if (msg == NULL || resp_data == NULL ||
899 active_comp_image_set_ver_str == NULL ||
900 pending_comp_image_set_ver_str == NULL ||
901 comp_parameter_table == NULL || !payload_length) {
902 return PLDM_ERROR_INVALID_DATA;
903 }
904
905 resp_data->completion_code = msg->payload[0];
906 if (PLDM_SUCCESS != resp_data->completion_code) {
907 return PLDM_SUCCESS;
908 }
909
910 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
911 return PLDM_ERROR_INVALID_LENGTH;
912 }
913
914 struct pldm_get_firmware_parameters_resp *response =
915 (struct pldm_get_firmware_parameters_resp *)msg->payload;
916
917 if (!is_string_type_valid(
918 response->active_comp_image_set_ver_str_type) ||
919 (response->active_comp_image_set_ver_str_len == 0)) {
920 return PLDM_ERROR_INVALID_DATA;
921 }
922
923 if (response->pending_comp_image_set_ver_str_len == 0) {
924 if (response->pending_comp_image_set_ver_str_type !=
925 PLDM_STR_TYPE_UNKNOWN) {
926 return PLDM_ERROR_INVALID_DATA;
927 }
928 } else {
929 if (!is_string_type_valid(
930 response->pending_comp_image_set_ver_str_type)) {
931 return PLDM_ERROR_INVALID_DATA;
932 }
933 }
934
935 size_t partial_response_length =
936 sizeof(struct pldm_get_firmware_parameters_resp) +
937 response->active_comp_image_set_ver_str_len +
938 response->pending_comp_image_set_ver_str_len;
939
940 if (payload_length < partial_response_length) {
941 return PLDM_ERROR_INVALID_LENGTH;
942 }
943
944 resp_data->capabilities_during_update.value =
945 le32toh(response->capabilities_during_update.value);
946 resp_data->comp_count = le16toh(response->comp_count);
947 resp_data->active_comp_image_set_ver_str_type =
948 response->active_comp_image_set_ver_str_type;
949 resp_data->active_comp_image_set_ver_str_len =
950 response->active_comp_image_set_ver_str_len;
951 resp_data->pending_comp_image_set_ver_str_type =
952 response->pending_comp_image_set_ver_str_type;
953 resp_data->pending_comp_image_set_ver_str_len =
954 response->pending_comp_image_set_ver_str_len;
955
956 active_comp_image_set_ver_str->ptr =
957 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
958 active_comp_image_set_ver_str->length =
959 resp_data->active_comp_image_set_ver_str_len;
960
961 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
962 pending_comp_image_set_ver_str->ptr =
963 msg->payload +
964 sizeof(struct pldm_get_firmware_parameters_resp) +
965 resp_data->active_comp_image_set_ver_str_len;
966 pending_comp_image_set_ver_str->length =
967 resp_data->pending_comp_image_set_ver_str_len;
968 } else {
969 pending_comp_image_set_ver_str->ptr = NULL;
970 pending_comp_image_set_ver_str->length = 0;
971 }
972
973 if (payload_length > partial_response_length && resp_data->comp_count) {
974 comp_parameter_table->ptr =
975 msg->payload +
976 sizeof(struct pldm_get_firmware_parameters_resp) +
977 resp_data->active_comp_image_set_ver_str_len +
978 resp_data->pending_comp_image_set_ver_str_len;
979 comp_parameter_table->length =
980 payload_length - partial_response_length;
981 } else {
982 comp_parameter_table->ptr = NULL;
983 comp_parameter_table->length = 0;
984 }
985
986 return PLDM_SUCCESS;
987 }
988
989 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)990 int encode_get_firmware_parameters_resp(
991 uint8_t instance_id,
992 const struct pldm_get_firmware_parameters_resp_full *resp_data,
993 struct pldm_msg *msg, size_t *payload_length)
994 {
995 int rc;
996 struct pldm_msgbuf _buf;
997 struct pldm_msgbuf *buf = &_buf;
998
999 if (resp_data == NULL || msg == NULL || payload_length == NULL) {
1000 return -EINVAL;
1001 }
1002
1003 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
1004 PLDM_GET_FIRMWARE_PARAMETERS, msg);
1005 if (rc) {
1006 return -EINVAL;
1007 }
1008
1009 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1010 if (rc) {
1011 return rc;
1012 }
1013
1014 pldm_msgbuf_insert(buf, resp_data->completion_code);
1015 pldm_msgbuf_insert(buf, resp_data->capabilities_during_update.value);
1016 pldm_msgbuf_insert(buf, resp_data->comp_count);
1017 pldm_msgbuf_insert(buf,
1018 resp_data->active_comp_image_set_ver_str.str_type);
1019 pldm_msgbuf_insert(buf,
1020 resp_data->active_comp_image_set_ver_str.str_len);
1021 pldm_msgbuf_insert(buf,
1022 resp_data->pending_comp_image_set_ver_str.str_type);
1023 pldm_msgbuf_insert(buf,
1024 resp_data->pending_comp_image_set_ver_str.str_len);
1025 /* String data appended */
1026 rc = pldm_msgbuf_insert_array(
1027 buf, resp_data->active_comp_image_set_ver_str.str_len,
1028 resp_data->active_comp_image_set_ver_str.str_data,
1029 resp_data->active_comp_image_set_ver_str.str_len);
1030 if (rc) {
1031 return rc;
1032 }
1033 rc = pldm_msgbuf_insert_array(
1034 buf, resp_data->pending_comp_image_set_ver_str.str_len,
1035 resp_data->pending_comp_image_set_ver_str.str_data,
1036 resp_data->pending_comp_image_set_ver_str.str_len);
1037 if (rc) {
1038 return rc;
1039 }
1040
1041 /* Further calls to encode_get_firmware_parameters_resp_comp_entry
1042 * will populate the remainder */
1043
1044 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
1045 }
1046
1047 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)1048 int encode_get_firmware_parameters_resp_comp_entry(
1049 const struct pldm_component_parameter_entry_full *comp,
1050 uint8_t *payload, size_t *payload_length)
1051 {
1052 int rc;
1053 struct pldm_msgbuf _buf;
1054 struct pldm_msgbuf *buf = &_buf;
1055
1056 if (comp == NULL || payload == NULL || payload_length == NULL) {
1057 return -EINVAL;
1058 }
1059
1060 rc = pldm_msgbuf_init_errno(buf, 0, payload, *payload_length);
1061 if (rc) {
1062 return rc;
1063 }
1064
1065 pldm_msgbuf_insert(buf, comp->comp_classification);
1066 pldm_msgbuf_insert(buf, comp->comp_identifier);
1067 pldm_msgbuf_insert(buf, comp->comp_classification_index);
1068
1069 pldm_msgbuf_insert(buf, comp->active_ver.comparison_stamp);
1070 pldm_msgbuf_insert(buf, (uint8_t)comp->active_ver.str.str_type);
1071 pldm_msgbuf_insert(buf, comp->active_ver.str.str_len);
1072 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1073 comp->active_ver.date,
1074 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1075 if (rc) {
1076 return rc;
1077 }
1078
1079 pldm_msgbuf_insert(buf, comp->pending_ver.comparison_stamp);
1080 pldm_msgbuf_insert(buf, (uint8_t)comp->pending_ver.str.str_type);
1081 pldm_msgbuf_insert(buf, comp->pending_ver.str.str_len);
1082 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1083 comp->pending_ver.date,
1084 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1085 if (rc) {
1086 return rc;
1087 }
1088
1089 pldm_msgbuf_insert(buf, comp->comp_activation_methods.value);
1090 pldm_msgbuf_insert(buf, comp->capabilities_during_update.value);
1091
1092 rc = pldm_msgbuf_insert_array(buf, comp->active_ver.str.str_len,
1093 comp->active_ver.str.str_data,
1094 comp->active_ver.str.str_len);
1095 if (rc) {
1096 return rc;
1097 }
1098 rc = pldm_msgbuf_insert_array(buf, comp->pending_ver.str.str_len,
1099 comp->pending_ver.str.str_data,
1100 comp->pending_ver.str.str_len);
1101 if (rc) {
1102 return rc;
1103 }
1104
1105 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
1106 }
1107
1108 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)1109 int decode_get_firmware_parameters_resp_comp_entry(
1110 const uint8_t *data, size_t length,
1111 struct pldm_component_parameter_entry *component_data,
1112 struct variable_field *active_comp_ver_str,
1113 struct variable_field *pending_comp_ver_str)
1114 {
1115 if (data == NULL || component_data == NULL ||
1116 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
1117 return PLDM_ERROR_INVALID_DATA;
1118 }
1119
1120 if (length < sizeof(struct pldm_component_parameter_entry)) {
1121 return PLDM_ERROR_INVALID_LENGTH;
1122 }
1123
1124 struct pldm_component_parameter_entry *entry =
1125 (struct pldm_component_parameter_entry *)(data);
1126
1127 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
1128 entry->active_comp_ver_str_len +
1129 entry->pending_comp_ver_str_len;
1130
1131 if (length < entry_length) {
1132 return PLDM_ERROR_INVALID_LENGTH;
1133 }
1134
1135 component_data->comp_classification =
1136 le16toh(entry->comp_classification);
1137 component_data->comp_identifier = le16toh(entry->comp_identifier);
1138 component_data->comp_classification_index =
1139 entry->comp_classification_index;
1140 component_data->active_comp_comparison_stamp =
1141 le32toh(entry->active_comp_comparison_stamp);
1142 component_data->active_comp_ver_str_type =
1143 entry->active_comp_ver_str_type;
1144 component_data->active_comp_ver_str_len =
1145 entry->active_comp_ver_str_len;
1146 memcpy(component_data->active_comp_release_date,
1147 entry->active_comp_release_date,
1148 sizeof(entry->active_comp_release_date));
1149 component_data->pending_comp_comparison_stamp =
1150 le32toh(entry->pending_comp_comparison_stamp);
1151 component_data->pending_comp_ver_str_type =
1152 entry->pending_comp_ver_str_type;
1153 component_data->pending_comp_ver_str_len =
1154 entry->pending_comp_ver_str_len;
1155 memcpy(component_data->pending_comp_release_date,
1156 entry->pending_comp_release_date,
1157 sizeof(entry->pending_comp_release_date));
1158 component_data->comp_activation_methods.value =
1159 le16toh(entry->comp_activation_methods.value);
1160 component_data->capabilities_during_update.value =
1161 le32toh(entry->capabilities_during_update.value);
1162
1163 if (entry->active_comp_ver_str_len != 0) {
1164 active_comp_ver_str->ptr =
1165 data + sizeof(struct pldm_component_parameter_entry);
1166 active_comp_ver_str->length = entry->active_comp_ver_str_len;
1167 } else {
1168 active_comp_ver_str->ptr = NULL;
1169 active_comp_ver_str->length = 0;
1170 }
1171
1172 if (entry->pending_comp_ver_str_len != 0) {
1173 pending_comp_ver_str->ptr =
1174 data + sizeof(struct pldm_component_parameter_entry) +
1175 entry->active_comp_ver_str_len;
1176 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
1177 } else {
1178 pending_comp_ver_str->ptr = NULL;
1179 pending_comp_ver_str->length = 0;
1180 }
1181 return PLDM_SUCCESS;
1182 }
1183
1184 LIBPLDM_ABI_STABLE
encode_query_downstream_devices_req(uint8_t instance_id,struct pldm_msg * msg)1185 int encode_query_downstream_devices_req(uint8_t instance_id,
1186 struct pldm_msg *msg)
1187 {
1188 if (msg == NULL) {
1189 return -EINVAL;
1190 }
1191
1192 return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id,
1193 PLDM_FWUP,
1194 PLDM_QUERY_DOWNSTREAM_DEVICES,
1195 msg);
1196 }
1197
1198 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)1199 int decode_query_downstream_devices_resp(
1200 const struct pldm_msg *msg, size_t payload_length,
1201 struct pldm_query_downstream_devices_resp *resp_data)
1202 {
1203 struct pldm_msgbuf _buf;
1204 struct pldm_msgbuf *buf = &_buf;
1205 int rc;
1206
1207 if (msg == NULL || resp_data == NULL || !payload_length) {
1208 return -EINVAL;
1209 }
1210
1211 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1212 msg->payload, payload_length);
1213 if (rc) {
1214 return rc;
1215 }
1216
1217 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1218 if (rc) {
1219 return rc;
1220 }
1221 if (PLDM_SUCCESS != resp_data->completion_code) {
1222 // Return the CC directly without decoding the rest of the payload
1223 return 0;
1224 }
1225
1226 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
1227 return -EBADMSG;
1228 }
1229
1230 rc = pldm_msgbuf_extract(buf,
1231 resp_data->downstream_device_update_supported);
1232 if (rc) {
1233 return rc;
1234 }
1235
1236 if (!is_downstream_device_update_support_valid(
1237 resp_data->downstream_device_update_supported)) {
1238 return -EINVAL;
1239 }
1240
1241 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1242 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
1243 pldm_msgbuf_extract(buf, resp_data->capabilities.value);
1244
1245 return pldm_msgbuf_destroy_consumed(buf);
1246 }
1247
1248 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)1249 int encode_query_downstream_identifiers_req(
1250 uint8_t instance_id,
1251 const struct pldm_query_downstream_identifiers_req *params_req,
1252 struct pldm_msg *msg, size_t payload_length)
1253 {
1254 struct pldm_msgbuf _buf;
1255 struct pldm_msgbuf *buf = &_buf;
1256 int rc;
1257
1258 if (!msg || !params_req) {
1259 return -EINVAL;
1260 }
1261
1262 if (!is_transfer_operation_flag_valid(
1263 (enum transfer_op_flag)
1264 params_req->transfer_operation_flag)) {
1265 return -EINVAL;
1266 }
1267
1268 struct pldm_header_info header = { 0 };
1269 header.instance = instance_id;
1270 header.msg_type = PLDM_REQUEST;
1271 header.pldm_type = PLDM_FWUP;
1272 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
1273 rc = pack_pldm_header_errno(&header, &(msg->hdr));
1274 if (rc) {
1275 return rc;
1276 }
1277
1278 rc = pldm_msgbuf_init_errno(buf,
1279 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
1280 msg->payload, payload_length);
1281 if (rc) {
1282 return rc;
1283 }
1284
1285 pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
1286 // Data correctness has been verified, cast it to 1-byte data directly.
1287 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
1288
1289 return pldm_msgbuf_destroy(buf);
1290 }
1291
1292 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)1293 int decode_query_downstream_identifiers_resp(
1294 const struct pldm_msg *msg, size_t payload_length,
1295 struct pldm_query_downstream_identifiers_resp *resp_data,
1296 struct pldm_downstream_device_iter *iter)
1297 {
1298 struct pldm_msgbuf _buf;
1299 struct pldm_msgbuf *buf = &_buf;
1300 void *remaining = NULL;
1301 int rc = 0;
1302
1303 if (msg == NULL || resp_data == NULL || iter == NULL ||
1304 !payload_length) {
1305 return -EINVAL;
1306 }
1307
1308 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1309 msg->payload, payload_length);
1310 if (rc) {
1311 return rc;
1312 }
1313
1314 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1315 if (rc) {
1316 return rc;
1317 }
1318 if (PLDM_SUCCESS != resp_data->completion_code) {
1319 return 0;
1320 }
1321
1322 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
1323 return -EBADMSG;
1324 }
1325
1326 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1327 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1328
1329 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
1330 if (rc) {
1331 return rc;
1332 }
1333
1334 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1335 rc = pldm_msgbuf_span_required(
1336 buf, resp_data->downstream_devices_length, &remaining);
1337 if (rc) {
1338 return rc;
1339 }
1340
1341 rc = pldm_msgbuf_destroy(buf);
1342 if (rc) {
1343 return rc;
1344 }
1345
1346 iter->field.ptr = remaining;
1347 iter->field.length = resp_data->downstream_devices_length;
1348 iter->devs = resp_data->number_of_downstream_devices;
1349
1350 return 0;
1351 }
1352
1353 LIBPLDM_ABI_STABLE
decode_pldm_downstream_device_from_iter(struct pldm_downstream_device_iter * iter,struct pldm_downstream_device * dev)1354 int decode_pldm_downstream_device_from_iter(
1355 struct pldm_downstream_device_iter *iter,
1356 struct pldm_downstream_device *dev)
1357 {
1358 struct pldm_msgbuf _buf;
1359 struct pldm_msgbuf *buf = &_buf;
1360 int rc;
1361
1362 if (!iter || !dev) {
1363 return -EINVAL;
1364 }
1365
1366 rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr,
1367 iter->field.length);
1368 if (rc) {
1369 return rc;
1370 }
1371
1372 pldm_msgbuf_extract(buf, dev->downstream_device_index);
1373 pldm_msgbuf_extract(buf, dev->downstream_descriptor_count);
1374 iter->field.ptr = NULL;
1375 pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr,
1376 &iter->field.length);
1377
1378 return pldm_msgbuf_destroy(buf);
1379 }
1380
1381 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)1382 int encode_get_downstream_firmware_parameters_req(
1383 uint8_t instance_id,
1384 const struct pldm_get_downstream_firmware_parameters_req *params_req,
1385 struct pldm_msg *msg, size_t payload_length)
1386 {
1387 struct pldm_msgbuf _buf;
1388 struct pldm_msgbuf *buf = &_buf;
1389 int rc;
1390
1391 if (!msg || !params_req) {
1392 return -EINVAL;
1393 }
1394
1395 rc = pldm_msgbuf_init_errno(
1396 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES,
1397 msg->payload, payload_length);
1398 if (rc < 0) {
1399 return rc;
1400 }
1401
1402 if (!is_transfer_operation_flag_valid(
1403 (enum transfer_op_flag)
1404 params_req->transfer_operation_flag)) {
1405 return -EBADMSG;
1406 }
1407
1408 struct pldm_header_info header = { 0 };
1409 header.instance = instance_id;
1410 header.msg_type = PLDM_REQUEST;
1411 header.pldm_type = PLDM_FWUP;
1412 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1413 rc = pack_pldm_header_errno(&header, &msg->hdr);
1414 if (rc < 0) {
1415 return rc;
1416 }
1417
1418 pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
1419 // Data correctness has been verified, cast it to 1-byte data directly.
1420 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
1421
1422 return pldm_msgbuf_destroy(buf);
1423 }
1424
1425 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)1426 int decode_get_downstream_firmware_parameters_resp(
1427 const struct pldm_msg *msg, size_t payload_length,
1428 struct pldm_get_downstream_firmware_parameters_resp *resp_data,
1429 struct pldm_downstream_device_parameters_iter *iter)
1430 {
1431 struct pldm_msgbuf _buf;
1432 struct pldm_msgbuf *buf = &_buf;
1433 void *remaining = NULL;
1434 size_t length;
1435 int rc;
1436
1437 if (msg == NULL || resp_data == NULL || iter == NULL) {
1438 return -EINVAL;
1439 }
1440
1441 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1442 msg->payload, payload_length);
1443 if (rc < 0) {
1444 return rc;
1445 }
1446
1447 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1448 if (rc < 0) {
1449 return rc;
1450 }
1451 if (PLDM_SUCCESS != resp_data->completion_code) {
1452 return 0;
1453 }
1454
1455 if (payload_length <
1456 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) {
1457 return -EBADMSG;
1458 }
1459
1460 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1461 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1462 pldm_msgbuf_extract(buf,
1463 resp_data->fdp_capabilities_during_update.value);
1464 pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1465
1466 rc = pldm_msgbuf_span_remaining(buf, &remaining, &length);
1467 if (rc) {
1468 return rc;
1469 }
1470
1471 rc = pldm_msgbuf_destroy(buf);
1472 if (rc) {
1473 return rc;
1474 }
1475
1476 iter->field.ptr = remaining;
1477 iter->field.length = length;
1478 iter->entries = resp_data->downstream_device_count;
1479
1480 return 0;
1481 }
1482
1483 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)1484 int decode_pldm_downstream_device_parameters_entry_from_iter(
1485 struct pldm_downstream_device_parameters_iter *iter,
1486 struct pldm_downstream_device_parameters_entry *entry)
1487 {
1488 struct pldm_msgbuf _buf;
1489 struct pldm_msgbuf *buf = &_buf;
1490 void *comp_ver_str;
1491 size_t remaining;
1492 void *cursor;
1493 int rc;
1494
1495 if (iter == NULL || entry == NULL) {
1496 return -EINVAL;
1497 }
1498
1499 rc = pldm_msgbuf_init_errno(
1500 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN,
1501 iter->field.ptr, iter->field.length);
1502 if (rc < 0) {
1503 return rc;
1504 }
1505
1506 pldm_msgbuf_extract(buf, entry->downstream_device_index);
1507 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1508 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1509 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1510 if (rc < 0) {
1511 return rc;
1512 }
1513 rc = pldm_msgbuf_extract_array(buf,
1514 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1515 entry->active_comp_release_date,
1516 sizeof(entry->active_comp_release_date));
1517 if (rc < 0) {
1518 return rc;
1519 }
1520
1521 // Fill the last byte with NULL character
1522 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1523 '\0';
1524
1525 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1526 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1527 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1528 if (rc < 0) {
1529 return rc;
1530 }
1531
1532 rc = pldm_msgbuf_extract_array(
1533 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1534 entry->pending_comp_release_date,
1535 sizeof(entry->pending_comp_release_date));
1536 if (rc < 0) {
1537 return rc;
1538 }
1539
1540 // Fill the last byte with NULL character
1541 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1542 '\0';
1543
1544 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1545 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
1546
1547 comp_ver_str = NULL;
1548 pldm_msgbuf_span_required(buf, entry->active_comp_ver_str_len,
1549 &comp_ver_str);
1550 entry->active_comp_ver_str = comp_ver_str;
1551
1552 comp_ver_str = NULL;
1553 pldm_msgbuf_span_required(buf, entry->pending_comp_ver_str_len,
1554 &comp_ver_str);
1555 entry->pending_comp_ver_str = comp_ver_str;
1556
1557 cursor = NULL;
1558 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1559 if (rc < 0) {
1560 return rc;
1561 }
1562
1563 iter->field.ptr = cursor;
1564 iter->field.length = remaining;
1565
1566 return 0;
1567 }
1568
1569 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)1570 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1571 uint16_t num_of_comp,
1572 uint8_t max_outstanding_transfer_req,
1573 uint16_t pkg_data_len,
1574 uint8_t comp_image_set_ver_str_type,
1575 uint8_t comp_image_set_ver_str_len,
1576 const struct variable_field *comp_img_set_ver_str,
1577 struct pldm_msg *msg, size_t payload_length)
1578 {
1579 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
1580 msg == NULL) {
1581 return PLDM_ERROR_INVALID_DATA;
1582 }
1583
1584 if (payload_length != sizeof(struct pldm_request_update_req) +
1585 comp_img_set_ver_str->length) {
1586 return PLDM_ERROR_INVALID_LENGTH;
1587 }
1588
1589 if ((comp_image_set_ver_str_len == 0) ||
1590 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
1591 return PLDM_ERROR_INVALID_DATA;
1592 }
1593
1594 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
1595 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
1596 return PLDM_ERROR_INVALID_DATA;
1597 }
1598
1599 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
1600 return PLDM_ERROR_INVALID_DATA;
1601 }
1602
1603 struct pldm_header_info header = { 0 };
1604 header.instance = instance_id;
1605 header.msg_type = PLDM_REQUEST;
1606 header.pldm_type = PLDM_FWUP;
1607 header.command = PLDM_REQUEST_UPDATE;
1608 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1609 if (rc) {
1610 return rc;
1611 }
1612
1613 struct pldm_request_update_req *request =
1614 (struct pldm_request_update_req *)msg->payload;
1615
1616 request->max_transfer_size = htole32(max_transfer_size);
1617 request->num_of_comp = htole16(num_of_comp);
1618 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
1619 request->pkg_data_len = htole16(pkg_data_len);
1620 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
1621 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
1622
1623 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
1624 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
1625
1626 return PLDM_SUCCESS;
1627 }
1628
1629 LIBPLDM_ABI_TESTING
decode_request_update_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_request_update_req_full * req)1630 int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length,
1631 struct pldm_request_update_req_full *req)
1632 {
1633 int rc;
1634 uint8_t t;
1635 struct pldm_msgbuf _buf;
1636 struct pldm_msgbuf *buf = &_buf;
1637
1638 if (msg == NULL || req == NULL) {
1639 return -EINVAL;
1640 }
1641
1642 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1643 if (rc) {
1644 return rc;
1645 }
1646
1647 pldm_msgbuf_extract(buf, req->max_transfer_size);
1648 pldm_msgbuf_extract(buf, req->num_of_comp);
1649 pldm_msgbuf_extract(buf, req->max_outstanding_transfer_req);
1650 pldm_msgbuf_extract(buf, req->pkg_data_len);
1651 rc = pldm_msgbuf_extract(buf, t);
1652 if (rc) {
1653 return rc;
1654 }
1655 if (t > PLDM_STR_TYPE_UTF_16BE) {
1656 return -EBADMSG;
1657 }
1658 req->image_set_ver.str_type = (enum pldm_firmware_update_string_type)t;
1659 pldm_msgbuf_extract(buf, req->image_set_ver.str_len);
1660 if (rc) {
1661 return rc;
1662 }
1663
1664 rc = pldm_msgbuf_extract_array(buf, req->image_set_ver.str_len,
1665 req->image_set_ver.str_data,
1666 PLDM_FIRMWARE_MAX_STRING);
1667 if (rc) {
1668 return rc;
1669 }
1670
1671 return pldm_msgbuf_destroy_consumed(buf);
1672 }
1673
1674 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)1675 int decode_request_update_resp(const struct pldm_msg *msg,
1676 size_t payload_length, uint8_t *completion_code,
1677 uint16_t *fd_meta_data_len,
1678 uint8_t *fd_will_send_pkg_data)
1679 {
1680 if (msg == NULL || completion_code == NULL ||
1681 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
1682 !payload_length) {
1683 return PLDM_ERROR_INVALID_DATA;
1684 }
1685
1686 *completion_code = msg->payload[0];
1687 if (*completion_code != PLDM_SUCCESS) {
1688 return PLDM_SUCCESS;
1689 }
1690
1691 if (payload_length != sizeof(struct pldm_request_update_resp)) {
1692 return PLDM_ERROR_INVALID_LENGTH;
1693 }
1694
1695 struct pldm_request_update_resp *response =
1696 (struct pldm_request_update_resp *)msg->payload;
1697
1698 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
1699 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1700
1701 return PLDM_SUCCESS;
1702 }
1703
1704 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)1705 int encode_request_update_resp(uint8_t instance_id,
1706 const struct pldm_request_update_resp *resp_data,
1707 struct pldm_msg *msg, size_t *payload_length)
1708 {
1709 int rc;
1710 struct pldm_msgbuf _buf;
1711 struct pldm_msgbuf *buf = &_buf;
1712
1713 if (msg == NULL || payload_length == NULL) {
1714 return -EINVAL;
1715 }
1716
1717 struct pldm_header_info header = {
1718 .instance = instance_id,
1719 .msg_type = PLDM_RESPONSE,
1720 .pldm_type = PLDM_FWUP,
1721 .command = PLDM_REQUEST_UPDATE,
1722 };
1723 rc = pack_pldm_header(&header, &(msg->hdr));
1724 if (rc) {
1725 return -EINVAL;
1726 }
1727
1728 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1729 if (rc) {
1730 return rc;
1731 }
1732
1733 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1734 pldm_msgbuf_insert(buf, resp_data->fd_meta_data_len);
1735 pldm_msgbuf_insert(buf, resp_data->fd_will_send_pkg_data);
1736
1737 /* TODO: DSP0267 1.3.0 adds GetPackageDataMaximumTransferSize */
1738
1739 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
1740 }
1741
1742 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)1743 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1744 uint16_t comp_classification,
1745 uint16_t comp_identifier,
1746 uint8_t comp_classification_index,
1747 uint32_t comp_comparison_stamp,
1748 uint8_t comp_ver_str_type,
1749 uint8_t comp_ver_str_len,
1750 const struct variable_field *comp_ver_str,
1751 struct pldm_msg *msg, size_t payload_length)
1752 {
1753 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1754 return PLDM_ERROR_INVALID_DATA;
1755 }
1756
1757 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
1758 comp_ver_str->length) {
1759 return PLDM_ERROR_INVALID_LENGTH;
1760 }
1761
1762 if ((comp_ver_str_len == 0) ||
1763 (comp_ver_str_len != comp_ver_str->length)) {
1764 return PLDM_ERROR_INVALID_DATA;
1765 }
1766
1767 if (!is_transfer_flag_valid(transfer_flag)) {
1768 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1769 }
1770
1771 if (!is_string_type_valid(comp_ver_str_type)) {
1772 return PLDM_ERROR_INVALID_DATA;
1773 }
1774
1775 struct pldm_header_info header = { 0 };
1776 header.instance = instance_id;
1777 header.msg_type = PLDM_REQUEST;
1778 header.pldm_type = PLDM_FWUP;
1779 header.command = PLDM_PASS_COMPONENT_TABLE;
1780 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1781 if (rc) {
1782 return rc;
1783 }
1784
1785 struct pldm_pass_component_table_req *request =
1786 (struct pldm_pass_component_table_req *)msg->payload;
1787
1788 request->transfer_flag = transfer_flag;
1789 request->comp_classification = htole16(comp_classification);
1790 request->comp_identifier = htole16(comp_identifier);
1791 request->comp_classification_index = comp_classification_index;
1792 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1793 request->comp_ver_str_type = comp_ver_str_type;
1794 request->comp_ver_str_len = comp_ver_str_len;
1795
1796 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1797 comp_ver_str->ptr, comp_ver_str->length);
1798
1799 return PLDM_SUCCESS;
1800 }
1801
1802 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)1803 int decode_pass_component_table_req(
1804 const struct pldm_msg *msg, size_t payload_length,
1805 struct pldm_pass_component_table_req_full *pcomp)
1806 {
1807 int rc;
1808 uint8_t t;
1809 struct pldm_msgbuf _buf;
1810 struct pldm_msgbuf *buf = &_buf;
1811
1812 if (msg == NULL || pcomp == NULL) {
1813 return -EINVAL;
1814 }
1815
1816 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1817 if (rc) {
1818 return rc;
1819 }
1820
1821 pldm_msgbuf_extract(buf, pcomp->transfer_flag);
1822 pldm_msgbuf_extract(buf, pcomp->comp_classification);
1823 pldm_msgbuf_extract(buf, pcomp->comp_identifier);
1824 pldm_msgbuf_extract(buf, pcomp->comp_classification_index);
1825 pldm_msgbuf_extract(buf, pcomp->comp_comparison_stamp);
1826 rc = pldm_msgbuf_extract(buf, t);
1827 if (rc) {
1828 return rc;
1829 }
1830 if (t > PLDM_STR_TYPE_UTF_16BE) {
1831 return -EBADMSG;
1832 }
1833 pcomp->version.str_type = (enum pldm_firmware_update_string_type)t;
1834 rc = pldm_msgbuf_extract(buf, pcomp->version.str_len);
1835 if (rc) {
1836 return rc;
1837 }
1838 rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len,
1839 pcomp->version.str_data,
1840 PLDM_FIRMWARE_MAX_STRING);
1841 if (rc) {
1842 return rc;
1843 }
1844
1845 return pldm_msgbuf_destroy_consumed(buf);
1846 }
1847
1848 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)1849 int decode_pass_component_table_resp(const struct pldm_msg *msg,
1850 const size_t payload_length,
1851 uint8_t *completion_code,
1852 uint8_t *comp_resp,
1853 uint8_t *comp_resp_code)
1854 {
1855 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1856 comp_resp_code == NULL || !payload_length) {
1857 return PLDM_ERROR_INVALID_DATA;
1858 }
1859
1860 *completion_code = msg->payload[0];
1861 if (*completion_code != PLDM_SUCCESS) {
1862 return PLDM_SUCCESS;
1863 }
1864
1865 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1866 return PLDM_ERROR_INVALID_LENGTH;
1867 }
1868
1869 struct pldm_pass_component_table_resp *response =
1870 (struct pldm_pass_component_table_resp *)msg->payload;
1871
1872 if (!is_comp_resp_valid(response->comp_resp)) {
1873 return PLDM_ERROR_INVALID_DATA;
1874 }
1875
1876 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1877 return PLDM_ERROR_INVALID_DATA;
1878 }
1879
1880 *comp_resp = response->comp_resp;
1881 *comp_resp_code = response->comp_resp_code;
1882
1883 return PLDM_SUCCESS;
1884 }
1885
1886 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)1887 int encode_pass_component_table_resp(
1888 uint8_t instance_id,
1889 const struct pldm_pass_component_table_resp *resp_data,
1890 struct pldm_msg *msg, size_t *payload_length)
1891 {
1892 int rc;
1893 struct pldm_msgbuf _buf;
1894 struct pldm_msgbuf *buf = &_buf;
1895
1896 if (msg == NULL || payload_length == NULL) {
1897 return -EINVAL;
1898 }
1899
1900 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
1901 PLDM_PASS_COMPONENT_TABLE, msg);
1902 if (rc) {
1903 return -EINVAL;
1904 }
1905
1906 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1907 if (rc) {
1908 return rc;
1909 }
1910
1911 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1912 pldm_msgbuf_insert(buf, resp_data->comp_resp);
1913 pldm_msgbuf_insert(buf, resp_data->comp_resp_code);
1914
1915 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
1916 }
1917
1918 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)1919 int encode_update_component_req(
1920 uint8_t instance_id, uint16_t comp_classification,
1921 uint16_t comp_identifier, uint8_t comp_classification_index,
1922 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1923 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1924 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1925 struct pldm_msg *msg, size_t payload_length)
1926 {
1927 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1928 return PLDM_ERROR_INVALID_DATA;
1929 }
1930
1931 if (payload_length !=
1932 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1933 return PLDM_ERROR_INVALID_LENGTH;
1934 }
1935
1936 if (!comp_image_size) {
1937 return PLDM_ERROR_INVALID_DATA;
1938 }
1939
1940 if ((comp_ver_str_len == 0) ||
1941 (comp_ver_str_len != comp_ver_str->length)) {
1942 return PLDM_ERROR_INVALID_DATA;
1943 }
1944
1945 if (!is_string_type_valid(comp_ver_str_type)) {
1946 return PLDM_ERROR_INVALID_DATA;
1947 }
1948
1949 struct pldm_header_info header = { 0 };
1950 header.instance = instance_id;
1951 header.msg_type = PLDM_REQUEST;
1952 header.pldm_type = PLDM_FWUP;
1953 header.command = PLDM_UPDATE_COMPONENT;
1954 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1955 if (rc) {
1956 return rc;
1957 }
1958
1959 struct pldm_update_component_req *request =
1960 (struct pldm_update_component_req *)msg->payload;
1961
1962 request->comp_classification = htole16(comp_classification);
1963 request->comp_identifier = htole16(comp_identifier);
1964 request->comp_classification_index = comp_classification_index;
1965 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1966 request->comp_image_size = htole32(comp_image_size);
1967 request->update_option_flags.value = htole32(update_option_flags.value);
1968 request->comp_ver_str_type = comp_ver_str_type;
1969 request->comp_ver_str_len = comp_ver_str_len;
1970
1971 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1972 comp_ver_str->ptr, comp_ver_str->length);
1973
1974 return PLDM_SUCCESS;
1975 }
1976
1977 LIBPLDM_ABI_TESTING
decode_update_component_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_update_component_req_full * up)1978 int decode_update_component_req(const struct pldm_msg *msg,
1979 size_t payload_length,
1980 struct pldm_update_component_req_full *up)
1981 {
1982 int rc;
1983 uint8_t t;
1984 struct pldm_msgbuf _buf;
1985 struct pldm_msgbuf *buf = &_buf;
1986
1987 if (msg == NULL || up == NULL) {
1988 return -EINVAL;
1989 }
1990
1991 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1992 if (rc) {
1993 return rc;
1994 }
1995
1996 pldm_msgbuf_extract(buf, up->comp_classification);
1997 pldm_msgbuf_extract(buf, up->comp_identifier);
1998 pldm_msgbuf_extract(buf, up->comp_classification_index);
1999 pldm_msgbuf_extract(buf, up->comp_comparison_stamp);
2000 pldm_msgbuf_extract(buf, up->comp_image_size);
2001 pldm_msgbuf_extract(buf, up->update_option_flags.value);
2002 rc = pldm_msgbuf_extract(buf, t);
2003 if (rc) {
2004 return rc;
2005 }
2006 if (t > PLDM_STR_TYPE_UTF_16BE) {
2007 return -EBADMSG;
2008 }
2009 up->version.str_type = (enum pldm_firmware_update_string_type)t;
2010 rc = pldm_msgbuf_extract(buf, up->version.str_len);
2011 if (rc) {
2012 return rc;
2013 }
2014 rc = pldm_msgbuf_extract_array(buf, up->version.str_len,
2015 up->version.str_data,
2016 PLDM_FIRMWARE_MAX_STRING);
2017 if (rc) {
2018 return rc;
2019 }
2020
2021 if (buf->remaining != 0) {
2022 return -EINVAL;
2023 }
2024
2025 return 0;
2026 }
2027
2028 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)2029 int decode_update_component_resp(const struct pldm_msg *msg,
2030 size_t payload_length,
2031 uint8_t *completion_code,
2032 uint8_t *comp_compatibility_resp,
2033 uint8_t *comp_compatibility_resp_code,
2034 bitfield32_t *update_option_flags_enabled,
2035 uint16_t *time_before_req_fw_data)
2036 {
2037 if (msg == NULL || completion_code == NULL ||
2038 comp_compatibility_resp == NULL ||
2039 comp_compatibility_resp_code == NULL ||
2040 update_option_flags_enabled == NULL ||
2041 time_before_req_fw_data == NULL || !payload_length) {
2042 return PLDM_ERROR_INVALID_DATA;
2043 }
2044
2045 *completion_code = msg->payload[0];
2046 if (*completion_code != PLDM_SUCCESS) {
2047 return PLDM_SUCCESS;
2048 }
2049
2050 if (payload_length != sizeof(struct pldm_update_component_resp)) {
2051 return PLDM_ERROR_INVALID_LENGTH;
2052 }
2053
2054 struct pldm_update_component_resp *response =
2055 (struct pldm_update_component_resp *)msg->payload;
2056
2057 if (!is_comp_compatibility_resp_valid(
2058 response->comp_compatibility_resp)) {
2059 return PLDM_ERROR_INVALID_DATA;
2060 }
2061
2062 if (!is_comp_compatibility_resp_code_valid(
2063 response->comp_compatibility_resp_code)) {
2064 return PLDM_ERROR_INVALID_DATA;
2065 }
2066
2067 *comp_compatibility_resp = response->comp_compatibility_resp;
2068 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
2069 update_option_flags_enabled->value =
2070 le32toh(response->update_option_flags_enabled.value);
2071 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
2072
2073 return PLDM_SUCCESS;
2074 }
2075
2076 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)2077 int encode_update_component_resp(
2078 uint8_t instance_id, const struct pldm_update_component_resp *resp_data,
2079 struct pldm_msg *msg, size_t *payload_length)
2080 {
2081 int rc;
2082 struct pldm_msgbuf _buf;
2083 struct pldm_msgbuf *buf = &_buf;
2084
2085 if (msg == NULL || payload_length == NULL) {
2086 return -EINVAL;
2087 }
2088
2089 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2090 PLDM_UPDATE_COMPONENT, msg);
2091 if (rc) {
2092 return -EINVAL;
2093 }
2094
2095 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2096 if (rc) {
2097 return rc;
2098 }
2099
2100 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2101 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp);
2102 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp_code);
2103 pldm_msgbuf_insert(buf, resp_data->update_option_flags_enabled.value);
2104 pldm_msgbuf_insert(buf, resp_data->time_before_req_fw_data);
2105
2106 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2107 }
2108
2109 LIBPLDM_ABI_STABLE
decode_request_firmware_data_req(const struct pldm_msg * msg,size_t payload_length,uint32_t * offset,uint32_t * length)2110 int decode_request_firmware_data_req(const struct pldm_msg *msg,
2111 size_t payload_length, uint32_t *offset,
2112 uint32_t *length)
2113 {
2114 if (msg == NULL || offset == NULL || length == NULL) {
2115 return PLDM_ERROR_INVALID_DATA;
2116 }
2117 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
2118 return PLDM_ERROR_INVALID_LENGTH;
2119 }
2120 struct pldm_request_firmware_data_req *request =
2121 (struct pldm_request_firmware_data_req *)msg->payload;
2122 *offset = le32toh(request->offset);
2123 *length = le32toh(request->length);
2124
2125 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
2126 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
2127 }
2128
2129 return PLDM_SUCCESS;
2130 }
2131
2132 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)2133 int encode_request_firmware_data_req(
2134 uint8_t instance_id,
2135 const struct pldm_request_firmware_data_req *req_params,
2136 struct pldm_msg *msg, size_t *payload_length)
2137 {
2138 int rc;
2139 struct pldm_msgbuf _buf;
2140 struct pldm_msgbuf *buf = &_buf;
2141
2142 if (msg == NULL || payload_length == NULL) {
2143 return -EINVAL;
2144 }
2145
2146 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2147 PLDM_REQUEST_FIRMWARE_DATA, msg);
2148 if (rc) {
2149 return -EINVAL;
2150 }
2151
2152 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2153 if (rc) {
2154 return rc;
2155 }
2156
2157 pldm_msgbuf_insert(buf, req_params->offset);
2158 pldm_msgbuf_insert(buf, req_params->length);
2159
2160 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2161 }
2162
2163 LIBPLDM_ABI_STABLE
encode_request_firmware_data_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2164 int encode_request_firmware_data_resp(uint8_t instance_id,
2165 uint8_t completion_code,
2166 struct pldm_msg *msg,
2167 size_t payload_length)
2168 {
2169 if (msg == NULL || !payload_length) {
2170 return PLDM_ERROR_INVALID_DATA;
2171 }
2172
2173 struct pldm_header_info header = { 0 };
2174 header.instance = instance_id;
2175 header.msg_type = PLDM_RESPONSE;
2176 header.pldm_type = PLDM_FWUP;
2177 header.command = PLDM_REQUEST_FIRMWARE_DATA;
2178 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2179 if (rc) {
2180 return rc;
2181 }
2182
2183 msg->payload[0] = completion_code;
2184
2185 return PLDM_SUCCESS;
2186 }
2187
2188 LIBPLDM_ABI_STABLE
decode_transfer_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * transfer_result)2189 int decode_transfer_complete_req(const struct pldm_msg *msg,
2190 size_t payload_length,
2191 uint8_t *transfer_result)
2192 {
2193 if (msg == NULL || transfer_result == NULL) {
2194 return PLDM_ERROR_INVALID_DATA;
2195 }
2196
2197 if (payload_length != sizeof(*transfer_result)) {
2198 return PLDM_ERROR_INVALID_LENGTH;
2199 }
2200
2201 *transfer_result = msg->payload[0];
2202 return PLDM_SUCCESS;
2203 }
2204
2205 LIBPLDM_ABI_TESTING
encode_transfer_complete_req(uint8_t instance_id,uint8_t transfer_result,struct pldm_msg * msg,size_t * payload_length)2206 int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
2207 struct pldm_msg *msg, size_t *payload_length)
2208 {
2209 int rc;
2210 struct pldm_msgbuf _buf;
2211 struct pldm_msgbuf *buf = &_buf;
2212
2213 if (msg == NULL || payload_length == NULL) {
2214 return -EINVAL;
2215 }
2216
2217 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2218 PLDM_TRANSFER_COMPLETE, msg);
2219 if (rc) {
2220 return -EINVAL;
2221 }
2222
2223 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2224 if (rc) {
2225 return rc;
2226 }
2227
2228 rc = pldm_msgbuf_insert(buf, transfer_result);
2229 if (rc) {
2230 return rc;
2231 }
2232
2233 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2234 }
2235
2236 LIBPLDM_ABI_STABLE
encode_transfer_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2237 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
2238 struct pldm_msg *msg, size_t payload_length)
2239 {
2240 if (msg == NULL) {
2241 return PLDM_ERROR_INVALID_DATA;
2242 }
2243
2244 if (payload_length != sizeof(completion_code)) {
2245 return PLDM_ERROR_INVALID_LENGTH;
2246 }
2247
2248 struct pldm_header_info header = { 0 };
2249 header.instance = instance_id;
2250 header.msg_type = PLDM_RESPONSE;
2251 header.pldm_type = PLDM_FWUP;
2252 header.command = PLDM_TRANSFER_COMPLETE;
2253 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2254 if (rc) {
2255 return rc;
2256 }
2257
2258 msg->payload[0] = completion_code;
2259
2260 return PLDM_SUCCESS;
2261 }
2262
2263 LIBPLDM_ABI_STABLE
decode_verify_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * verify_result)2264 int decode_verify_complete_req(const struct pldm_msg *msg,
2265 size_t payload_length, uint8_t *verify_result)
2266 {
2267 if (msg == NULL || verify_result == NULL) {
2268 return PLDM_ERROR_INVALID_DATA;
2269 }
2270
2271 if (payload_length != sizeof(*verify_result)) {
2272 return PLDM_ERROR_INVALID_LENGTH;
2273 }
2274
2275 *verify_result = msg->payload[0];
2276 return PLDM_SUCCESS;
2277 }
2278
2279 LIBPLDM_ABI_TESTING
encode_verify_complete_req(uint8_t instance_id,uint8_t verify_result,struct pldm_msg * msg,size_t * payload_length)2280 int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
2281 struct pldm_msg *msg, size_t *payload_length)
2282 {
2283 int rc;
2284 struct pldm_msgbuf _buf;
2285 struct pldm_msgbuf *buf = &_buf;
2286
2287 if (msg == NULL || payload_length == NULL) {
2288 return -EINVAL;
2289 }
2290
2291 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2292 PLDM_VERIFY_COMPLETE, msg);
2293 if (rc) {
2294 return EINVAL;
2295 }
2296
2297 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2298 if (rc) {
2299 return rc;
2300 }
2301
2302 rc = pldm_msgbuf_insert(buf, verify_result);
2303 if (rc) {
2304 return rc;
2305 }
2306
2307 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2308 }
2309
2310 LIBPLDM_ABI_STABLE
encode_verify_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2311 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
2312 struct pldm_msg *msg, size_t payload_length)
2313 {
2314 if (msg == NULL) {
2315 return PLDM_ERROR_INVALID_DATA;
2316 }
2317
2318 if (payload_length != sizeof(completion_code)) {
2319 return PLDM_ERROR_INVALID_LENGTH;
2320 }
2321
2322 struct pldm_header_info header = { 0 };
2323 header.instance = instance_id;
2324 header.msg_type = PLDM_RESPONSE;
2325 header.pldm_type = PLDM_FWUP;
2326 header.command = PLDM_VERIFY_COMPLETE;
2327 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2328 if (rc) {
2329 return rc;
2330 }
2331
2332 msg->payload[0] = completion_code;
2333
2334 return PLDM_SUCCESS;
2335 }
2336
2337 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)2338 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
2339 uint8_t *apply_result,
2340 bitfield16_t *comp_activation_methods_modification)
2341 {
2342 if (msg == NULL || apply_result == NULL ||
2343 comp_activation_methods_modification == NULL) {
2344 return PLDM_ERROR_INVALID_DATA;
2345 }
2346
2347 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
2348 return PLDM_ERROR_INVALID_LENGTH;
2349 }
2350
2351 struct pldm_apply_complete_req *request =
2352 (struct pldm_apply_complete_req *)msg->payload;
2353
2354 *apply_result = request->apply_result;
2355 comp_activation_methods_modification->value =
2356 le16toh(request->comp_activation_methods_modification.value);
2357
2358 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
2359 comp_activation_methods_modification->value) {
2360 return PLDM_ERROR_INVALID_DATA;
2361 }
2362
2363 return PLDM_SUCCESS;
2364 }
2365
2366 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)2367 int encode_apply_complete_req(uint8_t instance_id,
2368 const struct pldm_apply_complete_req *req_data,
2369 struct pldm_msg *msg, size_t *payload_length)
2370 {
2371 int rc;
2372 struct pldm_msgbuf _buf;
2373 struct pldm_msgbuf *buf = &_buf;
2374
2375 if (msg == NULL || payload_length == NULL) {
2376 return -EINVAL;
2377 }
2378
2379 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2380 PLDM_APPLY_COMPLETE, msg);
2381 if (rc) {
2382 return -EINVAL;
2383 }
2384
2385 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2386 if (rc) {
2387 return rc;
2388 }
2389
2390 pldm_msgbuf_insert(buf, req_data->apply_result);
2391 pldm_msgbuf_insert(
2392 buf, req_data->comp_activation_methods_modification.value);
2393
2394 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2395 }
2396
2397 LIBPLDM_ABI_STABLE
encode_apply_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2398 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
2399 struct pldm_msg *msg, size_t payload_length)
2400 {
2401 if (msg == NULL) {
2402 return PLDM_ERROR_INVALID_DATA;
2403 }
2404
2405 if (payload_length != sizeof(completion_code)) {
2406 return PLDM_ERROR_INVALID_LENGTH;
2407 }
2408
2409 struct pldm_header_info header = { 0 };
2410 header.instance = instance_id;
2411 header.msg_type = PLDM_RESPONSE;
2412 header.pldm_type = PLDM_FWUP;
2413 header.command = PLDM_APPLY_COMPLETE;
2414 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2415 if (rc) {
2416 return rc;
2417 }
2418
2419 msg->payload[0] = completion_code;
2420
2421 return PLDM_SUCCESS;
2422 }
2423
2424 LIBPLDM_ABI_TESTING
decode_activate_firmware_req(const struct pldm_msg * msg,size_t payload_length,bool * self_contained)2425 int decode_activate_firmware_req(const struct pldm_msg *msg,
2426 size_t payload_length, bool *self_contained)
2427 {
2428 int rc;
2429 struct pldm_msgbuf _buf;
2430 struct pldm_msgbuf *buf = &_buf;
2431
2432 if (msg == NULL || self_contained == NULL) {
2433 return -EINVAL;
2434 }
2435
2436 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
2437 if (rc) {
2438 return 0;
2439 }
2440
2441 uint8_t self_contained_u8 = 0;
2442 rc = pldm_msgbuf_extract(buf, self_contained_u8);
2443 if (rc) {
2444 return rc;
2445 }
2446 if (buf->remaining != 0) {
2447 return -EOVERFLOW;
2448 }
2449 *self_contained = (bool)self_contained_u8;
2450 return 0;
2451 }
2452
2453 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)2454 int encode_activate_firmware_req(uint8_t instance_id,
2455 bool8_t self_contained_activation_req,
2456 struct pldm_msg *msg, size_t payload_length)
2457 {
2458 if (msg == NULL) {
2459 return PLDM_ERROR_INVALID_DATA;
2460 }
2461
2462 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
2463 return PLDM_ERROR_INVALID_LENGTH;
2464 }
2465
2466 if (!is_self_contained_activation_req_valid(
2467 self_contained_activation_req)) {
2468 return PLDM_ERROR_INVALID_DATA;
2469 }
2470
2471 struct pldm_header_info header = { 0 };
2472 header.instance = instance_id;
2473 header.msg_type = PLDM_REQUEST;
2474 header.pldm_type = PLDM_FWUP;
2475 header.command = PLDM_ACTIVATE_FIRMWARE;
2476 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2477 if (rc) {
2478 return rc;
2479 }
2480
2481 struct pldm_activate_firmware_req *request =
2482 (struct pldm_activate_firmware_req *)msg->payload;
2483
2484 request->self_contained_activation_req = self_contained_activation_req;
2485
2486 return PLDM_SUCCESS;
2487 }
2488
2489 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)2490 int decode_activate_firmware_resp(const struct pldm_msg *msg,
2491 size_t payload_length,
2492 uint8_t *completion_code,
2493 uint16_t *estimated_time_activation)
2494 {
2495 if (msg == NULL || completion_code == NULL ||
2496 estimated_time_activation == NULL || !payload_length) {
2497 return PLDM_ERROR_INVALID_DATA;
2498 }
2499
2500 *completion_code = msg->payload[0];
2501 if (*completion_code != PLDM_SUCCESS) {
2502 return PLDM_SUCCESS;
2503 }
2504
2505 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
2506 return PLDM_ERROR_INVALID_LENGTH;
2507 }
2508
2509 struct pldm_activate_firmware_resp *response =
2510 (struct pldm_activate_firmware_resp *)msg->payload;
2511
2512 *estimated_time_activation =
2513 le16toh(response->estimated_time_activation);
2514
2515 return PLDM_SUCCESS;
2516 }
2517
2518 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)2519 int encode_activate_firmware_resp(
2520 uint8_t instance_id,
2521 const struct pldm_activate_firmware_resp *resp_data,
2522 struct pldm_msg *msg, size_t *payload_length)
2523 {
2524 int rc;
2525 struct pldm_msgbuf _buf;
2526 struct pldm_msgbuf *buf = &_buf;
2527
2528 if (msg == NULL || payload_length == NULL) {
2529 return -EINVAL;
2530 }
2531
2532 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2533 PLDM_ACTIVATE_FIRMWARE, msg);
2534 if (rc) {
2535 return -EINVAL;
2536 }
2537
2538 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2539 if (rc) {
2540 return rc;
2541 }
2542
2543 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2544 pldm_msgbuf_insert(buf, resp_data->estimated_time_activation);
2545
2546 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2547 }
2548
2549 LIBPLDM_ABI_STABLE
encode_get_status_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)2550 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
2551 size_t payload_length)
2552 {
2553 if (msg == NULL) {
2554 return PLDM_ERROR_INVALID_DATA;
2555 }
2556
2557 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
2558 return PLDM_ERROR_INVALID_LENGTH;
2559 }
2560
2561 struct pldm_header_info header = { 0 };
2562 header.instance = instance_id;
2563 header.msg_type = PLDM_REQUEST;
2564 header.pldm_type = PLDM_FWUP;
2565 header.command = PLDM_GET_STATUS;
2566 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2567 if (rc) {
2568 return rc;
2569 }
2570
2571 return PLDM_SUCCESS;
2572 }
2573
2574 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)2575 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
2576 uint8_t *completion_code, uint8_t *current_state,
2577 uint8_t *previous_state, uint8_t *aux_state,
2578 uint8_t *aux_state_status, uint8_t *progress_percent,
2579 uint8_t *reason_code,
2580 bitfield32_t *update_option_flags_enabled)
2581 {
2582 if (msg == NULL || completion_code == NULL || current_state == NULL ||
2583 previous_state == NULL || aux_state == NULL ||
2584 aux_state_status == NULL || progress_percent == NULL ||
2585 reason_code == NULL || update_option_flags_enabled == NULL ||
2586 !payload_length) {
2587 return PLDM_ERROR_INVALID_DATA;
2588 }
2589
2590 *completion_code = msg->payload[0];
2591 if (*completion_code != PLDM_SUCCESS) {
2592 return PLDM_SUCCESS;
2593 }
2594
2595 if (payload_length != sizeof(struct pldm_get_status_resp)) {
2596 return PLDM_ERROR_INVALID_LENGTH;
2597 }
2598 struct pldm_get_status_resp *response =
2599 (struct pldm_get_status_resp *)msg->payload;
2600
2601 if (!is_state_valid(response->current_state)) {
2602 return PLDM_ERROR_INVALID_DATA;
2603 }
2604 if (!is_state_valid(response->previous_state)) {
2605 return PLDM_ERROR_INVALID_DATA;
2606 }
2607 if (!is_aux_state_valid(response->aux_state)) {
2608 return PLDM_ERROR_INVALID_DATA;
2609 }
2610 if (!is_aux_state_status_valid(response->aux_state_status)) {
2611 return PLDM_ERROR_INVALID_DATA;
2612 }
2613 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
2614 return PLDM_ERROR_INVALID_DATA;
2615 }
2616 if (!is_reason_code_valid(response->reason_code)) {
2617 return PLDM_ERROR_INVALID_DATA;
2618 }
2619
2620 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
2621 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
2622 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
2623 if (response->aux_state !=
2624 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
2625 return PLDM_ERROR_INVALID_DATA;
2626 }
2627 }
2628
2629 *current_state = response->current_state;
2630 *previous_state = response->previous_state;
2631 *aux_state = response->aux_state;
2632 *aux_state_status = response->aux_state_status;
2633 *progress_percent = response->progress_percent;
2634 *reason_code = response->reason_code;
2635 update_option_flags_enabled->value =
2636 le32toh(response->update_option_flags_enabled.value);
2637
2638 return PLDM_SUCCESS;
2639 }
2640
2641 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)2642 int encode_get_status_resp(uint8_t instance_id,
2643 const struct pldm_get_status_resp *status,
2644 struct pldm_msg *msg, size_t *payload_length)
2645 {
2646 int rc;
2647 struct pldm_msgbuf _buf;
2648 struct pldm_msgbuf *buf = &_buf;
2649
2650 if (status == NULL || msg == NULL || payload_length == NULL) {
2651 return -EINVAL;
2652 }
2653
2654 if (status->completion_code != PLDM_SUCCESS) {
2655 return -EINVAL;
2656 }
2657
2658 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2659 PLDM_GET_STATUS, msg);
2660 if (rc) {
2661 return -EINVAL;
2662 }
2663
2664 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2665 if (rc) {
2666 return rc;
2667 }
2668
2669 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2670 pldm_msgbuf_insert(buf, status->current_state);
2671 pldm_msgbuf_insert(buf, status->previous_state);
2672 pldm_msgbuf_insert(buf, status->aux_state);
2673 pldm_msgbuf_insert(buf, status->aux_state_status);
2674 pldm_msgbuf_insert(buf, status->progress_percent);
2675 pldm_msgbuf_insert(buf, status->reason_code);
2676 pldm_msgbuf_insert(buf, status->update_option_flags_enabled.value);
2677
2678 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2679 }
2680
2681 LIBPLDM_ABI_STABLE
encode_cancel_update_component_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)2682 int encode_cancel_update_component_req(uint8_t instance_id,
2683 struct pldm_msg *msg,
2684 size_t payload_length)
2685 {
2686 if (msg == NULL) {
2687 return PLDM_ERROR_INVALID_DATA;
2688 }
2689
2690 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
2691 return PLDM_ERROR_INVALID_LENGTH;
2692 }
2693
2694 struct pldm_header_info header = { 0 };
2695 header.instance = instance_id;
2696 header.msg_type = PLDM_REQUEST;
2697 header.pldm_type = PLDM_FWUP;
2698 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
2699 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2700 if (rc) {
2701 return rc;
2702 }
2703
2704 return PLDM_SUCCESS;
2705 }
2706
2707 LIBPLDM_ABI_STABLE
decode_cancel_update_component_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code)2708 int decode_cancel_update_component_resp(const struct pldm_msg *msg,
2709 size_t payload_length,
2710 uint8_t *completion_code)
2711 {
2712 if (msg == NULL || completion_code == NULL) {
2713 return PLDM_ERROR_INVALID_DATA;
2714 }
2715
2716 if (payload_length != sizeof(*completion_code)) {
2717 return PLDM_ERROR_INVALID_LENGTH;
2718 }
2719
2720 *completion_code = msg->payload[0];
2721 return PLDM_SUCCESS;
2722 }
2723
2724 LIBPLDM_ABI_STABLE
encode_cancel_update_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)2725 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
2726 size_t payload_length)
2727 {
2728 if (msg == NULL) {
2729 return PLDM_ERROR_INVALID_DATA;
2730 }
2731
2732 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
2733 return PLDM_ERROR_INVALID_LENGTH;
2734 }
2735
2736 struct pldm_header_info header = { 0 };
2737 header.instance = instance_id;
2738 header.msg_type = PLDM_REQUEST;
2739 header.pldm_type = PLDM_FWUP;
2740 header.command = PLDM_CANCEL_UPDATE;
2741 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2742 if (rc) {
2743 return rc;
2744 }
2745
2746 return PLDM_SUCCESS;
2747 }
2748
2749 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)2750 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
2751 uint8_t *completion_code,
2752 bool8_t *non_functioning_component_indication,
2753 bitfield64_t *non_functioning_component_bitmap)
2754 {
2755 if (msg == NULL || completion_code == NULL ||
2756 non_functioning_component_indication == NULL ||
2757 non_functioning_component_bitmap == NULL || !payload_length) {
2758 return PLDM_ERROR_INVALID_DATA;
2759 }
2760
2761 *completion_code = msg->payload[0];
2762 if (*completion_code != PLDM_SUCCESS) {
2763 return PLDM_SUCCESS;
2764 }
2765
2766 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
2767 return PLDM_ERROR_INVALID_LENGTH;
2768 }
2769 struct pldm_cancel_update_resp *response =
2770 (struct pldm_cancel_update_resp *)msg->payload;
2771
2772 if (!is_non_functioning_component_indication_valid(
2773 response->non_functioning_component_indication)) {
2774 return PLDM_ERROR_INVALID_DATA;
2775 }
2776
2777 *non_functioning_component_indication =
2778 response->non_functioning_component_indication;
2779
2780 if (*non_functioning_component_indication) {
2781 non_functioning_component_bitmap->value =
2782 le64toh(response->non_functioning_component_bitmap);
2783 }
2784
2785 return PLDM_SUCCESS;
2786 }
2787
2788 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)2789 int encode_cancel_update_resp(uint8_t instance_id,
2790 const struct pldm_cancel_update_resp *resp_data,
2791 struct pldm_msg *msg, size_t *payload_length)
2792 {
2793 int rc;
2794 struct pldm_msgbuf _buf;
2795 struct pldm_msgbuf *buf = &_buf;
2796
2797 if (msg == NULL || payload_length == NULL) {
2798 return -EINVAL;
2799 }
2800
2801 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2802 PLDM_CANCEL_UPDATE, msg);
2803 if (rc) {
2804 return -EINVAL;
2805 }
2806
2807 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2808 if (rc) {
2809 return rc;
2810 }
2811
2812 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2813 pldm_msgbuf_insert(buf,
2814 resp_data->non_functioning_component_indication);
2815 pldm_msgbuf_insert(buf, resp_data->non_functioning_component_bitmap);
2816
2817 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2818 }
2819