blob: 0788d4b9626a84ff8ad057c133aefd9ffb3b02b3 [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10302#include <libpldm/firmware_update.h>
3#include <libpldm/utils.h>
4
Andrew Jeffery9c766792022-08-10 23:12:49 +09305#include <endian.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05306#include <stdbool.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09307#include <string.h>
8
9/** @brief Check whether string type value is valid
10 *
11 * @return true if string type value is valid, false if not
12 */
13static bool is_string_type_valid(uint8_t string_type)
14{
15 switch (string_type) {
16 case PLDM_STR_TYPE_UNKNOWN:
17 return false;
18 case PLDM_STR_TYPE_ASCII:
19 case PLDM_STR_TYPE_UTF_8:
20 case PLDM_STR_TYPE_UTF_16:
21 case PLDM_STR_TYPE_UTF_16LE:
22 case PLDM_STR_TYPE_UTF_16BE:
23 return true;
24 default:
25 return false;
26 }
27}
28
29/** @brief Return the length of the descriptor type described in firmware update
30 * specification
31 *
32 * @return length of the descriptor type if descriptor type is valid else
33 * return 0
34 */
35static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
36{
37 switch (descriptor_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093038 case PLDM_FWUP_PCI_VENDOR_ID:
39 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
40 case PLDM_FWUP_IANA_ENTERPRISE_ID:
41 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
42 case PLDM_FWUP_UUID:
43 return PLDM_FWUP_UUID_LENGTH;
44 case PLDM_FWUP_PNP_VENDOR_ID:
45 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
46 case PLDM_FWUP_ACPI_VENDOR_ID:
47 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
48 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
49 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
50 case PLDM_FWUP_SCSI_VENDOR_ID:
51 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
52 case PLDM_FWUP_PCI_DEVICE_ID:
53 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
54 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
55 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
56 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
57 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
58 case PLDM_FWUP_PCI_REVISION_ID:
59 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
60 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
61 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
62 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
63 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
64 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
65 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
66 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
67 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
68 case PLDM_FWUP_SCSI_PRODUCT_ID:
69 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
70 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
71 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
72 default:
73 return 0;
74 }
75}
76
77/** @brief Check whether ComponentResponse is valid
78 *
79 * @return true if ComponentResponse is valid, false if not
80 */
81static bool is_comp_resp_valid(uint8_t comp_resp)
82{
83 switch (comp_resp) {
84 case PLDM_CR_COMP_CAN_BE_UPDATED:
85 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
86 return true;
87
88 default:
89 return false;
90 }
91}
92
93/** @brief Check whether ComponentResponseCode is valid
94 *
95 * @return true if ComponentResponseCode is valid, false if not
96 */
97static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
98{
99 switch (comp_resp_code) {
100 case PLDM_CRC_COMP_CAN_BE_UPDATED:
101 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
102 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
103 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
104 case PLDM_CRC_COMP_CONFLICT:
105 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
106 case PLDM_CRC_COMP_NOT_SUPPORTED:
107 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
108 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
109 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
110 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
111 case PLDM_CRC_COMP_VER_STR_LOWER:
112 return true;
113
114 default:
115 if (comp_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930116 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930117 comp_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930118 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930119 return true;
120 }
121 return false;
122 }
123}
124
125/** @brief Check whether ComponentCompatibilityResponse is valid
126 *
127 * @return true if ComponentCompatibilityResponse is valid, false if not
128 */
129static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
130{
131 switch (comp_compatibility_resp) {
132 case PLDM_CCR_COMP_CAN_BE_UPDATED:
133 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
134 return true;
135
136 default:
137 return false;
138 }
139}
140
141/** @brief Check whether ComponentCompatibilityResponse Code is valid
142 *
143 * @return true if ComponentCompatibilityResponse Code is valid, false if not
144 */
145static bool
146is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
147{
148 switch (comp_compatibility_resp_code) {
149 case PLDM_CCRC_NO_RESPONSE_CODE:
150 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
151 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
152 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
153 case PLDM_CCRC_COMP_CONFLICT:
154 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
155 case PLDM_CCRC_COMP_NOT_SUPPORTED:
156 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
157 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
158 case PLDM_CCRC_COMP_INFO_NO_MATCH:
159 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
160 case PLDM_CCRC_COMP_VER_STR_LOWER:
161 return true;
162
163 default:
164 if (comp_compatibility_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930165 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930166 comp_compatibility_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930167 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930168 return true;
169 }
170 return false;
171 }
172}
173
174/** @brief Check whether SelfContainedActivationRequest is valid
175 *
176 * @return true if SelfContainedActivationRequest is valid, false if not
177 */
178static bool
179is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
180{
181 switch (self_contained_activation_req) {
182 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
183 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
184 return true;
185
186 default:
187 return false;
188 }
189}
190
191/** @brief Check if current or previous status in GetStatus command response is
192 * valid
193 *
194 * @param[in] state - current or previous different state machine state of
195 * the FD
196 * @return true if state is valid, false if not
197 */
198static bool is_state_valid(uint8_t state)
199{
200 switch (state) {
201 case PLDM_FD_STATE_IDLE:
202 case PLDM_FD_STATE_LEARN_COMPONENTS:
203 case PLDM_FD_STATE_READY_XFER:
204 case PLDM_FD_STATE_DOWNLOAD:
205 case PLDM_FD_STATE_VERIFY:
206 case PLDM_FD_STATE_APPLY:
207 case PLDM_FD_STATE_ACTIVATE:
208 return true;
209
210 default:
211 return false;
212 }
213}
214
215/** @brief Check if aux state in GetStatus command response is valid
216 *
217 * @param[in] aux_state - provides additional information to the UA to describe
218 * the current operation state of the FD/FDP
219 *
220 * @return true if aux state is valid, false if not
221 */
222static bool is_aux_state_valid(uint8_t aux_state)
223{
224 switch (aux_state) {
225 case PLDM_FD_OPERATION_IN_PROGRESS:
226 case PLDM_FD_OPERATION_SUCCESSFUL:
227 case PLDM_FD_OPERATION_FAILED:
228 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
229 return true;
230
231 default:
232 return false;
233 }
234}
235
236/** @brief Check if aux state status in GetStatus command response is valid
237 *
238 * @param[in] aux_state_status - aux state status
239 *
240 * @return true if aux state status is valid, false if not
241 */
242static bool is_aux_state_status_valid(uint8_t aux_state_status)
243{
244 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
245 aux_state_status == PLDM_FD_TIMEOUT ||
Andrew Jeffery67f7ed92023-04-05 14:00:00 +0930246 aux_state_status == PLDM_FD_GENERIC_ERROR ||
247 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
248 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930249 return true;
250 }
251
252 return false;
253}
254
255/** @brief Check if reason code in GetStatus command response is valid
256 *
257 * @param[in] reason_code - provides the reason for why the current state
258 * entered the IDLE state
259 *
260 * @return true if reason code is valid, false if not
261 */
262static bool is_reason_code_valid(uint8_t reason_code)
263{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930264 switch (reason_code) {
265 case PLDM_FD_INITIALIZATION:
266 case PLDM_FD_ACTIVATE_FW:
267 case PLDM_FD_CANCEL_UPDATE:
268 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
269 case PLDM_FD_TIMEOUT_READY_XFER:
270 case PLDM_FD_TIMEOUT_DOWNLOAD:
271 case PLDM_FD_TIMEOUT_VERIFY:
272 case PLDM_FD_TIMEOUT_APPLY:
273 return true;
274
275 default:
276 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
277 return true;
278 }
279 return false;
280 }
281}
282
283/** @brief Check if non functioning component indication in CancelUpdate
284 * response is valid
285 *
286 * @return true if non functioning component indication is valid, false if not
287 */
288static bool is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930289 bool8_t non_functioning_component_indication)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930290{
291 switch (non_functioning_component_indication) {
292 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
293 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
294 return true;
295
296 default:
297 return false;
298 }
299}
300
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930301LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930302int decode_pldm_package_header_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930303 const uint8_t *data, size_t length,
304 struct pldm_package_header_information *package_header_info,
305 struct variable_field *package_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930306{
307 if (data == NULL || package_header_info == NULL ||
308 package_version_str == NULL) {
309 return PLDM_ERROR_INVALID_DATA;
310 }
311
312 if (length < sizeof(struct pldm_package_header_information)) {
313 return PLDM_ERROR_INVALID_LENGTH;
314 }
315
316 struct pldm_package_header_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930317 (struct pldm_package_header_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930318
319 if (!is_string_type_valid(data_header->package_version_string_type) ||
320 (data_header->package_version_string_length == 0)) {
321 return PLDM_ERROR_INVALID_DATA;
322 }
323
324 if (length < sizeof(struct pldm_package_header_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930325 data_header->package_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930326 return PLDM_ERROR_INVALID_LENGTH;
327 }
328
329 if ((data_header->component_bitmap_bit_length %
330 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
331 return PLDM_ERROR_INVALID_DATA;
332 }
333
334 memcpy(package_header_info->uuid, data_header->uuid,
335 sizeof(data_header->uuid));
336 package_header_info->package_header_format_version =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930337 data_header->package_header_format_version;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930338 package_header_info->package_header_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930339 le16toh(data_header->package_header_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930340 memcpy(package_header_info->package_release_date_time,
341 data_header->package_release_date_time,
342 sizeof(data_header->package_release_date_time));
343 package_header_info->component_bitmap_bit_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930344 le16toh(data_header->component_bitmap_bit_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930345 package_header_info->package_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930346 data_header->package_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930347 package_header_info->package_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930348 data_header->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930349 package_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930350 data + sizeof(struct pldm_package_header_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930351 package_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930352 package_header_info->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930353
354 return PLDM_SUCCESS;
355}
356
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930357LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930358int decode_firmware_device_id_record(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930359 const uint8_t *data, size_t length,
360 uint16_t component_bitmap_bit_length,
361 struct pldm_firmware_device_id_record *fw_device_id_record,
362 struct variable_field *applicable_components,
363 struct variable_field *comp_image_set_version_str,
364 struct variable_field *record_descriptors,
365 struct variable_field *fw_device_pkg_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930366{
367 if (data == NULL || fw_device_id_record == NULL ||
368 applicable_components == NULL ||
369 comp_image_set_version_str == NULL || record_descriptors == NULL ||
370 fw_device_pkg_data == NULL) {
371 return PLDM_ERROR_INVALID_DATA;
372 }
373
374 if (length < sizeof(struct pldm_firmware_device_id_record)) {
375 return PLDM_ERROR_INVALID_LENGTH;
376 }
377
378 if ((component_bitmap_bit_length %
379 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
380 return PLDM_ERROR_INVALID_DATA;
381 }
382
383 struct pldm_firmware_device_id_record *data_record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930384 (struct pldm_firmware_device_id_record *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930385
386 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930387 data_record->comp_image_set_version_string_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930388 (data_record->comp_image_set_version_string_length == 0)) {
389 return PLDM_ERROR_INVALID_DATA;
390 }
391
392 fw_device_id_record->record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930393 le16toh(data_record->record_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930394 fw_device_id_record->descriptor_count = data_record->descriptor_count;
395 fw_device_id_record->device_update_option_flags.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930396 le32toh(data_record->device_update_option_flags.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930397 fw_device_id_record->comp_image_set_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930398 data_record->comp_image_set_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930399 fw_device_id_record->comp_image_set_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930400 data_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930401 fw_device_id_record->fw_device_pkg_data_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930402 le16toh(data_record->fw_device_pkg_data_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930403
404 if (length < fw_device_id_record->record_length) {
405 return PLDM_ERROR_INVALID_LENGTH;
406 }
407
408 uint16_t applicable_components_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930409 component_bitmap_bit_length /
410 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930411 uint16_t calc_min_record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930412 sizeof(struct pldm_firmware_device_id_record) +
413 applicable_components_length +
414 data_record->comp_image_set_version_string_length +
415 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
416 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930417
418 if (fw_device_id_record->record_length < calc_min_record_length) {
419 return PLDM_ERROR_INVALID_LENGTH;
420 }
421
422 applicable_components->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930423 data + sizeof(struct pldm_firmware_device_id_record);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930424 applicable_components->length = applicable_components_length;
425
426 comp_image_set_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930427 applicable_components->ptr + applicable_components->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930428 comp_image_set_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930429 fw_device_id_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930430
431 record_descriptors->ptr = comp_image_set_version_str->ptr +
432 comp_image_set_version_str->length;
433 record_descriptors->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930434 fw_device_id_record->record_length -
435 sizeof(struct pldm_firmware_device_id_record) -
436 applicable_components_length -
437 fw_device_id_record->comp_image_set_version_string_length -
438 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930439
440 if (fw_device_id_record->fw_device_pkg_data_length) {
441 fw_device_pkg_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930442 record_descriptors->ptr + record_descriptors->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930443 fw_device_pkg_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930444 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930445 }
446
447 return PLDM_SUCCESS;
448}
449
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930450LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930451int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
452 uint16_t *descriptor_type,
453 struct variable_field *descriptor_data)
454{
455 uint16_t descriptor_length = 0;
456
457 if (data == NULL || descriptor_type == NULL ||
458 descriptor_data == NULL) {
459 return PLDM_ERROR_INVALID_DATA;
460 }
461
462 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
463 return PLDM_ERROR_INVALID_LENGTH;
464 }
465
466 struct pldm_descriptor_tlv *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930467 (struct pldm_descriptor_tlv *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930468
469 *descriptor_type = le16toh(entry->descriptor_type);
470 descriptor_length = le16toh(entry->descriptor_length);
471 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
472 if (descriptor_length !=
473 get_descriptor_type_length(*descriptor_type)) {
474 return PLDM_ERROR_INVALID_LENGTH;
475 }
476 }
477
478 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
479 descriptor_length)) {
480 return PLDM_ERROR_INVALID_LENGTH;
481 }
482
483 descriptor_data->ptr = entry->descriptor_data;
484 descriptor_data->length = descriptor_length;
485
486 return PLDM_SUCCESS;
487}
488
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930489LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930490int decode_vendor_defined_descriptor_value(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930491 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
492 struct variable_field *descriptor_title_str,
493 struct variable_field *descriptor_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930494{
495 if (data == NULL || descriptor_title_str_type == NULL ||
496 descriptor_title_str == NULL || descriptor_data == NULL) {
497 return PLDM_ERROR_INVALID_DATA;
498 }
499
500 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
501 return PLDM_ERROR_INVALID_LENGTH;
502 }
503
504 struct pldm_vendor_defined_descriptor_title_data *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930505 (struct pldm_vendor_defined_descriptor_title_data *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930506 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930507 entry->vendor_defined_descriptor_title_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930508 (entry->vendor_defined_descriptor_title_str_len == 0)) {
509 return PLDM_ERROR_INVALID_DATA;
510 }
511
512 // Assuming atleast 1 byte of VendorDefinedDescriptorData
513 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
514 entry->vendor_defined_descriptor_title_str_len)) {
515 return PLDM_ERROR_INVALID_LENGTH;
516 }
517
518 *descriptor_title_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930519 entry->vendor_defined_descriptor_title_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930520 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
521 descriptor_title_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930522 entry->vendor_defined_descriptor_title_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930523
524 descriptor_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930525 descriptor_title_str->ptr + descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930526 descriptor_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930527 length -
528 sizeof(entry->vendor_defined_descriptor_title_str_type) -
529 sizeof(entry->vendor_defined_descriptor_title_str_len) -
530 descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930531
532 return PLDM_SUCCESS;
533}
534
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930535LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930536int decode_pldm_comp_image_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930537 const uint8_t *data, size_t length,
538 struct pldm_component_image_information *pldm_comp_image_info,
539 struct variable_field *comp_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930540{
541 if (data == NULL || pldm_comp_image_info == NULL ||
542 comp_version_str == NULL) {
543 return PLDM_ERROR_INVALID_DATA;
544 }
545
546 if (length < sizeof(struct pldm_component_image_information)) {
547 return PLDM_ERROR_INVALID_LENGTH;
548 }
549
550 struct pldm_component_image_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930551 (struct pldm_component_image_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930552
553 if (!is_string_type_valid(data_header->comp_version_string_type) ||
554 (data_header->comp_version_string_length == 0)) {
555 return PLDM_ERROR_INVALID_DATA;
556 }
557
558 if (length < sizeof(struct pldm_component_image_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930559 data_header->comp_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930560 return PLDM_ERROR_INVALID_LENGTH;
561 }
562
563 pldm_comp_image_info->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930564 le16toh(data_header->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930565 pldm_comp_image_info->comp_identifier =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930566 le16toh(data_header->comp_identifier);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930567 pldm_comp_image_info->comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930568 le32toh(data_header->comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930569 pldm_comp_image_info->comp_options.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930570 le16toh(data_header->comp_options.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930571 pldm_comp_image_info->requested_comp_activation_method.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930572 le16toh(data_header->requested_comp_activation_method.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930573 pldm_comp_image_info->comp_location_offset =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930574 le32toh(data_header->comp_location_offset);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930575 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
576 pldm_comp_image_info->comp_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930577 data_header->comp_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930578 pldm_comp_image_info->comp_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930579 data_header->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930580
581 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
582 pldm_comp_image_info->comp_comparison_stamp !=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930583 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930584 return PLDM_ERROR_INVALID_DATA;
585 }
586
587 if (pldm_comp_image_info->comp_location_offset == 0 ||
588 pldm_comp_image_info->comp_size == 0) {
589 return PLDM_ERROR_INVALID_DATA;
590 }
591
592 comp_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930593 data + sizeof(struct pldm_component_image_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930594 comp_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930595 pldm_comp_image_info->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930596
597 return PLDM_SUCCESS;
598}
599
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930600LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930601int encode_query_device_identifiers_req(uint8_t instance_id,
602 size_t payload_length,
603 struct pldm_msg *msg)
604{
605 if (msg == NULL) {
606 return PLDM_ERROR_INVALID_DATA;
607 }
608
609 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
610 return PLDM_ERROR_INVALID_LENGTH;
611 }
612
613 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
614 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
615}
616
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930617LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930618int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
619 size_t payload_length,
620 uint8_t *completion_code,
621 uint32_t *device_identifiers_len,
622 uint8_t *descriptor_count,
623 uint8_t **descriptor_data)
624{
625 if (msg == NULL || completion_code == NULL ||
626 device_identifiers_len == NULL || descriptor_count == NULL ||
627 descriptor_data == NULL) {
628 return PLDM_ERROR_INVALID_DATA;
629 }
630
631 *completion_code = msg->payload[0];
632 if (PLDM_SUCCESS != *completion_code) {
633 return PLDM_SUCCESS;
634 }
635
636 if (payload_length <
637 sizeof(struct pldm_query_device_identifiers_resp)) {
638 return PLDM_ERROR_INVALID_LENGTH;
639 }
640
641 struct pldm_query_device_identifiers_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930642 (struct pldm_query_device_identifiers_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930643 *device_identifiers_len = le32toh(response->device_identifiers_len);
644
645 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
646 return PLDM_ERROR_INVALID_LENGTH;
647 }
648
649 if (payload_length !=
650 sizeof(struct pldm_query_device_identifiers_resp) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930651 *device_identifiers_len) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930652 return PLDM_ERROR_INVALID_LENGTH;
653 }
654 *descriptor_count = response->descriptor_count;
655
656 if (*descriptor_count == 0) {
657 return PLDM_ERROR_INVALID_DATA;
658 }
659 *descriptor_data =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930660 (uint8_t *)(msg->payload +
661 sizeof(struct pldm_query_device_identifiers_resp));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930662 return PLDM_SUCCESS;
663}
664
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930665LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930666int encode_get_firmware_parameters_req(uint8_t instance_id,
667 size_t payload_length,
668 struct pldm_msg *msg)
669{
670 if (msg == NULL) {
671 return PLDM_ERROR_INVALID_DATA;
672 }
673
674 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
675 return PLDM_ERROR_INVALID_LENGTH;
676 }
677
678 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
679 PLDM_GET_FIRMWARE_PARAMETERS, msg);
680}
681
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930682LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930683int decode_get_firmware_parameters_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930684 const struct pldm_msg *msg, size_t payload_length,
685 struct pldm_get_firmware_parameters_resp *resp_data,
686 struct variable_field *active_comp_image_set_ver_str,
687 struct variable_field *pending_comp_image_set_ver_str,
688 struct variable_field *comp_parameter_table)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930689{
690 if (msg == NULL || resp_data == NULL ||
691 active_comp_image_set_ver_str == NULL ||
692 pending_comp_image_set_ver_str == NULL ||
693 comp_parameter_table == NULL || !payload_length) {
694 return PLDM_ERROR_INVALID_DATA;
695 }
696
697 resp_data->completion_code = msg->payload[0];
698 if (PLDM_SUCCESS != resp_data->completion_code) {
699 return PLDM_SUCCESS;
700 }
701
702 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
703 return PLDM_ERROR_INVALID_LENGTH;
704 }
705
706 struct pldm_get_firmware_parameters_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930707 (struct pldm_get_firmware_parameters_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930708
709 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930710 response->active_comp_image_set_ver_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930711 (response->active_comp_image_set_ver_str_len == 0)) {
712 return PLDM_ERROR_INVALID_DATA;
713 }
714
715 if (response->pending_comp_image_set_ver_str_len == 0) {
716 if (response->pending_comp_image_set_ver_str_type !=
717 PLDM_STR_TYPE_UNKNOWN) {
718 return PLDM_ERROR_INVALID_DATA;
719 }
720 } else {
721 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930722 response->pending_comp_image_set_ver_str_type)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930723 return PLDM_ERROR_INVALID_DATA;
724 }
725 }
726
727 size_t partial_response_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930728 sizeof(struct pldm_get_firmware_parameters_resp) +
729 response->active_comp_image_set_ver_str_len +
730 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930731
732 if (payload_length < partial_response_length) {
733 return PLDM_ERROR_INVALID_LENGTH;
734 }
735
736 resp_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930737 le32toh(response->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930738 resp_data->comp_count = le16toh(response->comp_count);
739 resp_data->active_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930740 response->active_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930741 resp_data->active_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930742 response->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930743 resp_data->pending_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930744 response->pending_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930745 resp_data->pending_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930746 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930747
748 active_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930749 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930750 active_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930751 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930752
753 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
754 pending_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930755 msg->payload +
756 sizeof(struct pldm_get_firmware_parameters_resp) +
757 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930758 pending_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930759 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930760 } else {
761 pending_comp_image_set_ver_str->ptr = NULL;
762 pending_comp_image_set_ver_str->length = 0;
763 }
764
765 if (payload_length > partial_response_length && resp_data->comp_count) {
766 comp_parameter_table->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930767 msg->payload +
768 sizeof(struct pldm_get_firmware_parameters_resp) +
769 resp_data->active_comp_image_set_ver_str_len +
770 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930771 comp_parameter_table->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930772 payload_length - partial_response_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930773 } else {
774 comp_parameter_table->ptr = NULL;
775 comp_parameter_table->length = 0;
776 }
777
778 return PLDM_SUCCESS;
779}
780
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930781LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930782int decode_get_firmware_parameters_resp_comp_entry(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930783 const uint8_t *data, size_t length,
784 struct pldm_component_parameter_entry *component_data,
785 struct variable_field *active_comp_ver_str,
786 struct variable_field *pending_comp_ver_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930787{
788 if (data == NULL || component_data == NULL ||
789 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
790 return PLDM_ERROR_INVALID_DATA;
791 }
792
793 if (length < sizeof(struct pldm_component_parameter_entry)) {
794 return PLDM_ERROR_INVALID_LENGTH;
795 }
796
797 struct pldm_component_parameter_entry *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930798 (struct pldm_component_parameter_entry *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930799
800 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
801 entry->active_comp_ver_str_len +
802 entry->pending_comp_ver_str_len;
803
804 if (length < entry_length) {
805 return PLDM_ERROR_INVALID_LENGTH;
806 }
807
808 component_data->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930809 le16toh(entry->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930810 component_data->comp_identifier = le16toh(entry->comp_identifier);
811 component_data->comp_classification_index =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930812 entry->comp_classification_index;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930813 component_data->active_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930814 le32toh(entry->active_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930815 component_data->active_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930816 entry->active_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930817 component_data->active_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930818 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930819 memcpy(component_data->active_comp_release_date,
820 entry->active_comp_release_date,
821 sizeof(entry->active_comp_release_date));
822 component_data->pending_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930823 le32toh(entry->pending_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930824 component_data->pending_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930825 entry->pending_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930826 component_data->pending_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930827 entry->pending_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930828 memcpy(component_data->pending_comp_release_date,
829 entry->pending_comp_release_date,
830 sizeof(entry->pending_comp_release_date));
831 component_data->comp_activation_methods.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930832 le16toh(entry->comp_activation_methods.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930833 component_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930834 le32toh(entry->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930835
836 if (entry->active_comp_ver_str_len != 0) {
837 active_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930838 data + sizeof(struct pldm_component_parameter_entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930839 active_comp_ver_str->length = entry->active_comp_ver_str_len;
840 } else {
841 active_comp_ver_str->ptr = NULL;
842 active_comp_ver_str->length = 0;
843 }
844
845 if (entry->pending_comp_ver_str_len != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930846 pending_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930847 data + sizeof(struct pldm_component_parameter_entry) +
848 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930849 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
850 } else {
851 pending_comp_ver_str->ptr = NULL;
852 pending_comp_ver_str->length = 0;
853 }
854 return PLDM_SUCCESS;
855}
856
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930857LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930858int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
859 uint16_t num_of_comp,
860 uint8_t max_outstanding_transfer_req,
861 uint16_t pkg_data_len,
862 uint8_t comp_image_set_ver_str_type,
863 uint8_t comp_image_set_ver_str_len,
864 const struct variable_field *comp_img_set_ver_str,
865 struct pldm_msg *msg, size_t payload_length)
866{
867 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
868 msg == NULL) {
869 return PLDM_ERROR_INVALID_DATA;
870 }
871
872 if (payload_length != sizeof(struct pldm_request_update_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930873 comp_img_set_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930874 return PLDM_ERROR_INVALID_LENGTH;
875 }
876
877 if ((comp_image_set_ver_str_len == 0) ||
878 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
879 return PLDM_ERROR_INVALID_DATA;
880 }
881
882 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
883 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
884 return PLDM_ERROR_INVALID_DATA;
885 }
886
887 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
888 return PLDM_ERROR_INVALID_DATA;
889 }
890
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930891 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930892 header.instance = instance_id;
893 header.msg_type = PLDM_REQUEST;
894 header.pldm_type = PLDM_FWUP;
895 header.command = PLDM_REQUEST_UPDATE;
896 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
897 if (rc) {
898 return rc;
899 }
900
901 struct pldm_request_update_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930902 (struct pldm_request_update_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930903
904 request->max_transfer_size = htole32(max_transfer_size);
905 request->num_of_comp = htole16(num_of_comp);
906 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
907 request->pkg_data_len = htole16(pkg_data_len);
908 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
909 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
910
911 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
912 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
913
914 return PLDM_SUCCESS;
915}
916
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930917LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930918int decode_request_update_resp(const struct pldm_msg *msg,
919 size_t payload_length, uint8_t *completion_code,
920 uint16_t *fd_meta_data_len,
921 uint8_t *fd_will_send_pkg_data)
922{
923 if (msg == NULL || completion_code == NULL ||
924 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
925 !payload_length) {
926 return PLDM_ERROR_INVALID_DATA;
927 }
928
929 *completion_code = msg->payload[0];
930 if (*completion_code != PLDM_SUCCESS) {
931 return PLDM_SUCCESS;
932 }
933
934 if (payload_length != sizeof(struct pldm_request_update_resp)) {
935 return PLDM_ERROR_INVALID_LENGTH;
936 }
937
938 struct pldm_request_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930939 (struct pldm_request_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930940
941 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
942 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
943
944 return PLDM_SUCCESS;
945}
946
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930947LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930948int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
949 uint16_t comp_classification,
950 uint16_t comp_identifier,
951 uint8_t comp_classification_index,
952 uint32_t comp_comparison_stamp,
953 uint8_t comp_ver_str_type,
954 uint8_t comp_ver_str_len,
955 const struct variable_field *comp_ver_str,
956 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930957{
958 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
959 return PLDM_ERROR_INVALID_DATA;
960 }
961
962 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930963 comp_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930964 return PLDM_ERROR_INVALID_LENGTH;
965 }
966
967 if ((comp_ver_str_len == 0) ||
968 (comp_ver_str_len != comp_ver_str->length)) {
969 return PLDM_ERROR_INVALID_DATA;
970 }
971
972 if (!is_transfer_flag_valid(transfer_flag)) {
973 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
974 }
975
976 if (!is_string_type_valid(comp_ver_str_type)) {
977 return PLDM_ERROR_INVALID_DATA;
978 }
979
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930980 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930981 header.instance = instance_id;
982 header.msg_type = PLDM_REQUEST;
983 header.pldm_type = PLDM_FWUP;
984 header.command = PLDM_PASS_COMPONENT_TABLE;
985 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
986 if (rc) {
987 return rc;
988 }
989
990 struct pldm_pass_component_table_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930991 (struct pldm_pass_component_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930992
993 request->transfer_flag = transfer_flag;
994 request->comp_classification = htole16(comp_classification);
995 request->comp_identifier = htole16(comp_identifier);
996 request->comp_classification_index = comp_classification_index;
997 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
998 request->comp_ver_str_type = comp_ver_str_type;
999 request->comp_ver_str_len = comp_ver_str_len;
1000
1001 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1002 comp_ver_str->ptr, comp_ver_str->length);
1003
1004 return PLDM_SUCCESS;
1005}
1006
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301007LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301008int decode_pass_component_table_resp(const struct pldm_msg *msg,
1009 const size_t payload_length,
1010 uint8_t *completion_code,
1011 uint8_t *comp_resp,
1012 uint8_t *comp_resp_code)
1013{
1014 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1015 comp_resp_code == NULL || !payload_length) {
1016 return PLDM_ERROR_INVALID_DATA;
1017 }
1018
1019 *completion_code = msg->payload[0];
1020 if (*completion_code != PLDM_SUCCESS) {
1021 return PLDM_SUCCESS;
1022 }
1023
1024 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1025 return PLDM_ERROR_INVALID_LENGTH;
1026 }
1027
1028 struct pldm_pass_component_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301029 (struct pldm_pass_component_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301030
1031 if (!is_comp_resp_valid(response->comp_resp)) {
1032 return PLDM_ERROR_INVALID_DATA;
1033 }
1034
1035 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1036 return PLDM_ERROR_INVALID_DATA;
1037 }
1038
1039 *comp_resp = response->comp_resp;
1040 *comp_resp_code = response->comp_resp_code;
1041
1042 return PLDM_SUCCESS;
1043}
1044
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301045LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301046int encode_update_component_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301047 uint8_t instance_id, uint16_t comp_classification,
1048 uint16_t comp_identifier, uint8_t comp_classification_index,
1049 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1050 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1051 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1052 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301053{
1054 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1055 return PLDM_ERROR_INVALID_DATA;
1056 }
1057
1058 if (payload_length !=
1059 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1060 return PLDM_ERROR_INVALID_LENGTH;
1061 }
1062
1063 if (!comp_image_size) {
1064 return PLDM_ERROR_INVALID_DATA;
1065 }
1066
1067 if ((comp_ver_str_len == 0) ||
1068 (comp_ver_str_len != comp_ver_str->length)) {
1069 return PLDM_ERROR_INVALID_DATA;
1070 }
1071
1072 if (!is_string_type_valid(comp_ver_str_type)) {
1073 return PLDM_ERROR_INVALID_DATA;
1074 }
1075
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301076 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301077 header.instance = instance_id;
1078 header.msg_type = PLDM_REQUEST;
1079 header.pldm_type = PLDM_FWUP;
1080 header.command = PLDM_UPDATE_COMPONENT;
1081 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1082 if (rc) {
1083 return rc;
1084 }
1085
1086 struct pldm_update_component_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301087 (struct pldm_update_component_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301088
1089 request->comp_classification = htole16(comp_classification);
1090 request->comp_identifier = htole16(comp_identifier);
1091 request->comp_classification_index = comp_classification_index;
1092 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1093 request->comp_image_size = htole32(comp_image_size);
1094 request->update_option_flags.value = htole32(update_option_flags.value);
1095 request->comp_ver_str_type = comp_ver_str_type;
1096 request->comp_ver_str_len = comp_ver_str_len;
1097
1098 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1099 comp_ver_str->ptr, comp_ver_str->length);
1100
1101 return PLDM_SUCCESS;
1102}
1103
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301104LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301105int decode_update_component_resp(const struct pldm_msg *msg,
1106 size_t payload_length,
1107 uint8_t *completion_code,
1108 uint8_t *comp_compatibility_resp,
1109 uint8_t *comp_compatibility_resp_code,
1110 bitfield32_t *update_option_flags_enabled,
1111 uint16_t *time_before_req_fw_data)
1112{
1113 if (msg == NULL || completion_code == NULL ||
1114 comp_compatibility_resp == NULL ||
1115 comp_compatibility_resp_code == NULL ||
1116 update_option_flags_enabled == NULL ||
1117 time_before_req_fw_data == NULL || !payload_length) {
1118 return PLDM_ERROR_INVALID_DATA;
1119 }
1120
1121 *completion_code = msg->payload[0];
1122 if (*completion_code != PLDM_SUCCESS) {
1123 return PLDM_SUCCESS;
1124 }
1125
1126 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1127 return PLDM_ERROR_INVALID_LENGTH;
1128 }
1129
1130 struct pldm_update_component_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301131 (struct pldm_update_component_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301132
1133 if (!is_comp_compatibility_resp_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301134 response->comp_compatibility_resp)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301135 return PLDM_ERROR_INVALID_DATA;
1136 }
1137
1138 if (!is_comp_compatibility_resp_code_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301139 response->comp_compatibility_resp_code)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301140 return PLDM_ERROR_INVALID_DATA;
1141 }
1142
1143 *comp_compatibility_resp = response->comp_compatibility_resp;
1144 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1145 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301146 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301147 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1148
1149 return PLDM_SUCCESS;
1150}
1151
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301152LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301153int decode_request_firmware_data_req(const struct pldm_msg *msg,
1154 size_t payload_length, uint32_t *offset,
1155 uint32_t *length)
1156{
1157 if (msg == NULL || offset == NULL || length == NULL) {
1158 return PLDM_ERROR_INVALID_DATA;
1159 }
1160 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1161 return PLDM_ERROR_INVALID_LENGTH;
1162 }
1163 struct pldm_request_firmware_data_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301164 (struct pldm_request_firmware_data_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301165 *offset = le32toh(request->offset);
1166 *length = le32toh(request->length);
1167
1168 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1169 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1170 }
1171
1172 return PLDM_SUCCESS;
1173}
1174
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301175LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301176int encode_request_firmware_data_resp(uint8_t instance_id,
1177 uint8_t completion_code,
1178 struct pldm_msg *msg,
1179 size_t payload_length)
1180{
1181 if (msg == NULL || !payload_length) {
1182 return PLDM_ERROR_INVALID_DATA;
1183 }
1184
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301185 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301186 header.instance = instance_id;
1187 header.msg_type = PLDM_RESPONSE;
1188 header.pldm_type = PLDM_FWUP;
1189 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1190 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1191 if (rc) {
1192 return rc;
1193 }
1194
1195 msg->payload[0] = completion_code;
1196
1197 return PLDM_SUCCESS;
1198}
1199
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301200LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301201int decode_transfer_complete_req(const struct pldm_msg *msg,
1202 size_t payload_length,
1203 uint8_t *transfer_result)
1204{
1205 if (msg == NULL || transfer_result == NULL) {
1206 return PLDM_ERROR_INVALID_DATA;
1207 }
1208
1209 if (payload_length != sizeof(*transfer_result)) {
1210 return PLDM_ERROR_INVALID_LENGTH;
1211 }
1212
1213 *transfer_result = msg->payload[0];
1214 return PLDM_SUCCESS;
1215}
1216
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301217LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301218int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1219 struct pldm_msg *msg, size_t payload_length)
1220{
1221 if (msg == NULL) {
1222 return PLDM_ERROR_INVALID_DATA;
1223 }
1224
1225 if (payload_length != sizeof(completion_code)) {
1226 return PLDM_ERROR_INVALID_LENGTH;
1227 }
1228
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301229 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301230 header.instance = instance_id;
1231 header.msg_type = PLDM_RESPONSE;
1232 header.pldm_type = PLDM_FWUP;
1233 header.command = PLDM_TRANSFER_COMPLETE;
1234 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1235 if (rc) {
1236 return rc;
1237 }
1238
1239 msg->payload[0] = completion_code;
1240
1241 return PLDM_SUCCESS;
1242}
1243
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301244LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301245int decode_verify_complete_req(const struct pldm_msg *msg,
1246 size_t payload_length, uint8_t *verify_result)
1247{
1248 if (msg == NULL || verify_result == NULL) {
1249 return PLDM_ERROR_INVALID_DATA;
1250 }
1251
1252 if (payload_length != sizeof(*verify_result)) {
1253 return PLDM_ERROR_INVALID_LENGTH;
1254 }
1255
1256 *verify_result = msg->payload[0];
1257 return PLDM_SUCCESS;
1258}
1259
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301260LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301261int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1262 struct pldm_msg *msg, size_t payload_length)
1263{
1264 if (msg == NULL) {
1265 return PLDM_ERROR_INVALID_DATA;
1266 }
1267
1268 if (payload_length != sizeof(completion_code)) {
1269 return PLDM_ERROR_INVALID_LENGTH;
1270 }
1271
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301272 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301273 header.instance = instance_id;
1274 header.msg_type = PLDM_RESPONSE;
1275 header.pldm_type = PLDM_FWUP;
1276 header.command = PLDM_VERIFY_COMPLETE;
1277 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1278 if (rc) {
1279 return rc;
1280 }
1281
1282 msg->payload[0] = completion_code;
1283
1284 return PLDM_SUCCESS;
1285}
1286
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301287LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301288int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
1289 uint8_t *apply_result,
1290 bitfield16_t *comp_activation_methods_modification)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301291{
1292 if (msg == NULL || apply_result == NULL ||
1293 comp_activation_methods_modification == NULL) {
1294 return PLDM_ERROR_INVALID_DATA;
1295 }
1296
1297 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1298 return PLDM_ERROR_INVALID_LENGTH;
1299 }
1300
1301 struct pldm_apply_complete_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301302 (struct pldm_apply_complete_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301303
1304 *apply_result = request->apply_result;
1305 comp_activation_methods_modification->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301306 le16toh(request->comp_activation_methods_modification.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301307
1308 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1309 comp_activation_methods_modification->value) {
1310 return PLDM_ERROR_INVALID_DATA;
1311 }
1312
1313 return PLDM_SUCCESS;
1314}
1315
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301316LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301317int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1318 struct pldm_msg *msg, size_t payload_length)
1319{
1320 if (msg == NULL) {
1321 return PLDM_ERROR_INVALID_DATA;
1322 }
1323
1324 if (payload_length != sizeof(completion_code)) {
1325 return PLDM_ERROR_INVALID_LENGTH;
1326 }
1327
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301328 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301329 header.instance = instance_id;
1330 header.msg_type = PLDM_RESPONSE;
1331 header.pldm_type = PLDM_FWUP;
1332 header.command = PLDM_APPLY_COMPLETE;
1333 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1334 if (rc) {
1335 return rc;
1336 }
1337
1338 msg->payload[0] = completion_code;
1339
1340 return PLDM_SUCCESS;
1341}
1342
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301343LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301344int encode_activate_firmware_req(uint8_t instance_id,
1345 bool8_t self_contained_activation_req,
1346 struct pldm_msg *msg, size_t payload_length)
1347{
1348 if (msg == NULL) {
1349 return PLDM_ERROR_INVALID_DATA;
1350 }
1351
1352 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1353 return PLDM_ERROR_INVALID_LENGTH;
1354 }
1355
1356 if (!is_self_contained_activation_req_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301357 self_contained_activation_req)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301358 return PLDM_ERROR_INVALID_DATA;
1359 }
1360
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301361 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301362 header.instance = instance_id;
1363 header.msg_type = PLDM_REQUEST;
1364 header.pldm_type = PLDM_FWUP;
1365 header.command = PLDM_ACTIVATE_FIRMWARE;
1366 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1367 if (rc) {
1368 return rc;
1369 }
1370
1371 struct pldm_activate_firmware_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301372 (struct pldm_activate_firmware_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301373
1374 request->self_contained_activation_req = self_contained_activation_req;
1375
1376 return PLDM_SUCCESS;
1377}
1378
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301379LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301380int decode_activate_firmware_resp(const struct pldm_msg *msg,
1381 size_t payload_length,
1382 uint8_t *completion_code,
1383 uint16_t *estimated_time_activation)
1384{
1385 if (msg == NULL || completion_code == NULL ||
1386 estimated_time_activation == NULL || !payload_length) {
1387 return PLDM_ERROR_INVALID_DATA;
1388 }
1389
1390 *completion_code = msg->payload[0];
1391 if (*completion_code != PLDM_SUCCESS) {
1392 return PLDM_SUCCESS;
1393 }
1394
1395 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1396 return PLDM_ERROR_INVALID_LENGTH;
1397 }
1398
1399 struct pldm_activate_firmware_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301400 (struct pldm_activate_firmware_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301401
1402 *estimated_time_activation =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301403 le16toh(response->estimated_time_activation);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301404
1405 return PLDM_SUCCESS;
1406}
1407
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301408LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301409int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1410 size_t payload_length)
1411{
1412 if (msg == NULL) {
1413 return PLDM_ERROR_INVALID_DATA;
1414 }
1415
1416 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1417 return PLDM_ERROR_INVALID_LENGTH;
1418 }
1419
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301420 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301421 header.instance = instance_id;
1422 header.msg_type = PLDM_REQUEST;
1423 header.pldm_type = PLDM_FWUP;
1424 header.command = PLDM_GET_STATUS;
1425 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1426 if (rc) {
1427 return rc;
1428 }
1429
1430 return PLDM_SUCCESS;
1431}
1432
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301433LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301434int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1435 uint8_t *completion_code, uint8_t *current_state,
1436 uint8_t *previous_state, uint8_t *aux_state,
1437 uint8_t *aux_state_status, uint8_t *progress_percent,
1438 uint8_t *reason_code,
1439 bitfield32_t *update_option_flags_enabled)
1440{
1441 if (msg == NULL || completion_code == NULL || current_state == NULL ||
1442 previous_state == NULL || aux_state == NULL ||
1443 aux_state_status == NULL || progress_percent == NULL ||
1444 reason_code == NULL || update_option_flags_enabled == NULL ||
1445 !payload_length) {
1446 return PLDM_ERROR_INVALID_DATA;
1447 }
1448
1449 *completion_code = msg->payload[0];
1450 if (*completion_code != PLDM_SUCCESS) {
1451 return PLDM_SUCCESS;
1452 }
1453
1454 if (payload_length != sizeof(struct pldm_get_status_resp)) {
1455 return PLDM_ERROR_INVALID_LENGTH;
1456 }
1457 struct pldm_get_status_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301458 (struct pldm_get_status_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301459
1460 if (!is_state_valid(response->current_state)) {
1461 return PLDM_ERROR_INVALID_DATA;
1462 }
1463 if (!is_state_valid(response->previous_state)) {
1464 return PLDM_ERROR_INVALID_DATA;
1465 }
1466 if (!is_aux_state_valid(response->aux_state)) {
1467 return PLDM_ERROR_INVALID_DATA;
1468 }
1469 if (!is_aux_state_status_valid(response->aux_state_status)) {
1470 return PLDM_ERROR_INVALID_DATA;
1471 }
1472 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1473 return PLDM_ERROR_INVALID_DATA;
1474 }
1475 if (!is_reason_code_valid(response->reason_code)) {
1476 return PLDM_ERROR_INVALID_DATA;
1477 }
1478
1479 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1480 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1481 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1482 if (response->aux_state !=
1483 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1484 return PLDM_ERROR_INVALID_DATA;
1485 }
1486 }
1487
1488 *current_state = response->current_state;
1489 *previous_state = response->previous_state;
1490 *aux_state = response->aux_state;
1491 *aux_state_status = response->aux_state_status;
1492 *progress_percent = response->progress_percent;
1493 *reason_code = response->reason_code;
1494 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301495 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301496
1497 return PLDM_SUCCESS;
1498}
1499
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301500LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301501int encode_cancel_update_component_req(uint8_t instance_id,
1502 struct pldm_msg *msg,
1503 size_t payload_length)
1504{
1505 if (msg == NULL) {
1506 return PLDM_ERROR_INVALID_DATA;
1507 }
1508
1509 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1510 return PLDM_ERROR_INVALID_LENGTH;
1511 }
1512
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301513 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301514 header.instance = instance_id;
1515 header.msg_type = PLDM_REQUEST;
1516 header.pldm_type = PLDM_FWUP;
1517 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
1518 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1519 if (rc) {
1520 return rc;
1521 }
1522
1523 return PLDM_SUCCESS;
1524}
1525
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301526LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301527int decode_cancel_update_component_resp(const struct pldm_msg *msg,
1528 size_t payload_length,
1529 uint8_t *completion_code)
1530{
1531 if (msg == NULL || completion_code == NULL) {
1532 return PLDM_ERROR_INVALID_DATA;
1533 }
1534
1535 if (payload_length != sizeof(*completion_code)) {
1536 return PLDM_ERROR_INVALID_LENGTH;
1537 }
1538
1539 *completion_code = msg->payload[0];
1540 return PLDM_SUCCESS;
1541}
1542
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301543LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301544int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
1545 size_t payload_length)
1546{
1547 if (msg == NULL) {
1548 return PLDM_ERROR_INVALID_DATA;
1549 }
1550
1551 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
1552 return PLDM_ERROR_INVALID_LENGTH;
1553 }
1554
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301555 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301556 header.instance = instance_id;
1557 header.msg_type = PLDM_REQUEST;
1558 header.pldm_type = PLDM_FWUP;
1559 header.command = PLDM_CANCEL_UPDATE;
1560 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1561 if (rc) {
1562 return rc;
1563 }
1564
1565 return PLDM_SUCCESS;
1566}
1567
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301568LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301569int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
1570 uint8_t *completion_code,
1571 bool8_t *non_functioning_component_indication,
1572 bitfield64_t *non_functioning_component_bitmap)
1573{
1574 if (msg == NULL || completion_code == NULL ||
1575 non_functioning_component_indication == NULL ||
1576 non_functioning_component_bitmap == NULL || !payload_length) {
1577 return PLDM_ERROR_INVALID_DATA;
1578 }
1579
1580 *completion_code = msg->payload[0];
1581 if (*completion_code != PLDM_SUCCESS) {
1582 return PLDM_SUCCESS;
1583 }
1584
1585 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
1586 return PLDM_ERROR_INVALID_LENGTH;
1587 }
1588 struct pldm_cancel_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301589 (struct pldm_cancel_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301590
1591 if (!is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301592 response->non_functioning_component_indication)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301593 return PLDM_ERROR_INVALID_DATA;
1594 }
1595
1596 *non_functioning_component_indication =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301597 response->non_functioning_component_indication;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301598
1599 if (*non_functioning_component_indication) {
1600 non_functioning_component_bitmap->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301601 le64toh(response->non_functioning_component_bitmap);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301602 }
1603
1604 return PLDM_SUCCESS;
1605}