blob: bd6ed9a0ba9ef62e8701841c5dfe68734486f60a [file] [log] [blame]
Andrew Jeffery9c766792022-08-10 23:12:49 +09301#include "firmware_update.h"
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05302#include "utils.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +09303#include <endian.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05304#include <stdbool.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09305#include <string.h>
6
7/** @brief Check whether string type value is valid
8 *
9 * @return true if string type value is valid, false if not
10 */
11static bool is_string_type_valid(uint8_t string_type)
12{
13 switch (string_type) {
14 case PLDM_STR_TYPE_UNKNOWN:
15 return false;
16 case PLDM_STR_TYPE_ASCII:
17 case PLDM_STR_TYPE_UTF_8:
18 case PLDM_STR_TYPE_UTF_16:
19 case PLDM_STR_TYPE_UTF_16LE:
20 case PLDM_STR_TYPE_UTF_16BE:
21 return true;
22 default:
23 return false;
24 }
25}
26
27/** @brief Return the length of the descriptor type described in firmware update
28 * specification
29 *
30 * @return length of the descriptor type if descriptor type is valid else
31 * return 0
32 */
33static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
34{
35 switch (descriptor_type) {
36
37 case PLDM_FWUP_PCI_VENDOR_ID:
38 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
39 case PLDM_FWUP_IANA_ENTERPRISE_ID:
40 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
41 case PLDM_FWUP_UUID:
42 return PLDM_FWUP_UUID_LENGTH;
43 case PLDM_FWUP_PNP_VENDOR_ID:
44 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
45 case PLDM_FWUP_ACPI_VENDOR_ID:
46 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
47 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
48 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
49 case PLDM_FWUP_SCSI_VENDOR_ID:
50 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
51 case PLDM_FWUP_PCI_DEVICE_ID:
52 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
53 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
54 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
55 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
56 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
57 case PLDM_FWUP_PCI_REVISION_ID:
58 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
59 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
60 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
61 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
62 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
63 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
64 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
65 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
66 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
67 case PLDM_FWUP_SCSI_PRODUCT_ID:
68 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
69 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
70 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
71 default:
72 return 0;
73 }
74}
75
76/** @brief Check whether ComponentResponse is valid
77 *
78 * @return true if ComponentResponse is valid, false if not
79 */
80static bool is_comp_resp_valid(uint8_t comp_resp)
81{
82 switch (comp_resp) {
83 case PLDM_CR_COMP_CAN_BE_UPDATED:
84 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
85 return true;
86
87 default:
88 return false;
89 }
90}
91
92/** @brief Check whether ComponentResponseCode is valid
93 *
94 * @return true if ComponentResponseCode is valid, false if not
95 */
96static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
97{
98 switch (comp_resp_code) {
99 case PLDM_CRC_COMP_CAN_BE_UPDATED:
100 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
101 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
102 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
103 case PLDM_CRC_COMP_CONFLICT:
104 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
105 case PLDM_CRC_COMP_NOT_SUPPORTED:
106 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
107 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
108 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
109 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
110 case PLDM_CRC_COMP_VER_STR_LOWER:
111 return true;
112
113 default:
114 if (comp_resp_code >=
115 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
116 comp_resp_code <=
117 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
118 return true;
119 }
120 return false;
121 }
122}
123
124/** @brief Check whether ComponentCompatibilityResponse is valid
125 *
126 * @return true if ComponentCompatibilityResponse is valid, false if not
127 */
128static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
129{
130 switch (comp_compatibility_resp) {
131 case PLDM_CCR_COMP_CAN_BE_UPDATED:
132 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
133 return true;
134
135 default:
136 return false;
137 }
138}
139
140/** @brief Check whether ComponentCompatibilityResponse Code is valid
141 *
142 * @return true if ComponentCompatibilityResponse Code is valid, false if not
143 */
144static bool
145is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
146{
147 switch (comp_compatibility_resp_code) {
148 case PLDM_CCRC_NO_RESPONSE_CODE:
149 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
150 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
151 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
152 case PLDM_CCRC_COMP_CONFLICT:
153 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
154 case PLDM_CCRC_COMP_NOT_SUPPORTED:
155 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
156 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
157 case PLDM_CCRC_COMP_INFO_NO_MATCH:
158 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
159 case PLDM_CCRC_COMP_VER_STR_LOWER:
160 return true;
161
162 default:
163 if (comp_compatibility_resp_code >=
164 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
165 comp_compatibility_resp_code <=
166 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
167 return true;
168 }
169 return false;
170 }
171}
172
173/** @brief Check whether SelfContainedActivationRequest is valid
174 *
175 * @return true if SelfContainedActivationRequest is valid, false if not
176 */
177static bool
178is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
179{
180 switch (self_contained_activation_req) {
181 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
182 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
183 return true;
184
185 default:
186 return false;
187 }
188}
189
190/** @brief Check if current or previous status in GetStatus command response is
191 * valid
192 *
193 * @param[in] state - current or previous different state machine state of
194 * the FD
195 * @return true if state is valid, false if not
196 */
197static bool is_state_valid(uint8_t state)
198{
199 switch (state) {
200 case PLDM_FD_STATE_IDLE:
201 case PLDM_FD_STATE_LEARN_COMPONENTS:
202 case PLDM_FD_STATE_READY_XFER:
203 case PLDM_FD_STATE_DOWNLOAD:
204 case PLDM_FD_STATE_VERIFY:
205 case PLDM_FD_STATE_APPLY:
206 case PLDM_FD_STATE_ACTIVATE:
207 return true;
208
209 default:
210 return false;
211 }
212}
213
214/** @brief Check if aux state in GetStatus command response is valid
215 *
216 * @param[in] aux_state - provides additional information to the UA to describe
217 * the current operation state of the FD/FDP
218 *
219 * @return true if aux state is valid, false if not
220 */
221static bool is_aux_state_valid(uint8_t aux_state)
222{
223 switch (aux_state) {
224 case PLDM_FD_OPERATION_IN_PROGRESS:
225 case PLDM_FD_OPERATION_SUCCESSFUL:
226 case PLDM_FD_OPERATION_FAILED:
227 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
228 return true;
229
230 default:
231 return false;
232 }
233}
234
235/** @brief Check if aux state status in GetStatus command response is valid
236 *
237 * @param[in] aux_state_status - aux state status
238 *
239 * @return true if aux state status is valid, false if not
240 */
241static bool is_aux_state_status_valid(uint8_t aux_state_status)
242{
243 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
244 aux_state_status == PLDM_FD_TIMEOUT ||
245 aux_state_status == PLDM_FD_GENERIC_ERROR) {
246 return true;
247 } else if (aux_state_status >=
248 PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
249 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END) {
250 return true;
251 }
252
253 return false;
254}
255
256/** @brief Check if reason code in GetStatus command response is valid
257 *
258 * @param[in] reason_code - provides the reason for why the current state
259 * entered the IDLE state
260 *
261 * @return true if reason code is valid, false if not
262 */
263static bool is_reason_code_valid(uint8_t reason_code)
264{
265
266 switch (reason_code) {
267 case PLDM_FD_INITIALIZATION:
268 case PLDM_FD_ACTIVATE_FW:
269 case PLDM_FD_CANCEL_UPDATE:
270 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
271 case PLDM_FD_TIMEOUT_READY_XFER:
272 case PLDM_FD_TIMEOUT_DOWNLOAD:
273 case PLDM_FD_TIMEOUT_VERIFY:
274 case PLDM_FD_TIMEOUT_APPLY:
275 return true;
276
277 default:
278 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
279 return true;
280 }
281 return false;
282 }
283}
284
285/** @brief Check if non functioning component indication in CancelUpdate
286 * response is valid
287 *
288 * @return true if non functioning component indication is valid, false if not
289 */
290static bool is_non_functioning_component_indication_valid(
291 bool8_t non_functioning_component_indication)
292{
293 switch (non_functioning_component_indication) {
294 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
295 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
296 return true;
297
298 default:
299 return false;
300 }
301}
302
303int decode_pldm_package_header_info(
304 const uint8_t *data, size_t length,
305 struct pldm_package_header_information *package_header_info,
306 struct variable_field *package_version_str)
307{
308 if (data == NULL || package_header_info == NULL ||
309 package_version_str == NULL) {
310 return PLDM_ERROR_INVALID_DATA;
311 }
312
313 if (length < sizeof(struct pldm_package_header_information)) {
314 return PLDM_ERROR_INVALID_LENGTH;
315 }
316
317 struct pldm_package_header_information *data_header =
318 (struct pldm_package_header_information *)(data);
319
320 if (!is_string_type_valid(data_header->package_version_string_type) ||
321 (data_header->package_version_string_length == 0)) {
322 return PLDM_ERROR_INVALID_DATA;
323 }
324
325 if (length < sizeof(struct pldm_package_header_information) +
326 data_header->package_version_string_length) {
327 return PLDM_ERROR_INVALID_LENGTH;
328 }
329
330 if ((data_header->component_bitmap_bit_length %
331 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
332 return PLDM_ERROR_INVALID_DATA;
333 }
334
335 memcpy(package_header_info->uuid, data_header->uuid,
336 sizeof(data_header->uuid));
337 package_header_info->package_header_format_version =
338 data_header->package_header_format_version;
339 package_header_info->package_header_size =
340 le16toh(data_header->package_header_size);
341 memcpy(package_header_info->package_release_date_time,
342 data_header->package_release_date_time,
343 sizeof(data_header->package_release_date_time));
344 package_header_info->component_bitmap_bit_length =
345 le16toh(data_header->component_bitmap_bit_length);
346 package_header_info->package_version_string_type =
347 data_header->package_version_string_type;
348 package_header_info->package_version_string_length =
349 data_header->package_version_string_length;
350 package_version_str->ptr =
351 data + sizeof(struct pldm_package_header_information);
352 package_version_str->length =
353 package_header_info->package_version_string_length;
354
355 return PLDM_SUCCESS;
356}
357
358int decode_firmware_device_id_record(
359 const uint8_t *data, size_t length, uint16_t component_bitmap_bit_length,
360 struct pldm_firmware_device_id_record *fw_device_id_record,
361 struct variable_field *applicable_components,
362 struct variable_field *comp_image_set_version_str,
363 struct variable_field *record_descriptors,
364 struct variable_field *fw_device_pkg_data)
365{
366 if (data == NULL || fw_device_id_record == NULL ||
367 applicable_components == NULL ||
368 comp_image_set_version_str == NULL || record_descriptors == NULL ||
369 fw_device_pkg_data == NULL) {
370 return PLDM_ERROR_INVALID_DATA;
371 }
372
373 if (length < sizeof(struct pldm_firmware_device_id_record)) {
374 return PLDM_ERROR_INVALID_LENGTH;
375 }
376
377 if ((component_bitmap_bit_length %
378 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
379 return PLDM_ERROR_INVALID_DATA;
380 }
381
382 struct pldm_firmware_device_id_record *data_record =
383 (struct pldm_firmware_device_id_record *)(data);
384
385 if (!is_string_type_valid(
386 data_record->comp_image_set_version_string_type) ||
387 (data_record->comp_image_set_version_string_length == 0)) {
388 return PLDM_ERROR_INVALID_DATA;
389 }
390
391 fw_device_id_record->record_length =
392 le16toh(data_record->record_length);
393 fw_device_id_record->descriptor_count = data_record->descriptor_count;
394 fw_device_id_record->device_update_option_flags.value =
395 le32toh(data_record->device_update_option_flags.value);
396 fw_device_id_record->comp_image_set_version_string_type =
397 data_record->comp_image_set_version_string_type;
398 fw_device_id_record->comp_image_set_version_string_length =
399 data_record->comp_image_set_version_string_length;
400 fw_device_id_record->fw_device_pkg_data_length =
401 le16toh(data_record->fw_device_pkg_data_length);
402
403 if (length < fw_device_id_record->record_length) {
404 return PLDM_ERROR_INVALID_LENGTH;
405 }
406
407 uint16_t applicable_components_length =
408 component_bitmap_bit_length / PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
409 uint16_t calc_min_record_length =
410 sizeof(struct pldm_firmware_device_id_record) +
411 applicable_components_length +
412 data_record->comp_image_set_version_string_length +
413 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
414 fw_device_id_record->fw_device_pkg_data_length;
415
416 if (fw_device_id_record->record_length < calc_min_record_length) {
417 return PLDM_ERROR_INVALID_LENGTH;
418 }
419
420 applicable_components->ptr =
421 data + sizeof(struct pldm_firmware_device_id_record);
422 applicable_components->length = applicable_components_length;
423
424 comp_image_set_version_str->ptr =
425 applicable_components->ptr + applicable_components->length;
426 comp_image_set_version_str->length =
427 fw_device_id_record->comp_image_set_version_string_length;
428
429 record_descriptors->ptr = comp_image_set_version_str->ptr +
430 comp_image_set_version_str->length;
431 record_descriptors->length =
432 fw_device_id_record->record_length -
433 sizeof(struct pldm_firmware_device_id_record) -
434 applicable_components_length -
435 fw_device_id_record->comp_image_set_version_string_length -
436 fw_device_id_record->fw_device_pkg_data_length;
437
438 if (fw_device_id_record->fw_device_pkg_data_length) {
439 fw_device_pkg_data->ptr =
440 record_descriptors->ptr + record_descriptors->length;
441 fw_device_pkg_data->length =
442 fw_device_id_record->fw_device_pkg_data_length;
443 }
444
445 return PLDM_SUCCESS;
446}
447
448int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
449 uint16_t *descriptor_type,
450 struct variable_field *descriptor_data)
451{
452 uint16_t descriptor_length = 0;
453
454 if (data == NULL || descriptor_type == NULL ||
455 descriptor_data == NULL) {
456 return PLDM_ERROR_INVALID_DATA;
457 }
458
459 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
460 return PLDM_ERROR_INVALID_LENGTH;
461 }
462
463 struct pldm_descriptor_tlv *entry =
464 (struct pldm_descriptor_tlv *)(data);
465
466 *descriptor_type = le16toh(entry->descriptor_type);
467 descriptor_length = le16toh(entry->descriptor_length);
468 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
469 if (descriptor_length !=
470 get_descriptor_type_length(*descriptor_type)) {
471 return PLDM_ERROR_INVALID_LENGTH;
472 }
473 }
474
475 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
476 descriptor_length)) {
477 return PLDM_ERROR_INVALID_LENGTH;
478 }
479
480 descriptor_data->ptr = entry->descriptor_data;
481 descriptor_data->length = descriptor_length;
482
483 return PLDM_SUCCESS;
484}
485
486int decode_vendor_defined_descriptor_value(
487 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
488 struct variable_field *descriptor_title_str,
489 struct variable_field *descriptor_data)
490{
491 if (data == NULL || descriptor_title_str_type == NULL ||
492 descriptor_title_str == NULL || descriptor_data == NULL) {
493 return PLDM_ERROR_INVALID_DATA;
494 }
495
496 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
497 return PLDM_ERROR_INVALID_LENGTH;
498 }
499
500 struct pldm_vendor_defined_descriptor_title_data *entry =
501 (struct pldm_vendor_defined_descriptor_title_data *)(data);
502 if (!is_string_type_valid(
503 entry->vendor_defined_descriptor_title_str_type) ||
504 (entry->vendor_defined_descriptor_title_str_len == 0)) {
505 return PLDM_ERROR_INVALID_DATA;
506 }
507
508 // Assuming atleast 1 byte of VendorDefinedDescriptorData
509 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
510 entry->vendor_defined_descriptor_title_str_len)) {
511 return PLDM_ERROR_INVALID_LENGTH;
512 }
513
514 *descriptor_title_str_type =
515 entry->vendor_defined_descriptor_title_str_type;
516 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
517 descriptor_title_str->length =
518 entry->vendor_defined_descriptor_title_str_len;
519
520 descriptor_data->ptr =
521 descriptor_title_str->ptr + descriptor_title_str->length;
522 descriptor_data->length =
523 length - sizeof(entry->vendor_defined_descriptor_title_str_type) -
524 sizeof(entry->vendor_defined_descriptor_title_str_len) -
525 descriptor_title_str->length;
526
527 return PLDM_SUCCESS;
528}
529
530int decode_pldm_comp_image_info(
531 const uint8_t *data, size_t length,
532 struct pldm_component_image_information *pldm_comp_image_info,
533 struct variable_field *comp_version_str)
534{
535 if (data == NULL || pldm_comp_image_info == NULL ||
536 comp_version_str == NULL) {
537 return PLDM_ERROR_INVALID_DATA;
538 }
539
540 if (length < sizeof(struct pldm_component_image_information)) {
541 return PLDM_ERROR_INVALID_LENGTH;
542 }
543
544 struct pldm_component_image_information *data_header =
545 (struct pldm_component_image_information *)(data);
546
547 if (!is_string_type_valid(data_header->comp_version_string_type) ||
548 (data_header->comp_version_string_length == 0)) {
549 return PLDM_ERROR_INVALID_DATA;
550 }
551
552 if (length < sizeof(struct pldm_component_image_information) +
553 data_header->comp_version_string_length) {
554 return PLDM_ERROR_INVALID_LENGTH;
555 }
556
557 pldm_comp_image_info->comp_classification =
558 le16toh(data_header->comp_classification);
559 pldm_comp_image_info->comp_identifier =
560 le16toh(data_header->comp_identifier);
561 pldm_comp_image_info->comp_comparison_stamp =
562 le32toh(data_header->comp_comparison_stamp);
563 pldm_comp_image_info->comp_options.value =
564 le16toh(data_header->comp_options.value);
565 pldm_comp_image_info->requested_comp_activation_method.value =
566 le16toh(data_header->requested_comp_activation_method.value);
567 pldm_comp_image_info->comp_location_offset =
568 le32toh(data_header->comp_location_offset);
569 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
570 pldm_comp_image_info->comp_version_string_type =
571 data_header->comp_version_string_type;
572 pldm_comp_image_info->comp_version_string_length =
573 data_header->comp_version_string_length;
574
575 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
576 pldm_comp_image_info->comp_comparison_stamp !=
577 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
578 return PLDM_ERROR_INVALID_DATA;
579 }
580
581 if (pldm_comp_image_info->comp_location_offset == 0 ||
582 pldm_comp_image_info->comp_size == 0) {
583 return PLDM_ERROR_INVALID_DATA;
584 }
585
586 comp_version_str->ptr =
587 data + sizeof(struct pldm_component_image_information);
588 comp_version_str->length =
589 pldm_comp_image_info->comp_version_string_length;
590
591 return PLDM_SUCCESS;
592}
593
594int encode_query_device_identifiers_req(uint8_t instance_id,
595 size_t payload_length,
596 struct pldm_msg *msg)
597{
598 if (msg == NULL) {
599 return PLDM_ERROR_INVALID_DATA;
600 }
601
602 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
603 return PLDM_ERROR_INVALID_LENGTH;
604 }
605
606 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
607 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
608}
609
610int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
611 size_t payload_length,
612 uint8_t *completion_code,
613 uint32_t *device_identifiers_len,
614 uint8_t *descriptor_count,
615 uint8_t **descriptor_data)
616{
617 if (msg == NULL || completion_code == NULL ||
618 device_identifiers_len == NULL || descriptor_count == NULL ||
619 descriptor_data == NULL) {
620 return PLDM_ERROR_INVALID_DATA;
621 }
622
623 *completion_code = msg->payload[0];
624 if (PLDM_SUCCESS != *completion_code) {
625 return PLDM_SUCCESS;
626 }
627
628 if (payload_length <
629 sizeof(struct pldm_query_device_identifiers_resp)) {
630 return PLDM_ERROR_INVALID_LENGTH;
631 }
632
633 struct pldm_query_device_identifiers_resp *response =
634 (struct pldm_query_device_identifiers_resp *)msg->payload;
635 *device_identifiers_len = le32toh(response->device_identifiers_len);
636
637 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
638 return PLDM_ERROR_INVALID_LENGTH;
639 }
640
641 if (payload_length !=
642 sizeof(struct pldm_query_device_identifiers_resp) +
643 *device_identifiers_len) {
644 return PLDM_ERROR_INVALID_LENGTH;
645 }
646 *descriptor_count = response->descriptor_count;
647
648 if (*descriptor_count == 0) {
649 return PLDM_ERROR_INVALID_DATA;
650 }
651 *descriptor_data =
652 (uint8_t *)(msg->payload +
653 sizeof(struct pldm_query_device_identifiers_resp));
654 return PLDM_SUCCESS;
655}
656
657int encode_get_firmware_parameters_req(uint8_t instance_id,
658 size_t payload_length,
659 struct pldm_msg *msg)
660{
661 if (msg == NULL) {
662 return PLDM_ERROR_INVALID_DATA;
663 }
664
665 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
666 return PLDM_ERROR_INVALID_LENGTH;
667 }
668
669 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
670 PLDM_GET_FIRMWARE_PARAMETERS, msg);
671}
672
673int decode_get_firmware_parameters_resp(
674 const struct pldm_msg *msg, size_t payload_length,
675 struct pldm_get_firmware_parameters_resp *resp_data,
676 struct variable_field *active_comp_image_set_ver_str,
677 struct variable_field *pending_comp_image_set_ver_str,
678 struct variable_field *comp_parameter_table)
679{
680 if (msg == NULL || resp_data == NULL ||
681 active_comp_image_set_ver_str == NULL ||
682 pending_comp_image_set_ver_str == NULL ||
683 comp_parameter_table == NULL || !payload_length) {
684 return PLDM_ERROR_INVALID_DATA;
685 }
686
687 resp_data->completion_code = msg->payload[0];
688 if (PLDM_SUCCESS != resp_data->completion_code) {
689 return PLDM_SUCCESS;
690 }
691
692 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
693 return PLDM_ERROR_INVALID_LENGTH;
694 }
695
696 struct pldm_get_firmware_parameters_resp *response =
697 (struct pldm_get_firmware_parameters_resp *)msg->payload;
698
699 if (!is_string_type_valid(
700 response->active_comp_image_set_ver_str_type) ||
701 (response->active_comp_image_set_ver_str_len == 0)) {
702 return PLDM_ERROR_INVALID_DATA;
703 }
704
705 if (response->pending_comp_image_set_ver_str_len == 0) {
706 if (response->pending_comp_image_set_ver_str_type !=
707 PLDM_STR_TYPE_UNKNOWN) {
708 return PLDM_ERROR_INVALID_DATA;
709 }
710 } else {
711 if (!is_string_type_valid(
712 response->pending_comp_image_set_ver_str_type)) {
713 return PLDM_ERROR_INVALID_DATA;
714 }
715 }
716
717 size_t partial_response_length =
718 sizeof(struct pldm_get_firmware_parameters_resp) +
719 response->active_comp_image_set_ver_str_len +
720 response->pending_comp_image_set_ver_str_len;
721
722 if (payload_length < partial_response_length) {
723 return PLDM_ERROR_INVALID_LENGTH;
724 }
725
726 resp_data->capabilities_during_update.value =
727 le32toh(response->capabilities_during_update.value);
728 resp_data->comp_count = le16toh(response->comp_count);
729 resp_data->active_comp_image_set_ver_str_type =
730 response->active_comp_image_set_ver_str_type;
731 resp_data->active_comp_image_set_ver_str_len =
732 response->active_comp_image_set_ver_str_len;
733 resp_data->pending_comp_image_set_ver_str_type =
734 response->pending_comp_image_set_ver_str_type;
735 resp_data->pending_comp_image_set_ver_str_len =
736 response->pending_comp_image_set_ver_str_len;
737
738 active_comp_image_set_ver_str->ptr =
739 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
740 active_comp_image_set_ver_str->length =
741 resp_data->active_comp_image_set_ver_str_len;
742
743 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
744 pending_comp_image_set_ver_str->ptr =
745 msg->payload +
746 sizeof(struct pldm_get_firmware_parameters_resp) +
747 resp_data->active_comp_image_set_ver_str_len;
748 pending_comp_image_set_ver_str->length =
749 resp_data->pending_comp_image_set_ver_str_len;
750 } else {
751 pending_comp_image_set_ver_str->ptr = NULL;
752 pending_comp_image_set_ver_str->length = 0;
753 }
754
755 if (payload_length > partial_response_length && resp_data->comp_count) {
756 comp_parameter_table->ptr =
757 msg->payload +
758 sizeof(struct pldm_get_firmware_parameters_resp) +
759 resp_data->active_comp_image_set_ver_str_len +
760 resp_data->pending_comp_image_set_ver_str_len;
761 comp_parameter_table->length =
762 payload_length - partial_response_length;
763 } else {
764 comp_parameter_table->ptr = NULL;
765 comp_parameter_table->length = 0;
766 }
767
768 return PLDM_SUCCESS;
769}
770
771int decode_get_firmware_parameters_resp_comp_entry(
772 const uint8_t *data, size_t length,
773 struct pldm_component_parameter_entry *component_data,
774 struct variable_field *active_comp_ver_str,
775 struct variable_field *pending_comp_ver_str)
776{
777 if (data == NULL || component_data == NULL ||
778 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
779 return PLDM_ERROR_INVALID_DATA;
780 }
781
782 if (length < sizeof(struct pldm_component_parameter_entry)) {
783 return PLDM_ERROR_INVALID_LENGTH;
784 }
785
786 struct pldm_component_parameter_entry *entry =
787 (struct pldm_component_parameter_entry *)(data);
788
789 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
790 entry->active_comp_ver_str_len +
791 entry->pending_comp_ver_str_len;
792
793 if (length < entry_length) {
794 return PLDM_ERROR_INVALID_LENGTH;
795 }
796
797 component_data->comp_classification =
798 le16toh(entry->comp_classification);
799 component_data->comp_identifier = le16toh(entry->comp_identifier);
800 component_data->comp_classification_index =
801 entry->comp_classification_index;
802 component_data->active_comp_comparison_stamp =
803 le32toh(entry->active_comp_comparison_stamp);
804 component_data->active_comp_ver_str_type =
805 entry->active_comp_ver_str_type;
806 component_data->active_comp_ver_str_len =
807 entry->active_comp_ver_str_len;
808 memcpy(component_data->active_comp_release_date,
809 entry->active_comp_release_date,
810 sizeof(entry->active_comp_release_date));
811 component_data->pending_comp_comparison_stamp =
812 le32toh(entry->pending_comp_comparison_stamp);
813 component_data->pending_comp_ver_str_type =
814 entry->pending_comp_ver_str_type;
815 component_data->pending_comp_ver_str_len =
816 entry->pending_comp_ver_str_len;
817 memcpy(component_data->pending_comp_release_date,
818 entry->pending_comp_release_date,
819 sizeof(entry->pending_comp_release_date));
820 component_data->comp_activation_methods.value =
821 le16toh(entry->comp_activation_methods.value);
822 component_data->capabilities_during_update.value =
823 le32toh(entry->capabilities_during_update.value);
824
825 if (entry->active_comp_ver_str_len != 0) {
826 active_comp_ver_str->ptr =
827 data + sizeof(struct pldm_component_parameter_entry);
828 active_comp_ver_str->length = entry->active_comp_ver_str_len;
829 } else {
830 active_comp_ver_str->ptr = NULL;
831 active_comp_ver_str->length = 0;
832 }
833
834 if (entry->pending_comp_ver_str_len != 0) {
835
836 pending_comp_ver_str->ptr =
837 data + sizeof(struct pldm_component_parameter_entry) +
838 entry->active_comp_ver_str_len;
839 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
840 } else {
841 pending_comp_ver_str->ptr = NULL;
842 pending_comp_ver_str->length = 0;
843 }
844 return PLDM_SUCCESS;
845}
846
847int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
848 uint16_t num_of_comp,
849 uint8_t max_outstanding_transfer_req,
850 uint16_t pkg_data_len,
851 uint8_t comp_image_set_ver_str_type,
852 uint8_t comp_image_set_ver_str_len,
853 const struct variable_field *comp_img_set_ver_str,
854 struct pldm_msg *msg, size_t payload_length)
855{
856 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
857 msg == NULL) {
858 return PLDM_ERROR_INVALID_DATA;
859 }
860
861 if (payload_length != sizeof(struct pldm_request_update_req) +
862 comp_img_set_ver_str->length) {
863 return PLDM_ERROR_INVALID_LENGTH;
864 }
865
866 if ((comp_image_set_ver_str_len == 0) ||
867 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
868 return PLDM_ERROR_INVALID_DATA;
869 }
870
871 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
872 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
873 return PLDM_ERROR_INVALID_DATA;
874 }
875
876 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
877 return PLDM_ERROR_INVALID_DATA;
878 }
879
880 struct pldm_header_info header = {0};
881 header.instance = instance_id;
882 header.msg_type = PLDM_REQUEST;
883 header.pldm_type = PLDM_FWUP;
884 header.command = PLDM_REQUEST_UPDATE;
885 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
886 if (rc) {
887 return rc;
888 }
889
890 struct pldm_request_update_req *request =
891 (struct pldm_request_update_req *)msg->payload;
892
893 request->max_transfer_size = htole32(max_transfer_size);
894 request->num_of_comp = htole16(num_of_comp);
895 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
896 request->pkg_data_len = htole16(pkg_data_len);
897 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
898 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
899
900 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
901 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
902
903 return PLDM_SUCCESS;
904}
905
906int decode_request_update_resp(const struct pldm_msg *msg,
907 size_t payload_length, uint8_t *completion_code,
908 uint16_t *fd_meta_data_len,
909 uint8_t *fd_will_send_pkg_data)
910{
911 if (msg == NULL || completion_code == NULL ||
912 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
913 !payload_length) {
914 return PLDM_ERROR_INVALID_DATA;
915 }
916
917 *completion_code = msg->payload[0];
918 if (*completion_code != PLDM_SUCCESS) {
919 return PLDM_SUCCESS;
920 }
921
922 if (payload_length != sizeof(struct pldm_request_update_resp)) {
923 return PLDM_ERROR_INVALID_LENGTH;
924 }
925
926 struct pldm_request_update_resp *response =
927 (struct pldm_request_update_resp *)msg->payload;
928
929 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
930 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
931
932 return PLDM_SUCCESS;
933}
934
935int encode_pass_component_table_req(
936 uint8_t instance_id, uint8_t transfer_flag, uint16_t comp_classification,
937 uint16_t comp_identifier, uint8_t comp_classification_index,
938 uint32_t comp_comparison_stamp, uint8_t comp_ver_str_type,
939 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
940 struct pldm_msg *msg, size_t payload_length)
941{
942 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
943 return PLDM_ERROR_INVALID_DATA;
944 }
945
946 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
947 comp_ver_str->length) {
948 return PLDM_ERROR_INVALID_LENGTH;
949 }
950
951 if ((comp_ver_str_len == 0) ||
952 (comp_ver_str_len != comp_ver_str->length)) {
953 return PLDM_ERROR_INVALID_DATA;
954 }
955
956 if (!is_transfer_flag_valid(transfer_flag)) {
957 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
958 }
959
960 if (!is_string_type_valid(comp_ver_str_type)) {
961 return PLDM_ERROR_INVALID_DATA;
962 }
963
964 struct pldm_header_info header = {0};
965 header.instance = instance_id;
966 header.msg_type = PLDM_REQUEST;
967 header.pldm_type = PLDM_FWUP;
968 header.command = PLDM_PASS_COMPONENT_TABLE;
969 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
970 if (rc) {
971 return rc;
972 }
973
974 struct pldm_pass_component_table_req *request =
975 (struct pldm_pass_component_table_req *)msg->payload;
976
977 request->transfer_flag = transfer_flag;
978 request->comp_classification = htole16(comp_classification);
979 request->comp_identifier = htole16(comp_identifier);
980 request->comp_classification_index = comp_classification_index;
981 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
982 request->comp_ver_str_type = comp_ver_str_type;
983 request->comp_ver_str_len = comp_ver_str_len;
984
985 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
986 comp_ver_str->ptr, comp_ver_str->length);
987
988 return PLDM_SUCCESS;
989}
990
991int decode_pass_component_table_resp(const struct pldm_msg *msg,
992 const size_t payload_length,
993 uint8_t *completion_code,
994 uint8_t *comp_resp,
995 uint8_t *comp_resp_code)
996{
997 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
998 comp_resp_code == NULL || !payload_length) {
999 return PLDM_ERROR_INVALID_DATA;
1000 }
1001
1002 *completion_code = msg->payload[0];
1003 if (*completion_code != PLDM_SUCCESS) {
1004 return PLDM_SUCCESS;
1005 }
1006
1007 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1008 return PLDM_ERROR_INVALID_LENGTH;
1009 }
1010
1011 struct pldm_pass_component_table_resp *response =
1012 (struct pldm_pass_component_table_resp *)msg->payload;
1013
1014 if (!is_comp_resp_valid(response->comp_resp)) {
1015 return PLDM_ERROR_INVALID_DATA;
1016 }
1017
1018 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1019 return PLDM_ERROR_INVALID_DATA;
1020 }
1021
1022 *comp_resp = response->comp_resp;
1023 *comp_resp_code = response->comp_resp_code;
1024
1025 return PLDM_SUCCESS;
1026}
1027
1028int encode_update_component_req(
1029 uint8_t instance_id, uint16_t comp_classification, uint16_t comp_identifier,
1030 uint8_t comp_classification_index, uint32_t comp_comparison_stamp,
1031 uint32_t comp_image_size, bitfield32_t update_option_flags,
1032 uint8_t comp_ver_str_type, uint8_t comp_ver_str_len,
1033 const struct variable_field *comp_ver_str, struct pldm_msg *msg,
1034 size_t payload_length)
1035{
1036 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1037 return PLDM_ERROR_INVALID_DATA;
1038 }
1039
1040 if (payload_length !=
1041 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1042 return PLDM_ERROR_INVALID_LENGTH;
1043 }
1044
1045 if (!comp_image_size) {
1046 return PLDM_ERROR_INVALID_DATA;
1047 }
1048
1049 if ((comp_ver_str_len == 0) ||
1050 (comp_ver_str_len != comp_ver_str->length)) {
1051 return PLDM_ERROR_INVALID_DATA;
1052 }
1053
1054 if (!is_string_type_valid(comp_ver_str_type)) {
1055 return PLDM_ERROR_INVALID_DATA;
1056 }
1057
1058 struct pldm_header_info header = {0};
1059 header.instance = instance_id;
1060 header.msg_type = PLDM_REQUEST;
1061 header.pldm_type = PLDM_FWUP;
1062 header.command = PLDM_UPDATE_COMPONENT;
1063 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1064 if (rc) {
1065 return rc;
1066 }
1067
1068 struct pldm_update_component_req *request =
1069 (struct pldm_update_component_req *)msg->payload;
1070
1071 request->comp_classification = htole16(comp_classification);
1072 request->comp_identifier = htole16(comp_identifier);
1073 request->comp_classification_index = comp_classification_index;
1074 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1075 request->comp_image_size = htole32(comp_image_size);
1076 request->update_option_flags.value = htole32(update_option_flags.value);
1077 request->comp_ver_str_type = comp_ver_str_type;
1078 request->comp_ver_str_len = comp_ver_str_len;
1079
1080 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1081 comp_ver_str->ptr, comp_ver_str->length);
1082
1083 return PLDM_SUCCESS;
1084}
1085
1086int decode_update_component_resp(const struct pldm_msg *msg,
1087 size_t payload_length,
1088 uint8_t *completion_code,
1089 uint8_t *comp_compatibility_resp,
1090 uint8_t *comp_compatibility_resp_code,
1091 bitfield32_t *update_option_flags_enabled,
1092 uint16_t *time_before_req_fw_data)
1093{
1094 if (msg == NULL || completion_code == NULL ||
1095 comp_compatibility_resp == NULL ||
1096 comp_compatibility_resp_code == NULL ||
1097 update_option_flags_enabled == NULL ||
1098 time_before_req_fw_data == NULL || !payload_length) {
1099 return PLDM_ERROR_INVALID_DATA;
1100 }
1101
1102 *completion_code = msg->payload[0];
1103 if (*completion_code != PLDM_SUCCESS) {
1104 return PLDM_SUCCESS;
1105 }
1106
1107 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1108 return PLDM_ERROR_INVALID_LENGTH;
1109 }
1110
1111 struct pldm_update_component_resp *response =
1112 (struct pldm_update_component_resp *)msg->payload;
1113
1114 if (!is_comp_compatibility_resp_valid(
1115 response->comp_compatibility_resp)) {
1116 return PLDM_ERROR_INVALID_DATA;
1117 }
1118
1119 if (!is_comp_compatibility_resp_code_valid(
1120 response->comp_compatibility_resp_code)) {
1121 return PLDM_ERROR_INVALID_DATA;
1122 }
1123
1124 *comp_compatibility_resp = response->comp_compatibility_resp;
1125 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1126 update_option_flags_enabled->value =
1127 le32toh(response->update_option_flags_enabled.value);
1128 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1129
1130 return PLDM_SUCCESS;
1131}
1132
1133int decode_request_firmware_data_req(const struct pldm_msg *msg,
1134 size_t payload_length, uint32_t *offset,
1135 uint32_t *length)
1136{
1137 if (msg == NULL || offset == NULL || length == NULL) {
1138 return PLDM_ERROR_INVALID_DATA;
1139 }
1140 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1141 return PLDM_ERROR_INVALID_LENGTH;
1142 }
1143 struct pldm_request_firmware_data_req *request =
1144 (struct pldm_request_firmware_data_req *)msg->payload;
1145 *offset = le32toh(request->offset);
1146 *length = le32toh(request->length);
1147
1148 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1149 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1150 }
1151
1152 return PLDM_SUCCESS;
1153}
1154
1155int encode_request_firmware_data_resp(uint8_t instance_id,
1156 uint8_t completion_code,
1157 struct pldm_msg *msg,
1158 size_t payload_length)
1159{
1160 if (msg == NULL || !payload_length) {
1161 return PLDM_ERROR_INVALID_DATA;
1162 }
1163
1164 struct pldm_header_info header = {0};
1165 header.instance = instance_id;
1166 header.msg_type = PLDM_RESPONSE;
1167 header.pldm_type = PLDM_FWUP;
1168 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1169 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1170 if (rc) {
1171 return rc;
1172 }
1173
1174 msg->payload[0] = completion_code;
1175
1176 return PLDM_SUCCESS;
1177}
1178
1179int decode_transfer_complete_req(const struct pldm_msg *msg,
1180 size_t payload_length,
1181 uint8_t *transfer_result)
1182{
1183 if (msg == NULL || transfer_result == NULL) {
1184 return PLDM_ERROR_INVALID_DATA;
1185 }
1186
1187 if (payload_length != sizeof(*transfer_result)) {
1188 return PLDM_ERROR_INVALID_LENGTH;
1189 }
1190
1191 *transfer_result = msg->payload[0];
1192 return PLDM_SUCCESS;
1193}
1194
1195int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1196 struct pldm_msg *msg, size_t payload_length)
1197{
1198 if (msg == NULL) {
1199 return PLDM_ERROR_INVALID_DATA;
1200 }
1201
1202 if (payload_length != sizeof(completion_code)) {
1203 return PLDM_ERROR_INVALID_LENGTH;
1204 }
1205
1206 struct pldm_header_info header = {0};
1207 header.instance = instance_id;
1208 header.msg_type = PLDM_RESPONSE;
1209 header.pldm_type = PLDM_FWUP;
1210 header.command = PLDM_TRANSFER_COMPLETE;
1211 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1212 if (rc) {
1213 return rc;
1214 }
1215
1216 msg->payload[0] = completion_code;
1217
1218 return PLDM_SUCCESS;
1219}
1220
1221int decode_verify_complete_req(const struct pldm_msg *msg,
1222 size_t payload_length, uint8_t *verify_result)
1223{
1224 if (msg == NULL || verify_result == NULL) {
1225 return PLDM_ERROR_INVALID_DATA;
1226 }
1227
1228 if (payload_length != sizeof(*verify_result)) {
1229 return PLDM_ERROR_INVALID_LENGTH;
1230 }
1231
1232 *verify_result = msg->payload[0];
1233 return PLDM_SUCCESS;
1234}
1235
1236int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1237 struct pldm_msg *msg, size_t payload_length)
1238{
1239 if (msg == NULL) {
1240 return PLDM_ERROR_INVALID_DATA;
1241 }
1242
1243 if (payload_length != sizeof(completion_code)) {
1244 return PLDM_ERROR_INVALID_LENGTH;
1245 }
1246
1247 struct pldm_header_info header = {0};
1248 header.instance = instance_id;
1249 header.msg_type = PLDM_RESPONSE;
1250 header.pldm_type = PLDM_FWUP;
1251 header.command = PLDM_VERIFY_COMPLETE;
1252 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1253 if (rc) {
1254 return rc;
1255 }
1256
1257 msg->payload[0] = completion_code;
1258
1259 return PLDM_SUCCESS;
1260}
1261
1262int decode_apply_complete_req(
1263 const struct pldm_msg *msg, size_t payload_length, uint8_t *apply_result,
1264 bitfield16_t *comp_activation_methods_modification)
1265{
1266 if (msg == NULL || apply_result == NULL ||
1267 comp_activation_methods_modification == NULL) {
1268 return PLDM_ERROR_INVALID_DATA;
1269 }
1270
1271 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1272 return PLDM_ERROR_INVALID_LENGTH;
1273 }
1274
1275 struct pldm_apply_complete_req *request =
1276 (struct pldm_apply_complete_req *)msg->payload;
1277
1278 *apply_result = request->apply_result;
1279 comp_activation_methods_modification->value =
1280 le16toh(request->comp_activation_methods_modification.value);
1281
1282 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1283 comp_activation_methods_modification->value) {
1284 return PLDM_ERROR_INVALID_DATA;
1285 }
1286
1287 return PLDM_SUCCESS;
1288}
1289
1290int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1291 struct pldm_msg *msg, size_t payload_length)
1292{
1293 if (msg == NULL) {
1294 return PLDM_ERROR_INVALID_DATA;
1295 }
1296
1297 if (payload_length != sizeof(completion_code)) {
1298 return PLDM_ERROR_INVALID_LENGTH;
1299 }
1300
1301 struct pldm_header_info header = {0};
1302 header.instance = instance_id;
1303 header.msg_type = PLDM_RESPONSE;
1304 header.pldm_type = PLDM_FWUP;
1305 header.command = PLDM_APPLY_COMPLETE;
1306 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1307 if (rc) {
1308 return rc;
1309 }
1310
1311 msg->payload[0] = completion_code;
1312
1313 return PLDM_SUCCESS;
1314}
1315
1316int encode_activate_firmware_req(uint8_t instance_id,
1317 bool8_t self_contained_activation_req,
1318 struct pldm_msg *msg, size_t payload_length)
1319{
1320 if (msg == NULL) {
1321 return PLDM_ERROR_INVALID_DATA;
1322 }
1323
1324 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1325 return PLDM_ERROR_INVALID_LENGTH;
1326 }
1327
1328 if (!is_self_contained_activation_req_valid(
1329 self_contained_activation_req)) {
1330 return PLDM_ERROR_INVALID_DATA;
1331 }
1332
1333 struct pldm_header_info header = {0};
1334 header.instance = instance_id;
1335 header.msg_type = PLDM_REQUEST;
1336 header.pldm_type = PLDM_FWUP;
1337 header.command = PLDM_ACTIVATE_FIRMWARE;
1338 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1339 if (rc) {
1340 return rc;
1341 }
1342
1343 struct pldm_activate_firmware_req *request =
1344 (struct pldm_activate_firmware_req *)msg->payload;
1345
1346 request->self_contained_activation_req = self_contained_activation_req;
1347
1348 return PLDM_SUCCESS;
1349}
1350
1351int decode_activate_firmware_resp(const struct pldm_msg *msg,
1352 size_t payload_length,
1353 uint8_t *completion_code,
1354 uint16_t *estimated_time_activation)
1355{
1356 if (msg == NULL || completion_code == NULL ||
1357 estimated_time_activation == NULL || !payload_length) {
1358 return PLDM_ERROR_INVALID_DATA;
1359 }
1360
1361 *completion_code = msg->payload[0];
1362 if (*completion_code != PLDM_SUCCESS) {
1363 return PLDM_SUCCESS;
1364 }
1365
1366 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1367 return PLDM_ERROR_INVALID_LENGTH;
1368 }
1369
1370 struct pldm_activate_firmware_resp *response =
1371 (struct pldm_activate_firmware_resp *)msg->payload;
1372
1373 *estimated_time_activation =
1374 le16toh(response->estimated_time_activation);
1375
1376 return PLDM_SUCCESS;
1377}
1378
1379int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1380 size_t payload_length)
1381{
1382 if (msg == NULL) {
1383 return PLDM_ERROR_INVALID_DATA;
1384 }
1385
1386 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1387 return PLDM_ERROR_INVALID_LENGTH;
1388 }
1389
1390 struct pldm_header_info header = {0};
1391 header.instance = instance_id;
1392 header.msg_type = PLDM_REQUEST;
1393 header.pldm_type = PLDM_FWUP;
1394 header.command = PLDM_GET_STATUS;
1395 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1396 if (rc) {
1397 return rc;
1398 }
1399
1400 return PLDM_SUCCESS;
1401}
1402
1403int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1404 uint8_t *completion_code, uint8_t *current_state,
1405 uint8_t *previous_state, uint8_t *aux_state,
1406 uint8_t *aux_state_status, uint8_t *progress_percent,
1407 uint8_t *reason_code,
1408 bitfield32_t *update_option_flags_enabled)
1409{
1410 if (msg == NULL || completion_code == NULL || current_state == NULL ||
1411 previous_state == NULL || aux_state == NULL ||
1412 aux_state_status == NULL || progress_percent == NULL ||
1413 reason_code == NULL || update_option_flags_enabled == NULL ||
1414 !payload_length) {
1415 return PLDM_ERROR_INVALID_DATA;
1416 }
1417
1418 *completion_code = msg->payload[0];
1419 if (*completion_code != PLDM_SUCCESS) {
1420 return PLDM_SUCCESS;
1421 }
1422
1423 if (payload_length != sizeof(struct pldm_get_status_resp)) {
1424 return PLDM_ERROR_INVALID_LENGTH;
1425 }
1426 struct pldm_get_status_resp *response =
1427 (struct pldm_get_status_resp *)msg->payload;
1428
1429 if (!is_state_valid(response->current_state)) {
1430 return PLDM_ERROR_INVALID_DATA;
1431 }
1432 if (!is_state_valid(response->previous_state)) {
1433 return PLDM_ERROR_INVALID_DATA;
1434 }
1435 if (!is_aux_state_valid(response->aux_state)) {
1436 return PLDM_ERROR_INVALID_DATA;
1437 }
1438 if (!is_aux_state_status_valid(response->aux_state_status)) {
1439 return PLDM_ERROR_INVALID_DATA;
1440 }
1441 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1442 return PLDM_ERROR_INVALID_DATA;
1443 }
1444 if (!is_reason_code_valid(response->reason_code)) {
1445 return PLDM_ERROR_INVALID_DATA;
1446 }
1447
1448 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1449 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1450 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1451 if (response->aux_state !=
1452 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1453 return PLDM_ERROR_INVALID_DATA;
1454 }
1455 }
1456
1457 *current_state = response->current_state;
1458 *previous_state = response->previous_state;
1459 *aux_state = response->aux_state;
1460 *aux_state_status = response->aux_state_status;
1461 *progress_percent = response->progress_percent;
1462 *reason_code = response->reason_code;
1463 update_option_flags_enabled->value =
1464 le32toh(response->update_option_flags_enabled.value);
1465
1466 return PLDM_SUCCESS;
1467}
1468
1469int encode_cancel_update_component_req(uint8_t instance_id,
1470 struct pldm_msg *msg,
1471 size_t payload_length)
1472{
1473 if (msg == NULL) {
1474 return PLDM_ERROR_INVALID_DATA;
1475 }
1476
1477 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1478 return PLDM_ERROR_INVALID_LENGTH;
1479 }
1480
1481 struct pldm_header_info header = {0};
1482 header.instance = instance_id;
1483 header.msg_type = PLDM_REQUEST;
1484 header.pldm_type = PLDM_FWUP;
1485 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
1486 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1487 if (rc) {
1488 return rc;
1489 }
1490
1491 return PLDM_SUCCESS;
1492}
1493
1494int decode_cancel_update_component_resp(const struct pldm_msg *msg,
1495 size_t payload_length,
1496 uint8_t *completion_code)
1497{
1498 if (msg == NULL || completion_code == NULL) {
1499 return PLDM_ERROR_INVALID_DATA;
1500 }
1501
1502 if (payload_length != sizeof(*completion_code)) {
1503 return PLDM_ERROR_INVALID_LENGTH;
1504 }
1505
1506 *completion_code = msg->payload[0];
1507 return PLDM_SUCCESS;
1508}
1509
1510int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
1511 size_t payload_length)
1512{
1513 if (msg == NULL) {
1514 return PLDM_ERROR_INVALID_DATA;
1515 }
1516
1517 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
1518 return PLDM_ERROR_INVALID_LENGTH;
1519 }
1520
1521 struct pldm_header_info header = {0};
1522 header.instance = instance_id;
1523 header.msg_type = PLDM_REQUEST;
1524 header.pldm_type = PLDM_FWUP;
1525 header.command = PLDM_CANCEL_UPDATE;
1526 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1527 if (rc) {
1528 return rc;
1529 }
1530
1531 return PLDM_SUCCESS;
1532}
1533
1534int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
1535 uint8_t *completion_code,
1536 bool8_t *non_functioning_component_indication,
1537 bitfield64_t *non_functioning_component_bitmap)
1538{
1539 if (msg == NULL || completion_code == NULL ||
1540 non_functioning_component_indication == NULL ||
1541 non_functioning_component_bitmap == NULL || !payload_length) {
1542 return PLDM_ERROR_INVALID_DATA;
1543 }
1544
1545 *completion_code = msg->payload[0];
1546 if (*completion_code != PLDM_SUCCESS) {
1547 return PLDM_SUCCESS;
1548 }
1549
1550 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
1551 return PLDM_ERROR_INVALID_LENGTH;
1552 }
1553 struct pldm_cancel_update_resp *response =
1554 (struct pldm_cancel_update_resp *)msg->payload;
1555
1556 if (!is_non_functioning_component_indication_valid(
1557 response->non_functioning_component_indication)) {
1558 return PLDM_ERROR_INVALID_DATA;
1559 }
1560
1561 *non_functioning_component_indication =
1562 response->non_functioning_component_indication;
1563
1564 if (*non_functioning_component_indication) {
1565 non_functioning_component_bitmap->value =
1566 le64toh(response->non_functioning_component_bitmap);
1567 }
1568
1569 return PLDM_SUCCESS;
1570}