blob: 8699bb5e49364c4e607c5864241a6547e3086c91 [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
Tom Joseph568e4702021-06-07 22:15:49 -0700122int decode_pldm_package_header_info(
123 const uint8_t *data, size_t length,
124 struct pldm_package_header_information *package_header_info,
125 struct variable_field *package_version_str)
126{
127 if (data == NULL || package_header_info == NULL ||
128 package_version_str == NULL) {
129 return PLDM_ERROR_INVALID_DATA;
130 }
131
132 if (length < sizeof(struct pldm_package_header_information)) {
133 return PLDM_ERROR_INVALID_LENGTH;
134 }
135
136 struct pldm_package_header_information *data_header =
137 (struct pldm_package_header_information *)(data);
138
139 if (!is_string_type_valid(data_header->package_version_string_type) ||
140 (data_header->package_version_string_length == 0)) {
141 return PLDM_ERROR_INVALID_DATA;
142 }
143
144 if (length < sizeof(struct pldm_package_header_information) +
145 data_header->package_version_string_length) {
146 return PLDM_ERROR_INVALID_LENGTH;
147 }
148
149 if ((data_header->component_bitmap_bit_length %
150 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
151 return PLDM_ERROR_INVALID_DATA;
152 }
153
154 memcpy(package_header_info->uuid, data_header->uuid,
155 sizeof(data_header->uuid));
156 package_header_info->package_header_format_version =
157 data_header->package_header_format_version;
158 package_header_info->package_header_size =
159 le16toh(data_header->package_header_size);
160 memcpy(package_header_info->timestamp104, data_header->timestamp104,
161 sizeof(data_header->timestamp104));
162 package_header_info->component_bitmap_bit_length =
163 le16toh(data_header->component_bitmap_bit_length);
164 package_header_info->package_version_string_type =
165 data_header->package_version_string_type;
166 package_header_info->package_version_string_length =
167 data_header->package_version_string_length;
168 package_version_str->ptr =
169 data + sizeof(struct pldm_package_header_information);
170 package_version_str->length =
171 package_header_info->package_version_string_length;
172
173 return PLDM_SUCCESS;
174}
175
Tom Joseph64af3452021-06-08 04:05:28 -0700176int decode_firmware_device_id_record(
177 const uint8_t *data, size_t length, uint16_t component_bitmap_bit_length,
178 struct pldm_firmware_device_id_record *fw_device_id_record,
179 struct variable_field *applicable_components,
180 struct variable_field *comp_image_set_version_str,
181 struct variable_field *record_descriptors,
182 struct variable_field *fw_device_pkg_data)
183{
184 if (data == NULL || fw_device_id_record == NULL ||
185 applicable_components == NULL ||
186 comp_image_set_version_str == NULL || record_descriptors == NULL ||
187 fw_device_pkg_data == NULL) {
188 return PLDM_ERROR_INVALID_DATA;
189 }
190
191 if (length < sizeof(struct pldm_firmware_device_id_record)) {
192 return PLDM_ERROR_INVALID_LENGTH;
193 }
194
195 if ((component_bitmap_bit_length %
196 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
197 return PLDM_ERROR_INVALID_DATA;
198 }
199
200 struct pldm_firmware_device_id_record *data_record =
201 (struct pldm_firmware_device_id_record *)(data);
202
203 if (!is_string_type_valid(
204 data_record->comp_image_set_version_string_type) ||
205 (data_record->comp_image_set_version_string_length == 0)) {
206 return PLDM_ERROR_INVALID_DATA;
207 }
208
209 fw_device_id_record->record_length =
210 le16toh(data_record->record_length);
211 fw_device_id_record->descriptor_count = data_record->descriptor_count;
212 fw_device_id_record->device_update_option_flags.value =
213 le32toh(data_record->device_update_option_flags.value);
214 fw_device_id_record->comp_image_set_version_string_type =
215 data_record->comp_image_set_version_string_type;
216 fw_device_id_record->comp_image_set_version_string_length =
217 data_record->comp_image_set_version_string_length;
218 fw_device_id_record->fw_device_pkg_data_length =
219 le16toh(data_record->fw_device_pkg_data_length);
220
221 if (length < fw_device_id_record->record_length) {
222 return PLDM_ERROR_INVALID_LENGTH;
223 }
224
225 uint16_t applicable_components_length =
226 component_bitmap_bit_length / PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
227 uint16_t calc_min_record_length =
228 sizeof(struct pldm_firmware_device_id_record) +
229 applicable_components_length +
230 data_record->comp_image_set_version_string_length +
231 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
232 fw_device_id_record->fw_device_pkg_data_length;
233
234 if (fw_device_id_record->record_length < calc_min_record_length) {
235 return PLDM_ERROR_INVALID_LENGTH;
236 }
237
238 applicable_components->ptr =
239 data + sizeof(struct pldm_firmware_device_id_record);
240 applicable_components->length = applicable_components_length;
241
242 comp_image_set_version_str->ptr =
243 applicable_components->ptr + applicable_components->length;
244 comp_image_set_version_str->length =
245 fw_device_id_record->comp_image_set_version_string_length;
246
247 record_descriptors->ptr = comp_image_set_version_str->ptr +
248 comp_image_set_version_str->length;
249 record_descriptors->length =
250 fw_device_id_record->record_length -
251 sizeof(struct pldm_firmware_device_id_record) -
252 applicable_components_length -
253 fw_device_id_record->comp_image_set_version_string_length -
254 fw_device_id_record->fw_device_pkg_data_length;
255
256 if (fw_device_id_record->fw_device_pkg_data_length) {
257 fw_device_pkg_data->ptr =
258 record_descriptors->ptr + record_descriptors->length;
259 fw_device_pkg_data->length =
260 fw_device_id_record->fw_device_pkg_data_length;
261 }
262
263 return PLDM_SUCCESS;
264}
265
Tom Joseph763b51e2021-06-05 04:50:47 -0700266int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
267 uint16_t *descriptor_type,
268 struct variable_field *descriptor_data)
269{
270 uint16_t descriptor_length = 0;
271
272 if (data == NULL || descriptor_type == NULL ||
273 descriptor_data == NULL) {
274 return PLDM_ERROR_INVALID_DATA;
275 }
276
277 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
278 return PLDM_ERROR_INVALID_LENGTH;
279 }
280
281 struct pldm_descriptor_tlv *entry =
282 (struct pldm_descriptor_tlv *)(data);
283
284 *descriptor_type = le16toh(entry->descriptor_type);
285 descriptor_length = le16toh(entry->descriptor_length);
286 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
287 if (descriptor_length !=
288 get_descriptor_type_length(*descriptor_type)) {
289 return PLDM_ERROR_INVALID_LENGTH;
290 }
291 }
292
293 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
294 descriptor_length)) {
295 return PLDM_ERROR_INVALID_LENGTH;
296 }
297
298 descriptor_data->ptr = entry->descriptor_data;
299 descriptor_data->length = descriptor_length;
300
301 return PLDM_SUCCESS;
302}
303
304int decode_vendor_defined_descriptor_value(
305 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
306 struct variable_field *descriptor_title_str,
307 struct variable_field *descriptor_data)
308{
309 if (data == NULL || descriptor_title_str_type == NULL ||
310 descriptor_title_str == NULL || descriptor_data == NULL) {
311 return PLDM_ERROR_INVALID_DATA;
312 }
313
314 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
315 return PLDM_ERROR_INVALID_LENGTH;
316 }
317
318 struct pldm_vendor_defined_descriptor_title_data *entry =
319 (struct pldm_vendor_defined_descriptor_title_data *)(data);
320 if (!is_string_type_valid(
321 entry->vendor_defined_descriptor_title_str_type) ||
322 (entry->vendor_defined_descriptor_title_str_len == 0)) {
323 return PLDM_ERROR_INVALID_DATA;
324 }
325
326 // Assuming atleast 1 byte of VendorDefinedDescriptorData
327 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
328 entry->vendor_defined_descriptor_title_str_len)) {
329 return PLDM_ERROR_INVALID_LENGTH;
330 }
331
332 *descriptor_title_str_type =
333 entry->vendor_defined_descriptor_title_str_type;
334 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
335 descriptor_title_str->length =
336 entry->vendor_defined_descriptor_title_str_len;
337
338 descriptor_data->ptr =
339 descriptor_title_str->ptr + descriptor_title_str->length;
340 descriptor_data->length =
341 length - sizeof(entry->vendor_defined_descriptor_title_str_type) -
342 sizeof(entry->vendor_defined_descriptor_title_str_len) -
343 descriptor_title_str->length;
344
345 return PLDM_SUCCESS;
346}
347
Tom Joseph58cc1722021-06-09 07:15:49 -0700348int decode_pldm_comp_image_info(
349 const uint8_t *data, size_t length,
350 struct pldm_component_image_information *pldm_comp_image_info,
351 struct variable_field *comp_version_str)
352{
353 if (data == NULL || pldm_comp_image_info == NULL ||
354 comp_version_str == NULL) {
355 return PLDM_ERROR_INVALID_DATA;
356 }
357
358 if (length < sizeof(struct pldm_component_image_information)) {
359 return PLDM_ERROR_INVALID_LENGTH;
360 }
361
362 struct pldm_component_image_information *data_header =
363 (struct pldm_component_image_information *)(data);
364
365 if (!is_string_type_valid(data_header->comp_version_string_type) ||
366 (data_header->comp_version_string_length == 0)) {
367 return PLDM_ERROR_INVALID_DATA;
368 }
369
370 if (length < sizeof(struct pldm_component_image_information) +
371 data_header->comp_version_string_length) {
372 return PLDM_ERROR_INVALID_LENGTH;
373 }
374
375 pldm_comp_image_info->comp_classification =
376 le16toh(data_header->comp_classification);
377 pldm_comp_image_info->comp_identifier =
378 le16toh(data_header->comp_identifier);
379 pldm_comp_image_info->comp_comparison_stamp =
380 le32toh(data_header->comp_comparison_stamp);
381 pldm_comp_image_info->comp_options.value =
382 le16toh(data_header->comp_options.value);
383 pldm_comp_image_info->requested_comp_activation_method.value =
384 le16toh(data_header->requested_comp_activation_method.value);
385 pldm_comp_image_info->comp_location_offset =
386 le32toh(data_header->comp_location_offset);
387 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
388 pldm_comp_image_info->comp_version_string_type =
389 data_header->comp_version_string_type;
390 pldm_comp_image_info->comp_version_string_length =
391 data_header->comp_version_string_length;
392
393 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
394 pldm_comp_image_info->comp_comparison_stamp !=
395 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
396 return PLDM_ERROR_INVALID_DATA;
397 }
398
399 if (pldm_comp_image_info->comp_location_offset == 0 ||
400 pldm_comp_image_info->comp_size == 0) {
401 return PLDM_ERROR_INVALID_DATA;
402 }
403
404 comp_version_str->ptr =
405 data + sizeof(struct pldm_component_image_information);
406 comp_version_str->length =
407 pldm_comp_image_info->comp_version_string_length;
408
409 return PLDM_SUCCESS;
410}
411
gokulsanker138ceba2021-04-05 13:25:25 +0530412int encode_query_device_identifiers_req(uint8_t instance_id,
413 size_t payload_length,
414 struct pldm_msg *msg)
415{
416 if (msg == NULL) {
417 return PLDM_ERROR_INVALID_DATA;
418 }
419
420 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
421 return PLDM_ERROR_INVALID_LENGTH;
422 }
423
424 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
425 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
426}
gokulsankereca3e192021-04-05 14:57:41 +0530427
428int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
429 size_t payload_length,
430 uint8_t *completion_code,
431 uint32_t *device_identifiers_len,
432 uint8_t *descriptor_count,
433 uint8_t **descriptor_data)
434{
435 if (msg == NULL || completion_code == NULL ||
436 device_identifiers_len == NULL || descriptor_count == NULL ||
437 descriptor_data == NULL) {
438 return PLDM_ERROR_INVALID_DATA;
439 }
440
441 *completion_code = msg->payload[0];
442 if (PLDM_SUCCESS != *completion_code) {
443 return PLDM_SUCCESS;
444 }
445
446 if (payload_length <
447 sizeof(struct pldm_query_device_identifiers_resp)) {
448 return PLDM_ERROR_INVALID_LENGTH;
449 }
450
451 struct pldm_query_device_identifiers_resp *response =
452 (struct pldm_query_device_identifiers_resp *)msg->payload;
453 *device_identifiers_len = le32toh(response->device_identifiers_len);
454
455 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
456 return PLDM_ERROR_INVALID_LENGTH;
457 }
458
459 if (payload_length !=
460 sizeof(struct pldm_query_device_identifiers_resp) +
461 *device_identifiers_len) {
462 return PLDM_ERROR_INVALID_LENGTH;
463 }
464 *descriptor_count = response->descriptor_count;
465
466 if (*descriptor_count == 0) {
467 return PLDM_ERROR_INVALID_DATA;
468 }
gokulsankereca3e192021-04-05 14:57:41 +0530469 *descriptor_data =
470 (uint8_t *)(msg->payload +
471 sizeof(struct pldm_query_device_identifiers_resp));
472 return PLDM_SUCCESS;
473}
gokulsanker981fbfb2021-04-05 15:17:25 +0530474
475int encode_get_firmware_parameters_req(uint8_t instance_id,
476 size_t payload_length,
477 struct pldm_msg *msg)
478{
479 if (msg == NULL) {
480 return PLDM_ERROR_INVALID_DATA;
481 }
482
483 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
484 return PLDM_ERROR_INVALID_LENGTH;
485 }
486
487 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
488 PLDM_GET_FIRMWARE_PARAMETERS, msg);
489}
gokulsanker22fbb342021-04-05 15:55:06 +0530490
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700491int decode_get_firmware_parameters_resp(
gokulsanker22fbb342021-04-05 15:55:06 +0530492 const struct pldm_msg *msg, size_t payload_length,
493 struct pldm_get_firmware_parameters_resp *resp_data,
494 struct variable_field *active_comp_image_set_ver_str,
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700495 struct variable_field *pending_comp_image_set_ver_str,
496 struct variable_field *comp_parameter_table)
gokulsanker22fbb342021-04-05 15:55:06 +0530497{
498 if (msg == NULL || resp_data == NULL ||
499 active_comp_image_set_ver_str == NULL ||
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700500 pending_comp_image_set_ver_str == NULL ||
Tom Joseph83a644c2021-06-22 22:25:25 -0700501 comp_parameter_table == NULL || !payload_length) {
gokulsanker22fbb342021-04-05 15:55:06 +0530502 return PLDM_ERROR_INVALID_DATA;
503 }
504
Tom Joseph83a644c2021-06-22 22:25:25 -0700505 resp_data->completion_code = msg->payload[0];
506 if (PLDM_SUCCESS != resp_data->completion_code) {
507 return PLDM_SUCCESS;
508 }
509
gokulsanker22fbb342021-04-05 15:55:06 +0530510 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
511 return PLDM_ERROR_INVALID_LENGTH;
512 }
513
514 struct pldm_get_firmware_parameters_resp *response =
515 (struct pldm_get_firmware_parameters_resp *)msg->payload;
516
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700517 if (!is_string_type_valid(
518 response->active_comp_image_set_ver_str_type) ||
519 (response->active_comp_image_set_ver_str_len == 0)) {
gokulsanker22fbb342021-04-05 15:55:06 +0530520 return PLDM_ERROR_INVALID_DATA;
521 }
522
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700523 if (response->pending_comp_image_set_ver_str_len == 0) {
524 if (response->pending_comp_image_set_ver_str_type !=
525 PLDM_STR_TYPE_UNKNOWN) {
526 return PLDM_ERROR_INVALID_DATA;
527 }
528 } else {
529 if (!is_string_type_valid(
530 response->pending_comp_image_set_ver_str_type)) {
531 return PLDM_ERROR_INVALID_DATA;
532 }
533 }
gokulsanker22fbb342021-04-05 15:55:06 +0530534
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700535 size_t partial_response_length =
536 sizeof(struct pldm_get_firmware_parameters_resp) +
537 response->active_comp_image_set_ver_str_len +
538 response->pending_comp_image_set_ver_str_len;
539
540 if (payload_length < partial_response_length) {
gokulsanker22fbb342021-04-05 15:55:06 +0530541 return PLDM_ERROR_INVALID_LENGTH;
542 }
543
544 resp_data->capabilities_during_update.value =
545 le32toh(response->capabilities_during_update.value);
gokulsanker22fbb342021-04-05 15:55:06 +0530546 resp_data->comp_count = le16toh(response->comp_count);
gokulsanker22fbb342021-04-05 15:55:06 +0530547 resp_data->active_comp_image_set_ver_str_type =
548 response->active_comp_image_set_ver_str_type;
549 resp_data->active_comp_image_set_ver_str_len =
550 response->active_comp_image_set_ver_str_len;
551 resp_data->pending_comp_image_set_ver_str_type =
552 response->pending_comp_image_set_ver_str_type;
553 resp_data->pending_comp_image_set_ver_str_len =
554 response->pending_comp_image_set_ver_str_len;
555
556 active_comp_image_set_ver_str->ptr =
557 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
558 active_comp_image_set_ver_str->length =
559 resp_data->active_comp_image_set_ver_str_len;
560
561 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
562 pending_comp_image_set_ver_str->ptr =
563 msg->payload +
564 sizeof(struct pldm_get_firmware_parameters_resp) +
565 resp_data->active_comp_image_set_ver_str_len;
566 pending_comp_image_set_ver_str->length =
567 resp_data->pending_comp_image_set_ver_str_len;
568 } else {
569 pending_comp_image_set_ver_str->ptr = NULL;
570 pending_comp_image_set_ver_str->length = 0;
571 }
572
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700573 if (payload_length > partial_response_length && resp_data->comp_count) {
574 comp_parameter_table->ptr =
575 msg->payload +
576 sizeof(struct pldm_get_firmware_parameters_resp) +
577 resp_data->active_comp_image_set_ver_str_len +
578 resp_data->pending_comp_image_set_ver_str_len;
579 comp_parameter_table->length =
580 payload_length - partial_response_length;
581 } else {
582 comp_parameter_table->ptr = NULL;
583 comp_parameter_table->length = 0;
584 }
585
gokulsanker22fbb342021-04-05 15:55:06 +0530586 return PLDM_SUCCESS;
587}
gokulsankere1fb7a82021-04-05 16:09:29 +0530588
589int decode_get_firmware_parameters_resp_comp_entry(
590 const uint8_t *data, size_t length,
591 struct pldm_component_parameter_entry *component_data,
592 struct variable_field *active_comp_ver_str,
593 struct variable_field *pending_comp_ver_str)
594{
595 if (data == NULL || component_data == NULL ||
596 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
597 return PLDM_ERROR_INVALID_DATA;
598 }
599
600 if (length < sizeof(struct pldm_component_parameter_entry)) {
601 return PLDM_ERROR_INVALID_LENGTH;
602 }
603
604 struct pldm_component_parameter_entry *entry =
605 (struct pldm_component_parameter_entry *)(data);
606 if (entry->active_comp_ver_str_len == 0) {
607 return PLDM_ERROR_INVALID_LENGTH;
608 }
609
610 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
611 entry->active_comp_ver_str_len +
612 entry->pending_comp_ver_str_len;
613
Tom Josephc33c2f02021-06-22 21:58:56 -0700614 if (length < entry_length) {
gokulsankere1fb7a82021-04-05 16:09:29 +0530615 return PLDM_ERROR_INVALID_LENGTH;
616 }
617
618 component_data->comp_classification =
619 le16toh(entry->comp_classification);
620 component_data->comp_identifier = le16toh(entry->comp_identifier);
621 component_data->comp_classification_index =
622 entry->comp_classification_index;
623 component_data->active_comp_comparison_stamp =
624 le32toh(entry->active_comp_comparison_stamp);
625 component_data->active_comp_ver_str_type =
626 entry->active_comp_ver_str_type;
627 component_data->active_comp_ver_str_len =
628 entry->active_comp_ver_str_len;
629 memcpy(component_data->active_comp_release_date,
630 entry->active_comp_release_date,
631 sizeof(entry->active_comp_release_date));
632 component_data->pending_comp_comparison_stamp =
633 le32toh(entry->pending_comp_comparison_stamp);
634 component_data->pending_comp_ver_str_type =
635 entry->pending_comp_ver_str_type;
636 component_data->pending_comp_ver_str_len =
637 entry->pending_comp_ver_str_len;
638 memcpy(component_data->pending_comp_release_date,
639 entry->pending_comp_release_date,
640 sizeof(entry->pending_comp_release_date));
641 component_data->comp_activation_methods.value =
642 le16toh(entry->comp_activation_methods.value);
643 component_data->capabilities_during_update.value =
644 le32toh(entry->capabilities_during_update.value);
645
646 active_comp_ver_str->ptr =
647 data + sizeof(struct pldm_component_parameter_entry);
648 active_comp_ver_str->length = entry->active_comp_ver_str_len;
649
650 if (entry->pending_comp_ver_str_len != 0) {
651
652 pending_comp_ver_str->ptr =
653 data + sizeof(struct pldm_component_parameter_entry) +
654 entry->active_comp_ver_str_len;
655 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
656 } else {
657 pending_comp_ver_str->ptr = NULL;
658 pending_comp_ver_str->length = 0;
659 }
660 return PLDM_SUCCESS;
661}
gokulsankerd434edc2021-04-05 16:36:04 +0530662
663int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
664 uint16_t num_of_comp,
665 uint8_t max_outstanding_transfer_req,
666 uint16_t pkg_data_len,
667 uint8_t comp_image_set_ver_str_type,
668 uint8_t comp_image_set_ver_str_len,
669 const struct variable_field *comp_img_set_ver_str,
670 struct pldm_msg *msg, size_t payload_length)
671{
672 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
673 msg == NULL) {
674 return PLDM_ERROR_INVALID_DATA;
675 }
676
677 if (payload_length != sizeof(struct pldm_request_update_req) +
678 comp_img_set_ver_str->length) {
679 return PLDM_ERROR_INVALID_LENGTH;
680 }
681
682 if ((comp_image_set_ver_str_len == 0) ||
683 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
684 return PLDM_ERROR_INVALID_DATA;
685 }
686
687 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
688 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
689 return PLDM_ERROR_INVALID_DATA;
690 }
691
692 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
693 return PLDM_ERROR_INVALID_DATA;
694 }
695
696 struct pldm_header_info header = {0};
697 header.instance = instance_id;
698 header.msg_type = PLDM_REQUEST;
699 header.pldm_type = PLDM_FWUP;
700 header.command = PLDM_REQUEST_UPDATE;
701 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
702 if (rc) {
703 return rc;
704 }
705
706 struct pldm_request_update_req *request =
707 (struct pldm_request_update_req *)msg->payload;
708
709 request->max_transfer_size = htole32(max_transfer_size);
710 request->num_of_comp = htole16(num_of_comp);
711 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
712 request->pkg_data_len = htole16(pkg_data_len);
713 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
714 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
715
716 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
717 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
718
719 return PLDM_SUCCESS;
gokulsanker611238c2021-04-05 16:50:44 +0530720}
721
722int decode_request_update_resp(const struct pldm_msg *msg,
723 size_t payload_length, uint8_t *completion_code,
724 uint16_t *fd_meta_data_len,
725 uint8_t *fd_will_send_pkg_data)
726{
727 if (msg == NULL || completion_code == NULL ||
728 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
729 !payload_length) {
730 return PLDM_ERROR_INVALID_DATA;
731 }
732
733 *completion_code = msg->payload[0];
734 if (*completion_code != PLDM_SUCCESS) {
735 return PLDM_SUCCESS;
736 }
737
738 if (payload_length != sizeof(struct pldm_request_update_resp)) {
739 return PLDM_ERROR_INVALID_LENGTH;
740 }
741
742 struct pldm_request_update_resp *response =
743 (struct pldm_request_update_resp *)msg->payload;
744
745 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
746 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
747
748 return PLDM_SUCCESS;
gokulsanker1b909d82021-04-05 17:26:02 +0530749}
750
751int encode_pass_component_table_req(
752 uint8_t instance_id, uint8_t transfer_flag, uint16_t comp_classification,
753 uint16_t comp_identifier, uint8_t comp_classification_index,
754 uint32_t comp_comparison_stamp, uint8_t comp_ver_str_type,
755 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
756 struct pldm_msg *msg, size_t payload_length)
757{
758 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
759 return PLDM_ERROR_INVALID_DATA;
760 }
761
762 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
763 comp_ver_str->length) {
764 return PLDM_ERROR_INVALID_LENGTH;
765 }
766
767 if ((comp_ver_str_len == 0) ||
768 (comp_ver_str_len != comp_ver_str->length)) {
769 return PLDM_ERROR_INVALID_DATA;
770 }
771
772 if (!is_transfer_flag_valid(transfer_flag)) {
773 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
774 }
775
776 if (!is_string_type_valid(comp_ver_str_type)) {
777 return PLDM_ERROR_INVALID_DATA;
778 }
779
780 struct pldm_header_info header = {0};
781 header.instance = instance_id;
782 header.msg_type = PLDM_REQUEST;
783 header.pldm_type = PLDM_FWUP;
784 header.command = PLDM_PASS_COMPONENT_TABLE;
785 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
786 if (rc) {
787 return rc;
788 }
789
790 struct pldm_pass_component_table_req *request =
791 (struct pldm_pass_component_table_req *)msg->payload;
792
793 request->transfer_flag = transfer_flag;
794 request->comp_classification = htole16(comp_classification);
795 request->comp_identifier = htole16(comp_identifier);
796 request->comp_classification_index = comp_classification_index;
797 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
798 request->comp_ver_str_type = comp_ver_str_type;
799 request->comp_ver_str_len = comp_ver_str_len;
800
801 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
802 comp_ver_str->ptr, comp_ver_str->length);
803
804 return PLDM_SUCCESS;
805}
gokulsanker566784b2021-04-05 17:47:04 +0530806
807int decode_pass_component_table_resp(const struct pldm_msg *msg,
808 const size_t payload_length,
809 uint8_t *completion_code,
810 uint8_t *comp_resp,
811 uint8_t *comp_resp_code)
812{
813 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
814 comp_resp_code == NULL || !payload_length) {
815 return PLDM_ERROR_INVALID_DATA;
816 }
817
818 *completion_code = msg->payload[0];
819 if (*completion_code != PLDM_SUCCESS) {
820 return PLDM_SUCCESS;
821 }
822
823 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
824 return PLDM_ERROR_INVALID_LENGTH;
825 }
826
827 struct pldm_pass_component_table_resp *response =
828 (struct pldm_pass_component_table_resp *)msg->payload;
829
830 if (!is_comp_resp_valid(response->comp_resp)) {
831 return PLDM_ERROR_INVALID_DATA;
832 }
833
834 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
835 return PLDM_ERROR_INVALID_DATA;
836 }
837
838 *comp_resp = response->comp_resp;
839 *comp_resp_code = response->comp_resp_code;
840
841 return PLDM_SUCCESS;
842}
gokulsankeraa3a5cd2021-04-22 11:06:42 +0530843
844int encode_update_component_req(
845 uint8_t instance_id, uint16_t comp_classification, uint16_t comp_identifier,
846 uint8_t comp_classification_index, uint32_t comp_comparison_stamp,
847 uint32_t comp_image_size, bitfield32_t update_option_flags,
848 uint8_t comp_ver_str_type, uint8_t comp_ver_str_len,
849 const struct variable_field *comp_ver_str, struct pldm_msg *msg,
850 size_t payload_length)
851{
852 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
853 return PLDM_ERROR_INVALID_DATA;
854 }
855
856 if (payload_length !=
857 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
858 return PLDM_ERROR_INVALID_LENGTH;
859 }
860
861 if (!comp_image_size) {
862 return PLDM_ERROR_INVALID_DATA;
863 }
864
865 if ((comp_ver_str_len == 0) ||
866 (comp_ver_str_len != comp_ver_str->length)) {
867 return PLDM_ERROR_INVALID_DATA;
868 }
869
870 if (!is_string_type_valid(comp_ver_str_type)) {
871 return PLDM_ERROR_INVALID_DATA;
872 }
873
874 struct pldm_header_info header = {0};
875 header.instance = instance_id;
876 header.msg_type = PLDM_REQUEST;
877 header.pldm_type = PLDM_FWUP;
878 header.command = PLDM_UPDATE_COMPONENT;
879 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
880 if (rc) {
881 return rc;
882 }
883
884 struct pldm_update_component_req *request =
885 (struct pldm_update_component_req *)msg->payload;
886
887 request->comp_classification = htole16(comp_classification);
888 request->comp_identifier = htole16(comp_identifier);
889 request->comp_classification_index = comp_classification_index;
890 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
891 request->comp_image_size = htole32(comp_image_size);
892 request->update_option_flags.value = htole32(update_option_flags.value);
893 request->comp_ver_str_type = comp_ver_str_type;
894 request->comp_ver_str_len = comp_ver_str_len;
895
896 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
897 comp_ver_str->ptr, comp_ver_str->length);
898
899 return PLDM_SUCCESS;
900}