blob: df58faa8bed69dd0a0076b231191639b2767e705 [file] [log] [blame]
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301#include "config.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +09302#include "firmware_update.h"
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05303#include "utils.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +09304#include <endian.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05305#include <stdbool.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09306#include <string.h>
7
8/** @brief Check whether string type value is valid
9 *
10 * @return true if string type value is valid, false if not
11 */
12static bool is_string_type_valid(uint8_t string_type)
13{
14 switch (string_type) {
15 case PLDM_STR_TYPE_UNKNOWN:
16 return false;
17 case PLDM_STR_TYPE_ASCII:
18 case PLDM_STR_TYPE_UTF_8:
19 case PLDM_STR_TYPE_UTF_16:
20 case PLDM_STR_TYPE_UTF_16LE:
21 case PLDM_STR_TYPE_UTF_16BE:
22 return true;
23 default:
24 return false;
25 }
26}
27
28/** @brief Return the length of the descriptor type described in firmware update
29 * specification
30 *
31 * @return length of the descriptor type if descriptor type is valid else
32 * return 0
33 */
34static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
35{
36 switch (descriptor_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093037 case PLDM_FWUP_PCI_VENDOR_ID:
38 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
39 case PLDM_FWUP_IANA_ENTERPRISE_ID:
40 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
41 case PLDM_FWUP_UUID:
42 return PLDM_FWUP_UUID_LENGTH;
43 case PLDM_FWUP_PNP_VENDOR_ID:
44 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
45 case PLDM_FWUP_ACPI_VENDOR_ID:
46 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
47 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
48 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
49 case PLDM_FWUP_SCSI_VENDOR_ID:
50 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
51 case PLDM_FWUP_PCI_DEVICE_ID:
52 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
53 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
54 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
55 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
56 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
57 case PLDM_FWUP_PCI_REVISION_ID:
58 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
59 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
60 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
61 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
62 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
63 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
64 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
65 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
66 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
67 case PLDM_FWUP_SCSI_PRODUCT_ID:
68 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
69 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
70 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
71 default:
72 return 0;
73 }
74}
75
76/** @brief Check whether ComponentResponse is valid
77 *
78 * @return true if ComponentResponse is valid, false if not
79 */
80static bool is_comp_resp_valid(uint8_t comp_resp)
81{
82 switch (comp_resp) {
83 case PLDM_CR_COMP_CAN_BE_UPDATED:
84 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
85 return true;
86
87 default:
88 return false;
89 }
90}
91
92/** @brief Check whether ComponentResponseCode is valid
93 *
94 * @return true if ComponentResponseCode is valid, false if not
95 */
96static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
97{
98 switch (comp_resp_code) {
99 case PLDM_CRC_COMP_CAN_BE_UPDATED:
100 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
101 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
102 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
103 case PLDM_CRC_COMP_CONFLICT:
104 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
105 case PLDM_CRC_COMP_NOT_SUPPORTED:
106 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
107 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
108 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
109 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
110 case PLDM_CRC_COMP_VER_STR_LOWER:
111 return true;
112
113 default:
114 if (comp_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930115 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930116 comp_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930117 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930118 return true;
119 }
120 return false;
121 }
122}
123
124/** @brief Check whether ComponentCompatibilityResponse is valid
125 *
126 * @return true if ComponentCompatibilityResponse is valid, false if not
127 */
128static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
129{
130 switch (comp_compatibility_resp) {
131 case PLDM_CCR_COMP_CAN_BE_UPDATED:
132 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
133 return true;
134
135 default:
136 return false;
137 }
138}
139
140/** @brief Check whether ComponentCompatibilityResponse Code is valid
141 *
142 * @return true if ComponentCompatibilityResponse Code is valid, false if not
143 */
144static bool
145is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
146{
147 switch (comp_compatibility_resp_code) {
148 case PLDM_CCRC_NO_RESPONSE_CODE:
149 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
150 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
151 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
152 case PLDM_CCRC_COMP_CONFLICT:
153 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
154 case PLDM_CCRC_COMP_NOT_SUPPORTED:
155 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
156 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
157 case PLDM_CCRC_COMP_INFO_NO_MATCH:
158 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
159 case PLDM_CCRC_COMP_VER_STR_LOWER:
160 return true;
161
162 default:
163 if (comp_compatibility_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930164 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930165 comp_compatibility_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930166 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930167 return true;
168 }
169 return false;
170 }
171}
172
173/** @brief Check whether SelfContainedActivationRequest is valid
174 *
175 * @return true if SelfContainedActivationRequest is valid, false if not
176 */
177static bool
178is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
179{
180 switch (self_contained_activation_req) {
181 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
182 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
183 return true;
184
185 default:
186 return false;
187 }
188}
189
190/** @brief Check if current or previous status in GetStatus command response is
191 * valid
192 *
193 * @param[in] state - current or previous different state machine state of
194 * the FD
195 * @return true if state is valid, false if not
196 */
197static bool is_state_valid(uint8_t state)
198{
199 switch (state) {
200 case PLDM_FD_STATE_IDLE:
201 case PLDM_FD_STATE_LEARN_COMPONENTS:
202 case PLDM_FD_STATE_READY_XFER:
203 case PLDM_FD_STATE_DOWNLOAD:
204 case PLDM_FD_STATE_VERIFY:
205 case PLDM_FD_STATE_APPLY:
206 case PLDM_FD_STATE_ACTIVATE:
207 return true;
208
209 default:
210 return false;
211 }
212}
213
214/** @brief Check if aux state in GetStatus command response is valid
215 *
216 * @param[in] aux_state - provides additional information to the UA to describe
217 * the current operation state of the FD/FDP
218 *
219 * @return true if aux state is valid, false if not
220 */
221static bool is_aux_state_valid(uint8_t aux_state)
222{
223 switch (aux_state) {
224 case PLDM_FD_OPERATION_IN_PROGRESS:
225 case PLDM_FD_OPERATION_SUCCESSFUL:
226 case PLDM_FD_OPERATION_FAILED:
227 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
228 return true;
229
230 default:
231 return false;
232 }
233}
234
235/** @brief Check if aux state status in GetStatus command response is valid
236 *
237 * @param[in] aux_state_status - aux state status
238 *
239 * @return true if aux state status is valid, false if not
240 */
241static bool is_aux_state_status_valid(uint8_t aux_state_status)
242{
243 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
244 aux_state_status == PLDM_FD_TIMEOUT ||
Andrew Jeffery67f7ed92023-04-05 14:00:00 +0930245 aux_state_status == PLDM_FD_GENERIC_ERROR ||
246 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
247 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930248 return true;
249 }
250
251 return false;
252}
253
254/** @brief Check if reason code in GetStatus command response is valid
255 *
256 * @param[in] reason_code - provides the reason for why the current state
257 * entered the IDLE state
258 *
259 * @return true if reason code is valid, false if not
260 */
261static bool is_reason_code_valid(uint8_t reason_code)
262{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930263 switch (reason_code) {
264 case PLDM_FD_INITIALIZATION:
265 case PLDM_FD_ACTIVATE_FW:
266 case PLDM_FD_CANCEL_UPDATE:
267 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
268 case PLDM_FD_TIMEOUT_READY_XFER:
269 case PLDM_FD_TIMEOUT_DOWNLOAD:
270 case PLDM_FD_TIMEOUT_VERIFY:
271 case PLDM_FD_TIMEOUT_APPLY:
272 return true;
273
274 default:
275 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
276 return true;
277 }
278 return false;
279 }
280}
281
282/** @brief Check if non functioning component indication in CancelUpdate
283 * response is valid
284 *
285 * @return true if non functioning component indication is valid, false if not
286 */
287static bool is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930288 bool8_t non_functioning_component_indication)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930289{
290 switch (non_functioning_component_indication) {
291 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
292 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
293 return true;
294
295 default:
296 return false;
297 }
298}
299
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930300LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930301int decode_pldm_package_header_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930302 const uint8_t *data, size_t length,
303 struct pldm_package_header_information *package_header_info,
304 struct variable_field *package_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930305{
306 if (data == NULL || package_header_info == NULL ||
307 package_version_str == NULL) {
308 return PLDM_ERROR_INVALID_DATA;
309 }
310
311 if (length < sizeof(struct pldm_package_header_information)) {
312 return PLDM_ERROR_INVALID_LENGTH;
313 }
314
315 struct pldm_package_header_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930316 (struct pldm_package_header_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930317
318 if (!is_string_type_valid(data_header->package_version_string_type) ||
319 (data_header->package_version_string_length == 0)) {
320 return PLDM_ERROR_INVALID_DATA;
321 }
322
323 if (length < sizeof(struct pldm_package_header_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930324 data_header->package_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930325 return PLDM_ERROR_INVALID_LENGTH;
326 }
327
328 if ((data_header->component_bitmap_bit_length %
329 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
330 return PLDM_ERROR_INVALID_DATA;
331 }
332
333 memcpy(package_header_info->uuid, data_header->uuid,
334 sizeof(data_header->uuid));
335 package_header_info->package_header_format_version =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930336 data_header->package_header_format_version;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930337 package_header_info->package_header_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930338 le16toh(data_header->package_header_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930339 memcpy(package_header_info->package_release_date_time,
340 data_header->package_release_date_time,
341 sizeof(data_header->package_release_date_time));
342 package_header_info->component_bitmap_bit_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930343 le16toh(data_header->component_bitmap_bit_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930344 package_header_info->package_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930345 data_header->package_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930346 package_header_info->package_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930347 data_header->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930348 package_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930349 data + sizeof(struct pldm_package_header_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930350 package_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930351 package_header_info->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930352
353 return PLDM_SUCCESS;
354}
355
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930356LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930357int decode_firmware_device_id_record(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930358 const uint8_t *data, size_t length,
359 uint16_t component_bitmap_bit_length,
360 struct pldm_firmware_device_id_record *fw_device_id_record,
361 struct variable_field *applicable_components,
362 struct variable_field *comp_image_set_version_str,
363 struct variable_field *record_descriptors,
364 struct variable_field *fw_device_pkg_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930365{
366 if (data == NULL || fw_device_id_record == NULL ||
367 applicable_components == NULL ||
368 comp_image_set_version_str == NULL || record_descriptors == NULL ||
369 fw_device_pkg_data == NULL) {
370 return PLDM_ERROR_INVALID_DATA;
371 }
372
373 if (length < sizeof(struct pldm_firmware_device_id_record)) {
374 return PLDM_ERROR_INVALID_LENGTH;
375 }
376
377 if ((component_bitmap_bit_length %
378 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
379 return PLDM_ERROR_INVALID_DATA;
380 }
381
382 struct pldm_firmware_device_id_record *data_record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930383 (struct pldm_firmware_device_id_record *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930384
385 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930386 data_record->comp_image_set_version_string_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930387 (data_record->comp_image_set_version_string_length == 0)) {
388 return PLDM_ERROR_INVALID_DATA;
389 }
390
391 fw_device_id_record->record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930392 le16toh(data_record->record_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930393 fw_device_id_record->descriptor_count = data_record->descriptor_count;
394 fw_device_id_record->device_update_option_flags.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930395 le32toh(data_record->device_update_option_flags.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930396 fw_device_id_record->comp_image_set_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930397 data_record->comp_image_set_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930398 fw_device_id_record->comp_image_set_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930399 data_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930400 fw_device_id_record->fw_device_pkg_data_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930401 le16toh(data_record->fw_device_pkg_data_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930402
403 if (length < fw_device_id_record->record_length) {
404 return PLDM_ERROR_INVALID_LENGTH;
405 }
406
407 uint16_t applicable_components_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930408 component_bitmap_bit_length /
409 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930410 uint16_t calc_min_record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930411 sizeof(struct pldm_firmware_device_id_record) +
412 applicable_components_length +
413 data_record->comp_image_set_version_string_length +
414 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
415 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930416
417 if (fw_device_id_record->record_length < calc_min_record_length) {
418 return PLDM_ERROR_INVALID_LENGTH;
419 }
420
421 applicable_components->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930422 data + sizeof(struct pldm_firmware_device_id_record);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930423 applicable_components->length = applicable_components_length;
424
425 comp_image_set_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930426 applicable_components->ptr + applicable_components->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930427 comp_image_set_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930428 fw_device_id_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930429
430 record_descriptors->ptr = comp_image_set_version_str->ptr +
431 comp_image_set_version_str->length;
432 record_descriptors->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930433 fw_device_id_record->record_length -
434 sizeof(struct pldm_firmware_device_id_record) -
435 applicable_components_length -
436 fw_device_id_record->comp_image_set_version_string_length -
437 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930438
439 if (fw_device_id_record->fw_device_pkg_data_length) {
440 fw_device_pkg_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930441 record_descriptors->ptr + record_descriptors->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930442 fw_device_pkg_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930443 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930444 }
445
446 return PLDM_SUCCESS;
447}
448
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930449LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930450int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
451 uint16_t *descriptor_type,
452 struct variable_field *descriptor_data)
453{
454 uint16_t descriptor_length = 0;
455
456 if (data == NULL || descriptor_type == NULL ||
457 descriptor_data == NULL) {
458 return PLDM_ERROR_INVALID_DATA;
459 }
460
461 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
462 return PLDM_ERROR_INVALID_LENGTH;
463 }
464
465 struct pldm_descriptor_tlv *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930466 (struct pldm_descriptor_tlv *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930467
468 *descriptor_type = le16toh(entry->descriptor_type);
469 descriptor_length = le16toh(entry->descriptor_length);
470 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
471 if (descriptor_length !=
472 get_descriptor_type_length(*descriptor_type)) {
473 return PLDM_ERROR_INVALID_LENGTH;
474 }
475 }
476
477 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
478 descriptor_length)) {
479 return PLDM_ERROR_INVALID_LENGTH;
480 }
481
482 descriptor_data->ptr = entry->descriptor_data;
483 descriptor_data->length = descriptor_length;
484
485 return PLDM_SUCCESS;
486}
487
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930488LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930489int decode_vendor_defined_descriptor_value(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930490 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
491 struct variable_field *descriptor_title_str,
492 struct variable_field *descriptor_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930493{
494 if (data == NULL || descriptor_title_str_type == NULL ||
495 descriptor_title_str == NULL || descriptor_data == NULL) {
496 return PLDM_ERROR_INVALID_DATA;
497 }
498
499 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
500 return PLDM_ERROR_INVALID_LENGTH;
501 }
502
503 struct pldm_vendor_defined_descriptor_title_data *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930504 (struct pldm_vendor_defined_descriptor_title_data *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930505 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930506 entry->vendor_defined_descriptor_title_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930507 (entry->vendor_defined_descriptor_title_str_len == 0)) {
508 return PLDM_ERROR_INVALID_DATA;
509 }
510
511 // Assuming atleast 1 byte of VendorDefinedDescriptorData
512 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
513 entry->vendor_defined_descriptor_title_str_len)) {
514 return PLDM_ERROR_INVALID_LENGTH;
515 }
516
517 *descriptor_title_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930518 entry->vendor_defined_descriptor_title_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930519 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
520 descriptor_title_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930521 entry->vendor_defined_descriptor_title_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930522
523 descriptor_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930524 descriptor_title_str->ptr + descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930525 descriptor_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930526 length -
527 sizeof(entry->vendor_defined_descriptor_title_str_type) -
528 sizeof(entry->vendor_defined_descriptor_title_str_len) -
529 descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930530
531 return PLDM_SUCCESS;
532}
533
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930534LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930535int decode_pldm_comp_image_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930536 const uint8_t *data, size_t length,
537 struct pldm_component_image_information *pldm_comp_image_info,
538 struct variable_field *comp_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930539{
540 if (data == NULL || pldm_comp_image_info == NULL ||
541 comp_version_str == NULL) {
542 return PLDM_ERROR_INVALID_DATA;
543 }
544
545 if (length < sizeof(struct pldm_component_image_information)) {
546 return PLDM_ERROR_INVALID_LENGTH;
547 }
548
549 struct pldm_component_image_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930550 (struct pldm_component_image_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930551
552 if (!is_string_type_valid(data_header->comp_version_string_type) ||
553 (data_header->comp_version_string_length == 0)) {
554 return PLDM_ERROR_INVALID_DATA;
555 }
556
557 if (length < sizeof(struct pldm_component_image_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930558 data_header->comp_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930559 return PLDM_ERROR_INVALID_LENGTH;
560 }
561
562 pldm_comp_image_info->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930563 le16toh(data_header->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930564 pldm_comp_image_info->comp_identifier =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930565 le16toh(data_header->comp_identifier);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930566 pldm_comp_image_info->comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930567 le32toh(data_header->comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930568 pldm_comp_image_info->comp_options.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930569 le16toh(data_header->comp_options.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930570 pldm_comp_image_info->requested_comp_activation_method.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930571 le16toh(data_header->requested_comp_activation_method.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930572 pldm_comp_image_info->comp_location_offset =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930573 le32toh(data_header->comp_location_offset);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930574 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
575 pldm_comp_image_info->comp_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930576 data_header->comp_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930577 pldm_comp_image_info->comp_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930578 data_header->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930579
580 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
581 pldm_comp_image_info->comp_comparison_stamp !=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930582 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930583 return PLDM_ERROR_INVALID_DATA;
584 }
585
586 if (pldm_comp_image_info->comp_location_offset == 0 ||
587 pldm_comp_image_info->comp_size == 0) {
588 return PLDM_ERROR_INVALID_DATA;
589 }
590
591 comp_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930592 data + sizeof(struct pldm_component_image_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930593 comp_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930594 pldm_comp_image_info->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930595
596 return PLDM_SUCCESS;
597}
598
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930599LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930600int encode_query_device_identifiers_req(uint8_t instance_id,
601 size_t payload_length,
602 struct pldm_msg *msg)
603{
604 if (msg == NULL) {
605 return PLDM_ERROR_INVALID_DATA;
606 }
607
608 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
609 return PLDM_ERROR_INVALID_LENGTH;
610 }
611
612 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
613 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
614}
615
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930616LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930617int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
618 size_t payload_length,
619 uint8_t *completion_code,
620 uint32_t *device_identifiers_len,
621 uint8_t *descriptor_count,
622 uint8_t **descriptor_data)
623{
624 if (msg == NULL || completion_code == NULL ||
625 device_identifiers_len == NULL || descriptor_count == NULL ||
626 descriptor_data == NULL) {
627 return PLDM_ERROR_INVALID_DATA;
628 }
629
630 *completion_code = msg->payload[0];
631 if (PLDM_SUCCESS != *completion_code) {
632 return PLDM_SUCCESS;
633 }
634
635 if (payload_length <
636 sizeof(struct pldm_query_device_identifiers_resp)) {
637 return PLDM_ERROR_INVALID_LENGTH;
638 }
639
640 struct pldm_query_device_identifiers_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930641 (struct pldm_query_device_identifiers_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930642 *device_identifiers_len = le32toh(response->device_identifiers_len);
643
644 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
645 return PLDM_ERROR_INVALID_LENGTH;
646 }
647
648 if (payload_length !=
649 sizeof(struct pldm_query_device_identifiers_resp) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930650 *device_identifiers_len) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930651 return PLDM_ERROR_INVALID_LENGTH;
652 }
653 *descriptor_count = response->descriptor_count;
654
655 if (*descriptor_count == 0) {
656 return PLDM_ERROR_INVALID_DATA;
657 }
658 *descriptor_data =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930659 (uint8_t *)(msg->payload +
660 sizeof(struct pldm_query_device_identifiers_resp));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930661 return PLDM_SUCCESS;
662}
663
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930664LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930665int encode_get_firmware_parameters_req(uint8_t instance_id,
666 size_t payload_length,
667 struct pldm_msg *msg)
668{
669 if (msg == NULL) {
670 return PLDM_ERROR_INVALID_DATA;
671 }
672
673 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
674 return PLDM_ERROR_INVALID_LENGTH;
675 }
676
677 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
678 PLDM_GET_FIRMWARE_PARAMETERS, msg);
679}
680
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930681LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930682int decode_get_firmware_parameters_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930683 const struct pldm_msg *msg, size_t payload_length,
684 struct pldm_get_firmware_parameters_resp *resp_data,
685 struct variable_field *active_comp_image_set_ver_str,
686 struct variable_field *pending_comp_image_set_ver_str,
687 struct variable_field *comp_parameter_table)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930688{
689 if (msg == NULL || resp_data == NULL ||
690 active_comp_image_set_ver_str == NULL ||
691 pending_comp_image_set_ver_str == NULL ||
692 comp_parameter_table == NULL || !payload_length) {
693 return PLDM_ERROR_INVALID_DATA;
694 }
695
696 resp_data->completion_code = msg->payload[0];
697 if (PLDM_SUCCESS != resp_data->completion_code) {
698 return PLDM_SUCCESS;
699 }
700
701 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
702 return PLDM_ERROR_INVALID_LENGTH;
703 }
704
705 struct pldm_get_firmware_parameters_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930706 (struct pldm_get_firmware_parameters_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930707
708 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930709 response->active_comp_image_set_ver_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930710 (response->active_comp_image_set_ver_str_len == 0)) {
711 return PLDM_ERROR_INVALID_DATA;
712 }
713
714 if (response->pending_comp_image_set_ver_str_len == 0) {
715 if (response->pending_comp_image_set_ver_str_type !=
716 PLDM_STR_TYPE_UNKNOWN) {
717 return PLDM_ERROR_INVALID_DATA;
718 }
719 } else {
720 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930721 response->pending_comp_image_set_ver_str_type)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930722 return PLDM_ERROR_INVALID_DATA;
723 }
724 }
725
726 size_t partial_response_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930727 sizeof(struct pldm_get_firmware_parameters_resp) +
728 response->active_comp_image_set_ver_str_len +
729 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930730
731 if (payload_length < partial_response_length) {
732 return PLDM_ERROR_INVALID_LENGTH;
733 }
734
735 resp_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930736 le32toh(response->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930737 resp_data->comp_count = le16toh(response->comp_count);
738 resp_data->active_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930739 response->active_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930740 resp_data->active_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930741 response->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930742 resp_data->pending_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930743 response->pending_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930744 resp_data->pending_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930745 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930746
747 active_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930748 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930749 active_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930750 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930751
752 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
753 pending_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930754 msg->payload +
755 sizeof(struct pldm_get_firmware_parameters_resp) +
756 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930757 pending_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930758 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930759 } else {
760 pending_comp_image_set_ver_str->ptr = NULL;
761 pending_comp_image_set_ver_str->length = 0;
762 }
763
764 if (payload_length > partial_response_length && resp_data->comp_count) {
765 comp_parameter_table->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930766 msg->payload +
767 sizeof(struct pldm_get_firmware_parameters_resp) +
768 resp_data->active_comp_image_set_ver_str_len +
769 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930770 comp_parameter_table->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930771 payload_length - partial_response_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930772 } else {
773 comp_parameter_table->ptr = NULL;
774 comp_parameter_table->length = 0;
775 }
776
777 return PLDM_SUCCESS;
778}
779
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930780LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930781int decode_get_firmware_parameters_resp_comp_entry(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930782 const uint8_t *data, size_t length,
783 struct pldm_component_parameter_entry *component_data,
784 struct variable_field *active_comp_ver_str,
785 struct variable_field *pending_comp_ver_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930786{
787 if (data == NULL || component_data == NULL ||
788 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
789 return PLDM_ERROR_INVALID_DATA;
790 }
791
792 if (length < sizeof(struct pldm_component_parameter_entry)) {
793 return PLDM_ERROR_INVALID_LENGTH;
794 }
795
796 struct pldm_component_parameter_entry *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930797 (struct pldm_component_parameter_entry *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930798
799 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
800 entry->active_comp_ver_str_len +
801 entry->pending_comp_ver_str_len;
802
803 if (length < entry_length) {
804 return PLDM_ERROR_INVALID_LENGTH;
805 }
806
807 component_data->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930808 le16toh(entry->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930809 component_data->comp_identifier = le16toh(entry->comp_identifier);
810 component_data->comp_classification_index =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930811 entry->comp_classification_index;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930812 component_data->active_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930813 le32toh(entry->active_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930814 component_data->active_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930815 entry->active_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930816 component_data->active_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930817 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930818 memcpy(component_data->active_comp_release_date,
819 entry->active_comp_release_date,
820 sizeof(entry->active_comp_release_date));
821 component_data->pending_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930822 le32toh(entry->pending_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930823 component_data->pending_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930824 entry->pending_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930825 component_data->pending_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930826 entry->pending_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930827 memcpy(component_data->pending_comp_release_date,
828 entry->pending_comp_release_date,
829 sizeof(entry->pending_comp_release_date));
830 component_data->comp_activation_methods.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930831 le16toh(entry->comp_activation_methods.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930832 component_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930833 le32toh(entry->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930834
835 if (entry->active_comp_ver_str_len != 0) {
836 active_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930837 data + sizeof(struct pldm_component_parameter_entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930838 active_comp_ver_str->length = entry->active_comp_ver_str_len;
839 } else {
840 active_comp_ver_str->ptr = NULL;
841 active_comp_ver_str->length = 0;
842 }
843
844 if (entry->pending_comp_ver_str_len != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930845 pending_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930846 data + sizeof(struct pldm_component_parameter_entry) +
847 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930848 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
849 } else {
850 pending_comp_ver_str->ptr = NULL;
851 pending_comp_ver_str->length = 0;
852 }
853 return PLDM_SUCCESS;
854}
855
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930856LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930857int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
858 uint16_t num_of_comp,
859 uint8_t max_outstanding_transfer_req,
860 uint16_t pkg_data_len,
861 uint8_t comp_image_set_ver_str_type,
862 uint8_t comp_image_set_ver_str_len,
863 const struct variable_field *comp_img_set_ver_str,
864 struct pldm_msg *msg, size_t payload_length)
865{
866 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
867 msg == NULL) {
868 return PLDM_ERROR_INVALID_DATA;
869 }
870
871 if (payload_length != sizeof(struct pldm_request_update_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930872 comp_img_set_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930873 return PLDM_ERROR_INVALID_LENGTH;
874 }
875
876 if ((comp_image_set_ver_str_len == 0) ||
877 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
878 return PLDM_ERROR_INVALID_DATA;
879 }
880
881 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
882 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
883 return PLDM_ERROR_INVALID_DATA;
884 }
885
886 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
887 return PLDM_ERROR_INVALID_DATA;
888 }
889
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930890 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930891 header.instance = instance_id;
892 header.msg_type = PLDM_REQUEST;
893 header.pldm_type = PLDM_FWUP;
894 header.command = PLDM_REQUEST_UPDATE;
895 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
896 if (rc) {
897 return rc;
898 }
899
900 struct pldm_request_update_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930901 (struct pldm_request_update_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930902
903 request->max_transfer_size = htole32(max_transfer_size);
904 request->num_of_comp = htole16(num_of_comp);
905 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
906 request->pkg_data_len = htole16(pkg_data_len);
907 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
908 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
909
910 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
911 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
912
913 return PLDM_SUCCESS;
914}
915
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930916LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930917int decode_request_update_resp(const struct pldm_msg *msg,
918 size_t payload_length, uint8_t *completion_code,
919 uint16_t *fd_meta_data_len,
920 uint8_t *fd_will_send_pkg_data)
921{
922 if (msg == NULL || completion_code == NULL ||
923 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
924 !payload_length) {
925 return PLDM_ERROR_INVALID_DATA;
926 }
927
928 *completion_code = msg->payload[0];
929 if (*completion_code != PLDM_SUCCESS) {
930 return PLDM_SUCCESS;
931 }
932
933 if (payload_length != sizeof(struct pldm_request_update_resp)) {
934 return PLDM_ERROR_INVALID_LENGTH;
935 }
936
937 struct pldm_request_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930938 (struct pldm_request_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930939
940 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
941 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
942
943 return PLDM_SUCCESS;
944}
945
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930946LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930947int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
948 uint16_t comp_classification,
949 uint16_t comp_identifier,
950 uint8_t comp_classification_index,
951 uint32_t comp_comparison_stamp,
952 uint8_t comp_ver_str_type,
953 uint8_t comp_ver_str_len,
954 const struct variable_field *comp_ver_str,
955 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930956{
957 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
958 return PLDM_ERROR_INVALID_DATA;
959 }
960
961 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930962 comp_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930963 return PLDM_ERROR_INVALID_LENGTH;
964 }
965
966 if ((comp_ver_str_len == 0) ||
967 (comp_ver_str_len != comp_ver_str->length)) {
968 return PLDM_ERROR_INVALID_DATA;
969 }
970
971 if (!is_transfer_flag_valid(transfer_flag)) {
972 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
973 }
974
975 if (!is_string_type_valid(comp_ver_str_type)) {
976 return PLDM_ERROR_INVALID_DATA;
977 }
978
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930979 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930980 header.instance = instance_id;
981 header.msg_type = PLDM_REQUEST;
982 header.pldm_type = PLDM_FWUP;
983 header.command = PLDM_PASS_COMPONENT_TABLE;
984 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
985 if (rc) {
986 return rc;
987 }
988
989 struct pldm_pass_component_table_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930990 (struct pldm_pass_component_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930991
992 request->transfer_flag = transfer_flag;
993 request->comp_classification = htole16(comp_classification);
994 request->comp_identifier = htole16(comp_identifier);
995 request->comp_classification_index = comp_classification_index;
996 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
997 request->comp_ver_str_type = comp_ver_str_type;
998 request->comp_ver_str_len = comp_ver_str_len;
999
1000 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1001 comp_ver_str->ptr, comp_ver_str->length);
1002
1003 return PLDM_SUCCESS;
1004}
1005
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301006LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301007int decode_pass_component_table_resp(const struct pldm_msg *msg,
1008 const size_t payload_length,
1009 uint8_t *completion_code,
1010 uint8_t *comp_resp,
1011 uint8_t *comp_resp_code)
1012{
1013 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1014 comp_resp_code == NULL || !payload_length) {
1015 return PLDM_ERROR_INVALID_DATA;
1016 }
1017
1018 *completion_code = msg->payload[0];
1019 if (*completion_code != PLDM_SUCCESS) {
1020 return PLDM_SUCCESS;
1021 }
1022
1023 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1024 return PLDM_ERROR_INVALID_LENGTH;
1025 }
1026
1027 struct pldm_pass_component_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301028 (struct pldm_pass_component_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301029
1030 if (!is_comp_resp_valid(response->comp_resp)) {
1031 return PLDM_ERROR_INVALID_DATA;
1032 }
1033
1034 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1035 return PLDM_ERROR_INVALID_DATA;
1036 }
1037
1038 *comp_resp = response->comp_resp;
1039 *comp_resp_code = response->comp_resp_code;
1040
1041 return PLDM_SUCCESS;
1042}
1043
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301044LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301045int encode_update_component_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301046 uint8_t instance_id, uint16_t comp_classification,
1047 uint16_t comp_identifier, uint8_t comp_classification_index,
1048 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1049 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1050 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1051 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301052{
1053 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1054 return PLDM_ERROR_INVALID_DATA;
1055 }
1056
1057 if (payload_length !=
1058 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1059 return PLDM_ERROR_INVALID_LENGTH;
1060 }
1061
1062 if (!comp_image_size) {
1063 return PLDM_ERROR_INVALID_DATA;
1064 }
1065
1066 if ((comp_ver_str_len == 0) ||
1067 (comp_ver_str_len != comp_ver_str->length)) {
1068 return PLDM_ERROR_INVALID_DATA;
1069 }
1070
1071 if (!is_string_type_valid(comp_ver_str_type)) {
1072 return PLDM_ERROR_INVALID_DATA;
1073 }
1074
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301075 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301076 header.instance = instance_id;
1077 header.msg_type = PLDM_REQUEST;
1078 header.pldm_type = PLDM_FWUP;
1079 header.command = PLDM_UPDATE_COMPONENT;
1080 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1081 if (rc) {
1082 return rc;
1083 }
1084
1085 struct pldm_update_component_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301086 (struct pldm_update_component_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301087
1088 request->comp_classification = htole16(comp_classification);
1089 request->comp_identifier = htole16(comp_identifier);
1090 request->comp_classification_index = comp_classification_index;
1091 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1092 request->comp_image_size = htole32(comp_image_size);
1093 request->update_option_flags.value = htole32(update_option_flags.value);
1094 request->comp_ver_str_type = comp_ver_str_type;
1095 request->comp_ver_str_len = comp_ver_str_len;
1096
1097 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1098 comp_ver_str->ptr, comp_ver_str->length);
1099
1100 return PLDM_SUCCESS;
1101}
1102
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301103LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301104int decode_update_component_resp(const struct pldm_msg *msg,
1105 size_t payload_length,
1106 uint8_t *completion_code,
1107 uint8_t *comp_compatibility_resp,
1108 uint8_t *comp_compatibility_resp_code,
1109 bitfield32_t *update_option_flags_enabled,
1110 uint16_t *time_before_req_fw_data)
1111{
1112 if (msg == NULL || completion_code == NULL ||
1113 comp_compatibility_resp == NULL ||
1114 comp_compatibility_resp_code == NULL ||
1115 update_option_flags_enabled == NULL ||
1116 time_before_req_fw_data == NULL || !payload_length) {
1117 return PLDM_ERROR_INVALID_DATA;
1118 }
1119
1120 *completion_code = msg->payload[0];
1121 if (*completion_code != PLDM_SUCCESS) {
1122 return PLDM_SUCCESS;
1123 }
1124
1125 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1126 return PLDM_ERROR_INVALID_LENGTH;
1127 }
1128
1129 struct pldm_update_component_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301130 (struct pldm_update_component_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301131
1132 if (!is_comp_compatibility_resp_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301133 response->comp_compatibility_resp)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301134 return PLDM_ERROR_INVALID_DATA;
1135 }
1136
1137 if (!is_comp_compatibility_resp_code_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301138 response->comp_compatibility_resp_code)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301139 return PLDM_ERROR_INVALID_DATA;
1140 }
1141
1142 *comp_compatibility_resp = response->comp_compatibility_resp;
1143 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1144 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301145 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301146 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1147
1148 return PLDM_SUCCESS;
1149}
1150
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301151LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301152int decode_request_firmware_data_req(const struct pldm_msg *msg,
1153 size_t payload_length, uint32_t *offset,
1154 uint32_t *length)
1155{
1156 if (msg == NULL || offset == NULL || length == NULL) {
1157 return PLDM_ERROR_INVALID_DATA;
1158 }
1159 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1160 return PLDM_ERROR_INVALID_LENGTH;
1161 }
1162 struct pldm_request_firmware_data_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301163 (struct pldm_request_firmware_data_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301164 *offset = le32toh(request->offset);
1165 *length = le32toh(request->length);
1166
1167 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1168 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1169 }
1170
1171 return PLDM_SUCCESS;
1172}
1173
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301174LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301175int encode_request_firmware_data_resp(uint8_t instance_id,
1176 uint8_t completion_code,
1177 struct pldm_msg *msg,
1178 size_t payload_length)
1179{
1180 if (msg == NULL || !payload_length) {
1181 return PLDM_ERROR_INVALID_DATA;
1182 }
1183
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301184 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301185 header.instance = instance_id;
1186 header.msg_type = PLDM_RESPONSE;
1187 header.pldm_type = PLDM_FWUP;
1188 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1189 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1190 if (rc) {
1191 return rc;
1192 }
1193
1194 msg->payload[0] = completion_code;
1195
1196 return PLDM_SUCCESS;
1197}
1198
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301199LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301200int decode_transfer_complete_req(const struct pldm_msg *msg,
1201 size_t payload_length,
1202 uint8_t *transfer_result)
1203{
1204 if (msg == NULL || transfer_result == NULL) {
1205 return PLDM_ERROR_INVALID_DATA;
1206 }
1207
1208 if (payload_length != sizeof(*transfer_result)) {
1209 return PLDM_ERROR_INVALID_LENGTH;
1210 }
1211
1212 *transfer_result = msg->payload[0];
1213 return PLDM_SUCCESS;
1214}
1215
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301216LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301217int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1218 struct pldm_msg *msg, size_t payload_length)
1219{
1220 if (msg == NULL) {
1221 return PLDM_ERROR_INVALID_DATA;
1222 }
1223
1224 if (payload_length != sizeof(completion_code)) {
1225 return PLDM_ERROR_INVALID_LENGTH;
1226 }
1227
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301228 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301229 header.instance = instance_id;
1230 header.msg_type = PLDM_RESPONSE;
1231 header.pldm_type = PLDM_FWUP;
1232 header.command = PLDM_TRANSFER_COMPLETE;
1233 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1234 if (rc) {
1235 return rc;
1236 }
1237
1238 msg->payload[0] = completion_code;
1239
1240 return PLDM_SUCCESS;
1241}
1242
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301243LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301244int decode_verify_complete_req(const struct pldm_msg *msg,
1245 size_t payload_length, uint8_t *verify_result)
1246{
1247 if (msg == NULL || verify_result == NULL) {
1248 return PLDM_ERROR_INVALID_DATA;
1249 }
1250
1251 if (payload_length != sizeof(*verify_result)) {
1252 return PLDM_ERROR_INVALID_LENGTH;
1253 }
1254
1255 *verify_result = msg->payload[0];
1256 return PLDM_SUCCESS;
1257}
1258
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301259LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301260int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1261 struct pldm_msg *msg, size_t payload_length)
1262{
1263 if (msg == NULL) {
1264 return PLDM_ERROR_INVALID_DATA;
1265 }
1266
1267 if (payload_length != sizeof(completion_code)) {
1268 return PLDM_ERROR_INVALID_LENGTH;
1269 }
1270
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301271 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301272 header.instance = instance_id;
1273 header.msg_type = PLDM_RESPONSE;
1274 header.pldm_type = PLDM_FWUP;
1275 header.command = PLDM_VERIFY_COMPLETE;
1276 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1277 if (rc) {
1278 return rc;
1279 }
1280
1281 msg->payload[0] = completion_code;
1282
1283 return PLDM_SUCCESS;
1284}
1285
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301286LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301287int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
1288 uint8_t *apply_result,
1289 bitfield16_t *comp_activation_methods_modification)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301290{
1291 if (msg == NULL || apply_result == NULL ||
1292 comp_activation_methods_modification == NULL) {
1293 return PLDM_ERROR_INVALID_DATA;
1294 }
1295
1296 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1297 return PLDM_ERROR_INVALID_LENGTH;
1298 }
1299
1300 struct pldm_apply_complete_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301301 (struct pldm_apply_complete_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301302
1303 *apply_result = request->apply_result;
1304 comp_activation_methods_modification->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301305 le16toh(request->comp_activation_methods_modification.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301306
1307 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1308 comp_activation_methods_modification->value) {
1309 return PLDM_ERROR_INVALID_DATA;
1310 }
1311
1312 return PLDM_SUCCESS;
1313}
1314
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301315LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301316int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1317 struct pldm_msg *msg, size_t payload_length)
1318{
1319 if (msg == NULL) {
1320 return PLDM_ERROR_INVALID_DATA;
1321 }
1322
1323 if (payload_length != sizeof(completion_code)) {
1324 return PLDM_ERROR_INVALID_LENGTH;
1325 }
1326
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301327 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301328 header.instance = instance_id;
1329 header.msg_type = PLDM_RESPONSE;
1330 header.pldm_type = PLDM_FWUP;
1331 header.command = PLDM_APPLY_COMPLETE;
1332 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1333 if (rc) {
1334 return rc;
1335 }
1336
1337 msg->payload[0] = completion_code;
1338
1339 return PLDM_SUCCESS;
1340}
1341
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301342LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301343int encode_activate_firmware_req(uint8_t instance_id,
1344 bool8_t self_contained_activation_req,
1345 struct pldm_msg *msg, size_t payload_length)
1346{
1347 if (msg == NULL) {
1348 return PLDM_ERROR_INVALID_DATA;
1349 }
1350
1351 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1352 return PLDM_ERROR_INVALID_LENGTH;
1353 }
1354
1355 if (!is_self_contained_activation_req_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301356 self_contained_activation_req)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301357 return PLDM_ERROR_INVALID_DATA;
1358 }
1359
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301360 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301361 header.instance = instance_id;
1362 header.msg_type = PLDM_REQUEST;
1363 header.pldm_type = PLDM_FWUP;
1364 header.command = PLDM_ACTIVATE_FIRMWARE;
1365 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1366 if (rc) {
1367 return rc;
1368 }
1369
1370 struct pldm_activate_firmware_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301371 (struct pldm_activate_firmware_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301372
1373 request->self_contained_activation_req = self_contained_activation_req;
1374
1375 return PLDM_SUCCESS;
1376}
1377
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301378LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301379int decode_activate_firmware_resp(const struct pldm_msg *msg,
1380 size_t payload_length,
1381 uint8_t *completion_code,
1382 uint16_t *estimated_time_activation)
1383{
1384 if (msg == NULL || completion_code == NULL ||
1385 estimated_time_activation == NULL || !payload_length) {
1386 return PLDM_ERROR_INVALID_DATA;
1387 }
1388
1389 *completion_code = msg->payload[0];
1390 if (*completion_code != PLDM_SUCCESS) {
1391 return PLDM_SUCCESS;
1392 }
1393
1394 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1395 return PLDM_ERROR_INVALID_LENGTH;
1396 }
1397
1398 struct pldm_activate_firmware_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301399 (struct pldm_activate_firmware_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301400
1401 *estimated_time_activation =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301402 le16toh(response->estimated_time_activation);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301403
1404 return PLDM_SUCCESS;
1405}
1406
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301407LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301408int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1409 size_t payload_length)
1410{
1411 if (msg == NULL) {
1412 return PLDM_ERROR_INVALID_DATA;
1413 }
1414
1415 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1416 return PLDM_ERROR_INVALID_LENGTH;
1417 }
1418
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301419 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301420 header.instance = instance_id;
1421 header.msg_type = PLDM_REQUEST;
1422 header.pldm_type = PLDM_FWUP;
1423 header.command = PLDM_GET_STATUS;
1424 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1425 if (rc) {
1426 return rc;
1427 }
1428
1429 return PLDM_SUCCESS;
1430}
1431
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301432LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301433int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1434 uint8_t *completion_code, uint8_t *current_state,
1435 uint8_t *previous_state, uint8_t *aux_state,
1436 uint8_t *aux_state_status, uint8_t *progress_percent,
1437 uint8_t *reason_code,
1438 bitfield32_t *update_option_flags_enabled)
1439{
1440 if (msg == NULL || completion_code == NULL || current_state == NULL ||
1441 previous_state == NULL || aux_state == NULL ||
1442 aux_state_status == NULL || progress_percent == NULL ||
1443 reason_code == NULL || update_option_flags_enabled == NULL ||
1444 !payload_length) {
1445 return PLDM_ERROR_INVALID_DATA;
1446 }
1447
1448 *completion_code = msg->payload[0];
1449 if (*completion_code != PLDM_SUCCESS) {
1450 return PLDM_SUCCESS;
1451 }
1452
1453 if (payload_length != sizeof(struct pldm_get_status_resp)) {
1454 return PLDM_ERROR_INVALID_LENGTH;
1455 }
1456 struct pldm_get_status_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301457 (struct pldm_get_status_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301458
1459 if (!is_state_valid(response->current_state)) {
1460 return PLDM_ERROR_INVALID_DATA;
1461 }
1462 if (!is_state_valid(response->previous_state)) {
1463 return PLDM_ERROR_INVALID_DATA;
1464 }
1465 if (!is_aux_state_valid(response->aux_state)) {
1466 return PLDM_ERROR_INVALID_DATA;
1467 }
1468 if (!is_aux_state_status_valid(response->aux_state_status)) {
1469 return PLDM_ERROR_INVALID_DATA;
1470 }
1471 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1472 return PLDM_ERROR_INVALID_DATA;
1473 }
1474 if (!is_reason_code_valid(response->reason_code)) {
1475 return PLDM_ERROR_INVALID_DATA;
1476 }
1477
1478 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1479 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1480 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1481 if (response->aux_state !=
1482 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1483 return PLDM_ERROR_INVALID_DATA;
1484 }
1485 }
1486
1487 *current_state = response->current_state;
1488 *previous_state = response->previous_state;
1489 *aux_state = response->aux_state;
1490 *aux_state_status = response->aux_state_status;
1491 *progress_percent = response->progress_percent;
1492 *reason_code = response->reason_code;
1493 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301494 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301495
1496 return PLDM_SUCCESS;
1497}
1498
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301499LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301500int encode_cancel_update_component_req(uint8_t instance_id,
1501 struct pldm_msg *msg,
1502 size_t payload_length)
1503{
1504 if (msg == NULL) {
1505 return PLDM_ERROR_INVALID_DATA;
1506 }
1507
1508 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1509 return PLDM_ERROR_INVALID_LENGTH;
1510 }
1511
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301512 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301513 header.instance = instance_id;
1514 header.msg_type = PLDM_REQUEST;
1515 header.pldm_type = PLDM_FWUP;
1516 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
1517 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1518 if (rc) {
1519 return rc;
1520 }
1521
1522 return PLDM_SUCCESS;
1523}
1524
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301525LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301526int decode_cancel_update_component_resp(const struct pldm_msg *msg,
1527 size_t payload_length,
1528 uint8_t *completion_code)
1529{
1530 if (msg == NULL || completion_code == NULL) {
1531 return PLDM_ERROR_INVALID_DATA;
1532 }
1533
1534 if (payload_length != sizeof(*completion_code)) {
1535 return PLDM_ERROR_INVALID_LENGTH;
1536 }
1537
1538 *completion_code = msg->payload[0];
1539 return PLDM_SUCCESS;
1540}
1541
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301542LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301543int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
1544 size_t payload_length)
1545{
1546 if (msg == NULL) {
1547 return PLDM_ERROR_INVALID_DATA;
1548 }
1549
1550 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
1551 return PLDM_ERROR_INVALID_LENGTH;
1552 }
1553
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301554 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301555 header.instance = instance_id;
1556 header.msg_type = PLDM_REQUEST;
1557 header.pldm_type = PLDM_FWUP;
1558 header.command = PLDM_CANCEL_UPDATE;
1559 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1560 if (rc) {
1561 return rc;
1562 }
1563
1564 return PLDM_SUCCESS;
1565}
1566
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301567LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301568int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
1569 uint8_t *completion_code,
1570 bool8_t *non_functioning_component_indication,
1571 bitfield64_t *non_functioning_component_bitmap)
1572{
1573 if (msg == NULL || completion_code == NULL ||
1574 non_functioning_component_indication == NULL ||
1575 non_functioning_component_bitmap == NULL || !payload_length) {
1576 return PLDM_ERROR_INVALID_DATA;
1577 }
1578
1579 *completion_code = msg->payload[0];
1580 if (*completion_code != PLDM_SUCCESS) {
1581 return PLDM_SUCCESS;
1582 }
1583
1584 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
1585 return PLDM_ERROR_INVALID_LENGTH;
1586 }
1587 struct pldm_cancel_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301588 (struct pldm_cancel_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301589
1590 if (!is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301591 response->non_functioning_component_indication)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301592 return PLDM_ERROR_INVALID_DATA;
1593 }
1594
1595 *non_functioning_component_indication =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301596 response->non_functioning_component_indication;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301597
1598 if (*non_functioning_component_indication) {
1599 non_functioning_component_bitmap->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301600 le64toh(response->non_functioning_component_bitmap);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301601 }
1602
1603 return PLDM_SUCCESS;
1604}