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