blob: 3cab7d0f0720c0e4fff5e009af74df9e3a62d3ec [file] [log] [blame]
Andrew Jeffery9c766792022-08-10 23:12:49 +09301#include "firmware_update.h"
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05302#include "utils.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +09303#include <endian.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05304#include <stdbool.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09305#include <string.h>
6
7/** @brief Check whether string type value is valid
8 *
9 * @return true if string type value is valid, false if not
10 */
11static bool is_string_type_valid(uint8_t string_type)
12{
13 switch (string_type) {
14 case PLDM_STR_TYPE_UNKNOWN:
15 return false;
16 case PLDM_STR_TYPE_ASCII:
17 case PLDM_STR_TYPE_UTF_8:
18 case PLDM_STR_TYPE_UTF_16:
19 case PLDM_STR_TYPE_UTF_16LE:
20 case PLDM_STR_TYPE_UTF_16BE:
21 return true;
22 default:
23 return false;
24 }
25}
26
27/** @brief Return the length of the descriptor type described in firmware update
28 * specification
29 *
30 * @return length of the descriptor type if descriptor type is valid else
31 * return 0
32 */
33static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
34{
35 switch (descriptor_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093036 case PLDM_FWUP_PCI_VENDOR_ID:
37 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
38 case PLDM_FWUP_IANA_ENTERPRISE_ID:
39 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
40 case PLDM_FWUP_UUID:
41 return PLDM_FWUP_UUID_LENGTH;
42 case PLDM_FWUP_PNP_VENDOR_ID:
43 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
44 case PLDM_FWUP_ACPI_VENDOR_ID:
45 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
46 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
47 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
48 case PLDM_FWUP_SCSI_VENDOR_ID:
49 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
50 case PLDM_FWUP_PCI_DEVICE_ID:
51 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
52 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
53 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
54 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
55 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
56 case PLDM_FWUP_PCI_REVISION_ID:
57 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
58 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
59 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
60 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
61 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
62 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
63 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
64 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
65 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
66 case PLDM_FWUP_SCSI_PRODUCT_ID:
67 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
68 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
69 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
70 default:
71 return 0;
72 }
73}
74
75/** @brief Check whether ComponentResponse is valid
76 *
77 * @return true if ComponentResponse is valid, false if not
78 */
79static bool is_comp_resp_valid(uint8_t comp_resp)
80{
81 switch (comp_resp) {
82 case PLDM_CR_COMP_CAN_BE_UPDATED:
83 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
84 return true;
85
86 default:
87 return false;
88 }
89}
90
91/** @brief Check whether ComponentResponseCode is valid
92 *
93 * @return true if ComponentResponseCode is valid, false if not
94 */
95static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
96{
97 switch (comp_resp_code) {
98 case PLDM_CRC_COMP_CAN_BE_UPDATED:
99 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
100 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
101 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
102 case PLDM_CRC_COMP_CONFLICT:
103 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
104 case PLDM_CRC_COMP_NOT_SUPPORTED:
105 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
106 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
107 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
108 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
109 case PLDM_CRC_COMP_VER_STR_LOWER:
110 return true;
111
112 default:
113 if (comp_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930114 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930115 comp_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930116 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930117 return true;
118 }
119 return false;
120 }
121}
122
123/** @brief Check whether ComponentCompatibilityResponse is valid
124 *
125 * @return true if ComponentCompatibilityResponse is valid, false if not
126 */
127static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
128{
129 switch (comp_compatibility_resp) {
130 case PLDM_CCR_COMP_CAN_BE_UPDATED:
131 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
132 return true;
133
134 default:
135 return false;
136 }
137}
138
139/** @brief Check whether ComponentCompatibilityResponse Code is valid
140 *
141 * @return true if ComponentCompatibilityResponse Code is valid, false if not
142 */
143static bool
144is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
145{
146 switch (comp_compatibility_resp_code) {
147 case PLDM_CCRC_NO_RESPONSE_CODE:
148 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
149 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
150 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
151 case PLDM_CCRC_COMP_CONFLICT:
152 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
153 case PLDM_CCRC_COMP_NOT_SUPPORTED:
154 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
155 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
156 case PLDM_CCRC_COMP_INFO_NO_MATCH:
157 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
158 case PLDM_CCRC_COMP_VER_STR_LOWER:
159 return true;
160
161 default:
162 if (comp_compatibility_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930163 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930164 comp_compatibility_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930165 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930166 return true;
167 }
168 return false;
169 }
170}
171
172/** @brief Check whether SelfContainedActivationRequest is valid
173 *
174 * @return true if SelfContainedActivationRequest is valid, false if not
175 */
176static bool
177is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
178{
179 switch (self_contained_activation_req) {
180 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
181 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
182 return true;
183
184 default:
185 return false;
186 }
187}
188
189/** @brief Check if current or previous status in GetStatus command response is
190 * valid
191 *
192 * @param[in] state - current or previous different state machine state of
193 * the FD
194 * @return true if state is valid, false if not
195 */
196static bool is_state_valid(uint8_t state)
197{
198 switch (state) {
199 case PLDM_FD_STATE_IDLE:
200 case PLDM_FD_STATE_LEARN_COMPONENTS:
201 case PLDM_FD_STATE_READY_XFER:
202 case PLDM_FD_STATE_DOWNLOAD:
203 case PLDM_FD_STATE_VERIFY:
204 case PLDM_FD_STATE_APPLY:
205 case PLDM_FD_STATE_ACTIVATE:
206 return true;
207
208 default:
209 return false;
210 }
211}
212
213/** @brief Check if aux state in GetStatus command response is valid
214 *
215 * @param[in] aux_state - provides additional information to the UA to describe
216 * the current operation state of the FD/FDP
217 *
218 * @return true if aux state is valid, false if not
219 */
220static bool is_aux_state_valid(uint8_t aux_state)
221{
222 switch (aux_state) {
223 case PLDM_FD_OPERATION_IN_PROGRESS:
224 case PLDM_FD_OPERATION_SUCCESSFUL:
225 case PLDM_FD_OPERATION_FAILED:
226 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
227 return true;
228
229 default:
230 return false;
231 }
232}
233
234/** @brief Check if aux state status in GetStatus command response is valid
235 *
236 * @param[in] aux_state_status - aux state status
237 *
238 * @return true if aux state status is valid, false if not
239 */
240static bool is_aux_state_status_valid(uint8_t aux_state_status)
241{
242 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
243 aux_state_status == PLDM_FD_TIMEOUT ||
Andrew Jeffery67f7ed92023-04-05 14:00:00 +0930244 aux_state_status == PLDM_FD_GENERIC_ERROR ||
245 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
246 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930247 return true;
248 }
249
250 return false;
251}
252
253/** @brief Check if reason code in GetStatus command response is valid
254 *
255 * @param[in] reason_code - provides the reason for why the current state
256 * entered the IDLE state
257 *
258 * @return true if reason code is valid, false if not
259 */
260static bool is_reason_code_valid(uint8_t reason_code)
261{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930262 switch (reason_code) {
263 case PLDM_FD_INITIALIZATION:
264 case PLDM_FD_ACTIVATE_FW:
265 case PLDM_FD_CANCEL_UPDATE:
266 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
267 case PLDM_FD_TIMEOUT_READY_XFER:
268 case PLDM_FD_TIMEOUT_DOWNLOAD:
269 case PLDM_FD_TIMEOUT_VERIFY:
270 case PLDM_FD_TIMEOUT_APPLY:
271 return true;
272
273 default:
274 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
275 return true;
276 }
277 return false;
278 }
279}
280
281/** @brief Check if non functioning component indication in CancelUpdate
282 * response is valid
283 *
284 * @return true if non functioning component indication is valid, false if not
285 */
286static bool is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930287 bool8_t non_functioning_component_indication)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930288{
289 switch (non_functioning_component_indication) {
290 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
291 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
292 return true;
293
294 default:
295 return false;
296 }
297}
298
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930299LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930300int decode_pldm_package_header_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930301 const uint8_t *data, size_t length,
302 struct pldm_package_header_information *package_header_info,
303 struct variable_field *package_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930304{
305 if (data == NULL || package_header_info == NULL ||
306 package_version_str == NULL) {
307 return PLDM_ERROR_INVALID_DATA;
308 }
309
310 if (length < sizeof(struct pldm_package_header_information)) {
311 return PLDM_ERROR_INVALID_LENGTH;
312 }
313
314 struct pldm_package_header_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930315 (struct pldm_package_header_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930316
317 if (!is_string_type_valid(data_header->package_version_string_type) ||
318 (data_header->package_version_string_length == 0)) {
319 return PLDM_ERROR_INVALID_DATA;
320 }
321
322 if (length < sizeof(struct pldm_package_header_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930323 data_header->package_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930324 return PLDM_ERROR_INVALID_LENGTH;
325 }
326
327 if ((data_header->component_bitmap_bit_length %
328 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
329 return PLDM_ERROR_INVALID_DATA;
330 }
331
332 memcpy(package_header_info->uuid, data_header->uuid,
333 sizeof(data_header->uuid));
334 package_header_info->package_header_format_version =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930335 data_header->package_header_format_version;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930336 package_header_info->package_header_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930337 le16toh(data_header->package_header_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930338 memcpy(package_header_info->package_release_date_time,
339 data_header->package_release_date_time,
340 sizeof(data_header->package_release_date_time));
341 package_header_info->component_bitmap_bit_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930342 le16toh(data_header->component_bitmap_bit_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930343 package_header_info->package_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930344 data_header->package_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930345 package_header_info->package_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930346 data_header->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930347 package_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930348 data + sizeof(struct pldm_package_header_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930349 package_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930350 package_header_info->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930351
352 return PLDM_SUCCESS;
353}
354
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930355LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930356int decode_firmware_device_id_record(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930357 const uint8_t *data, size_t length,
358 uint16_t component_bitmap_bit_length,
359 struct pldm_firmware_device_id_record *fw_device_id_record,
360 struct variable_field *applicable_components,
361 struct variable_field *comp_image_set_version_str,
362 struct variable_field *record_descriptors,
363 struct variable_field *fw_device_pkg_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930364{
365 if (data == NULL || fw_device_id_record == NULL ||
366 applicable_components == NULL ||
367 comp_image_set_version_str == NULL || record_descriptors == NULL ||
368 fw_device_pkg_data == NULL) {
369 return PLDM_ERROR_INVALID_DATA;
370 }
371
372 if (length < sizeof(struct pldm_firmware_device_id_record)) {
373 return PLDM_ERROR_INVALID_LENGTH;
374 }
375
376 if ((component_bitmap_bit_length %
377 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
378 return PLDM_ERROR_INVALID_DATA;
379 }
380
381 struct pldm_firmware_device_id_record *data_record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930382 (struct pldm_firmware_device_id_record *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930383
384 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930385 data_record->comp_image_set_version_string_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930386 (data_record->comp_image_set_version_string_length == 0)) {
387 return PLDM_ERROR_INVALID_DATA;
388 }
389
390 fw_device_id_record->record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930391 le16toh(data_record->record_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930392 fw_device_id_record->descriptor_count = data_record->descriptor_count;
393 fw_device_id_record->device_update_option_flags.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930394 le32toh(data_record->device_update_option_flags.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930395 fw_device_id_record->comp_image_set_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930396 data_record->comp_image_set_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930397 fw_device_id_record->comp_image_set_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930398 data_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930399 fw_device_id_record->fw_device_pkg_data_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930400 le16toh(data_record->fw_device_pkg_data_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930401
402 if (length < fw_device_id_record->record_length) {
403 return PLDM_ERROR_INVALID_LENGTH;
404 }
405
406 uint16_t applicable_components_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930407 component_bitmap_bit_length /
408 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930409 uint16_t calc_min_record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930410 sizeof(struct pldm_firmware_device_id_record) +
411 applicable_components_length +
412 data_record->comp_image_set_version_string_length +
413 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
414 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930415
416 if (fw_device_id_record->record_length < calc_min_record_length) {
417 return PLDM_ERROR_INVALID_LENGTH;
418 }
419
420 applicable_components->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930421 data + sizeof(struct pldm_firmware_device_id_record);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930422 applicable_components->length = applicable_components_length;
423
424 comp_image_set_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930425 applicable_components->ptr + applicable_components->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930426 comp_image_set_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930427 fw_device_id_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930428
429 record_descriptors->ptr = comp_image_set_version_str->ptr +
430 comp_image_set_version_str->length;
431 record_descriptors->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930432 fw_device_id_record->record_length -
433 sizeof(struct pldm_firmware_device_id_record) -
434 applicable_components_length -
435 fw_device_id_record->comp_image_set_version_string_length -
436 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930437
438 if (fw_device_id_record->fw_device_pkg_data_length) {
439 fw_device_pkg_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930440 record_descriptors->ptr + record_descriptors->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930441 fw_device_pkg_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930442 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930443 }
444
445 return PLDM_SUCCESS;
446}
447
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930448LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930449int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
450 uint16_t *descriptor_type,
451 struct variable_field *descriptor_data)
452{
453 uint16_t descriptor_length = 0;
454
455 if (data == NULL || descriptor_type == NULL ||
456 descriptor_data == NULL) {
457 return PLDM_ERROR_INVALID_DATA;
458 }
459
460 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
461 return PLDM_ERROR_INVALID_LENGTH;
462 }
463
464 struct pldm_descriptor_tlv *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930465 (struct pldm_descriptor_tlv *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930466
467 *descriptor_type = le16toh(entry->descriptor_type);
468 descriptor_length = le16toh(entry->descriptor_length);
469 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
470 if (descriptor_length !=
471 get_descriptor_type_length(*descriptor_type)) {
472 return PLDM_ERROR_INVALID_LENGTH;
473 }
474 }
475
476 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
477 descriptor_length)) {
478 return PLDM_ERROR_INVALID_LENGTH;
479 }
480
481 descriptor_data->ptr = entry->descriptor_data;
482 descriptor_data->length = descriptor_length;
483
484 return PLDM_SUCCESS;
485}
486
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930487LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930488int decode_vendor_defined_descriptor_value(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930489 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
490 struct variable_field *descriptor_title_str,
491 struct variable_field *descriptor_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930492{
493 if (data == NULL || descriptor_title_str_type == NULL ||
494 descriptor_title_str == NULL || descriptor_data == NULL) {
495 return PLDM_ERROR_INVALID_DATA;
496 }
497
498 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
499 return PLDM_ERROR_INVALID_LENGTH;
500 }
501
502 struct pldm_vendor_defined_descriptor_title_data *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930503 (struct pldm_vendor_defined_descriptor_title_data *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930504 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930505 entry->vendor_defined_descriptor_title_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930506 (entry->vendor_defined_descriptor_title_str_len == 0)) {
507 return PLDM_ERROR_INVALID_DATA;
508 }
509
510 // Assuming atleast 1 byte of VendorDefinedDescriptorData
511 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
512 entry->vendor_defined_descriptor_title_str_len)) {
513 return PLDM_ERROR_INVALID_LENGTH;
514 }
515
516 *descriptor_title_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930517 entry->vendor_defined_descriptor_title_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930518 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
519 descriptor_title_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930520 entry->vendor_defined_descriptor_title_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930521
522 descriptor_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930523 descriptor_title_str->ptr + descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930524 descriptor_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930525 length -
526 sizeof(entry->vendor_defined_descriptor_title_str_type) -
527 sizeof(entry->vendor_defined_descriptor_title_str_len) -
528 descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930529
530 return PLDM_SUCCESS;
531}
532
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930533LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930534int decode_pldm_comp_image_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930535 const uint8_t *data, size_t length,
536 struct pldm_component_image_information *pldm_comp_image_info,
537 struct variable_field *comp_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930538{
539 if (data == NULL || pldm_comp_image_info == NULL ||
540 comp_version_str == NULL) {
541 return PLDM_ERROR_INVALID_DATA;
542 }
543
544 if (length < sizeof(struct pldm_component_image_information)) {
545 return PLDM_ERROR_INVALID_LENGTH;
546 }
547
548 struct pldm_component_image_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930549 (struct pldm_component_image_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930550
551 if (!is_string_type_valid(data_header->comp_version_string_type) ||
552 (data_header->comp_version_string_length == 0)) {
553 return PLDM_ERROR_INVALID_DATA;
554 }
555
556 if (length < sizeof(struct pldm_component_image_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930557 data_header->comp_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930558 return PLDM_ERROR_INVALID_LENGTH;
559 }
560
561 pldm_comp_image_info->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930562 le16toh(data_header->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930563 pldm_comp_image_info->comp_identifier =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930564 le16toh(data_header->comp_identifier);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930565 pldm_comp_image_info->comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930566 le32toh(data_header->comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930567 pldm_comp_image_info->comp_options.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930568 le16toh(data_header->comp_options.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930569 pldm_comp_image_info->requested_comp_activation_method.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930570 le16toh(data_header->requested_comp_activation_method.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930571 pldm_comp_image_info->comp_location_offset =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930572 le32toh(data_header->comp_location_offset);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930573 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
574 pldm_comp_image_info->comp_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930575 data_header->comp_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930576 pldm_comp_image_info->comp_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930577 data_header->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930578
579 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
580 pldm_comp_image_info->comp_comparison_stamp !=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930581 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930582 return PLDM_ERROR_INVALID_DATA;
583 }
584
585 if (pldm_comp_image_info->comp_location_offset == 0 ||
586 pldm_comp_image_info->comp_size == 0) {
587 return PLDM_ERROR_INVALID_DATA;
588 }
589
590 comp_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930591 data + sizeof(struct pldm_component_image_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930592 comp_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930593 pldm_comp_image_info->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930594
595 return PLDM_SUCCESS;
596}
597
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930598LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930599int encode_query_device_identifiers_req(uint8_t instance_id,
600 size_t payload_length,
601 struct pldm_msg *msg)
602{
603 if (msg == NULL) {
604 return PLDM_ERROR_INVALID_DATA;
605 }
606
607 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
608 return PLDM_ERROR_INVALID_LENGTH;
609 }
610
611 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
612 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
613}
614
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930615LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930616int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
617 size_t payload_length,
618 uint8_t *completion_code,
619 uint32_t *device_identifiers_len,
620 uint8_t *descriptor_count,
621 uint8_t **descriptor_data)
622{
623 if (msg == NULL || completion_code == NULL ||
624 device_identifiers_len == NULL || descriptor_count == NULL ||
625 descriptor_data == NULL) {
626 return PLDM_ERROR_INVALID_DATA;
627 }
628
629 *completion_code = msg->payload[0];
630 if (PLDM_SUCCESS != *completion_code) {
631 return PLDM_SUCCESS;
632 }
633
634 if (payload_length <
635 sizeof(struct pldm_query_device_identifiers_resp)) {
636 return PLDM_ERROR_INVALID_LENGTH;
637 }
638
639 struct pldm_query_device_identifiers_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930640 (struct pldm_query_device_identifiers_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930641 *device_identifiers_len = le32toh(response->device_identifiers_len);
642
643 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
644 return PLDM_ERROR_INVALID_LENGTH;
645 }
646
647 if (payload_length !=
648 sizeof(struct pldm_query_device_identifiers_resp) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930649 *device_identifiers_len) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930650 return PLDM_ERROR_INVALID_LENGTH;
651 }
652 *descriptor_count = response->descriptor_count;
653
654 if (*descriptor_count == 0) {
655 return PLDM_ERROR_INVALID_DATA;
656 }
657 *descriptor_data =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930658 (uint8_t *)(msg->payload +
659 sizeof(struct pldm_query_device_identifiers_resp));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930660 return PLDM_SUCCESS;
661}
662
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930663LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930664int encode_get_firmware_parameters_req(uint8_t instance_id,
665 size_t payload_length,
666 struct pldm_msg *msg)
667{
668 if (msg == NULL) {
669 return PLDM_ERROR_INVALID_DATA;
670 }
671
672 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
673 return PLDM_ERROR_INVALID_LENGTH;
674 }
675
676 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
677 PLDM_GET_FIRMWARE_PARAMETERS, msg);
678}
679
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930680LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930681int decode_get_firmware_parameters_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930682 const struct pldm_msg *msg, size_t payload_length,
683 struct pldm_get_firmware_parameters_resp *resp_data,
684 struct variable_field *active_comp_image_set_ver_str,
685 struct variable_field *pending_comp_image_set_ver_str,
686 struct variable_field *comp_parameter_table)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930687{
688 if (msg == NULL || resp_data == NULL ||
689 active_comp_image_set_ver_str == NULL ||
690 pending_comp_image_set_ver_str == NULL ||
691 comp_parameter_table == NULL || !payload_length) {
692 return PLDM_ERROR_INVALID_DATA;
693 }
694
695 resp_data->completion_code = msg->payload[0];
696 if (PLDM_SUCCESS != resp_data->completion_code) {
697 return PLDM_SUCCESS;
698 }
699
700 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
701 return PLDM_ERROR_INVALID_LENGTH;
702 }
703
704 struct pldm_get_firmware_parameters_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930705 (struct pldm_get_firmware_parameters_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930706
707 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930708 response->active_comp_image_set_ver_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930709 (response->active_comp_image_set_ver_str_len == 0)) {
710 return PLDM_ERROR_INVALID_DATA;
711 }
712
713 if (response->pending_comp_image_set_ver_str_len == 0) {
714 if (response->pending_comp_image_set_ver_str_type !=
715 PLDM_STR_TYPE_UNKNOWN) {
716 return PLDM_ERROR_INVALID_DATA;
717 }
718 } else {
719 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930720 response->pending_comp_image_set_ver_str_type)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930721 return PLDM_ERROR_INVALID_DATA;
722 }
723 }
724
725 size_t partial_response_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930726 sizeof(struct pldm_get_firmware_parameters_resp) +
727 response->active_comp_image_set_ver_str_len +
728 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930729
730 if (payload_length < partial_response_length) {
731 return PLDM_ERROR_INVALID_LENGTH;
732 }
733
734 resp_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930735 le32toh(response->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930736 resp_data->comp_count = le16toh(response->comp_count);
737 resp_data->active_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930738 response->active_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930739 resp_data->active_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930740 response->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930741 resp_data->pending_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930742 response->pending_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930743 resp_data->pending_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930744 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930745
746 active_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930747 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930748 active_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930749 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930750
751 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
752 pending_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930753 msg->payload +
754 sizeof(struct pldm_get_firmware_parameters_resp) +
755 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930756 pending_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930757 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930758 } else {
759 pending_comp_image_set_ver_str->ptr = NULL;
760 pending_comp_image_set_ver_str->length = 0;
761 }
762
763 if (payload_length > partial_response_length && resp_data->comp_count) {
764 comp_parameter_table->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930765 msg->payload +
766 sizeof(struct pldm_get_firmware_parameters_resp) +
767 resp_data->active_comp_image_set_ver_str_len +
768 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930769 comp_parameter_table->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930770 payload_length - partial_response_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930771 } else {
772 comp_parameter_table->ptr = NULL;
773 comp_parameter_table->length = 0;
774 }
775
776 return PLDM_SUCCESS;
777}
778
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930779LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930780int decode_get_firmware_parameters_resp_comp_entry(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930781 const uint8_t *data, size_t length,
782 struct pldm_component_parameter_entry *component_data,
783 struct variable_field *active_comp_ver_str,
784 struct variable_field *pending_comp_ver_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930785{
786 if (data == NULL || component_data == NULL ||
787 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
788 return PLDM_ERROR_INVALID_DATA;
789 }
790
791 if (length < sizeof(struct pldm_component_parameter_entry)) {
792 return PLDM_ERROR_INVALID_LENGTH;
793 }
794
795 struct pldm_component_parameter_entry *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930796 (struct pldm_component_parameter_entry *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930797
798 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
799 entry->active_comp_ver_str_len +
800 entry->pending_comp_ver_str_len;
801
802 if (length < entry_length) {
803 return PLDM_ERROR_INVALID_LENGTH;
804 }
805
806 component_data->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930807 le16toh(entry->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930808 component_data->comp_identifier = le16toh(entry->comp_identifier);
809 component_data->comp_classification_index =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930810 entry->comp_classification_index;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930811 component_data->active_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930812 le32toh(entry->active_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930813 component_data->active_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930814 entry->active_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930815 component_data->active_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930816 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930817 memcpy(component_data->active_comp_release_date,
818 entry->active_comp_release_date,
819 sizeof(entry->active_comp_release_date));
820 component_data->pending_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930821 le32toh(entry->pending_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930822 component_data->pending_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930823 entry->pending_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930824 component_data->pending_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930825 entry->pending_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930826 memcpy(component_data->pending_comp_release_date,
827 entry->pending_comp_release_date,
828 sizeof(entry->pending_comp_release_date));
829 component_data->comp_activation_methods.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930830 le16toh(entry->comp_activation_methods.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930831 component_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930832 le32toh(entry->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930833
834 if (entry->active_comp_ver_str_len != 0) {
835 active_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930836 data + sizeof(struct pldm_component_parameter_entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930837 active_comp_ver_str->length = entry->active_comp_ver_str_len;
838 } else {
839 active_comp_ver_str->ptr = NULL;
840 active_comp_ver_str->length = 0;
841 }
842
843 if (entry->pending_comp_ver_str_len != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930844 pending_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930845 data + sizeof(struct pldm_component_parameter_entry) +
846 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930847 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
848 } else {
849 pending_comp_ver_str->ptr = NULL;
850 pending_comp_ver_str->length = 0;
851 }
852 return PLDM_SUCCESS;
853}
854
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930855LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930856int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
857 uint16_t num_of_comp,
858 uint8_t max_outstanding_transfer_req,
859 uint16_t pkg_data_len,
860 uint8_t comp_image_set_ver_str_type,
861 uint8_t comp_image_set_ver_str_len,
862 const struct variable_field *comp_img_set_ver_str,
863 struct pldm_msg *msg, size_t payload_length)
864{
865 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
866 msg == NULL) {
867 return PLDM_ERROR_INVALID_DATA;
868 }
869
870 if (payload_length != sizeof(struct pldm_request_update_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930871 comp_img_set_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930872 return PLDM_ERROR_INVALID_LENGTH;
873 }
874
875 if ((comp_image_set_ver_str_len == 0) ||
876 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
877 return PLDM_ERROR_INVALID_DATA;
878 }
879
880 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
881 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
882 return PLDM_ERROR_INVALID_DATA;
883 }
884
885 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
886 return PLDM_ERROR_INVALID_DATA;
887 }
888
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930889 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930890 header.instance = instance_id;
891 header.msg_type = PLDM_REQUEST;
892 header.pldm_type = PLDM_FWUP;
893 header.command = PLDM_REQUEST_UPDATE;
894 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
895 if (rc) {
896 return rc;
897 }
898
899 struct pldm_request_update_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930900 (struct pldm_request_update_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930901
902 request->max_transfer_size = htole32(max_transfer_size);
903 request->num_of_comp = htole16(num_of_comp);
904 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
905 request->pkg_data_len = htole16(pkg_data_len);
906 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
907 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
908
909 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
910 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
911
912 return PLDM_SUCCESS;
913}
914
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930915LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930916int decode_request_update_resp(const struct pldm_msg *msg,
917 size_t payload_length, uint8_t *completion_code,
918 uint16_t *fd_meta_data_len,
919 uint8_t *fd_will_send_pkg_data)
920{
921 if (msg == NULL || completion_code == NULL ||
922 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
923 !payload_length) {
924 return PLDM_ERROR_INVALID_DATA;
925 }
926
927 *completion_code = msg->payload[0];
928 if (*completion_code != PLDM_SUCCESS) {
929 return PLDM_SUCCESS;
930 }
931
932 if (payload_length != sizeof(struct pldm_request_update_resp)) {
933 return PLDM_ERROR_INVALID_LENGTH;
934 }
935
936 struct pldm_request_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930937 (struct pldm_request_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930938
939 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
940 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
941
942 return PLDM_SUCCESS;
943}
944
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930945LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930946int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
947 uint16_t comp_classification,
948 uint16_t comp_identifier,
949 uint8_t comp_classification_index,
950 uint32_t comp_comparison_stamp,
951 uint8_t comp_ver_str_type,
952 uint8_t comp_ver_str_len,
953 const struct variable_field *comp_ver_str,
954 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930955{
956 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
957 return PLDM_ERROR_INVALID_DATA;
958 }
959
960 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930961 comp_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930962 return PLDM_ERROR_INVALID_LENGTH;
963 }
964
965 if ((comp_ver_str_len == 0) ||
966 (comp_ver_str_len != comp_ver_str->length)) {
967 return PLDM_ERROR_INVALID_DATA;
968 }
969
970 if (!is_transfer_flag_valid(transfer_flag)) {
971 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
972 }
973
974 if (!is_string_type_valid(comp_ver_str_type)) {
975 return PLDM_ERROR_INVALID_DATA;
976 }
977
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930978 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930979 header.instance = instance_id;
980 header.msg_type = PLDM_REQUEST;
981 header.pldm_type = PLDM_FWUP;
982 header.command = PLDM_PASS_COMPONENT_TABLE;
983 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
984 if (rc) {
985 return rc;
986 }
987
988 struct pldm_pass_component_table_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930989 (struct pldm_pass_component_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930990
991 request->transfer_flag = transfer_flag;
992 request->comp_classification = htole16(comp_classification);
993 request->comp_identifier = htole16(comp_identifier);
994 request->comp_classification_index = comp_classification_index;
995 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
996 request->comp_ver_str_type = comp_ver_str_type;
997 request->comp_ver_str_len = comp_ver_str_len;
998
999 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1000 comp_ver_str->ptr, comp_ver_str->length);
1001
1002 return PLDM_SUCCESS;
1003}
1004
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301005LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301006int decode_pass_component_table_resp(const struct pldm_msg *msg,
1007 const size_t payload_length,
1008 uint8_t *completion_code,
1009 uint8_t *comp_resp,
1010 uint8_t *comp_resp_code)
1011{
1012 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1013 comp_resp_code == NULL || !payload_length) {
1014 return PLDM_ERROR_INVALID_DATA;
1015 }
1016
1017 *completion_code = msg->payload[0];
1018 if (*completion_code != PLDM_SUCCESS) {
1019 return PLDM_SUCCESS;
1020 }
1021
1022 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1023 return PLDM_ERROR_INVALID_LENGTH;
1024 }
1025
1026 struct pldm_pass_component_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301027 (struct pldm_pass_component_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301028
1029 if (!is_comp_resp_valid(response->comp_resp)) {
1030 return PLDM_ERROR_INVALID_DATA;
1031 }
1032
1033 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1034 return PLDM_ERROR_INVALID_DATA;
1035 }
1036
1037 *comp_resp = response->comp_resp;
1038 *comp_resp_code = response->comp_resp_code;
1039
1040 return PLDM_SUCCESS;
1041}
1042
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301043LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301044int encode_update_component_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301045 uint8_t instance_id, uint16_t comp_classification,
1046 uint16_t comp_identifier, uint8_t comp_classification_index,
1047 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1048 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1049 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1050 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301051{
1052 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1053 return PLDM_ERROR_INVALID_DATA;
1054 }
1055
1056 if (payload_length !=
1057 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1058 return PLDM_ERROR_INVALID_LENGTH;
1059 }
1060
1061 if (!comp_image_size) {
1062 return PLDM_ERROR_INVALID_DATA;
1063 }
1064
1065 if ((comp_ver_str_len == 0) ||
1066 (comp_ver_str_len != comp_ver_str->length)) {
1067 return PLDM_ERROR_INVALID_DATA;
1068 }
1069
1070 if (!is_string_type_valid(comp_ver_str_type)) {
1071 return PLDM_ERROR_INVALID_DATA;
1072 }
1073
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301074 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301075 header.instance = instance_id;
1076 header.msg_type = PLDM_REQUEST;
1077 header.pldm_type = PLDM_FWUP;
1078 header.command = PLDM_UPDATE_COMPONENT;
1079 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1080 if (rc) {
1081 return rc;
1082 }
1083
1084 struct pldm_update_component_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301085 (struct pldm_update_component_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301086
1087 request->comp_classification = htole16(comp_classification);
1088 request->comp_identifier = htole16(comp_identifier);
1089 request->comp_classification_index = comp_classification_index;
1090 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1091 request->comp_image_size = htole32(comp_image_size);
1092 request->update_option_flags.value = htole32(update_option_flags.value);
1093 request->comp_ver_str_type = comp_ver_str_type;
1094 request->comp_ver_str_len = comp_ver_str_len;
1095
1096 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1097 comp_ver_str->ptr, comp_ver_str->length);
1098
1099 return PLDM_SUCCESS;
1100}
1101
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301102LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301103int decode_update_component_resp(const struct pldm_msg *msg,
1104 size_t payload_length,
1105 uint8_t *completion_code,
1106 uint8_t *comp_compatibility_resp,
1107 uint8_t *comp_compatibility_resp_code,
1108 bitfield32_t *update_option_flags_enabled,
1109 uint16_t *time_before_req_fw_data)
1110{
1111 if (msg == NULL || completion_code == NULL ||
1112 comp_compatibility_resp == NULL ||
1113 comp_compatibility_resp_code == NULL ||
1114 update_option_flags_enabled == NULL ||
1115 time_before_req_fw_data == NULL || !payload_length) {
1116 return PLDM_ERROR_INVALID_DATA;
1117 }
1118
1119 *completion_code = msg->payload[0];
1120 if (*completion_code != PLDM_SUCCESS) {
1121 return PLDM_SUCCESS;
1122 }
1123
1124 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1125 return PLDM_ERROR_INVALID_LENGTH;
1126 }
1127
1128 struct pldm_update_component_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301129 (struct pldm_update_component_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301130
1131 if (!is_comp_compatibility_resp_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301132 response->comp_compatibility_resp)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301133 return PLDM_ERROR_INVALID_DATA;
1134 }
1135
1136 if (!is_comp_compatibility_resp_code_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301137 response->comp_compatibility_resp_code)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301138 return PLDM_ERROR_INVALID_DATA;
1139 }
1140
1141 *comp_compatibility_resp = response->comp_compatibility_resp;
1142 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1143 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301144 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301145 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1146
1147 return PLDM_SUCCESS;
1148}
1149
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301150LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301151int decode_request_firmware_data_req(const struct pldm_msg *msg,
1152 size_t payload_length, uint32_t *offset,
1153 uint32_t *length)
1154{
1155 if (msg == NULL || offset == NULL || length == NULL) {
1156 return PLDM_ERROR_INVALID_DATA;
1157 }
1158 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1159 return PLDM_ERROR_INVALID_LENGTH;
1160 }
1161 struct pldm_request_firmware_data_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301162 (struct pldm_request_firmware_data_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301163 *offset = le32toh(request->offset);
1164 *length = le32toh(request->length);
1165
1166 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1167 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1168 }
1169
1170 return PLDM_SUCCESS;
1171}
1172
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301173LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301174int encode_request_firmware_data_resp(uint8_t instance_id,
1175 uint8_t completion_code,
1176 struct pldm_msg *msg,
1177 size_t payload_length)
1178{
1179 if (msg == NULL || !payload_length) {
1180 return PLDM_ERROR_INVALID_DATA;
1181 }
1182
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301183 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301184 header.instance = instance_id;
1185 header.msg_type = PLDM_RESPONSE;
1186 header.pldm_type = PLDM_FWUP;
1187 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1188 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1189 if (rc) {
1190 return rc;
1191 }
1192
1193 msg->payload[0] = completion_code;
1194
1195 return PLDM_SUCCESS;
1196}
1197
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301198LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301199int decode_transfer_complete_req(const struct pldm_msg *msg,
1200 size_t payload_length,
1201 uint8_t *transfer_result)
1202{
1203 if (msg == NULL || transfer_result == NULL) {
1204 return PLDM_ERROR_INVALID_DATA;
1205 }
1206
1207 if (payload_length != sizeof(*transfer_result)) {
1208 return PLDM_ERROR_INVALID_LENGTH;
1209 }
1210
1211 *transfer_result = msg->payload[0];
1212 return PLDM_SUCCESS;
1213}
1214
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301215LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301216int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1217 struct pldm_msg *msg, size_t payload_length)
1218{
1219 if (msg == NULL) {
1220 return PLDM_ERROR_INVALID_DATA;
1221 }
1222
1223 if (payload_length != sizeof(completion_code)) {
1224 return PLDM_ERROR_INVALID_LENGTH;
1225 }
1226
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301227 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301228 header.instance = instance_id;
1229 header.msg_type = PLDM_RESPONSE;
1230 header.pldm_type = PLDM_FWUP;
1231 header.command = PLDM_TRANSFER_COMPLETE;
1232 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1233 if (rc) {
1234 return rc;
1235 }
1236
1237 msg->payload[0] = completion_code;
1238
1239 return PLDM_SUCCESS;
1240}
1241
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301242LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301243int decode_verify_complete_req(const struct pldm_msg *msg,
1244 size_t payload_length, uint8_t *verify_result)
1245{
1246 if (msg == NULL || verify_result == NULL) {
1247 return PLDM_ERROR_INVALID_DATA;
1248 }
1249
1250 if (payload_length != sizeof(*verify_result)) {
1251 return PLDM_ERROR_INVALID_LENGTH;
1252 }
1253
1254 *verify_result = msg->payload[0];
1255 return PLDM_SUCCESS;
1256}
1257
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301258LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301259int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1260 struct pldm_msg *msg, size_t payload_length)
1261{
1262 if (msg == NULL) {
1263 return PLDM_ERROR_INVALID_DATA;
1264 }
1265
1266 if (payload_length != sizeof(completion_code)) {
1267 return PLDM_ERROR_INVALID_LENGTH;
1268 }
1269
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301270 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301271 header.instance = instance_id;
1272 header.msg_type = PLDM_RESPONSE;
1273 header.pldm_type = PLDM_FWUP;
1274 header.command = PLDM_VERIFY_COMPLETE;
1275 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1276 if (rc) {
1277 return rc;
1278 }
1279
1280 msg->payload[0] = completion_code;
1281
1282 return PLDM_SUCCESS;
1283}
1284
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301285LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301286int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
1287 uint8_t *apply_result,
1288 bitfield16_t *comp_activation_methods_modification)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301289{
1290 if (msg == NULL || apply_result == NULL ||
1291 comp_activation_methods_modification == NULL) {
1292 return PLDM_ERROR_INVALID_DATA;
1293 }
1294
1295 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1296 return PLDM_ERROR_INVALID_LENGTH;
1297 }
1298
1299 struct pldm_apply_complete_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301300 (struct pldm_apply_complete_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301301
1302 *apply_result = request->apply_result;
1303 comp_activation_methods_modification->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301304 le16toh(request->comp_activation_methods_modification.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301305
1306 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1307 comp_activation_methods_modification->value) {
1308 return PLDM_ERROR_INVALID_DATA;
1309 }
1310
1311 return PLDM_SUCCESS;
1312}
1313
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301314LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301315int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1316 struct pldm_msg *msg, size_t payload_length)
1317{
1318 if (msg == NULL) {
1319 return PLDM_ERROR_INVALID_DATA;
1320 }
1321
1322 if (payload_length != sizeof(completion_code)) {
1323 return PLDM_ERROR_INVALID_LENGTH;
1324 }
1325
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301326 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301327 header.instance = instance_id;
1328 header.msg_type = PLDM_RESPONSE;
1329 header.pldm_type = PLDM_FWUP;
1330 header.command = PLDM_APPLY_COMPLETE;
1331 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1332 if (rc) {
1333 return rc;
1334 }
1335
1336 msg->payload[0] = completion_code;
1337
1338 return PLDM_SUCCESS;
1339}
1340
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301341LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301342int encode_activate_firmware_req(uint8_t instance_id,
1343 bool8_t self_contained_activation_req,
1344 struct pldm_msg *msg, size_t payload_length)
1345{
1346 if (msg == NULL) {
1347 return PLDM_ERROR_INVALID_DATA;
1348 }
1349
1350 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1351 return PLDM_ERROR_INVALID_LENGTH;
1352 }
1353
1354 if (!is_self_contained_activation_req_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301355 self_contained_activation_req)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301356 return PLDM_ERROR_INVALID_DATA;
1357 }
1358
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301359 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301360 header.instance = instance_id;
1361 header.msg_type = PLDM_REQUEST;
1362 header.pldm_type = PLDM_FWUP;
1363 header.command = PLDM_ACTIVATE_FIRMWARE;
1364 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1365 if (rc) {
1366 return rc;
1367 }
1368
1369 struct pldm_activate_firmware_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301370 (struct pldm_activate_firmware_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301371
1372 request->self_contained_activation_req = self_contained_activation_req;
1373
1374 return PLDM_SUCCESS;
1375}
1376
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301377LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301378int decode_activate_firmware_resp(const struct pldm_msg *msg,
1379 size_t payload_length,
1380 uint8_t *completion_code,
1381 uint16_t *estimated_time_activation)
1382{
1383 if (msg == NULL || completion_code == NULL ||
1384 estimated_time_activation == NULL || !payload_length) {
1385 return PLDM_ERROR_INVALID_DATA;
1386 }
1387
1388 *completion_code = msg->payload[0];
1389 if (*completion_code != PLDM_SUCCESS) {
1390 return PLDM_SUCCESS;
1391 }
1392
1393 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1394 return PLDM_ERROR_INVALID_LENGTH;
1395 }
1396
1397 struct pldm_activate_firmware_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301398 (struct pldm_activate_firmware_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301399
1400 *estimated_time_activation =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301401 le16toh(response->estimated_time_activation);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301402
1403 return PLDM_SUCCESS;
1404}
1405
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301406LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301407int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1408 size_t payload_length)
1409{
1410 if (msg == NULL) {
1411 return PLDM_ERROR_INVALID_DATA;
1412 }
1413
1414 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1415 return PLDM_ERROR_INVALID_LENGTH;
1416 }
1417
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301418 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301419 header.instance = instance_id;
1420 header.msg_type = PLDM_REQUEST;
1421 header.pldm_type = PLDM_FWUP;
1422 header.command = PLDM_GET_STATUS;
1423 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1424 if (rc) {
1425 return rc;
1426 }
1427
1428 return PLDM_SUCCESS;
1429}
1430
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301431LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301432int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1433 uint8_t *completion_code, uint8_t *current_state,
1434 uint8_t *previous_state, uint8_t *aux_state,
1435 uint8_t *aux_state_status, uint8_t *progress_percent,
1436 uint8_t *reason_code,
1437 bitfield32_t *update_option_flags_enabled)
1438{
1439 if (msg == NULL || completion_code == NULL || current_state == NULL ||
1440 previous_state == NULL || aux_state == NULL ||
1441 aux_state_status == NULL || progress_percent == NULL ||
1442 reason_code == NULL || update_option_flags_enabled == NULL ||
1443 !payload_length) {
1444 return PLDM_ERROR_INVALID_DATA;
1445 }
1446
1447 *completion_code = msg->payload[0];
1448 if (*completion_code != PLDM_SUCCESS) {
1449 return PLDM_SUCCESS;
1450 }
1451
1452 if (payload_length != sizeof(struct pldm_get_status_resp)) {
1453 return PLDM_ERROR_INVALID_LENGTH;
1454 }
1455 struct pldm_get_status_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301456 (struct pldm_get_status_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301457
1458 if (!is_state_valid(response->current_state)) {
1459 return PLDM_ERROR_INVALID_DATA;
1460 }
1461 if (!is_state_valid(response->previous_state)) {
1462 return PLDM_ERROR_INVALID_DATA;
1463 }
1464 if (!is_aux_state_valid(response->aux_state)) {
1465 return PLDM_ERROR_INVALID_DATA;
1466 }
1467 if (!is_aux_state_status_valid(response->aux_state_status)) {
1468 return PLDM_ERROR_INVALID_DATA;
1469 }
1470 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1471 return PLDM_ERROR_INVALID_DATA;
1472 }
1473 if (!is_reason_code_valid(response->reason_code)) {
1474 return PLDM_ERROR_INVALID_DATA;
1475 }
1476
1477 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1478 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1479 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1480 if (response->aux_state !=
1481 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1482 return PLDM_ERROR_INVALID_DATA;
1483 }
1484 }
1485
1486 *current_state = response->current_state;
1487 *previous_state = response->previous_state;
1488 *aux_state = response->aux_state;
1489 *aux_state_status = response->aux_state_status;
1490 *progress_percent = response->progress_percent;
1491 *reason_code = response->reason_code;
1492 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301493 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301494
1495 return PLDM_SUCCESS;
1496}
1497
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301498LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301499int encode_cancel_update_component_req(uint8_t instance_id,
1500 struct pldm_msg *msg,
1501 size_t payload_length)
1502{
1503 if (msg == NULL) {
1504 return PLDM_ERROR_INVALID_DATA;
1505 }
1506
1507 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1508 return PLDM_ERROR_INVALID_LENGTH;
1509 }
1510
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301511 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301512 header.instance = instance_id;
1513 header.msg_type = PLDM_REQUEST;
1514 header.pldm_type = PLDM_FWUP;
1515 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
1516 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1517 if (rc) {
1518 return rc;
1519 }
1520
1521 return PLDM_SUCCESS;
1522}
1523
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301524LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301525int decode_cancel_update_component_resp(const struct pldm_msg *msg,
1526 size_t payload_length,
1527 uint8_t *completion_code)
1528{
1529 if (msg == NULL || completion_code == NULL) {
1530 return PLDM_ERROR_INVALID_DATA;
1531 }
1532
1533 if (payload_length != sizeof(*completion_code)) {
1534 return PLDM_ERROR_INVALID_LENGTH;
1535 }
1536
1537 *completion_code = msg->payload[0];
1538 return PLDM_SUCCESS;
1539}
1540
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301541LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301542int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
1543 size_t payload_length)
1544{
1545 if (msg == NULL) {
1546 return PLDM_ERROR_INVALID_DATA;
1547 }
1548
1549 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
1550 return PLDM_ERROR_INVALID_LENGTH;
1551 }
1552
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301553 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301554 header.instance = instance_id;
1555 header.msg_type = PLDM_REQUEST;
1556 header.pldm_type = PLDM_FWUP;
1557 header.command = PLDM_CANCEL_UPDATE;
1558 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1559 if (rc) {
1560 return rc;
1561 }
1562
1563 return PLDM_SUCCESS;
1564}
1565
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301566LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301567int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
1568 uint8_t *completion_code,
1569 bool8_t *non_functioning_component_indication,
1570 bitfield64_t *non_functioning_component_bitmap)
1571{
1572 if (msg == NULL || completion_code == NULL ||
1573 non_functioning_component_indication == NULL ||
1574 non_functioning_component_bitmap == NULL || !payload_length) {
1575 return PLDM_ERROR_INVALID_DATA;
1576 }
1577
1578 *completion_code = msg->payload[0];
1579 if (*completion_code != PLDM_SUCCESS) {
1580 return PLDM_SUCCESS;
1581 }
1582
1583 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
1584 return PLDM_ERROR_INVALID_LENGTH;
1585 }
1586 struct pldm_cancel_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301587 (struct pldm_cancel_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301588
1589 if (!is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301590 response->non_functioning_component_indication)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301591 return PLDM_ERROR_INVALID_DATA;
1592 }
1593
1594 *non_functioning_component_indication =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301595 response->non_functioning_component_indication;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301596
1597 if (*non_functioning_component_indication) {
1598 non_functioning_component_bitmap->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301599 le64toh(response->non_functioning_component_bitmap);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301600 }
1601
1602 return PLDM_SUCCESS;
1603}