blob: 7a4fbba367d13d578388449236bcae06e4312751 [file] [log] [blame]
gokulsanker138ceba2021-04-05 13:25:25 +05301#include "firmware_update.h"
gokulsankereca3e192021-04-05 14:57:41 +05302#include <endian.h>
gokulsankere1fb7a82021-04-05 16:09:29 +05303#include <string.h>
gokulsanker138ceba2021-04-05 13:25:25 +05304
Tom Joseph763b51e2021-06-05 04:50:47 -07005/** @brief Check whether string type value is valid
6 *
7 * @return true if string type value is valid, false if not
8 */
9static bool is_string_type_valid(uint8_t string_type)
10{
11 switch (string_type) {
12 case PLDM_STR_TYPE_UNKNOWN:
Tom Josephbc44b7b2021-06-19 01:13:52 -070013 return false;
Tom Joseph763b51e2021-06-05 04:50:47 -070014 case PLDM_STR_TYPE_ASCII:
15 case PLDM_STR_TYPE_UTF_8:
16 case PLDM_STR_TYPE_UTF_16:
17 case PLDM_STR_TYPE_UTF_16LE:
18 case PLDM_STR_TYPE_UTF_16BE:
19 return true;
20 default:
21 return false;
22 }
23}
24
25/** @brief Return the length of the descriptor type described in firmware update
26 * specification
27 *
28 * @return length of the descriptor type if descriptor type is valid else
29 * return 0
30 */
31static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
32{
33 switch (descriptor_type) {
34
35 case PLDM_FWUP_PCI_VENDOR_ID:
36 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
37 case PLDM_FWUP_IANA_ENTERPRISE_ID:
38 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
39 case PLDM_FWUP_UUID:
40 return PLDM_FWUP_UUID_LENGTH;
41 case PLDM_FWUP_PNP_VENDOR_ID:
42 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
43 case PLDM_FWUP_ACPI_VENDOR_ID:
44 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
45 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
46 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
47 case PLDM_FWUP_SCSI_VENDOR_ID:
48 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
49 case PLDM_FWUP_PCI_DEVICE_ID:
50 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
51 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
52 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
53 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
54 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
55 case PLDM_FWUP_PCI_REVISION_ID:
56 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
57 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
58 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
59 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
60 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
61 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
62 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
63 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
64 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
65 case PLDM_FWUP_SCSI_PRODUCT_ID:
66 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
67 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
68 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
69 default:
70 return 0;
71 }
72}
73
gokulsanker566784b2021-04-05 17:47:04 +053074/** @brief Check whether ComponentResponse is valid
75 *
76 * @return true if ComponentResponse is valid, false if not
77 */
78static bool is_comp_resp_valid(uint8_t comp_resp)
79{
80 switch (comp_resp) {
81 case PLDM_CR_COMP_CAN_BE_UPDATED:
82 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
83 return true;
84
85 default:
86 return false;
87 }
88}
89
90/** @brief Check whether ComponentResponseCode is valid
91 *
92 * @return true if ComponentResponseCode is valid, false if not
93 */
94static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
95{
96 switch (comp_resp_code) {
97 case PLDM_CRC_COMP_CAN_BE_UPDATED:
98 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
99 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
100 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
101 case PLDM_CRC_COMP_CONFLICT:
102 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
103 case PLDM_CRC_COMP_NOT_SUPPORTED:
104 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
105 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
106 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
107 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
108 case PLDM_CRC_COMP_VER_STR_LOWER:
109 return true;
110
111 default:
112 if (comp_resp_code >=
113 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
114 comp_resp_code <=
115 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
116 return true;
117 }
118 return false;
119 }
120}
121
gokulsanker4b533f22021-04-22 12:53:00 +0530122/** @brief Check whether ComponentCompatibilityResponse is valid
123 *
124 * @return true if ComponentCompatibilityResponse is valid, false if not
125 */
126static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
127{
128 switch (comp_compatibility_resp) {
129 case PLDM_CCR_COMP_CAN_BE_UPDATED:
130 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
131 return true;
132
133 default:
134 return false;
135 }
136}
137
138/** @brief Check whether ComponentCompatibilityResponse Code is valid
139 *
140 * @return true if ComponentCompatibilityResponse Code is valid, false if not
141 */
142static bool
143is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
144{
145 switch (comp_compatibility_resp_code) {
146 case PLDM_CCRC_NO_RESPONSE_CODE:
147 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
148 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
149 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
150 case PLDM_CCRC_COMP_CONFLICT:
151 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
152 case PLDM_CCRC_COMP_NOT_SUPPORTED:
153 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
154 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
155 case PLDM_CCRC_COMP_INFO_NO_MATCH:
156 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
157 case PLDM_CCRC_COMP_VER_STR_LOWER:
158 return true;
159
160 default:
161 if (comp_compatibility_resp_code >=
162 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
163 comp_compatibility_resp_code <=
164 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
165 return true;
166 }
167 return false;
168 }
169}
170
gokulsanker773cd1f2021-04-27 17:59:15 +0530171/** @brief Check whether SelfContainedActivationRequest is valid
172 *
173 * @return true if SelfContainedActivationRequest is valid, false if not
174 */
175static bool
176is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
177{
178 switch (self_contained_activation_req) {
179 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
180 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
181 return true;
182
183 default:
184 return false;
185 }
186}
187
Tom Joseph568e4702021-06-07 22:15:49 -0700188int decode_pldm_package_header_info(
189 const uint8_t *data, size_t length,
190 struct pldm_package_header_information *package_header_info,
191 struct variable_field *package_version_str)
192{
193 if (data == NULL || package_header_info == NULL ||
194 package_version_str == NULL) {
195 return PLDM_ERROR_INVALID_DATA;
196 }
197
198 if (length < sizeof(struct pldm_package_header_information)) {
199 return PLDM_ERROR_INVALID_LENGTH;
200 }
201
202 struct pldm_package_header_information *data_header =
203 (struct pldm_package_header_information *)(data);
204
205 if (!is_string_type_valid(data_header->package_version_string_type) ||
206 (data_header->package_version_string_length == 0)) {
207 return PLDM_ERROR_INVALID_DATA;
208 }
209
210 if (length < sizeof(struct pldm_package_header_information) +
211 data_header->package_version_string_length) {
212 return PLDM_ERROR_INVALID_LENGTH;
213 }
214
215 if ((data_header->component_bitmap_bit_length %
216 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
217 return PLDM_ERROR_INVALID_DATA;
218 }
219
220 memcpy(package_header_info->uuid, data_header->uuid,
221 sizeof(data_header->uuid));
222 package_header_info->package_header_format_version =
223 data_header->package_header_format_version;
224 package_header_info->package_header_size =
225 le16toh(data_header->package_header_size);
226 memcpy(package_header_info->timestamp104, data_header->timestamp104,
227 sizeof(data_header->timestamp104));
228 package_header_info->component_bitmap_bit_length =
229 le16toh(data_header->component_bitmap_bit_length);
230 package_header_info->package_version_string_type =
231 data_header->package_version_string_type;
232 package_header_info->package_version_string_length =
233 data_header->package_version_string_length;
234 package_version_str->ptr =
235 data + sizeof(struct pldm_package_header_information);
236 package_version_str->length =
237 package_header_info->package_version_string_length;
238
239 return PLDM_SUCCESS;
240}
241
Tom Joseph64af3452021-06-08 04:05:28 -0700242int decode_firmware_device_id_record(
243 const uint8_t *data, size_t length, uint16_t component_bitmap_bit_length,
244 struct pldm_firmware_device_id_record *fw_device_id_record,
245 struct variable_field *applicable_components,
246 struct variable_field *comp_image_set_version_str,
247 struct variable_field *record_descriptors,
248 struct variable_field *fw_device_pkg_data)
249{
250 if (data == NULL || fw_device_id_record == NULL ||
251 applicable_components == NULL ||
252 comp_image_set_version_str == NULL || record_descriptors == NULL ||
253 fw_device_pkg_data == NULL) {
254 return PLDM_ERROR_INVALID_DATA;
255 }
256
257 if (length < sizeof(struct pldm_firmware_device_id_record)) {
258 return PLDM_ERROR_INVALID_LENGTH;
259 }
260
261 if ((component_bitmap_bit_length %
262 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
263 return PLDM_ERROR_INVALID_DATA;
264 }
265
266 struct pldm_firmware_device_id_record *data_record =
267 (struct pldm_firmware_device_id_record *)(data);
268
269 if (!is_string_type_valid(
270 data_record->comp_image_set_version_string_type) ||
271 (data_record->comp_image_set_version_string_length == 0)) {
272 return PLDM_ERROR_INVALID_DATA;
273 }
274
275 fw_device_id_record->record_length =
276 le16toh(data_record->record_length);
277 fw_device_id_record->descriptor_count = data_record->descriptor_count;
278 fw_device_id_record->device_update_option_flags.value =
279 le32toh(data_record->device_update_option_flags.value);
280 fw_device_id_record->comp_image_set_version_string_type =
281 data_record->comp_image_set_version_string_type;
282 fw_device_id_record->comp_image_set_version_string_length =
283 data_record->comp_image_set_version_string_length;
284 fw_device_id_record->fw_device_pkg_data_length =
285 le16toh(data_record->fw_device_pkg_data_length);
286
287 if (length < fw_device_id_record->record_length) {
288 return PLDM_ERROR_INVALID_LENGTH;
289 }
290
291 uint16_t applicable_components_length =
292 component_bitmap_bit_length / PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
293 uint16_t calc_min_record_length =
294 sizeof(struct pldm_firmware_device_id_record) +
295 applicable_components_length +
296 data_record->comp_image_set_version_string_length +
297 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
298 fw_device_id_record->fw_device_pkg_data_length;
299
300 if (fw_device_id_record->record_length < calc_min_record_length) {
301 return PLDM_ERROR_INVALID_LENGTH;
302 }
303
304 applicable_components->ptr =
305 data + sizeof(struct pldm_firmware_device_id_record);
306 applicable_components->length = applicable_components_length;
307
308 comp_image_set_version_str->ptr =
309 applicable_components->ptr + applicable_components->length;
310 comp_image_set_version_str->length =
311 fw_device_id_record->comp_image_set_version_string_length;
312
313 record_descriptors->ptr = comp_image_set_version_str->ptr +
314 comp_image_set_version_str->length;
315 record_descriptors->length =
316 fw_device_id_record->record_length -
317 sizeof(struct pldm_firmware_device_id_record) -
318 applicable_components_length -
319 fw_device_id_record->comp_image_set_version_string_length -
320 fw_device_id_record->fw_device_pkg_data_length;
321
322 if (fw_device_id_record->fw_device_pkg_data_length) {
323 fw_device_pkg_data->ptr =
324 record_descriptors->ptr + record_descriptors->length;
325 fw_device_pkg_data->length =
326 fw_device_id_record->fw_device_pkg_data_length;
327 }
328
329 return PLDM_SUCCESS;
330}
331
Tom Joseph763b51e2021-06-05 04:50:47 -0700332int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
333 uint16_t *descriptor_type,
334 struct variable_field *descriptor_data)
335{
336 uint16_t descriptor_length = 0;
337
338 if (data == NULL || descriptor_type == NULL ||
339 descriptor_data == NULL) {
340 return PLDM_ERROR_INVALID_DATA;
341 }
342
343 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
344 return PLDM_ERROR_INVALID_LENGTH;
345 }
346
347 struct pldm_descriptor_tlv *entry =
348 (struct pldm_descriptor_tlv *)(data);
349
350 *descriptor_type = le16toh(entry->descriptor_type);
351 descriptor_length = le16toh(entry->descriptor_length);
352 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
353 if (descriptor_length !=
354 get_descriptor_type_length(*descriptor_type)) {
355 return PLDM_ERROR_INVALID_LENGTH;
356 }
357 }
358
359 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
360 descriptor_length)) {
361 return PLDM_ERROR_INVALID_LENGTH;
362 }
363
364 descriptor_data->ptr = entry->descriptor_data;
365 descriptor_data->length = descriptor_length;
366
367 return PLDM_SUCCESS;
368}
369
370int decode_vendor_defined_descriptor_value(
371 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
372 struct variable_field *descriptor_title_str,
373 struct variable_field *descriptor_data)
374{
375 if (data == NULL || descriptor_title_str_type == NULL ||
376 descriptor_title_str == NULL || descriptor_data == NULL) {
377 return PLDM_ERROR_INVALID_DATA;
378 }
379
380 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
381 return PLDM_ERROR_INVALID_LENGTH;
382 }
383
384 struct pldm_vendor_defined_descriptor_title_data *entry =
385 (struct pldm_vendor_defined_descriptor_title_data *)(data);
386 if (!is_string_type_valid(
387 entry->vendor_defined_descriptor_title_str_type) ||
388 (entry->vendor_defined_descriptor_title_str_len == 0)) {
389 return PLDM_ERROR_INVALID_DATA;
390 }
391
392 // Assuming atleast 1 byte of VendorDefinedDescriptorData
393 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
394 entry->vendor_defined_descriptor_title_str_len)) {
395 return PLDM_ERROR_INVALID_LENGTH;
396 }
397
398 *descriptor_title_str_type =
399 entry->vendor_defined_descriptor_title_str_type;
400 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
401 descriptor_title_str->length =
402 entry->vendor_defined_descriptor_title_str_len;
403
404 descriptor_data->ptr =
405 descriptor_title_str->ptr + descriptor_title_str->length;
406 descriptor_data->length =
407 length - sizeof(entry->vendor_defined_descriptor_title_str_type) -
408 sizeof(entry->vendor_defined_descriptor_title_str_len) -
409 descriptor_title_str->length;
410
411 return PLDM_SUCCESS;
412}
413
Tom Joseph58cc1722021-06-09 07:15:49 -0700414int decode_pldm_comp_image_info(
415 const uint8_t *data, size_t length,
416 struct pldm_component_image_information *pldm_comp_image_info,
417 struct variable_field *comp_version_str)
418{
419 if (data == NULL || pldm_comp_image_info == NULL ||
420 comp_version_str == NULL) {
421 return PLDM_ERROR_INVALID_DATA;
422 }
423
424 if (length < sizeof(struct pldm_component_image_information)) {
425 return PLDM_ERROR_INVALID_LENGTH;
426 }
427
428 struct pldm_component_image_information *data_header =
429 (struct pldm_component_image_information *)(data);
430
431 if (!is_string_type_valid(data_header->comp_version_string_type) ||
432 (data_header->comp_version_string_length == 0)) {
433 return PLDM_ERROR_INVALID_DATA;
434 }
435
436 if (length < sizeof(struct pldm_component_image_information) +
437 data_header->comp_version_string_length) {
438 return PLDM_ERROR_INVALID_LENGTH;
439 }
440
441 pldm_comp_image_info->comp_classification =
442 le16toh(data_header->comp_classification);
443 pldm_comp_image_info->comp_identifier =
444 le16toh(data_header->comp_identifier);
445 pldm_comp_image_info->comp_comparison_stamp =
446 le32toh(data_header->comp_comparison_stamp);
447 pldm_comp_image_info->comp_options.value =
448 le16toh(data_header->comp_options.value);
449 pldm_comp_image_info->requested_comp_activation_method.value =
450 le16toh(data_header->requested_comp_activation_method.value);
451 pldm_comp_image_info->comp_location_offset =
452 le32toh(data_header->comp_location_offset);
453 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
454 pldm_comp_image_info->comp_version_string_type =
455 data_header->comp_version_string_type;
456 pldm_comp_image_info->comp_version_string_length =
457 data_header->comp_version_string_length;
458
459 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
460 pldm_comp_image_info->comp_comparison_stamp !=
461 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
462 return PLDM_ERROR_INVALID_DATA;
463 }
464
465 if (pldm_comp_image_info->comp_location_offset == 0 ||
466 pldm_comp_image_info->comp_size == 0) {
467 return PLDM_ERROR_INVALID_DATA;
468 }
469
470 comp_version_str->ptr =
471 data + sizeof(struct pldm_component_image_information);
472 comp_version_str->length =
473 pldm_comp_image_info->comp_version_string_length;
474
475 return PLDM_SUCCESS;
476}
477
gokulsanker138ceba2021-04-05 13:25:25 +0530478int encode_query_device_identifiers_req(uint8_t instance_id,
479 size_t payload_length,
480 struct pldm_msg *msg)
481{
482 if (msg == NULL) {
483 return PLDM_ERROR_INVALID_DATA;
484 }
485
486 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
487 return PLDM_ERROR_INVALID_LENGTH;
488 }
489
490 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
491 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
492}
gokulsankereca3e192021-04-05 14:57:41 +0530493
494int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
495 size_t payload_length,
496 uint8_t *completion_code,
497 uint32_t *device_identifiers_len,
498 uint8_t *descriptor_count,
499 uint8_t **descriptor_data)
500{
501 if (msg == NULL || completion_code == NULL ||
502 device_identifiers_len == NULL || descriptor_count == NULL ||
503 descriptor_data == NULL) {
504 return PLDM_ERROR_INVALID_DATA;
505 }
506
507 *completion_code = msg->payload[0];
508 if (PLDM_SUCCESS != *completion_code) {
509 return PLDM_SUCCESS;
510 }
511
512 if (payload_length <
513 sizeof(struct pldm_query_device_identifiers_resp)) {
514 return PLDM_ERROR_INVALID_LENGTH;
515 }
516
517 struct pldm_query_device_identifiers_resp *response =
518 (struct pldm_query_device_identifiers_resp *)msg->payload;
519 *device_identifiers_len = le32toh(response->device_identifiers_len);
520
521 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
522 return PLDM_ERROR_INVALID_LENGTH;
523 }
524
525 if (payload_length !=
526 sizeof(struct pldm_query_device_identifiers_resp) +
527 *device_identifiers_len) {
528 return PLDM_ERROR_INVALID_LENGTH;
529 }
530 *descriptor_count = response->descriptor_count;
531
532 if (*descriptor_count == 0) {
533 return PLDM_ERROR_INVALID_DATA;
534 }
gokulsankereca3e192021-04-05 14:57:41 +0530535 *descriptor_data =
536 (uint8_t *)(msg->payload +
537 sizeof(struct pldm_query_device_identifiers_resp));
538 return PLDM_SUCCESS;
539}
gokulsanker981fbfb2021-04-05 15:17:25 +0530540
541int encode_get_firmware_parameters_req(uint8_t instance_id,
542 size_t payload_length,
543 struct pldm_msg *msg)
544{
545 if (msg == NULL) {
546 return PLDM_ERROR_INVALID_DATA;
547 }
548
549 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
550 return PLDM_ERROR_INVALID_LENGTH;
551 }
552
553 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
554 PLDM_GET_FIRMWARE_PARAMETERS, msg);
555}
gokulsanker22fbb342021-04-05 15:55:06 +0530556
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700557int decode_get_firmware_parameters_resp(
gokulsanker22fbb342021-04-05 15:55:06 +0530558 const struct pldm_msg *msg, size_t payload_length,
559 struct pldm_get_firmware_parameters_resp *resp_data,
560 struct variable_field *active_comp_image_set_ver_str,
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700561 struct variable_field *pending_comp_image_set_ver_str,
562 struct variable_field *comp_parameter_table)
gokulsanker22fbb342021-04-05 15:55:06 +0530563{
564 if (msg == NULL || resp_data == NULL ||
565 active_comp_image_set_ver_str == NULL ||
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700566 pending_comp_image_set_ver_str == NULL ||
Tom Joseph83a644c2021-06-22 22:25:25 -0700567 comp_parameter_table == NULL || !payload_length) {
gokulsanker22fbb342021-04-05 15:55:06 +0530568 return PLDM_ERROR_INVALID_DATA;
569 }
570
Tom Joseph83a644c2021-06-22 22:25:25 -0700571 resp_data->completion_code = msg->payload[0];
572 if (PLDM_SUCCESS != resp_data->completion_code) {
573 return PLDM_SUCCESS;
574 }
575
gokulsanker22fbb342021-04-05 15:55:06 +0530576 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
577 return PLDM_ERROR_INVALID_LENGTH;
578 }
579
580 struct pldm_get_firmware_parameters_resp *response =
581 (struct pldm_get_firmware_parameters_resp *)msg->payload;
582
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700583 if (!is_string_type_valid(
584 response->active_comp_image_set_ver_str_type) ||
585 (response->active_comp_image_set_ver_str_len == 0)) {
gokulsanker22fbb342021-04-05 15:55:06 +0530586 return PLDM_ERROR_INVALID_DATA;
587 }
588
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700589 if (response->pending_comp_image_set_ver_str_len == 0) {
590 if (response->pending_comp_image_set_ver_str_type !=
591 PLDM_STR_TYPE_UNKNOWN) {
592 return PLDM_ERROR_INVALID_DATA;
593 }
594 } else {
595 if (!is_string_type_valid(
596 response->pending_comp_image_set_ver_str_type)) {
597 return PLDM_ERROR_INVALID_DATA;
598 }
599 }
gokulsanker22fbb342021-04-05 15:55:06 +0530600
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700601 size_t partial_response_length =
602 sizeof(struct pldm_get_firmware_parameters_resp) +
603 response->active_comp_image_set_ver_str_len +
604 response->pending_comp_image_set_ver_str_len;
605
606 if (payload_length < partial_response_length) {
gokulsanker22fbb342021-04-05 15:55:06 +0530607 return PLDM_ERROR_INVALID_LENGTH;
608 }
609
610 resp_data->capabilities_during_update.value =
611 le32toh(response->capabilities_during_update.value);
gokulsanker22fbb342021-04-05 15:55:06 +0530612 resp_data->comp_count = le16toh(response->comp_count);
gokulsanker22fbb342021-04-05 15:55:06 +0530613 resp_data->active_comp_image_set_ver_str_type =
614 response->active_comp_image_set_ver_str_type;
615 resp_data->active_comp_image_set_ver_str_len =
616 response->active_comp_image_set_ver_str_len;
617 resp_data->pending_comp_image_set_ver_str_type =
618 response->pending_comp_image_set_ver_str_type;
619 resp_data->pending_comp_image_set_ver_str_len =
620 response->pending_comp_image_set_ver_str_len;
621
622 active_comp_image_set_ver_str->ptr =
623 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
624 active_comp_image_set_ver_str->length =
625 resp_data->active_comp_image_set_ver_str_len;
626
627 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
628 pending_comp_image_set_ver_str->ptr =
629 msg->payload +
630 sizeof(struct pldm_get_firmware_parameters_resp) +
631 resp_data->active_comp_image_set_ver_str_len;
632 pending_comp_image_set_ver_str->length =
633 resp_data->pending_comp_image_set_ver_str_len;
634 } else {
635 pending_comp_image_set_ver_str->ptr = NULL;
636 pending_comp_image_set_ver_str->length = 0;
637 }
638
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700639 if (payload_length > partial_response_length && resp_data->comp_count) {
640 comp_parameter_table->ptr =
641 msg->payload +
642 sizeof(struct pldm_get_firmware_parameters_resp) +
643 resp_data->active_comp_image_set_ver_str_len +
644 resp_data->pending_comp_image_set_ver_str_len;
645 comp_parameter_table->length =
646 payload_length - partial_response_length;
647 } else {
648 comp_parameter_table->ptr = NULL;
649 comp_parameter_table->length = 0;
650 }
651
gokulsanker22fbb342021-04-05 15:55:06 +0530652 return PLDM_SUCCESS;
653}
gokulsankere1fb7a82021-04-05 16:09:29 +0530654
655int decode_get_firmware_parameters_resp_comp_entry(
656 const uint8_t *data, size_t length,
657 struct pldm_component_parameter_entry *component_data,
658 struct variable_field *active_comp_ver_str,
659 struct variable_field *pending_comp_ver_str)
660{
661 if (data == NULL || component_data == NULL ||
662 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
663 return PLDM_ERROR_INVALID_DATA;
664 }
665
666 if (length < sizeof(struct pldm_component_parameter_entry)) {
667 return PLDM_ERROR_INVALID_LENGTH;
668 }
669
670 struct pldm_component_parameter_entry *entry =
671 (struct pldm_component_parameter_entry *)(data);
672 if (entry->active_comp_ver_str_len == 0) {
673 return PLDM_ERROR_INVALID_LENGTH;
674 }
675
676 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
677 entry->active_comp_ver_str_len +
678 entry->pending_comp_ver_str_len;
679
Tom Josephc33c2f02021-06-22 21:58:56 -0700680 if (length < entry_length) {
gokulsankere1fb7a82021-04-05 16:09:29 +0530681 return PLDM_ERROR_INVALID_LENGTH;
682 }
683
684 component_data->comp_classification =
685 le16toh(entry->comp_classification);
686 component_data->comp_identifier = le16toh(entry->comp_identifier);
687 component_data->comp_classification_index =
688 entry->comp_classification_index;
689 component_data->active_comp_comparison_stamp =
690 le32toh(entry->active_comp_comparison_stamp);
691 component_data->active_comp_ver_str_type =
692 entry->active_comp_ver_str_type;
693 component_data->active_comp_ver_str_len =
694 entry->active_comp_ver_str_len;
695 memcpy(component_data->active_comp_release_date,
696 entry->active_comp_release_date,
697 sizeof(entry->active_comp_release_date));
698 component_data->pending_comp_comparison_stamp =
699 le32toh(entry->pending_comp_comparison_stamp);
700 component_data->pending_comp_ver_str_type =
701 entry->pending_comp_ver_str_type;
702 component_data->pending_comp_ver_str_len =
703 entry->pending_comp_ver_str_len;
704 memcpy(component_data->pending_comp_release_date,
705 entry->pending_comp_release_date,
706 sizeof(entry->pending_comp_release_date));
707 component_data->comp_activation_methods.value =
708 le16toh(entry->comp_activation_methods.value);
709 component_data->capabilities_during_update.value =
710 le32toh(entry->capabilities_during_update.value);
711
712 active_comp_ver_str->ptr =
713 data + sizeof(struct pldm_component_parameter_entry);
714 active_comp_ver_str->length = entry->active_comp_ver_str_len;
715
716 if (entry->pending_comp_ver_str_len != 0) {
717
718 pending_comp_ver_str->ptr =
719 data + sizeof(struct pldm_component_parameter_entry) +
720 entry->active_comp_ver_str_len;
721 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
722 } else {
723 pending_comp_ver_str->ptr = NULL;
724 pending_comp_ver_str->length = 0;
725 }
726 return PLDM_SUCCESS;
727}
gokulsankerd434edc2021-04-05 16:36:04 +0530728
729int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
730 uint16_t num_of_comp,
731 uint8_t max_outstanding_transfer_req,
732 uint16_t pkg_data_len,
733 uint8_t comp_image_set_ver_str_type,
734 uint8_t comp_image_set_ver_str_len,
735 const struct variable_field *comp_img_set_ver_str,
736 struct pldm_msg *msg, size_t payload_length)
737{
738 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
739 msg == NULL) {
740 return PLDM_ERROR_INVALID_DATA;
741 }
742
743 if (payload_length != sizeof(struct pldm_request_update_req) +
744 comp_img_set_ver_str->length) {
745 return PLDM_ERROR_INVALID_LENGTH;
746 }
747
748 if ((comp_image_set_ver_str_len == 0) ||
749 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
750 return PLDM_ERROR_INVALID_DATA;
751 }
752
753 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
754 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
755 return PLDM_ERROR_INVALID_DATA;
756 }
757
758 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
759 return PLDM_ERROR_INVALID_DATA;
760 }
761
762 struct pldm_header_info header = {0};
763 header.instance = instance_id;
764 header.msg_type = PLDM_REQUEST;
765 header.pldm_type = PLDM_FWUP;
766 header.command = PLDM_REQUEST_UPDATE;
767 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
768 if (rc) {
769 return rc;
770 }
771
772 struct pldm_request_update_req *request =
773 (struct pldm_request_update_req *)msg->payload;
774
775 request->max_transfer_size = htole32(max_transfer_size);
776 request->num_of_comp = htole16(num_of_comp);
777 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
778 request->pkg_data_len = htole16(pkg_data_len);
779 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
780 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
781
782 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
783 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
784
785 return PLDM_SUCCESS;
gokulsanker611238c2021-04-05 16:50:44 +0530786}
787
788int decode_request_update_resp(const struct pldm_msg *msg,
789 size_t payload_length, uint8_t *completion_code,
790 uint16_t *fd_meta_data_len,
791 uint8_t *fd_will_send_pkg_data)
792{
793 if (msg == NULL || completion_code == NULL ||
794 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
795 !payload_length) {
796 return PLDM_ERROR_INVALID_DATA;
797 }
798
799 *completion_code = msg->payload[0];
800 if (*completion_code != PLDM_SUCCESS) {
801 return PLDM_SUCCESS;
802 }
803
804 if (payload_length != sizeof(struct pldm_request_update_resp)) {
805 return PLDM_ERROR_INVALID_LENGTH;
806 }
807
808 struct pldm_request_update_resp *response =
809 (struct pldm_request_update_resp *)msg->payload;
810
811 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
812 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
813
814 return PLDM_SUCCESS;
gokulsanker1b909d82021-04-05 17:26:02 +0530815}
816
817int encode_pass_component_table_req(
818 uint8_t instance_id, uint8_t transfer_flag, uint16_t comp_classification,
819 uint16_t comp_identifier, uint8_t comp_classification_index,
820 uint32_t comp_comparison_stamp, uint8_t comp_ver_str_type,
821 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
822 struct pldm_msg *msg, size_t payload_length)
823{
824 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
825 return PLDM_ERROR_INVALID_DATA;
826 }
827
828 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
829 comp_ver_str->length) {
830 return PLDM_ERROR_INVALID_LENGTH;
831 }
832
833 if ((comp_ver_str_len == 0) ||
834 (comp_ver_str_len != comp_ver_str->length)) {
835 return PLDM_ERROR_INVALID_DATA;
836 }
837
838 if (!is_transfer_flag_valid(transfer_flag)) {
839 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
840 }
841
842 if (!is_string_type_valid(comp_ver_str_type)) {
843 return PLDM_ERROR_INVALID_DATA;
844 }
845
846 struct pldm_header_info header = {0};
847 header.instance = instance_id;
848 header.msg_type = PLDM_REQUEST;
849 header.pldm_type = PLDM_FWUP;
850 header.command = PLDM_PASS_COMPONENT_TABLE;
851 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
852 if (rc) {
853 return rc;
854 }
855
856 struct pldm_pass_component_table_req *request =
857 (struct pldm_pass_component_table_req *)msg->payload;
858
859 request->transfer_flag = transfer_flag;
860 request->comp_classification = htole16(comp_classification);
861 request->comp_identifier = htole16(comp_identifier);
862 request->comp_classification_index = comp_classification_index;
863 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
864 request->comp_ver_str_type = comp_ver_str_type;
865 request->comp_ver_str_len = comp_ver_str_len;
866
867 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
868 comp_ver_str->ptr, comp_ver_str->length);
869
870 return PLDM_SUCCESS;
871}
gokulsanker566784b2021-04-05 17:47:04 +0530872
873int decode_pass_component_table_resp(const struct pldm_msg *msg,
874 const size_t payload_length,
875 uint8_t *completion_code,
876 uint8_t *comp_resp,
877 uint8_t *comp_resp_code)
878{
879 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
880 comp_resp_code == NULL || !payload_length) {
881 return PLDM_ERROR_INVALID_DATA;
882 }
883
884 *completion_code = msg->payload[0];
885 if (*completion_code != PLDM_SUCCESS) {
886 return PLDM_SUCCESS;
887 }
888
889 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
890 return PLDM_ERROR_INVALID_LENGTH;
891 }
892
893 struct pldm_pass_component_table_resp *response =
894 (struct pldm_pass_component_table_resp *)msg->payload;
895
896 if (!is_comp_resp_valid(response->comp_resp)) {
897 return PLDM_ERROR_INVALID_DATA;
898 }
899
900 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
901 return PLDM_ERROR_INVALID_DATA;
902 }
903
904 *comp_resp = response->comp_resp;
905 *comp_resp_code = response->comp_resp_code;
906
907 return PLDM_SUCCESS;
908}
gokulsankeraa3a5cd2021-04-22 11:06:42 +0530909
910int encode_update_component_req(
911 uint8_t instance_id, uint16_t comp_classification, uint16_t comp_identifier,
912 uint8_t comp_classification_index, uint32_t comp_comparison_stamp,
913 uint32_t comp_image_size, bitfield32_t update_option_flags,
914 uint8_t comp_ver_str_type, uint8_t comp_ver_str_len,
915 const struct variable_field *comp_ver_str, struct pldm_msg *msg,
916 size_t payload_length)
917{
918 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
919 return PLDM_ERROR_INVALID_DATA;
920 }
921
922 if (payload_length !=
923 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
924 return PLDM_ERROR_INVALID_LENGTH;
925 }
926
927 if (!comp_image_size) {
928 return PLDM_ERROR_INVALID_DATA;
929 }
930
931 if ((comp_ver_str_len == 0) ||
932 (comp_ver_str_len != comp_ver_str->length)) {
933 return PLDM_ERROR_INVALID_DATA;
934 }
935
936 if (!is_string_type_valid(comp_ver_str_type)) {
937 return PLDM_ERROR_INVALID_DATA;
938 }
939
940 struct pldm_header_info header = {0};
941 header.instance = instance_id;
942 header.msg_type = PLDM_REQUEST;
943 header.pldm_type = PLDM_FWUP;
944 header.command = PLDM_UPDATE_COMPONENT;
945 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
946 if (rc) {
947 return rc;
948 }
949
950 struct pldm_update_component_req *request =
951 (struct pldm_update_component_req *)msg->payload;
952
953 request->comp_classification = htole16(comp_classification);
954 request->comp_identifier = htole16(comp_identifier);
955 request->comp_classification_index = comp_classification_index;
956 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
957 request->comp_image_size = htole32(comp_image_size);
958 request->update_option_flags.value = htole32(update_option_flags.value);
959 request->comp_ver_str_type = comp_ver_str_type;
960 request->comp_ver_str_len = comp_ver_str_len;
961
962 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
963 comp_ver_str->ptr, comp_ver_str->length);
964
965 return PLDM_SUCCESS;
gokulsanker4b533f22021-04-22 12:53:00 +0530966}
967
968int decode_update_component_resp(const struct pldm_msg *msg,
969 size_t payload_length,
970 uint8_t *completion_code,
971 uint8_t *comp_compatability_resp,
972 uint8_t *comp_compatability_resp_code,
973 bitfield32_t *update_option_flags_enabled,
974 uint16_t *time_before_req_fw_data)
975{
976 if (msg == NULL || completion_code == NULL ||
977 comp_compatability_resp == NULL ||
978 comp_compatability_resp_code == NULL ||
979 update_option_flags_enabled == NULL ||
980 time_before_req_fw_data == NULL || !payload_length) {
981 return PLDM_ERROR_INVALID_DATA;
982 }
983
984 *completion_code = msg->payload[0];
985 if (*completion_code != PLDM_SUCCESS) {
986 return PLDM_SUCCESS;
987 }
988
989 if (payload_length != sizeof(struct pldm_update_component_resp)) {
990 return PLDM_ERROR_INVALID_LENGTH;
991 }
992
993 struct pldm_update_component_resp *response =
994 (struct pldm_update_component_resp *)msg->payload;
995
996 if (!is_comp_compatibility_resp_valid(
997 response->comp_compatability_resp)) {
998 return PLDM_ERROR_INVALID_DATA;
999 }
1000
1001 if (!is_comp_compatibility_resp_code_valid(
1002 response->comp_compatability_resp_code)) {
1003 return PLDM_ERROR_INVALID_DATA;
1004 }
1005
1006 *comp_compatability_resp = response->comp_compatability_resp;
1007 *comp_compatability_resp_code = response->comp_compatability_resp_code;
1008 update_option_flags_enabled->value =
1009 le32toh(response->update_option_flags_enabled.value);
1010 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1011
1012 return PLDM_SUCCESS;
gokulsankera4e6b292021-06-02 16:35:39 +05301013}
1014
1015int decode_request_firmware_data_req(const struct pldm_msg *msg,
1016 size_t payload_length, uint32_t *offset,
1017 uint32_t *length)
1018{
1019 if (msg == NULL || offset == NULL || length == NULL) {
1020 return PLDM_ERROR_INVALID_DATA;
1021 }
1022 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1023 return PLDM_ERROR_INVALID_LENGTH;
1024 }
1025 struct pldm_request_firmware_data_req *request =
1026 (struct pldm_request_firmware_data_req *)msg->payload;
1027 *offset = le32toh(request->offset);
1028 *length = le32toh(request->length);
1029
1030 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1031 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1032 }
1033
1034 return PLDM_SUCCESS;
gokulsanker9c440d02021-06-03 09:54:02 +05301035}
1036
1037int encode_request_firmware_data_resp(uint8_t instance_id,
1038 uint8_t completion_code,
1039 struct pldm_msg *msg,
1040 size_t payload_length)
1041{
1042 if (msg == NULL || !payload_length) {
1043 return PLDM_ERROR_INVALID_DATA;
1044 }
1045
1046 struct pldm_header_info header = {0};
1047 header.instance = instance_id;
1048 header.msg_type = PLDM_RESPONSE;
1049 header.pldm_type = PLDM_FWUP;
1050 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1051 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1052 if (rc) {
1053 return rc;
1054 }
1055
1056 msg->payload[0] = completion_code;
1057
1058 return PLDM_SUCCESS;
gokulsankere3807022021-06-26 19:12:01 +05301059}
1060
1061int decode_transfer_complete_req(const struct pldm_msg *msg,
1062 size_t payload_length,
1063 uint8_t *transfer_result)
1064{
1065 if (msg == NULL || transfer_result == NULL) {
1066 return PLDM_ERROR_INVALID_DATA;
1067 }
1068
1069 if (payload_length != sizeof(*transfer_result)) {
1070 return PLDM_ERROR_INVALID_LENGTH;
1071 }
1072
1073 *transfer_result = msg->payload[0];
1074 return PLDM_SUCCESS;
1075}
gokulsanker50107cf2021-06-27 09:44:12 +05301076
1077int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1078 struct pldm_msg *msg, size_t payload_length)
1079{
1080 if (msg == NULL) {
1081 return PLDM_ERROR_INVALID_DATA;
1082 }
1083
1084 if (payload_length != sizeof(completion_code)) {
1085 return PLDM_ERROR_INVALID_LENGTH;
1086 }
1087
1088 struct pldm_header_info header = {0};
1089 header.instance = instance_id;
1090 header.msg_type = PLDM_RESPONSE;
1091 header.pldm_type = PLDM_FWUP;
1092 header.command = PLDM_TRANSFER_COMPLETE;
1093 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1094 if (rc) {
1095 return rc;
1096 }
1097
1098 msg->payload[0] = completion_code;
1099
1100 return PLDM_SUCCESS;
gokulsankerb79b91a2021-06-27 11:26:36 +05301101}
1102
1103int decode_verify_complete_req(const struct pldm_msg *msg,
1104 size_t payload_length, uint8_t *verify_result)
1105{
1106 if (msg == NULL || verify_result == NULL) {
1107 return PLDM_ERROR_INVALID_DATA;
1108 }
1109
1110 if (payload_length != sizeof(*verify_result)) {
1111 return PLDM_ERROR_INVALID_LENGTH;
1112 }
1113
1114 *verify_result = msg->payload[0];
1115 return PLDM_SUCCESS;
gokulsanker9a693582021-06-27 11:35:09 +05301116}
1117
1118int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1119 struct pldm_msg *msg, size_t payload_length)
1120{
1121 if (msg == NULL) {
1122 return PLDM_ERROR_INVALID_DATA;
1123 }
1124
1125 if (payload_length != sizeof(completion_code)) {
1126 return PLDM_ERROR_INVALID_LENGTH;
1127 }
1128
1129 struct pldm_header_info header = {0};
1130 header.instance = instance_id;
1131 header.msg_type = PLDM_RESPONSE;
1132 header.pldm_type = PLDM_FWUP;
1133 header.command = PLDM_VERIFY_COMPLETE;
1134 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1135 if (rc) {
1136 return rc;
1137 }
1138
1139 msg->payload[0] = completion_code;
1140
1141 return PLDM_SUCCESS;
gokulsanker4687f242021-06-27 11:50:26 +05301142}
1143
1144int decode_apply_complete_req(
1145 const struct pldm_msg *msg, size_t payload_length, uint8_t *apply_result,
1146 bitfield16_t *comp_activation_methods_modification)
1147{
1148 if (msg == NULL || apply_result == NULL ||
1149 comp_activation_methods_modification == NULL) {
1150 return PLDM_ERROR_INVALID_DATA;
1151 }
1152
1153 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1154 return PLDM_ERROR_INVALID_LENGTH;
1155 }
1156
1157 struct pldm_apply_complete_req *request =
1158 (struct pldm_apply_complete_req *)msg->payload;
1159
1160 *apply_result = request->apply_result;
1161 comp_activation_methods_modification->value =
1162 le16toh(request->comp_activation_methods_modification.value);
1163
1164 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1165 comp_activation_methods_modification->value) {
1166 return PLDM_ERROR_INVALID_DATA;
1167 }
1168
1169 return PLDM_SUCCESS;
1170}
gokulsankerd6f79b82021-06-27 12:00:25 +05301171
1172int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1173 struct pldm_msg *msg, size_t payload_length)
1174{
1175 if (msg == NULL) {
1176 return PLDM_ERROR_INVALID_DATA;
1177 }
1178
1179 if (payload_length != sizeof(completion_code)) {
1180 return PLDM_ERROR_INVALID_LENGTH;
1181 }
1182
1183 struct pldm_header_info header = {0};
1184 header.instance = instance_id;
1185 header.msg_type = PLDM_RESPONSE;
1186 header.pldm_type = PLDM_FWUP;
1187 header.command = PLDM_APPLY_COMPLETE;
1188 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1189 if (rc) {
1190 return rc;
1191 }
1192
1193 msg->payload[0] = completion_code;
1194
1195 return PLDM_SUCCESS;
1196}
gokulsanker773cd1f2021-04-27 17:59:15 +05301197
1198int encode_activate_firmware_req(uint8_t instance_id,
1199 bool8_t self_contained_activation_req,
1200 struct pldm_msg *msg, size_t payload_length)
1201{
1202 if (msg == NULL) {
1203 return PLDM_ERROR_INVALID_DATA;
1204 }
1205
1206 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1207 return PLDM_ERROR_INVALID_LENGTH;
1208 }
1209
1210 if (!is_self_contained_activation_req_valid(
1211 self_contained_activation_req)) {
1212 return PLDM_ERROR_INVALID_DATA;
1213 }
1214
1215 struct pldm_header_info header = {0};
1216 header.instance = instance_id;
1217 header.msg_type = PLDM_REQUEST;
1218 header.pldm_type = PLDM_FWUP;
1219 header.command = PLDM_ACTIVATE_FIRMWARE;
1220 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1221 if (rc) {
1222 return rc;
1223 }
1224
1225 struct pldm_activate_firmware_req *request =
1226 (struct pldm_activate_firmware_req *)msg->payload;
1227
1228 request->self_contained_activation_req = self_contained_activation_req;
1229
1230 return PLDM_SUCCESS;
1231}