blob: 91fbb331347709e418e64cce8bf9fec5ac9d5b52 [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) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093036 case PLDM_FWUP_PCI_VENDOR_ID:
37 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
38 case PLDM_FWUP_IANA_ENTERPRISE_ID:
39 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
40 case PLDM_FWUP_UUID:
41 return PLDM_FWUP_UUID_LENGTH;
42 case PLDM_FWUP_PNP_VENDOR_ID:
43 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
44 case PLDM_FWUP_ACPI_VENDOR_ID:
45 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
46 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
47 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
48 case PLDM_FWUP_SCSI_VENDOR_ID:
49 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
50 case PLDM_FWUP_PCI_DEVICE_ID:
51 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
52 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
53 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
54 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
55 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
56 case PLDM_FWUP_PCI_REVISION_ID:
57 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
58 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
59 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
60 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
61 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
62 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
63 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
64 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
65 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
66 case PLDM_FWUP_SCSI_PRODUCT_ID:
67 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
68 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
69 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
70 default:
71 return 0;
72 }
73}
74
75/** @brief Check whether ComponentResponse is valid
76 *
77 * @return true if ComponentResponse is valid, false if not
78 */
79static bool is_comp_resp_valid(uint8_t comp_resp)
80{
81 switch (comp_resp) {
82 case PLDM_CR_COMP_CAN_BE_UPDATED:
83 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
84 return true;
85
86 default:
87 return false;
88 }
89}
90
91/** @brief Check whether ComponentResponseCode is valid
92 *
93 * @return true if ComponentResponseCode is valid, false if not
94 */
95static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
96{
97 switch (comp_resp_code) {
98 case PLDM_CRC_COMP_CAN_BE_UPDATED:
99 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
100 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
101 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
102 case PLDM_CRC_COMP_CONFLICT:
103 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
104 case PLDM_CRC_COMP_NOT_SUPPORTED:
105 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
106 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
107 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
108 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
109 case PLDM_CRC_COMP_VER_STR_LOWER:
110 return true;
111
112 default:
113 if (comp_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930114 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930115 comp_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930116 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930117 return true;
118 }
119 return false;
120 }
121}
122
123/** @brief Check whether ComponentCompatibilityResponse is valid
124 *
125 * @return true if ComponentCompatibilityResponse is valid, false if not
126 */
127static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
128{
129 switch (comp_compatibility_resp) {
130 case PLDM_CCR_COMP_CAN_BE_UPDATED:
131 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
132 return true;
133
134 default:
135 return false;
136 }
137}
138
139/** @brief Check whether ComponentCompatibilityResponse Code is valid
140 *
141 * @return true if ComponentCompatibilityResponse Code is valid, false if not
142 */
143static bool
144is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
145{
146 switch (comp_compatibility_resp_code) {
147 case PLDM_CCRC_NO_RESPONSE_CODE:
148 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
149 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
150 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
151 case PLDM_CCRC_COMP_CONFLICT:
152 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
153 case PLDM_CCRC_COMP_NOT_SUPPORTED:
154 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
155 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
156 case PLDM_CCRC_COMP_INFO_NO_MATCH:
157 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
158 case PLDM_CCRC_COMP_VER_STR_LOWER:
159 return true;
160
161 default:
162 if (comp_compatibility_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930163 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930164 comp_compatibility_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930165 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930166 return true;
167 }
168 return false;
169 }
170}
171
172/** @brief Check whether SelfContainedActivationRequest is valid
173 *
174 * @return true if SelfContainedActivationRequest is valid, false if not
175 */
176static bool
177is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
178{
179 switch (self_contained_activation_req) {
180 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
181 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
182 return true;
183
184 default:
185 return false;
186 }
187}
188
189/** @brief Check if current or previous status in GetStatus command response is
190 * valid
191 *
192 * @param[in] state - current or previous different state machine state of
193 * the FD
194 * @return true if state is valid, false if not
195 */
196static bool is_state_valid(uint8_t state)
197{
198 switch (state) {
199 case PLDM_FD_STATE_IDLE:
200 case PLDM_FD_STATE_LEARN_COMPONENTS:
201 case PLDM_FD_STATE_READY_XFER:
202 case PLDM_FD_STATE_DOWNLOAD:
203 case PLDM_FD_STATE_VERIFY:
204 case PLDM_FD_STATE_APPLY:
205 case PLDM_FD_STATE_ACTIVATE:
206 return true;
207
208 default:
209 return false;
210 }
211}
212
213/** @brief Check if aux state in GetStatus command response is valid
214 *
215 * @param[in] aux_state - provides additional information to the UA to describe
216 * the current operation state of the FD/FDP
217 *
218 * @return true if aux state is valid, false if not
219 */
220static bool is_aux_state_valid(uint8_t aux_state)
221{
222 switch (aux_state) {
223 case PLDM_FD_OPERATION_IN_PROGRESS:
224 case PLDM_FD_OPERATION_SUCCESSFUL:
225 case PLDM_FD_OPERATION_FAILED:
226 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
227 return true;
228
229 default:
230 return false;
231 }
232}
233
234/** @brief Check if aux state status in GetStatus command response is valid
235 *
236 * @param[in] aux_state_status - aux state status
237 *
238 * @return true if aux state status is valid, false if not
239 */
240static bool is_aux_state_status_valid(uint8_t aux_state_status)
241{
242 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
243 aux_state_status == PLDM_FD_TIMEOUT ||
Andrew Jeffery67f7ed92023-04-05 14:00:00 +0930244 aux_state_status == PLDM_FD_GENERIC_ERROR ||
245 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
246 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930247 return true;
248 }
249
250 return false;
251}
252
253/** @brief Check if reason code in GetStatus command response is valid
254 *
255 * @param[in] reason_code - provides the reason for why the current state
256 * entered the IDLE state
257 *
258 * @return true if reason code is valid, false if not
259 */
260static bool is_reason_code_valid(uint8_t reason_code)
261{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930262 switch (reason_code) {
263 case PLDM_FD_INITIALIZATION:
264 case PLDM_FD_ACTIVATE_FW:
265 case PLDM_FD_CANCEL_UPDATE:
266 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
267 case PLDM_FD_TIMEOUT_READY_XFER:
268 case PLDM_FD_TIMEOUT_DOWNLOAD:
269 case PLDM_FD_TIMEOUT_VERIFY:
270 case PLDM_FD_TIMEOUT_APPLY:
271 return true;
272
273 default:
274 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
275 return true;
276 }
277 return false;
278 }
279}
280
281/** @brief Check if non functioning component indication in CancelUpdate
282 * response is valid
283 *
284 * @return true if non functioning component indication is valid, false if not
285 */
286static bool is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930287 bool8_t non_functioning_component_indication)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930288{
289 switch (non_functioning_component_indication) {
290 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
291 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
292 return true;
293
294 default:
295 return false;
296 }
297}
298
299int decode_pldm_package_header_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930300 const uint8_t *data, size_t length,
301 struct pldm_package_header_information *package_header_info,
302 struct variable_field *package_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930303{
304 if (data == NULL || package_header_info == NULL ||
305 package_version_str == NULL) {
306 return PLDM_ERROR_INVALID_DATA;
307 }
308
309 if (length < sizeof(struct pldm_package_header_information)) {
310 return PLDM_ERROR_INVALID_LENGTH;
311 }
312
313 struct pldm_package_header_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930314 (struct pldm_package_header_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930315
316 if (!is_string_type_valid(data_header->package_version_string_type) ||
317 (data_header->package_version_string_length == 0)) {
318 return PLDM_ERROR_INVALID_DATA;
319 }
320
321 if (length < sizeof(struct pldm_package_header_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930322 data_header->package_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930323 return PLDM_ERROR_INVALID_LENGTH;
324 }
325
326 if ((data_header->component_bitmap_bit_length %
327 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
328 return PLDM_ERROR_INVALID_DATA;
329 }
330
331 memcpy(package_header_info->uuid, data_header->uuid,
332 sizeof(data_header->uuid));
333 package_header_info->package_header_format_version =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930334 data_header->package_header_format_version;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930335 package_header_info->package_header_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930336 le16toh(data_header->package_header_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930337 memcpy(package_header_info->package_release_date_time,
338 data_header->package_release_date_time,
339 sizeof(data_header->package_release_date_time));
340 package_header_info->component_bitmap_bit_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930341 le16toh(data_header->component_bitmap_bit_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930342 package_header_info->package_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930343 data_header->package_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930344 package_header_info->package_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930345 data_header->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930346 package_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930347 data + sizeof(struct pldm_package_header_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930348 package_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930349 package_header_info->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930350
351 return PLDM_SUCCESS;
352}
353
354int decode_firmware_device_id_record(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930355 const uint8_t *data, size_t length,
356 uint16_t component_bitmap_bit_length,
357 struct pldm_firmware_device_id_record *fw_device_id_record,
358 struct variable_field *applicable_components,
359 struct variable_field *comp_image_set_version_str,
360 struct variable_field *record_descriptors,
361 struct variable_field *fw_device_pkg_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930362{
363 if (data == NULL || fw_device_id_record == NULL ||
364 applicable_components == NULL ||
365 comp_image_set_version_str == NULL || record_descriptors == NULL ||
366 fw_device_pkg_data == NULL) {
367 return PLDM_ERROR_INVALID_DATA;
368 }
369
370 if (length < sizeof(struct pldm_firmware_device_id_record)) {
371 return PLDM_ERROR_INVALID_LENGTH;
372 }
373
374 if ((component_bitmap_bit_length %
375 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
376 return PLDM_ERROR_INVALID_DATA;
377 }
378
379 struct pldm_firmware_device_id_record *data_record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930380 (struct pldm_firmware_device_id_record *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930381
382 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930383 data_record->comp_image_set_version_string_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930384 (data_record->comp_image_set_version_string_length == 0)) {
385 return PLDM_ERROR_INVALID_DATA;
386 }
387
388 fw_device_id_record->record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930389 le16toh(data_record->record_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930390 fw_device_id_record->descriptor_count = data_record->descriptor_count;
391 fw_device_id_record->device_update_option_flags.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930392 le32toh(data_record->device_update_option_flags.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930393 fw_device_id_record->comp_image_set_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930394 data_record->comp_image_set_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930395 fw_device_id_record->comp_image_set_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930396 data_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930397 fw_device_id_record->fw_device_pkg_data_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930398 le16toh(data_record->fw_device_pkg_data_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930399
400 if (length < fw_device_id_record->record_length) {
401 return PLDM_ERROR_INVALID_LENGTH;
402 }
403
404 uint16_t applicable_components_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930405 component_bitmap_bit_length /
406 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930407 uint16_t calc_min_record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930408 sizeof(struct pldm_firmware_device_id_record) +
409 applicable_components_length +
410 data_record->comp_image_set_version_string_length +
411 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
412 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930413
414 if (fw_device_id_record->record_length < calc_min_record_length) {
415 return PLDM_ERROR_INVALID_LENGTH;
416 }
417
418 applicable_components->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930419 data + sizeof(struct pldm_firmware_device_id_record);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930420 applicable_components->length = applicable_components_length;
421
422 comp_image_set_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930423 applicable_components->ptr + applicable_components->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930424 comp_image_set_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930425 fw_device_id_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930426
427 record_descriptors->ptr = comp_image_set_version_str->ptr +
428 comp_image_set_version_str->length;
429 record_descriptors->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930430 fw_device_id_record->record_length -
431 sizeof(struct pldm_firmware_device_id_record) -
432 applicable_components_length -
433 fw_device_id_record->comp_image_set_version_string_length -
434 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930435
436 if (fw_device_id_record->fw_device_pkg_data_length) {
437 fw_device_pkg_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930438 record_descriptors->ptr + record_descriptors->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930439 fw_device_pkg_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930440 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930441 }
442
443 return PLDM_SUCCESS;
444}
445
446int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
447 uint16_t *descriptor_type,
448 struct variable_field *descriptor_data)
449{
450 uint16_t descriptor_length = 0;
451
452 if (data == NULL || descriptor_type == NULL ||
453 descriptor_data == NULL) {
454 return PLDM_ERROR_INVALID_DATA;
455 }
456
457 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
458 return PLDM_ERROR_INVALID_LENGTH;
459 }
460
461 struct pldm_descriptor_tlv *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930462 (struct pldm_descriptor_tlv *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930463
464 *descriptor_type = le16toh(entry->descriptor_type);
465 descriptor_length = le16toh(entry->descriptor_length);
466 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
467 if (descriptor_length !=
468 get_descriptor_type_length(*descriptor_type)) {
469 return PLDM_ERROR_INVALID_LENGTH;
470 }
471 }
472
473 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
474 descriptor_length)) {
475 return PLDM_ERROR_INVALID_LENGTH;
476 }
477
478 descriptor_data->ptr = entry->descriptor_data;
479 descriptor_data->length = descriptor_length;
480
481 return PLDM_SUCCESS;
482}
483
484int decode_vendor_defined_descriptor_value(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930485 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
486 struct variable_field *descriptor_title_str,
487 struct variable_field *descriptor_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930488{
489 if (data == NULL || descriptor_title_str_type == NULL ||
490 descriptor_title_str == NULL || descriptor_data == NULL) {
491 return PLDM_ERROR_INVALID_DATA;
492 }
493
494 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
495 return PLDM_ERROR_INVALID_LENGTH;
496 }
497
498 struct pldm_vendor_defined_descriptor_title_data *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930499 (struct pldm_vendor_defined_descriptor_title_data *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930500 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930501 entry->vendor_defined_descriptor_title_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930502 (entry->vendor_defined_descriptor_title_str_len == 0)) {
503 return PLDM_ERROR_INVALID_DATA;
504 }
505
506 // Assuming atleast 1 byte of VendorDefinedDescriptorData
507 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
508 entry->vendor_defined_descriptor_title_str_len)) {
509 return PLDM_ERROR_INVALID_LENGTH;
510 }
511
512 *descriptor_title_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930513 entry->vendor_defined_descriptor_title_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930514 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
515 descriptor_title_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930516 entry->vendor_defined_descriptor_title_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930517
518 descriptor_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930519 descriptor_title_str->ptr + descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930520 descriptor_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930521 length -
522 sizeof(entry->vendor_defined_descriptor_title_str_type) -
523 sizeof(entry->vendor_defined_descriptor_title_str_len) -
524 descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930525
526 return PLDM_SUCCESS;
527}
528
529int decode_pldm_comp_image_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930530 const uint8_t *data, size_t length,
531 struct pldm_component_image_information *pldm_comp_image_info,
532 struct variable_field *comp_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930533{
534 if (data == NULL || pldm_comp_image_info == NULL ||
535 comp_version_str == NULL) {
536 return PLDM_ERROR_INVALID_DATA;
537 }
538
539 if (length < sizeof(struct pldm_component_image_information)) {
540 return PLDM_ERROR_INVALID_LENGTH;
541 }
542
543 struct pldm_component_image_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930544 (struct pldm_component_image_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930545
546 if (!is_string_type_valid(data_header->comp_version_string_type) ||
547 (data_header->comp_version_string_length == 0)) {
548 return PLDM_ERROR_INVALID_DATA;
549 }
550
551 if (length < sizeof(struct pldm_component_image_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930552 data_header->comp_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930553 return PLDM_ERROR_INVALID_LENGTH;
554 }
555
556 pldm_comp_image_info->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930557 le16toh(data_header->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930558 pldm_comp_image_info->comp_identifier =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930559 le16toh(data_header->comp_identifier);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930560 pldm_comp_image_info->comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930561 le32toh(data_header->comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930562 pldm_comp_image_info->comp_options.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930563 le16toh(data_header->comp_options.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930564 pldm_comp_image_info->requested_comp_activation_method.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930565 le16toh(data_header->requested_comp_activation_method.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930566 pldm_comp_image_info->comp_location_offset =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930567 le32toh(data_header->comp_location_offset);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930568 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
569 pldm_comp_image_info->comp_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930570 data_header->comp_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930571 pldm_comp_image_info->comp_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930572 data_header->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930573
574 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
575 pldm_comp_image_info->comp_comparison_stamp !=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930576 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930577 return PLDM_ERROR_INVALID_DATA;
578 }
579
580 if (pldm_comp_image_info->comp_location_offset == 0 ||
581 pldm_comp_image_info->comp_size == 0) {
582 return PLDM_ERROR_INVALID_DATA;
583 }
584
585 comp_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930586 data + sizeof(struct pldm_component_image_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930587 comp_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930588 pldm_comp_image_info->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930589
590 return PLDM_SUCCESS;
591}
592
593int encode_query_device_identifiers_req(uint8_t instance_id,
594 size_t payload_length,
595 struct pldm_msg *msg)
596{
597 if (msg == NULL) {
598 return PLDM_ERROR_INVALID_DATA;
599 }
600
601 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
602 return PLDM_ERROR_INVALID_LENGTH;
603 }
604
605 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
606 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
607}
608
609int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
610 size_t payload_length,
611 uint8_t *completion_code,
612 uint32_t *device_identifiers_len,
613 uint8_t *descriptor_count,
614 uint8_t **descriptor_data)
615{
616 if (msg == NULL || completion_code == NULL ||
617 device_identifiers_len == NULL || descriptor_count == NULL ||
618 descriptor_data == NULL) {
619 return PLDM_ERROR_INVALID_DATA;
620 }
621
622 *completion_code = msg->payload[0];
623 if (PLDM_SUCCESS != *completion_code) {
624 return PLDM_SUCCESS;
625 }
626
627 if (payload_length <
628 sizeof(struct pldm_query_device_identifiers_resp)) {
629 return PLDM_ERROR_INVALID_LENGTH;
630 }
631
632 struct pldm_query_device_identifiers_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930633 (struct pldm_query_device_identifiers_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930634 *device_identifiers_len = le32toh(response->device_identifiers_len);
635
636 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
637 return PLDM_ERROR_INVALID_LENGTH;
638 }
639
640 if (payload_length !=
641 sizeof(struct pldm_query_device_identifiers_resp) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930642 *device_identifiers_len) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930643 return PLDM_ERROR_INVALID_LENGTH;
644 }
645 *descriptor_count = response->descriptor_count;
646
647 if (*descriptor_count == 0) {
648 return PLDM_ERROR_INVALID_DATA;
649 }
650 *descriptor_data =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930651 (uint8_t *)(msg->payload +
652 sizeof(struct pldm_query_device_identifiers_resp));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930653 return PLDM_SUCCESS;
654}
655
656int encode_get_firmware_parameters_req(uint8_t instance_id,
657 size_t payload_length,
658 struct pldm_msg *msg)
659{
660 if (msg == NULL) {
661 return PLDM_ERROR_INVALID_DATA;
662 }
663
664 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
665 return PLDM_ERROR_INVALID_LENGTH;
666 }
667
668 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
669 PLDM_GET_FIRMWARE_PARAMETERS, msg);
670}
671
672int decode_get_firmware_parameters_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930673 const struct pldm_msg *msg, size_t payload_length,
674 struct pldm_get_firmware_parameters_resp *resp_data,
675 struct variable_field *active_comp_image_set_ver_str,
676 struct variable_field *pending_comp_image_set_ver_str,
677 struct variable_field *comp_parameter_table)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930678{
679 if (msg == NULL || resp_data == NULL ||
680 active_comp_image_set_ver_str == NULL ||
681 pending_comp_image_set_ver_str == NULL ||
682 comp_parameter_table == NULL || !payload_length) {
683 return PLDM_ERROR_INVALID_DATA;
684 }
685
686 resp_data->completion_code = msg->payload[0];
687 if (PLDM_SUCCESS != resp_data->completion_code) {
688 return PLDM_SUCCESS;
689 }
690
691 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
692 return PLDM_ERROR_INVALID_LENGTH;
693 }
694
695 struct pldm_get_firmware_parameters_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930696 (struct pldm_get_firmware_parameters_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930697
698 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930699 response->active_comp_image_set_ver_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930700 (response->active_comp_image_set_ver_str_len == 0)) {
701 return PLDM_ERROR_INVALID_DATA;
702 }
703
704 if (response->pending_comp_image_set_ver_str_len == 0) {
705 if (response->pending_comp_image_set_ver_str_type !=
706 PLDM_STR_TYPE_UNKNOWN) {
707 return PLDM_ERROR_INVALID_DATA;
708 }
709 } else {
710 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930711 response->pending_comp_image_set_ver_str_type)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930712 return PLDM_ERROR_INVALID_DATA;
713 }
714 }
715
716 size_t partial_response_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930717 sizeof(struct pldm_get_firmware_parameters_resp) +
718 response->active_comp_image_set_ver_str_len +
719 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930720
721 if (payload_length < partial_response_length) {
722 return PLDM_ERROR_INVALID_LENGTH;
723 }
724
725 resp_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930726 le32toh(response->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930727 resp_data->comp_count = le16toh(response->comp_count);
728 resp_data->active_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930729 response->active_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930730 resp_data->active_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930731 response->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930732 resp_data->pending_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930733 response->pending_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930734 resp_data->pending_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930735 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930736
737 active_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930738 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930739 active_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930740 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930741
742 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
743 pending_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930744 msg->payload +
745 sizeof(struct pldm_get_firmware_parameters_resp) +
746 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930747 pending_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930748 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930749 } else {
750 pending_comp_image_set_ver_str->ptr = NULL;
751 pending_comp_image_set_ver_str->length = 0;
752 }
753
754 if (payload_length > partial_response_length && resp_data->comp_count) {
755 comp_parameter_table->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930756 msg->payload +
757 sizeof(struct pldm_get_firmware_parameters_resp) +
758 resp_data->active_comp_image_set_ver_str_len +
759 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930760 comp_parameter_table->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930761 payload_length - partial_response_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930762 } else {
763 comp_parameter_table->ptr = NULL;
764 comp_parameter_table->length = 0;
765 }
766
767 return PLDM_SUCCESS;
768}
769
770int decode_get_firmware_parameters_resp_comp_entry(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930771 const uint8_t *data, size_t length,
772 struct pldm_component_parameter_entry *component_data,
773 struct variable_field *active_comp_ver_str,
774 struct variable_field *pending_comp_ver_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930775{
776 if (data == NULL || component_data == NULL ||
777 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
778 return PLDM_ERROR_INVALID_DATA;
779 }
780
781 if (length < sizeof(struct pldm_component_parameter_entry)) {
782 return PLDM_ERROR_INVALID_LENGTH;
783 }
784
785 struct pldm_component_parameter_entry *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930786 (struct pldm_component_parameter_entry *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930787
788 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
789 entry->active_comp_ver_str_len +
790 entry->pending_comp_ver_str_len;
791
792 if (length < entry_length) {
793 return PLDM_ERROR_INVALID_LENGTH;
794 }
795
796 component_data->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930797 le16toh(entry->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930798 component_data->comp_identifier = le16toh(entry->comp_identifier);
799 component_data->comp_classification_index =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930800 entry->comp_classification_index;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930801 component_data->active_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930802 le32toh(entry->active_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930803 component_data->active_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930804 entry->active_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930805 component_data->active_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930806 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930807 memcpy(component_data->active_comp_release_date,
808 entry->active_comp_release_date,
809 sizeof(entry->active_comp_release_date));
810 component_data->pending_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930811 le32toh(entry->pending_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930812 component_data->pending_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930813 entry->pending_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930814 component_data->pending_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930815 entry->pending_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930816 memcpy(component_data->pending_comp_release_date,
817 entry->pending_comp_release_date,
818 sizeof(entry->pending_comp_release_date));
819 component_data->comp_activation_methods.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930820 le16toh(entry->comp_activation_methods.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930821 component_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930822 le32toh(entry->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930823
824 if (entry->active_comp_ver_str_len != 0) {
825 active_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930826 data + sizeof(struct pldm_component_parameter_entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930827 active_comp_ver_str->length = entry->active_comp_ver_str_len;
828 } else {
829 active_comp_ver_str->ptr = NULL;
830 active_comp_ver_str->length = 0;
831 }
832
833 if (entry->pending_comp_ver_str_len != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930834 pending_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930835 data + sizeof(struct pldm_component_parameter_entry) +
836 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930837 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
838 } else {
839 pending_comp_ver_str->ptr = NULL;
840 pending_comp_ver_str->length = 0;
841 }
842 return PLDM_SUCCESS;
843}
844
845int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
846 uint16_t num_of_comp,
847 uint8_t max_outstanding_transfer_req,
848 uint16_t pkg_data_len,
849 uint8_t comp_image_set_ver_str_type,
850 uint8_t comp_image_set_ver_str_len,
851 const struct variable_field *comp_img_set_ver_str,
852 struct pldm_msg *msg, size_t payload_length)
853{
854 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
855 msg == NULL) {
856 return PLDM_ERROR_INVALID_DATA;
857 }
858
859 if (payload_length != sizeof(struct pldm_request_update_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930860 comp_img_set_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930861 return PLDM_ERROR_INVALID_LENGTH;
862 }
863
864 if ((comp_image_set_ver_str_len == 0) ||
865 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
866 return PLDM_ERROR_INVALID_DATA;
867 }
868
869 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
870 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
871 return PLDM_ERROR_INVALID_DATA;
872 }
873
874 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
875 return PLDM_ERROR_INVALID_DATA;
876 }
877
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930878 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930879 header.instance = instance_id;
880 header.msg_type = PLDM_REQUEST;
881 header.pldm_type = PLDM_FWUP;
882 header.command = PLDM_REQUEST_UPDATE;
883 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
884 if (rc) {
885 return rc;
886 }
887
888 struct pldm_request_update_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930889 (struct pldm_request_update_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930890
891 request->max_transfer_size = htole32(max_transfer_size);
892 request->num_of_comp = htole16(num_of_comp);
893 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
894 request->pkg_data_len = htole16(pkg_data_len);
895 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
896 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
897
898 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
899 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
900
901 return PLDM_SUCCESS;
902}
903
904int decode_request_update_resp(const struct pldm_msg *msg,
905 size_t payload_length, uint8_t *completion_code,
906 uint16_t *fd_meta_data_len,
907 uint8_t *fd_will_send_pkg_data)
908{
909 if (msg == NULL || completion_code == NULL ||
910 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
911 !payload_length) {
912 return PLDM_ERROR_INVALID_DATA;
913 }
914
915 *completion_code = msg->payload[0];
916 if (*completion_code != PLDM_SUCCESS) {
917 return PLDM_SUCCESS;
918 }
919
920 if (payload_length != sizeof(struct pldm_request_update_resp)) {
921 return PLDM_ERROR_INVALID_LENGTH;
922 }
923
924 struct pldm_request_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930925 (struct pldm_request_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930926
927 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
928 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
929
930 return PLDM_SUCCESS;
931}
932
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930933int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
934 uint16_t comp_classification,
935 uint16_t comp_identifier,
936 uint8_t comp_classification_index,
937 uint32_t comp_comparison_stamp,
938 uint8_t comp_ver_str_type,
939 uint8_t comp_ver_str_len,
940 const struct variable_field *comp_ver_str,
941 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930942{
943 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
944 return PLDM_ERROR_INVALID_DATA;
945 }
946
947 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930948 comp_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930949 return PLDM_ERROR_INVALID_LENGTH;
950 }
951
952 if ((comp_ver_str_len == 0) ||
953 (comp_ver_str_len != comp_ver_str->length)) {
954 return PLDM_ERROR_INVALID_DATA;
955 }
956
957 if (!is_transfer_flag_valid(transfer_flag)) {
958 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
959 }
960
961 if (!is_string_type_valid(comp_ver_str_type)) {
962 return PLDM_ERROR_INVALID_DATA;
963 }
964
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930965 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930966 header.instance = instance_id;
967 header.msg_type = PLDM_REQUEST;
968 header.pldm_type = PLDM_FWUP;
969 header.command = PLDM_PASS_COMPONENT_TABLE;
970 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
971 if (rc) {
972 return rc;
973 }
974
975 struct pldm_pass_component_table_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930976 (struct pldm_pass_component_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930977
978 request->transfer_flag = transfer_flag;
979 request->comp_classification = htole16(comp_classification);
980 request->comp_identifier = htole16(comp_identifier);
981 request->comp_classification_index = comp_classification_index;
982 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
983 request->comp_ver_str_type = comp_ver_str_type;
984 request->comp_ver_str_len = comp_ver_str_len;
985
986 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
987 comp_ver_str->ptr, comp_ver_str->length);
988
989 return PLDM_SUCCESS;
990}
991
992int decode_pass_component_table_resp(const struct pldm_msg *msg,
993 const size_t payload_length,
994 uint8_t *completion_code,
995 uint8_t *comp_resp,
996 uint8_t *comp_resp_code)
997{
998 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
999 comp_resp_code == NULL || !payload_length) {
1000 return PLDM_ERROR_INVALID_DATA;
1001 }
1002
1003 *completion_code = msg->payload[0];
1004 if (*completion_code != PLDM_SUCCESS) {
1005 return PLDM_SUCCESS;
1006 }
1007
1008 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1009 return PLDM_ERROR_INVALID_LENGTH;
1010 }
1011
1012 struct pldm_pass_component_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301013 (struct pldm_pass_component_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301014
1015 if (!is_comp_resp_valid(response->comp_resp)) {
1016 return PLDM_ERROR_INVALID_DATA;
1017 }
1018
1019 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1020 return PLDM_ERROR_INVALID_DATA;
1021 }
1022
1023 *comp_resp = response->comp_resp;
1024 *comp_resp_code = response->comp_resp_code;
1025
1026 return PLDM_SUCCESS;
1027}
1028
1029int encode_update_component_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301030 uint8_t instance_id, uint16_t comp_classification,
1031 uint16_t comp_identifier, uint8_t comp_classification_index,
1032 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1033 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1034 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1035 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301036{
1037 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1038 return PLDM_ERROR_INVALID_DATA;
1039 }
1040
1041 if (payload_length !=
1042 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1043 return PLDM_ERROR_INVALID_LENGTH;
1044 }
1045
1046 if (!comp_image_size) {
1047 return PLDM_ERROR_INVALID_DATA;
1048 }
1049
1050 if ((comp_ver_str_len == 0) ||
1051 (comp_ver_str_len != comp_ver_str->length)) {
1052 return PLDM_ERROR_INVALID_DATA;
1053 }
1054
1055 if (!is_string_type_valid(comp_ver_str_type)) {
1056 return PLDM_ERROR_INVALID_DATA;
1057 }
1058
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301059 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301060 header.instance = instance_id;
1061 header.msg_type = PLDM_REQUEST;
1062 header.pldm_type = PLDM_FWUP;
1063 header.command = PLDM_UPDATE_COMPONENT;
1064 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1065 if (rc) {
1066 return rc;
1067 }
1068
1069 struct pldm_update_component_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301070 (struct pldm_update_component_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301071
1072 request->comp_classification = htole16(comp_classification);
1073 request->comp_identifier = htole16(comp_identifier);
1074 request->comp_classification_index = comp_classification_index;
1075 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1076 request->comp_image_size = htole32(comp_image_size);
1077 request->update_option_flags.value = htole32(update_option_flags.value);
1078 request->comp_ver_str_type = comp_ver_str_type;
1079 request->comp_ver_str_len = comp_ver_str_len;
1080
1081 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1082 comp_ver_str->ptr, comp_ver_str->length);
1083
1084 return PLDM_SUCCESS;
1085}
1086
1087int decode_update_component_resp(const struct pldm_msg *msg,
1088 size_t payload_length,
1089 uint8_t *completion_code,
1090 uint8_t *comp_compatibility_resp,
1091 uint8_t *comp_compatibility_resp_code,
1092 bitfield32_t *update_option_flags_enabled,
1093 uint16_t *time_before_req_fw_data)
1094{
1095 if (msg == NULL || completion_code == NULL ||
1096 comp_compatibility_resp == NULL ||
1097 comp_compatibility_resp_code == NULL ||
1098 update_option_flags_enabled == NULL ||
1099 time_before_req_fw_data == NULL || !payload_length) {
1100 return PLDM_ERROR_INVALID_DATA;
1101 }
1102
1103 *completion_code = msg->payload[0];
1104 if (*completion_code != PLDM_SUCCESS) {
1105 return PLDM_SUCCESS;
1106 }
1107
1108 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1109 return PLDM_ERROR_INVALID_LENGTH;
1110 }
1111
1112 struct pldm_update_component_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301113 (struct pldm_update_component_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301114
1115 if (!is_comp_compatibility_resp_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301116 response->comp_compatibility_resp)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301117 return PLDM_ERROR_INVALID_DATA;
1118 }
1119
1120 if (!is_comp_compatibility_resp_code_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301121 response->comp_compatibility_resp_code)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301122 return PLDM_ERROR_INVALID_DATA;
1123 }
1124
1125 *comp_compatibility_resp = response->comp_compatibility_resp;
1126 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1127 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301128 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301129 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1130
1131 return PLDM_SUCCESS;
1132}
1133
1134int decode_request_firmware_data_req(const struct pldm_msg *msg,
1135 size_t payload_length, uint32_t *offset,
1136 uint32_t *length)
1137{
1138 if (msg == NULL || offset == NULL || length == NULL) {
1139 return PLDM_ERROR_INVALID_DATA;
1140 }
1141 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1142 return PLDM_ERROR_INVALID_LENGTH;
1143 }
1144 struct pldm_request_firmware_data_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301145 (struct pldm_request_firmware_data_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301146 *offset = le32toh(request->offset);
1147 *length = le32toh(request->length);
1148
1149 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1150 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1151 }
1152
1153 return PLDM_SUCCESS;
1154}
1155
1156int encode_request_firmware_data_resp(uint8_t instance_id,
1157 uint8_t completion_code,
1158 struct pldm_msg *msg,
1159 size_t payload_length)
1160{
1161 if (msg == NULL || !payload_length) {
1162 return PLDM_ERROR_INVALID_DATA;
1163 }
1164
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301165 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301166 header.instance = instance_id;
1167 header.msg_type = PLDM_RESPONSE;
1168 header.pldm_type = PLDM_FWUP;
1169 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1170 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1171 if (rc) {
1172 return rc;
1173 }
1174
1175 msg->payload[0] = completion_code;
1176
1177 return PLDM_SUCCESS;
1178}
1179
1180int decode_transfer_complete_req(const struct pldm_msg *msg,
1181 size_t payload_length,
1182 uint8_t *transfer_result)
1183{
1184 if (msg == NULL || transfer_result == NULL) {
1185 return PLDM_ERROR_INVALID_DATA;
1186 }
1187
1188 if (payload_length != sizeof(*transfer_result)) {
1189 return PLDM_ERROR_INVALID_LENGTH;
1190 }
1191
1192 *transfer_result = msg->payload[0];
1193 return PLDM_SUCCESS;
1194}
1195
1196int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1197 struct pldm_msg *msg, size_t payload_length)
1198{
1199 if (msg == NULL) {
1200 return PLDM_ERROR_INVALID_DATA;
1201 }
1202
1203 if (payload_length != sizeof(completion_code)) {
1204 return PLDM_ERROR_INVALID_LENGTH;
1205 }
1206
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301207 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301208 header.instance = instance_id;
1209 header.msg_type = PLDM_RESPONSE;
1210 header.pldm_type = PLDM_FWUP;
1211 header.command = PLDM_TRANSFER_COMPLETE;
1212 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1213 if (rc) {
1214 return rc;
1215 }
1216
1217 msg->payload[0] = completion_code;
1218
1219 return PLDM_SUCCESS;
1220}
1221
1222int decode_verify_complete_req(const struct pldm_msg *msg,
1223 size_t payload_length, uint8_t *verify_result)
1224{
1225 if (msg == NULL || verify_result == NULL) {
1226 return PLDM_ERROR_INVALID_DATA;
1227 }
1228
1229 if (payload_length != sizeof(*verify_result)) {
1230 return PLDM_ERROR_INVALID_LENGTH;
1231 }
1232
1233 *verify_result = msg->payload[0];
1234 return PLDM_SUCCESS;
1235}
1236
1237int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1238 struct pldm_msg *msg, size_t payload_length)
1239{
1240 if (msg == NULL) {
1241 return PLDM_ERROR_INVALID_DATA;
1242 }
1243
1244 if (payload_length != sizeof(completion_code)) {
1245 return PLDM_ERROR_INVALID_LENGTH;
1246 }
1247
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301248 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301249 header.instance = instance_id;
1250 header.msg_type = PLDM_RESPONSE;
1251 header.pldm_type = PLDM_FWUP;
1252 header.command = PLDM_VERIFY_COMPLETE;
1253 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1254 if (rc) {
1255 return rc;
1256 }
1257
1258 msg->payload[0] = completion_code;
1259
1260 return PLDM_SUCCESS;
1261}
1262
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301263int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
1264 uint8_t *apply_result,
1265 bitfield16_t *comp_activation_methods_modification)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301266{
1267 if (msg == NULL || apply_result == NULL ||
1268 comp_activation_methods_modification == NULL) {
1269 return PLDM_ERROR_INVALID_DATA;
1270 }
1271
1272 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1273 return PLDM_ERROR_INVALID_LENGTH;
1274 }
1275
1276 struct pldm_apply_complete_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301277 (struct pldm_apply_complete_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301278
1279 *apply_result = request->apply_result;
1280 comp_activation_methods_modification->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301281 le16toh(request->comp_activation_methods_modification.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301282
1283 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1284 comp_activation_methods_modification->value) {
1285 return PLDM_ERROR_INVALID_DATA;
1286 }
1287
1288 return PLDM_SUCCESS;
1289}
1290
1291int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1292 struct pldm_msg *msg, size_t payload_length)
1293{
1294 if (msg == NULL) {
1295 return PLDM_ERROR_INVALID_DATA;
1296 }
1297
1298 if (payload_length != sizeof(completion_code)) {
1299 return PLDM_ERROR_INVALID_LENGTH;
1300 }
1301
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301302 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301303 header.instance = instance_id;
1304 header.msg_type = PLDM_RESPONSE;
1305 header.pldm_type = PLDM_FWUP;
1306 header.command = PLDM_APPLY_COMPLETE;
1307 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1308 if (rc) {
1309 return rc;
1310 }
1311
1312 msg->payload[0] = completion_code;
1313
1314 return PLDM_SUCCESS;
1315}
1316
1317int encode_activate_firmware_req(uint8_t instance_id,
1318 bool8_t self_contained_activation_req,
1319 struct pldm_msg *msg, size_t payload_length)
1320{
1321 if (msg == NULL) {
1322 return PLDM_ERROR_INVALID_DATA;
1323 }
1324
1325 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1326 return PLDM_ERROR_INVALID_LENGTH;
1327 }
1328
1329 if (!is_self_contained_activation_req_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301330 self_contained_activation_req)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301331 return PLDM_ERROR_INVALID_DATA;
1332 }
1333
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301334 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301335 header.instance = instance_id;
1336 header.msg_type = PLDM_REQUEST;
1337 header.pldm_type = PLDM_FWUP;
1338 header.command = PLDM_ACTIVATE_FIRMWARE;
1339 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1340 if (rc) {
1341 return rc;
1342 }
1343
1344 struct pldm_activate_firmware_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301345 (struct pldm_activate_firmware_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301346
1347 request->self_contained_activation_req = self_contained_activation_req;
1348
1349 return PLDM_SUCCESS;
1350}
1351
1352int decode_activate_firmware_resp(const struct pldm_msg *msg,
1353 size_t payload_length,
1354 uint8_t *completion_code,
1355 uint16_t *estimated_time_activation)
1356{
1357 if (msg == NULL || completion_code == NULL ||
1358 estimated_time_activation == NULL || !payload_length) {
1359 return PLDM_ERROR_INVALID_DATA;
1360 }
1361
1362 *completion_code = msg->payload[0];
1363 if (*completion_code != PLDM_SUCCESS) {
1364 return PLDM_SUCCESS;
1365 }
1366
1367 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1368 return PLDM_ERROR_INVALID_LENGTH;
1369 }
1370
1371 struct pldm_activate_firmware_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301372 (struct pldm_activate_firmware_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301373
1374 *estimated_time_activation =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301375 le16toh(response->estimated_time_activation);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301376
1377 return PLDM_SUCCESS;
1378}
1379
1380int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1381 size_t payload_length)
1382{
1383 if (msg == NULL) {
1384 return PLDM_ERROR_INVALID_DATA;
1385 }
1386
1387 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1388 return PLDM_ERROR_INVALID_LENGTH;
1389 }
1390
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301391 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301392 header.instance = instance_id;
1393 header.msg_type = PLDM_REQUEST;
1394 header.pldm_type = PLDM_FWUP;
1395 header.command = PLDM_GET_STATUS;
1396 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1397 if (rc) {
1398 return rc;
1399 }
1400
1401 return PLDM_SUCCESS;
1402}
1403
1404int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1405 uint8_t *completion_code, uint8_t *current_state,
1406 uint8_t *previous_state, uint8_t *aux_state,
1407 uint8_t *aux_state_status, uint8_t *progress_percent,
1408 uint8_t *reason_code,
1409 bitfield32_t *update_option_flags_enabled)
1410{
1411 if (msg == NULL || completion_code == NULL || current_state == NULL ||
1412 previous_state == NULL || aux_state == NULL ||
1413 aux_state_status == NULL || progress_percent == NULL ||
1414 reason_code == NULL || update_option_flags_enabled == NULL ||
1415 !payload_length) {
1416 return PLDM_ERROR_INVALID_DATA;
1417 }
1418
1419 *completion_code = msg->payload[0];
1420 if (*completion_code != PLDM_SUCCESS) {
1421 return PLDM_SUCCESS;
1422 }
1423
1424 if (payload_length != sizeof(struct pldm_get_status_resp)) {
1425 return PLDM_ERROR_INVALID_LENGTH;
1426 }
1427 struct pldm_get_status_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301428 (struct pldm_get_status_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301429
1430 if (!is_state_valid(response->current_state)) {
1431 return PLDM_ERROR_INVALID_DATA;
1432 }
1433 if (!is_state_valid(response->previous_state)) {
1434 return PLDM_ERROR_INVALID_DATA;
1435 }
1436 if (!is_aux_state_valid(response->aux_state)) {
1437 return PLDM_ERROR_INVALID_DATA;
1438 }
1439 if (!is_aux_state_status_valid(response->aux_state_status)) {
1440 return PLDM_ERROR_INVALID_DATA;
1441 }
1442 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1443 return PLDM_ERROR_INVALID_DATA;
1444 }
1445 if (!is_reason_code_valid(response->reason_code)) {
1446 return PLDM_ERROR_INVALID_DATA;
1447 }
1448
1449 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1450 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1451 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1452 if (response->aux_state !=
1453 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1454 return PLDM_ERROR_INVALID_DATA;
1455 }
1456 }
1457
1458 *current_state = response->current_state;
1459 *previous_state = response->previous_state;
1460 *aux_state = response->aux_state;
1461 *aux_state_status = response->aux_state_status;
1462 *progress_percent = response->progress_percent;
1463 *reason_code = response->reason_code;
1464 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301465 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301466
1467 return PLDM_SUCCESS;
1468}
1469
1470int encode_cancel_update_component_req(uint8_t instance_id,
1471 struct pldm_msg *msg,
1472 size_t payload_length)
1473{
1474 if (msg == NULL) {
1475 return PLDM_ERROR_INVALID_DATA;
1476 }
1477
1478 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1479 return PLDM_ERROR_INVALID_LENGTH;
1480 }
1481
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301482 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301483 header.instance = instance_id;
1484 header.msg_type = PLDM_REQUEST;
1485 header.pldm_type = PLDM_FWUP;
1486 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
1487 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1488 if (rc) {
1489 return rc;
1490 }
1491
1492 return PLDM_SUCCESS;
1493}
1494
1495int decode_cancel_update_component_resp(const struct pldm_msg *msg,
1496 size_t payload_length,
1497 uint8_t *completion_code)
1498{
1499 if (msg == NULL || completion_code == NULL) {
1500 return PLDM_ERROR_INVALID_DATA;
1501 }
1502
1503 if (payload_length != sizeof(*completion_code)) {
1504 return PLDM_ERROR_INVALID_LENGTH;
1505 }
1506
1507 *completion_code = msg->payload[0];
1508 return PLDM_SUCCESS;
1509}
1510
1511int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
1512 size_t payload_length)
1513{
1514 if (msg == NULL) {
1515 return PLDM_ERROR_INVALID_DATA;
1516 }
1517
1518 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
1519 return PLDM_ERROR_INVALID_LENGTH;
1520 }
1521
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301522 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301523 header.instance = instance_id;
1524 header.msg_type = PLDM_REQUEST;
1525 header.pldm_type = PLDM_FWUP;
1526 header.command = PLDM_CANCEL_UPDATE;
1527 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1528 if (rc) {
1529 return rc;
1530 }
1531
1532 return PLDM_SUCCESS;
1533}
1534
1535int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
1536 uint8_t *completion_code,
1537 bool8_t *non_functioning_component_indication,
1538 bitfield64_t *non_functioning_component_bitmap)
1539{
1540 if (msg == NULL || completion_code == NULL ||
1541 non_functioning_component_indication == NULL ||
1542 non_functioning_component_bitmap == NULL || !payload_length) {
1543 return PLDM_ERROR_INVALID_DATA;
1544 }
1545
1546 *completion_code = msg->payload[0];
1547 if (*completion_code != PLDM_SUCCESS) {
1548 return PLDM_SUCCESS;
1549 }
1550
1551 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
1552 return PLDM_ERROR_INVALID_LENGTH;
1553 }
1554 struct pldm_cancel_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301555 (struct pldm_cancel_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301556
1557 if (!is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301558 response->non_functioning_component_indication)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301559 return PLDM_ERROR_INVALID_DATA;
1560 }
1561
1562 *non_functioning_component_indication =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301563 response->non_functioning_component_indication;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301564
1565 if (*non_functioning_component_indication) {
1566 non_functioning_component_bitmap->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301567 le64toh(response->non_functioning_component_bitmap);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301568 }
1569
1570 return PLDM_SUCCESS;
1571}