blob: 23487eb6a4ac0339e8282d0230a18b9ea90e84b2 [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
Tom Joseph568e4702021-06-07 22:15:49 -070074int decode_pldm_package_header_info(
75 const uint8_t *data, size_t length,
76 struct pldm_package_header_information *package_header_info,
77 struct variable_field *package_version_str)
78{
79 if (data == NULL || package_header_info == NULL ||
80 package_version_str == NULL) {
81 return PLDM_ERROR_INVALID_DATA;
82 }
83
84 if (length < sizeof(struct pldm_package_header_information)) {
85 return PLDM_ERROR_INVALID_LENGTH;
86 }
87
88 struct pldm_package_header_information *data_header =
89 (struct pldm_package_header_information *)(data);
90
91 if (!is_string_type_valid(data_header->package_version_string_type) ||
92 (data_header->package_version_string_length == 0)) {
93 return PLDM_ERROR_INVALID_DATA;
94 }
95
96 if (length < sizeof(struct pldm_package_header_information) +
97 data_header->package_version_string_length) {
98 return PLDM_ERROR_INVALID_LENGTH;
99 }
100
101 if ((data_header->component_bitmap_bit_length %
102 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
103 return PLDM_ERROR_INVALID_DATA;
104 }
105
106 memcpy(package_header_info->uuid, data_header->uuid,
107 sizeof(data_header->uuid));
108 package_header_info->package_header_format_version =
109 data_header->package_header_format_version;
110 package_header_info->package_header_size =
111 le16toh(data_header->package_header_size);
112 memcpy(package_header_info->timestamp104, data_header->timestamp104,
113 sizeof(data_header->timestamp104));
114 package_header_info->component_bitmap_bit_length =
115 le16toh(data_header->component_bitmap_bit_length);
116 package_header_info->package_version_string_type =
117 data_header->package_version_string_type;
118 package_header_info->package_version_string_length =
119 data_header->package_version_string_length;
120 package_version_str->ptr =
121 data + sizeof(struct pldm_package_header_information);
122 package_version_str->length =
123 package_header_info->package_version_string_length;
124
125 return PLDM_SUCCESS;
126}
127
Tom Joseph64af3452021-06-08 04:05:28 -0700128int decode_firmware_device_id_record(
129 const uint8_t *data, size_t length, uint16_t component_bitmap_bit_length,
130 struct pldm_firmware_device_id_record *fw_device_id_record,
131 struct variable_field *applicable_components,
132 struct variable_field *comp_image_set_version_str,
133 struct variable_field *record_descriptors,
134 struct variable_field *fw_device_pkg_data)
135{
136 if (data == NULL || fw_device_id_record == NULL ||
137 applicable_components == NULL ||
138 comp_image_set_version_str == NULL || record_descriptors == NULL ||
139 fw_device_pkg_data == NULL) {
140 return PLDM_ERROR_INVALID_DATA;
141 }
142
143 if (length < sizeof(struct pldm_firmware_device_id_record)) {
144 return PLDM_ERROR_INVALID_LENGTH;
145 }
146
147 if ((component_bitmap_bit_length %
148 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
149 return PLDM_ERROR_INVALID_DATA;
150 }
151
152 struct pldm_firmware_device_id_record *data_record =
153 (struct pldm_firmware_device_id_record *)(data);
154
155 if (!is_string_type_valid(
156 data_record->comp_image_set_version_string_type) ||
157 (data_record->comp_image_set_version_string_length == 0)) {
158 return PLDM_ERROR_INVALID_DATA;
159 }
160
161 fw_device_id_record->record_length =
162 le16toh(data_record->record_length);
163 fw_device_id_record->descriptor_count = data_record->descriptor_count;
164 fw_device_id_record->device_update_option_flags.value =
165 le32toh(data_record->device_update_option_flags.value);
166 fw_device_id_record->comp_image_set_version_string_type =
167 data_record->comp_image_set_version_string_type;
168 fw_device_id_record->comp_image_set_version_string_length =
169 data_record->comp_image_set_version_string_length;
170 fw_device_id_record->fw_device_pkg_data_length =
171 le16toh(data_record->fw_device_pkg_data_length);
172
173 if (length < fw_device_id_record->record_length) {
174 return PLDM_ERROR_INVALID_LENGTH;
175 }
176
177 uint16_t applicable_components_length =
178 component_bitmap_bit_length / PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
179 uint16_t calc_min_record_length =
180 sizeof(struct pldm_firmware_device_id_record) +
181 applicable_components_length +
182 data_record->comp_image_set_version_string_length +
183 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
184 fw_device_id_record->fw_device_pkg_data_length;
185
186 if (fw_device_id_record->record_length < calc_min_record_length) {
187 return PLDM_ERROR_INVALID_LENGTH;
188 }
189
190 applicable_components->ptr =
191 data + sizeof(struct pldm_firmware_device_id_record);
192 applicable_components->length = applicable_components_length;
193
194 comp_image_set_version_str->ptr =
195 applicable_components->ptr + applicable_components->length;
196 comp_image_set_version_str->length =
197 fw_device_id_record->comp_image_set_version_string_length;
198
199 record_descriptors->ptr = comp_image_set_version_str->ptr +
200 comp_image_set_version_str->length;
201 record_descriptors->length =
202 fw_device_id_record->record_length -
203 sizeof(struct pldm_firmware_device_id_record) -
204 applicable_components_length -
205 fw_device_id_record->comp_image_set_version_string_length -
206 fw_device_id_record->fw_device_pkg_data_length;
207
208 if (fw_device_id_record->fw_device_pkg_data_length) {
209 fw_device_pkg_data->ptr =
210 record_descriptors->ptr + record_descriptors->length;
211 fw_device_pkg_data->length =
212 fw_device_id_record->fw_device_pkg_data_length;
213 }
214
215 return PLDM_SUCCESS;
216}
217
Tom Joseph763b51e2021-06-05 04:50:47 -0700218int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
219 uint16_t *descriptor_type,
220 struct variable_field *descriptor_data)
221{
222 uint16_t descriptor_length = 0;
223
224 if (data == NULL || descriptor_type == NULL ||
225 descriptor_data == NULL) {
226 return PLDM_ERROR_INVALID_DATA;
227 }
228
229 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
230 return PLDM_ERROR_INVALID_LENGTH;
231 }
232
233 struct pldm_descriptor_tlv *entry =
234 (struct pldm_descriptor_tlv *)(data);
235
236 *descriptor_type = le16toh(entry->descriptor_type);
237 descriptor_length = le16toh(entry->descriptor_length);
238 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
239 if (descriptor_length !=
240 get_descriptor_type_length(*descriptor_type)) {
241 return PLDM_ERROR_INVALID_LENGTH;
242 }
243 }
244
245 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
246 descriptor_length)) {
247 return PLDM_ERROR_INVALID_LENGTH;
248 }
249
250 descriptor_data->ptr = entry->descriptor_data;
251 descriptor_data->length = descriptor_length;
252
253 return PLDM_SUCCESS;
254}
255
256int decode_vendor_defined_descriptor_value(
257 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
258 struct variable_field *descriptor_title_str,
259 struct variable_field *descriptor_data)
260{
261 if (data == NULL || descriptor_title_str_type == NULL ||
262 descriptor_title_str == NULL || descriptor_data == NULL) {
263 return PLDM_ERROR_INVALID_DATA;
264 }
265
266 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
267 return PLDM_ERROR_INVALID_LENGTH;
268 }
269
270 struct pldm_vendor_defined_descriptor_title_data *entry =
271 (struct pldm_vendor_defined_descriptor_title_data *)(data);
272 if (!is_string_type_valid(
273 entry->vendor_defined_descriptor_title_str_type) ||
274 (entry->vendor_defined_descriptor_title_str_len == 0)) {
275 return PLDM_ERROR_INVALID_DATA;
276 }
277
278 // Assuming atleast 1 byte of VendorDefinedDescriptorData
279 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
280 entry->vendor_defined_descriptor_title_str_len)) {
281 return PLDM_ERROR_INVALID_LENGTH;
282 }
283
284 *descriptor_title_str_type =
285 entry->vendor_defined_descriptor_title_str_type;
286 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
287 descriptor_title_str->length =
288 entry->vendor_defined_descriptor_title_str_len;
289
290 descriptor_data->ptr =
291 descriptor_title_str->ptr + descriptor_title_str->length;
292 descriptor_data->length =
293 length - sizeof(entry->vendor_defined_descriptor_title_str_type) -
294 sizeof(entry->vendor_defined_descriptor_title_str_len) -
295 descriptor_title_str->length;
296
297 return PLDM_SUCCESS;
298}
299
Tom Joseph58cc1722021-06-09 07:15:49 -0700300int decode_pldm_comp_image_info(
301 const uint8_t *data, size_t length,
302 struct pldm_component_image_information *pldm_comp_image_info,
303 struct variable_field *comp_version_str)
304{
305 if (data == NULL || pldm_comp_image_info == NULL ||
306 comp_version_str == NULL) {
307 return PLDM_ERROR_INVALID_DATA;
308 }
309
310 if (length < sizeof(struct pldm_component_image_information)) {
311 return PLDM_ERROR_INVALID_LENGTH;
312 }
313
314 struct pldm_component_image_information *data_header =
315 (struct pldm_component_image_information *)(data);
316
317 if (!is_string_type_valid(data_header->comp_version_string_type) ||
318 (data_header->comp_version_string_length == 0)) {
319 return PLDM_ERROR_INVALID_DATA;
320 }
321
322 if (length < sizeof(struct pldm_component_image_information) +
323 data_header->comp_version_string_length) {
324 return PLDM_ERROR_INVALID_LENGTH;
325 }
326
327 pldm_comp_image_info->comp_classification =
328 le16toh(data_header->comp_classification);
329 pldm_comp_image_info->comp_identifier =
330 le16toh(data_header->comp_identifier);
331 pldm_comp_image_info->comp_comparison_stamp =
332 le32toh(data_header->comp_comparison_stamp);
333 pldm_comp_image_info->comp_options.value =
334 le16toh(data_header->comp_options.value);
335 pldm_comp_image_info->requested_comp_activation_method.value =
336 le16toh(data_header->requested_comp_activation_method.value);
337 pldm_comp_image_info->comp_location_offset =
338 le32toh(data_header->comp_location_offset);
339 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
340 pldm_comp_image_info->comp_version_string_type =
341 data_header->comp_version_string_type;
342 pldm_comp_image_info->comp_version_string_length =
343 data_header->comp_version_string_length;
344
345 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
346 pldm_comp_image_info->comp_comparison_stamp !=
347 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
348 return PLDM_ERROR_INVALID_DATA;
349 }
350
351 if (pldm_comp_image_info->comp_location_offset == 0 ||
352 pldm_comp_image_info->comp_size == 0) {
353 return PLDM_ERROR_INVALID_DATA;
354 }
355
356 comp_version_str->ptr =
357 data + sizeof(struct pldm_component_image_information);
358 comp_version_str->length =
359 pldm_comp_image_info->comp_version_string_length;
360
361 return PLDM_SUCCESS;
362}
363
gokulsanker138ceba2021-04-05 13:25:25 +0530364int encode_query_device_identifiers_req(uint8_t instance_id,
365 size_t payload_length,
366 struct pldm_msg *msg)
367{
368 if (msg == NULL) {
369 return PLDM_ERROR_INVALID_DATA;
370 }
371
372 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
373 return PLDM_ERROR_INVALID_LENGTH;
374 }
375
376 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
377 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
378}
gokulsankereca3e192021-04-05 14:57:41 +0530379
380int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
381 size_t payload_length,
382 uint8_t *completion_code,
383 uint32_t *device_identifiers_len,
384 uint8_t *descriptor_count,
385 uint8_t **descriptor_data)
386{
387 if (msg == NULL || completion_code == NULL ||
388 device_identifiers_len == NULL || descriptor_count == NULL ||
389 descriptor_data == NULL) {
390 return PLDM_ERROR_INVALID_DATA;
391 }
392
393 *completion_code = msg->payload[0];
394 if (PLDM_SUCCESS != *completion_code) {
395 return PLDM_SUCCESS;
396 }
397
398 if (payload_length <
399 sizeof(struct pldm_query_device_identifiers_resp)) {
400 return PLDM_ERROR_INVALID_LENGTH;
401 }
402
403 struct pldm_query_device_identifiers_resp *response =
404 (struct pldm_query_device_identifiers_resp *)msg->payload;
405 *device_identifiers_len = le32toh(response->device_identifiers_len);
406
407 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
408 return PLDM_ERROR_INVALID_LENGTH;
409 }
410
411 if (payload_length !=
412 sizeof(struct pldm_query_device_identifiers_resp) +
413 *device_identifiers_len) {
414 return PLDM_ERROR_INVALID_LENGTH;
415 }
416 *descriptor_count = response->descriptor_count;
417
418 if (*descriptor_count == 0) {
419 return PLDM_ERROR_INVALID_DATA;
420 }
gokulsankereca3e192021-04-05 14:57:41 +0530421 *descriptor_data =
422 (uint8_t *)(msg->payload +
423 sizeof(struct pldm_query_device_identifiers_resp));
424 return PLDM_SUCCESS;
425}
gokulsanker981fbfb2021-04-05 15:17:25 +0530426
427int encode_get_firmware_parameters_req(uint8_t instance_id,
428 size_t payload_length,
429 struct pldm_msg *msg)
430{
431 if (msg == NULL) {
432 return PLDM_ERROR_INVALID_DATA;
433 }
434
435 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
436 return PLDM_ERROR_INVALID_LENGTH;
437 }
438
439 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
440 PLDM_GET_FIRMWARE_PARAMETERS, msg);
441}
gokulsanker22fbb342021-04-05 15:55:06 +0530442
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700443int decode_get_firmware_parameters_resp(
gokulsanker22fbb342021-04-05 15:55:06 +0530444 const struct pldm_msg *msg, size_t payload_length,
445 struct pldm_get_firmware_parameters_resp *resp_data,
446 struct variable_field *active_comp_image_set_ver_str,
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700447 struct variable_field *pending_comp_image_set_ver_str,
448 struct variable_field *comp_parameter_table)
gokulsanker22fbb342021-04-05 15:55:06 +0530449{
450 if (msg == NULL || resp_data == NULL ||
451 active_comp_image_set_ver_str == NULL ||
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700452 pending_comp_image_set_ver_str == NULL ||
453 comp_parameter_table == NULL) {
gokulsanker22fbb342021-04-05 15:55:06 +0530454 return PLDM_ERROR_INVALID_DATA;
455 }
456
457 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
458 return PLDM_ERROR_INVALID_LENGTH;
459 }
460
461 struct pldm_get_firmware_parameters_resp *response =
462 (struct pldm_get_firmware_parameters_resp *)msg->payload;
463
464 resp_data->completion_code = response->completion_code;
465
466 if (PLDM_SUCCESS != resp_data->completion_code) {
467 return PLDM_SUCCESS;
468 }
469
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700470 if (!is_string_type_valid(
471 response->active_comp_image_set_ver_str_type) ||
472 (response->active_comp_image_set_ver_str_len == 0)) {
gokulsanker22fbb342021-04-05 15:55:06 +0530473 return PLDM_ERROR_INVALID_DATA;
474 }
475
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700476 if (response->pending_comp_image_set_ver_str_len == 0) {
477 if (response->pending_comp_image_set_ver_str_type !=
478 PLDM_STR_TYPE_UNKNOWN) {
479 return PLDM_ERROR_INVALID_DATA;
480 }
481 } else {
482 if (!is_string_type_valid(
483 response->pending_comp_image_set_ver_str_type)) {
484 return PLDM_ERROR_INVALID_DATA;
485 }
486 }
gokulsanker22fbb342021-04-05 15:55:06 +0530487
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700488 size_t partial_response_length =
489 sizeof(struct pldm_get_firmware_parameters_resp) +
490 response->active_comp_image_set_ver_str_len +
491 response->pending_comp_image_set_ver_str_len;
492
493 if (payload_length < partial_response_length) {
gokulsanker22fbb342021-04-05 15:55:06 +0530494 return PLDM_ERROR_INVALID_LENGTH;
495 }
496
497 resp_data->capabilities_during_update.value =
498 le32toh(response->capabilities_during_update.value);
gokulsanker22fbb342021-04-05 15:55:06 +0530499 resp_data->comp_count = le16toh(response->comp_count);
gokulsanker22fbb342021-04-05 15:55:06 +0530500 resp_data->active_comp_image_set_ver_str_type =
501 response->active_comp_image_set_ver_str_type;
502 resp_data->active_comp_image_set_ver_str_len =
503 response->active_comp_image_set_ver_str_len;
504 resp_data->pending_comp_image_set_ver_str_type =
505 response->pending_comp_image_set_ver_str_type;
506 resp_data->pending_comp_image_set_ver_str_len =
507 response->pending_comp_image_set_ver_str_len;
508
509 active_comp_image_set_ver_str->ptr =
510 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
511 active_comp_image_set_ver_str->length =
512 resp_data->active_comp_image_set_ver_str_len;
513
514 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
515 pending_comp_image_set_ver_str->ptr =
516 msg->payload +
517 sizeof(struct pldm_get_firmware_parameters_resp) +
518 resp_data->active_comp_image_set_ver_str_len;
519 pending_comp_image_set_ver_str->length =
520 resp_data->pending_comp_image_set_ver_str_len;
521 } else {
522 pending_comp_image_set_ver_str->ptr = NULL;
523 pending_comp_image_set_ver_str->length = 0;
524 }
525
Tom Joseph3fd3eb82021-06-18 04:13:29 -0700526 if (payload_length > partial_response_length && resp_data->comp_count) {
527 comp_parameter_table->ptr =
528 msg->payload +
529 sizeof(struct pldm_get_firmware_parameters_resp) +
530 resp_data->active_comp_image_set_ver_str_len +
531 resp_data->pending_comp_image_set_ver_str_len;
532 comp_parameter_table->length =
533 payload_length - partial_response_length;
534 } else {
535 comp_parameter_table->ptr = NULL;
536 comp_parameter_table->length = 0;
537 }
538
gokulsanker22fbb342021-04-05 15:55:06 +0530539 return PLDM_SUCCESS;
540}
gokulsankere1fb7a82021-04-05 16:09:29 +0530541
542int decode_get_firmware_parameters_resp_comp_entry(
543 const uint8_t *data, size_t length,
544 struct pldm_component_parameter_entry *component_data,
545 struct variable_field *active_comp_ver_str,
546 struct variable_field *pending_comp_ver_str)
547{
548 if (data == NULL || component_data == NULL ||
549 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
550 return PLDM_ERROR_INVALID_DATA;
551 }
552
553 if (length < sizeof(struct pldm_component_parameter_entry)) {
554 return PLDM_ERROR_INVALID_LENGTH;
555 }
556
557 struct pldm_component_parameter_entry *entry =
558 (struct pldm_component_parameter_entry *)(data);
559 if (entry->active_comp_ver_str_len == 0) {
560 return PLDM_ERROR_INVALID_LENGTH;
561 }
562
563 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
564 entry->active_comp_ver_str_len +
565 entry->pending_comp_ver_str_len;
566
567 if (length != entry_length) {
568 return PLDM_ERROR_INVALID_LENGTH;
569 }
570
571 component_data->comp_classification =
572 le16toh(entry->comp_classification);
573 component_data->comp_identifier = le16toh(entry->comp_identifier);
574 component_data->comp_classification_index =
575 entry->comp_classification_index;
576 component_data->active_comp_comparison_stamp =
577 le32toh(entry->active_comp_comparison_stamp);
578 component_data->active_comp_ver_str_type =
579 entry->active_comp_ver_str_type;
580 component_data->active_comp_ver_str_len =
581 entry->active_comp_ver_str_len;
582 memcpy(component_data->active_comp_release_date,
583 entry->active_comp_release_date,
584 sizeof(entry->active_comp_release_date));
585 component_data->pending_comp_comparison_stamp =
586 le32toh(entry->pending_comp_comparison_stamp);
587 component_data->pending_comp_ver_str_type =
588 entry->pending_comp_ver_str_type;
589 component_data->pending_comp_ver_str_len =
590 entry->pending_comp_ver_str_len;
591 memcpy(component_data->pending_comp_release_date,
592 entry->pending_comp_release_date,
593 sizeof(entry->pending_comp_release_date));
594 component_data->comp_activation_methods.value =
595 le16toh(entry->comp_activation_methods.value);
596 component_data->capabilities_during_update.value =
597 le32toh(entry->capabilities_during_update.value);
598
599 active_comp_ver_str->ptr =
600 data + sizeof(struct pldm_component_parameter_entry);
601 active_comp_ver_str->length = entry->active_comp_ver_str_len;
602
603 if (entry->pending_comp_ver_str_len != 0) {
604
605 pending_comp_ver_str->ptr =
606 data + sizeof(struct pldm_component_parameter_entry) +
607 entry->active_comp_ver_str_len;
608 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
609 } else {
610 pending_comp_ver_str->ptr = NULL;
611 pending_comp_ver_str->length = 0;
612 }
613 return PLDM_SUCCESS;
614}