blob: 2afcaabe1aeba37f09c7f670e278cc9afca20e9d [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09302#include "api.h"
Chris Wangb6ef35b2024-07-03 09:35:42 +08003#include "dsp/base.h"
Chris Wang4c1f2c72024-03-21 17:09:44 +08004#include "msgbuf.h"
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10305#include <libpldm/firmware_update.h>
6#include <libpldm/utils.h>
7
Andrew Jeffery9c766792022-08-10 23:12:49 +09308#include <endian.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05309#include <stdbool.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +093010#include <string.h>
11
12/** @brief Check whether string type value is valid
13 *
14 * @return true if string type value is valid, false if not
15 */
16static bool is_string_type_valid(uint8_t string_type)
17{
18 switch (string_type) {
19 case PLDM_STR_TYPE_UNKNOWN:
20 return false;
21 case PLDM_STR_TYPE_ASCII:
22 case PLDM_STR_TYPE_UTF_8:
23 case PLDM_STR_TYPE_UTF_16:
24 case PLDM_STR_TYPE_UTF_16LE:
25 case PLDM_STR_TYPE_UTF_16BE:
26 return true;
27 default:
28 return false;
29 }
30}
31
32/** @brief Return the length of the descriptor type described in firmware update
33 * specification
34 *
35 * @return length of the descriptor type if descriptor type is valid else
36 * return 0
37 */
38static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
39{
40 switch (descriptor_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093041 case PLDM_FWUP_PCI_VENDOR_ID:
42 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
43 case PLDM_FWUP_IANA_ENTERPRISE_ID:
44 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
45 case PLDM_FWUP_UUID:
46 return PLDM_FWUP_UUID_LENGTH;
47 case PLDM_FWUP_PNP_VENDOR_ID:
48 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
49 case PLDM_FWUP_ACPI_VENDOR_ID:
50 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
51 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
52 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
53 case PLDM_FWUP_SCSI_VENDOR_ID:
54 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
55 case PLDM_FWUP_PCI_DEVICE_ID:
56 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
57 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
58 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
59 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
60 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
61 case PLDM_FWUP_PCI_REVISION_ID:
62 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
63 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
64 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
65 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
66 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
67 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
68 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
69 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
70 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
71 case PLDM_FWUP_SCSI_PRODUCT_ID:
72 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
73 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
74 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
75 default:
76 return 0;
77 }
78}
79
Chris Wang4c1f2c72024-03-21 17:09:44 +080080static bool is_downstream_device_update_support_valid(uint8_t resp)
81{
82 switch (resp) {
83 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
84 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
85 return true;
86 default:
87 return false;
88 }
89}
90
Chris Wang458475a2024-03-26 17:59:19 +080091static bool
92is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)
93{
94 switch (transfer_op_flag) {
95 case PLDM_GET_NEXTPART:
96 case PLDM_GET_FIRSTPART:
97 return true;
98 default:
99 return false;
100 }
101}
102
Andrew Jeffery9c766792022-08-10 23:12:49 +0930103/** @brief Check whether ComponentResponse is valid
104 *
105 * @return true if ComponentResponse is valid, false if not
106 */
107static bool is_comp_resp_valid(uint8_t comp_resp)
108{
109 switch (comp_resp) {
110 case PLDM_CR_COMP_CAN_BE_UPDATED:
111 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
112 return true;
113
114 default:
115 return false;
116 }
117}
118
119/** @brief Check whether ComponentResponseCode is valid
120 *
121 * @return true if ComponentResponseCode is valid, false if not
122 */
123static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
124{
125 switch (comp_resp_code) {
126 case PLDM_CRC_COMP_CAN_BE_UPDATED:
127 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
128 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
129 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
130 case PLDM_CRC_COMP_CONFLICT:
131 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
132 case PLDM_CRC_COMP_NOT_SUPPORTED:
133 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
134 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
135 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
136 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
137 case PLDM_CRC_COMP_VER_STR_LOWER:
138 return true;
139
140 default:
141 if (comp_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930142 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930143 comp_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930144 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930145 return true;
146 }
147 return false;
148 }
149}
150
151/** @brief Check whether ComponentCompatibilityResponse is valid
152 *
153 * @return true if ComponentCompatibilityResponse is valid, false if not
154 */
155static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
156{
157 switch (comp_compatibility_resp) {
158 case PLDM_CCR_COMP_CAN_BE_UPDATED:
159 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
160 return true;
161
162 default:
163 return false;
164 }
165}
166
167/** @brief Check whether ComponentCompatibilityResponse Code is valid
168 *
169 * @return true if ComponentCompatibilityResponse Code is valid, false if not
170 */
171static bool
172is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
173{
174 switch (comp_compatibility_resp_code) {
175 case PLDM_CCRC_NO_RESPONSE_CODE:
176 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
177 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
178 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
179 case PLDM_CCRC_COMP_CONFLICT:
180 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
181 case PLDM_CCRC_COMP_NOT_SUPPORTED:
182 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
183 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
184 case PLDM_CCRC_COMP_INFO_NO_MATCH:
185 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
186 case PLDM_CCRC_COMP_VER_STR_LOWER:
187 return true;
188
189 default:
190 if (comp_compatibility_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930191 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930192 comp_compatibility_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930193 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930194 return true;
195 }
196 return false;
197 }
198}
199
200/** @brief Check whether SelfContainedActivationRequest is valid
201 *
202 * @return true if SelfContainedActivationRequest is valid, false if not
203 */
204static bool
205is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
206{
207 switch (self_contained_activation_req) {
208 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
209 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
210 return true;
211
212 default:
213 return false;
214 }
215}
216
217/** @brief Check if current or previous status in GetStatus command response is
218 * valid
219 *
220 * @param[in] state - current or previous different state machine state of
221 * the FD
222 * @return true if state is valid, false if not
223 */
224static bool is_state_valid(uint8_t state)
225{
226 switch (state) {
227 case PLDM_FD_STATE_IDLE:
228 case PLDM_FD_STATE_LEARN_COMPONENTS:
229 case PLDM_FD_STATE_READY_XFER:
230 case PLDM_FD_STATE_DOWNLOAD:
231 case PLDM_FD_STATE_VERIFY:
232 case PLDM_FD_STATE_APPLY:
233 case PLDM_FD_STATE_ACTIVATE:
234 return true;
235
236 default:
237 return false;
238 }
239}
240
241/** @brief Check if aux state in GetStatus command response is valid
242 *
243 * @param[in] aux_state - provides additional information to the UA to describe
244 * the current operation state of the FD/FDP
245 *
246 * @return true if aux state is valid, false if not
247 */
248static bool is_aux_state_valid(uint8_t aux_state)
249{
250 switch (aux_state) {
251 case PLDM_FD_OPERATION_IN_PROGRESS:
252 case PLDM_FD_OPERATION_SUCCESSFUL:
253 case PLDM_FD_OPERATION_FAILED:
254 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
255 return true;
256
257 default:
258 return false;
259 }
260}
261
262/** @brief Check if aux state status in GetStatus command response is valid
263 *
264 * @param[in] aux_state_status - aux state status
265 *
266 * @return true if aux state status is valid, false if not
267 */
268static bool is_aux_state_status_valid(uint8_t aux_state_status)
269{
270 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
271 aux_state_status == PLDM_FD_TIMEOUT ||
Andrew Jeffery67f7ed92023-04-05 14:00:00 +0930272 aux_state_status == PLDM_FD_GENERIC_ERROR ||
273 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
274 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930275 return true;
276 }
277
278 return false;
279}
280
281/** @brief Check if reason code in GetStatus command response is valid
282 *
283 * @param[in] reason_code - provides the reason for why the current state
284 * entered the IDLE state
285 *
286 * @return true if reason code is valid, false if not
287 */
288static bool is_reason_code_valid(uint8_t reason_code)
289{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930290 switch (reason_code) {
291 case PLDM_FD_INITIALIZATION:
292 case PLDM_FD_ACTIVATE_FW:
293 case PLDM_FD_CANCEL_UPDATE:
294 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
295 case PLDM_FD_TIMEOUT_READY_XFER:
296 case PLDM_FD_TIMEOUT_DOWNLOAD:
297 case PLDM_FD_TIMEOUT_VERIFY:
298 case PLDM_FD_TIMEOUT_APPLY:
299 return true;
300
301 default:
302 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
303 return true;
304 }
305 return false;
306 }
307}
308
309/** @brief Check if non functioning component indication in CancelUpdate
310 * response is valid
311 *
312 * @return true if non functioning component indication is valid, false if not
313 */
314static bool is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930315 bool8_t non_functioning_component_indication)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930316{
317 switch (non_functioning_component_indication) {
318 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
319 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
320 return true;
321
322 default:
323 return false;
324 }
325}
326
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930327LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930328int decode_pldm_package_header_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930329 const uint8_t *data, size_t length,
330 struct pldm_package_header_information *package_header_info,
331 struct variable_field *package_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930332{
333 if (data == NULL || package_header_info == NULL ||
334 package_version_str == NULL) {
335 return PLDM_ERROR_INVALID_DATA;
336 }
337
338 if (length < sizeof(struct pldm_package_header_information)) {
339 return PLDM_ERROR_INVALID_LENGTH;
340 }
341
342 struct pldm_package_header_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930343 (struct pldm_package_header_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930344
345 if (!is_string_type_valid(data_header->package_version_string_type) ||
346 (data_header->package_version_string_length == 0)) {
347 return PLDM_ERROR_INVALID_DATA;
348 }
349
350 if (length < sizeof(struct pldm_package_header_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930351 data_header->package_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930352 return PLDM_ERROR_INVALID_LENGTH;
353 }
354
355 if ((data_header->component_bitmap_bit_length %
356 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
357 return PLDM_ERROR_INVALID_DATA;
358 }
359
360 memcpy(package_header_info->uuid, data_header->uuid,
361 sizeof(data_header->uuid));
362 package_header_info->package_header_format_version =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930363 data_header->package_header_format_version;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930364 package_header_info->package_header_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930365 le16toh(data_header->package_header_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930366 memcpy(package_header_info->package_release_date_time,
367 data_header->package_release_date_time,
368 sizeof(data_header->package_release_date_time));
369 package_header_info->component_bitmap_bit_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930370 le16toh(data_header->component_bitmap_bit_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930371 package_header_info->package_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930372 data_header->package_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930373 package_header_info->package_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930374 data_header->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930375 package_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930376 data + sizeof(struct pldm_package_header_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930377 package_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930378 package_header_info->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930379
380 return PLDM_SUCCESS;
381}
382
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930383LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930384int decode_firmware_device_id_record(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930385 const uint8_t *data, size_t length,
386 uint16_t component_bitmap_bit_length,
387 struct pldm_firmware_device_id_record *fw_device_id_record,
388 struct variable_field *applicable_components,
389 struct variable_field *comp_image_set_version_str,
390 struct variable_field *record_descriptors,
391 struct variable_field *fw_device_pkg_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930392{
393 if (data == NULL || fw_device_id_record == NULL ||
394 applicable_components == NULL ||
395 comp_image_set_version_str == NULL || record_descriptors == NULL ||
396 fw_device_pkg_data == NULL) {
397 return PLDM_ERROR_INVALID_DATA;
398 }
399
400 if (length < sizeof(struct pldm_firmware_device_id_record)) {
401 return PLDM_ERROR_INVALID_LENGTH;
402 }
403
404 if ((component_bitmap_bit_length %
405 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
406 return PLDM_ERROR_INVALID_DATA;
407 }
408
409 struct pldm_firmware_device_id_record *data_record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930410 (struct pldm_firmware_device_id_record *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930411
412 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930413 data_record->comp_image_set_version_string_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930414 (data_record->comp_image_set_version_string_length == 0)) {
415 return PLDM_ERROR_INVALID_DATA;
416 }
417
418 fw_device_id_record->record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930419 le16toh(data_record->record_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930420 fw_device_id_record->descriptor_count = data_record->descriptor_count;
421 fw_device_id_record->device_update_option_flags.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930422 le32toh(data_record->device_update_option_flags.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930423 fw_device_id_record->comp_image_set_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930424 data_record->comp_image_set_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930425 fw_device_id_record->comp_image_set_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930426 data_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930427 fw_device_id_record->fw_device_pkg_data_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930428 le16toh(data_record->fw_device_pkg_data_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930429
430 if (length < fw_device_id_record->record_length) {
431 return PLDM_ERROR_INVALID_LENGTH;
432 }
433
434 uint16_t applicable_components_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930435 component_bitmap_bit_length /
436 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930437 uint16_t calc_min_record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930438 sizeof(struct pldm_firmware_device_id_record) +
439 applicable_components_length +
440 data_record->comp_image_set_version_string_length +
441 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
442 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930443
444 if (fw_device_id_record->record_length < calc_min_record_length) {
445 return PLDM_ERROR_INVALID_LENGTH;
446 }
447
448 applicable_components->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930449 data + sizeof(struct pldm_firmware_device_id_record);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930450 applicable_components->length = applicable_components_length;
451
452 comp_image_set_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930453 applicable_components->ptr + applicable_components->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930454 comp_image_set_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930455 fw_device_id_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930456
457 record_descriptors->ptr = comp_image_set_version_str->ptr +
458 comp_image_set_version_str->length;
459 record_descriptors->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930460 fw_device_id_record->record_length -
461 sizeof(struct pldm_firmware_device_id_record) -
462 applicable_components_length -
463 fw_device_id_record->comp_image_set_version_string_length -
464 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930465
466 if (fw_device_id_record->fw_device_pkg_data_length) {
467 fw_device_pkg_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930468 record_descriptors->ptr + record_descriptors->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930469 fw_device_pkg_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930470 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930471 }
472
473 return PLDM_SUCCESS;
474}
475
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930476LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930477int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
478 uint16_t *descriptor_type,
479 struct variable_field *descriptor_data)
480{
481 uint16_t descriptor_length = 0;
482
483 if (data == NULL || descriptor_type == NULL ||
484 descriptor_data == NULL) {
485 return PLDM_ERROR_INVALID_DATA;
486 }
487
488 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
489 return PLDM_ERROR_INVALID_LENGTH;
490 }
491
492 struct pldm_descriptor_tlv *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930493 (struct pldm_descriptor_tlv *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930494
495 *descriptor_type = le16toh(entry->descriptor_type);
496 descriptor_length = le16toh(entry->descriptor_length);
497 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
498 if (descriptor_length !=
499 get_descriptor_type_length(*descriptor_type)) {
500 return PLDM_ERROR_INVALID_LENGTH;
501 }
502 }
503
504 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
505 descriptor_length)) {
506 return PLDM_ERROR_INVALID_LENGTH;
507 }
508
509 descriptor_data->ptr = entry->descriptor_data;
510 descriptor_data->length = descriptor_length;
511
512 return PLDM_SUCCESS;
513}
514
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930515LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930516int decode_vendor_defined_descriptor_value(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930517 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
518 struct variable_field *descriptor_title_str,
519 struct variable_field *descriptor_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930520{
521 if (data == NULL || descriptor_title_str_type == NULL ||
522 descriptor_title_str == NULL || descriptor_data == NULL) {
523 return PLDM_ERROR_INVALID_DATA;
524 }
525
526 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
527 return PLDM_ERROR_INVALID_LENGTH;
528 }
529
530 struct pldm_vendor_defined_descriptor_title_data *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930531 (struct pldm_vendor_defined_descriptor_title_data *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930532 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930533 entry->vendor_defined_descriptor_title_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930534 (entry->vendor_defined_descriptor_title_str_len == 0)) {
535 return PLDM_ERROR_INVALID_DATA;
536 }
537
Manojkiran Eda9e3a5d42024-06-17 16:06:42 +0530538 // Assuming at least 1 byte of VendorDefinedDescriptorData
Andrew Jeffery9c766792022-08-10 23:12:49 +0930539 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
540 entry->vendor_defined_descriptor_title_str_len)) {
541 return PLDM_ERROR_INVALID_LENGTH;
542 }
543
544 *descriptor_title_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930545 entry->vendor_defined_descriptor_title_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930546 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
547 descriptor_title_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930548 entry->vendor_defined_descriptor_title_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930549
550 descriptor_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930551 descriptor_title_str->ptr + descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930552 descriptor_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930553 length -
554 sizeof(entry->vendor_defined_descriptor_title_str_type) -
555 sizeof(entry->vendor_defined_descriptor_title_str_len) -
556 descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930557
558 return PLDM_SUCCESS;
559}
560
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930561LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930562int decode_pldm_comp_image_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930563 const uint8_t *data, size_t length,
564 struct pldm_component_image_information *pldm_comp_image_info,
565 struct variable_field *comp_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930566{
567 if (data == NULL || pldm_comp_image_info == NULL ||
568 comp_version_str == NULL) {
569 return PLDM_ERROR_INVALID_DATA;
570 }
571
572 if (length < sizeof(struct pldm_component_image_information)) {
573 return PLDM_ERROR_INVALID_LENGTH;
574 }
575
576 struct pldm_component_image_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930577 (struct pldm_component_image_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930578
579 if (!is_string_type_valid(data_header->comp_version_string_type) ||
580 (data_header->comp_version_string_length == 0)) {
581 return PLDM_ERROR_INVALID_DATA;
582 }
583
584 if (length < sizeof(struct pldm_component_image_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930585 data_header->comp_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930586 return PLDM_ERROR_INVALID_LENGTH;
587 }
588
589 pldm_comp_image_info->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930590 le16toh(data_header->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930591 pldm_comp_image_info->comp_identifier =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930592 le16toh(data_header->comp_identifier);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930593 pldm_comp_image_info->comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930594 le32toh(data_header->comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930595 pldm_comp_image_info->comp_options.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930596 le16toh(data_header->comp_options.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930597 pldm_comp_image_info->requested_comp_activation_method.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930598 le16toh(data_header->requested_comp_activation_method.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930599 pldm_comp_image_info->comp_location_offset =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930600 le32toh(data_header->comp_location_offset);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930601 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
602 pldm_comp_image_info->comp_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930603 data_header->comp_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930604 pldm_comp_image_info->comp_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930605 data_header->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930606
607 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
608 pldm_comp_image_info->comp_comparison_stamp !=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930609 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930610 return PLDM_ERROR_INVALID_DATA;
611 }
612
613 if (pldm_comp_image_info->comp_location_offset == 0 ||
614 pldm_comp_image_info->comp_size == 0) {
615 return PLDM_ERROR_INVALID_DATA;
616 }
617
618 comp_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930619 data + sizeof(struct pldm_component_image_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930620 comp_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930621 pldm_comp_image_info->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930622
623 return PLDM_SUCCESS;
624}
625
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930626LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930627int encode_query_device_identifiers_req(uint8_t instance_id,
628 size_t payload_length,
629 struct pldm_msg *msg)
630{
631 if (msg == NULL) {
632 return PLDM_ERROR_INVALID_DATA;
633 }
634
635 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
636 return PLDM_ERROR_INVALID_LENGTH;
637 }
638
639 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
640 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
641}
642
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930643LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930644int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
645 size_t payload_length,
646 uint8_t *completion_code,
647 uint32_t *device_identifiers_len,
648 uint8_t *descriptor_count,
649 uint8_t **descriptor_data)
650{
651 if (msg == NULL || completion_code == NULL ||
652 device_identifiers_len == NULL || descriptor_count == NULL ||
653 descriptor_data == NULL) {
654 return PLDM_ERROR_INVALID_DATA;
655 }
656
657 *completion_code = msg->payload[0];
658 if (PLDM_SUCCESS != *completion_code) {
659 return PLDM_SUCCESS;
660 }
661
662 if (payload_length <
663 sizeof(struct pldm_query_device_identifiers_resp)) {
664 return PLDM_ERROR_INVALID_LENGTH;
665 }
666
667 struct pldm_query_device_identifiers_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930668 (struct pldm_query_device_identifiers_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930669 *device_identifiers_len = le32toh(response->device_identifiers_len);
670
671 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
672 return PLDM_ERROR_INVALID_LENGTH;
673 }
674
675 if (payload_length !=
676 sizeof(struct pldm_query_device_identifiers_resp) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930677 *device_identifiers_len) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930678 return PLDM_ERROR_INVALID_LENGTH;
679 }
680 *descriptor_count = response->descriptor_count;
681
682 if (*descriptor_count == 0) {
683 return PLDM_ERROR_INVALID_DATA;
684 }
685 *descriptor_data =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930686 (uint8_t *)(msg->payload +
687 sizeof(struct pldm_query_device_identifiers_resp));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930688 return PLDM_SUCCESS;
689}
690
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930691LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930692int encode_get_firmware_parameters_req(uint8_t instance_id,
693 size_t payload_length,
694 struct pldm_msg *msg)
695{
696 if (msg == NULL) {
697 return PLDM_ERROR_INVALID_DATA;
698 }
699
700 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
701 return PLDM_ERROR_INVALID_LENGTH;
702 }
703
704 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
705 PLDM_GET_FIRMWARE_PARAMETERS, msg);
706}
707
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930708LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930709int decode_get_firmware_parameters_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930710 const struct pldm_msg *msg, size_t payload_length,
711 struct pldm_get_firmware_parameters_resp *resp_data,
712 struct variable_field *active_comp_image_set_ver_str,
713 struct variable_field *pending_comp_image_set_ver_str,
714 struct variable_field *comp_parameter_table)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930715{
716 if (msg == NULL || resp_data == NULL ||
717 active_comp_image_set_ver_str == NULL ||
718 pending_comp_image_set_ver_str == NULL ||
719 comp_parameter_table == NULL || !payload_length) {
720 return PLDM_ERROR_INVALID_DATA;
721 }
722
723 resp_data->completion_code = msg->payload[0];
724 if (PLDM_SUCCESS != resp_data->completion_code) {
725 return PLDM_SUCCESS;
726 }
727
728 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
729 return PLDM_ERROR_INVALID_LENGTH;
730 }
731
732 struct pldm_get_firmware_parameters_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930733 (struct pldm_get_firmware_parameters_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930734
735 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930736 response->active_comp_image_set_ver_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930737 (response->active_comp_image_set_ver_str_len == 0)) {
738 return PLDM_ERROR_INVALID_DATA;
739 }
740
741 if (response->pending_comp_image_set_ver_str_len == 0) {
742 if (response->pending_comp_image_set_ver_str_type !=
743 PLDM_STR_TYPE_UNKNOWN) {
744 return PLDM_ERROR_INVALID_DATA;
745 }
746 } else {
747 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930748 response->pending_comp_image_set_ver_str_type)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930749 return PLDM_ERROR_INVALID_DATA;
750 }
751 }
752
753 size_t partial_response_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930754 sizeof(struct pldm_get_firmware_parameters_resp) +
755 response->active_comp_image_set_ver_str_len +
756 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930757
758 if (payload_length < partial_response_length) {
759 return PLDM_ERROR_INVALID_LENGTH;
760 }
761
762 resp_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930763 le32toh(response->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930764 resp_data->comp_count = le16toh(response->comp_count);
765 resp_data->active_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930766 response->active_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930767 resp_data->active_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930768 response->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930769 resp_data->pending_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930770 response->pending_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930771 resp_data->pending_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930772 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930773
774 active_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930775 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930776 active_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930777 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930778
779 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
780 pending_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930781 msg->payload +
782 sizeof(struct pldm_get_firmware_parameters_resp) +
783 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930784 pending_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930785 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930786 } else {
787 pending_comp_image_set_ver_str->ptr = NULL;
788 pending_comp_image_set_ver_str->length = 0;
789 }
790
791 if (payload_length > partial_response_length && resp_data->comp_count) {
792 comp_parameter_table->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930793 msg->payload +
794 sizeof(struct pldm_get_firmware_parameters_resp) +
795 resp_data->active_comp_image_set_ver_str_len +
796 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930797 comp_parameter_table->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930798 payload_length - partial_response_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930799 } else {
800 comp_parameter_table->ptr = NULL;
801 comp_parameter_table->length = 0;
802 }
803
804 return PLDM_SUCCESS;
805}
806
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930807LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930808int decode_get_firmware_parameters_resp_comp_entry(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930809 const uint8_t *data, size_t length,
810 struct pldm_component_parameter_entry *component_data,
811 struct variable_field *active_comp_ver_str,
812 struct variable_field *pending_comp_ver_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930813{
814 if (data == NULL || component_data == NULL ||
815 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
816 return PLDM_ERROR_INVALID_DATA;
817 }
818
819 if (length < sizeof(struct pldm_component_parameter_entry)) {
820 return PLDM_ERROR_INVALID_LENGTH;
821 }
822
823 struct pldm_component_parameter_entry *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930824 (struct pldm_component_parameter_entry *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930825
826 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
827 entry->active_comp_ver_str_len +
828 entry->pending_comp_ver_str_len;
829
830 if (length < entry_length) {
831 return PLDM_ERROR_INVALID_LENGTH;
832 }
833
834 component_data->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930835 le16toh(entry->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930836 component_data->comp_identifier = le16toh(entry->comp_identifier);
837 component_data->comp_classification_index =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930838 entry->comp_classification_index;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930839 component_data->active_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930840 le32toh(entry->active_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930841 component_data->active_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930842 entry->active_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930843 component_data->active_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930844 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930845 memcpy(component_data->active_comp_release_date,
846 entry->active_comp_release_date,
847 sizeof(entry->active_comp_release_date));
848 component_data->pending_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930849 le32toh(entry->pending_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930850 component_data->pending_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930851 entry->pending_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930852 component_data->pending_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930853 entry->pending_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930854 memcpy(component_data->pending_comp_release_date,
855 entry->pending_comp_release_date,
856 sizeof(entry->pending_comp_release_date));
857 component_data->comp_activation_methods.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930858 le16toh(entry->comp_activation_methods.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930859 component_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930860 le32toh(entry->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930861
862 if (entry->active_comp_ver_str_len != 0) {
863 active_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930864 data + sizeof(struct pldm_component_parameter_entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930865 active_comp_ver_str->length = entry->active_comp_ver_str_len;
866 } else {
867 active_comp_ver_str->ptr = NULL;
868 active_comp_ver_str->length = 0;
869 }
870
871 if (entry->pending_comp_ver_str_len != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930872 pending_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930873 data + sizeof(struct pldm_component_parameter_entry) +
874 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930875 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
876 } else {
877 pending_comp_ver_str->ptr = NULL;
878 pending_comp_ver_str->length = 0;
879 }
880 return PLDM_SUCCESS;
881}
882
Chris Wang4c1f2c72024-03-21 17:09:44 +0800883LIBPLDM_ABI_TESTING
884int encode_query_downstream_devices_req(uint8_t instance_id,
885 struct pldm_msg *msg)
886{
887 if (msg == NULL) {
888 return PLDM_ERROR_INVALID_DATA;
889 }
890
891 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
892 PLDM_QUERY_DOWNSTREAM_DEVICES, msg);
893}
894
895LIBPLDM_ABI_TESTING
896int decode_query_downstream_devices_resp(
897 const struct pldm_msg *msg, size_t payload_length,
898 struct pldm_query_downstream_devices_resp *resp_data)
899{
900 struct pldm_msgbuf _buf;
901 struct pldm_msgbuf *buf = &_buf;
902 int rc;
903
904 if (msg == NULL || resp_data == NULL || !payload_length) {
905 return PLDM_ERROR_INVALID_DATA;
906 }
907
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930908 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
909 msg->payload, payload_length);
Chris Wang4c1f2c72024-03-21 17:09:44 +0800910 if (rc) {
911 return rc;
912 }
913
914 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
915 if (rc) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930916 return pldm_xlate_errno(rc);
Chris Wang4c1f2c72024-03-21 17:09:44 +0800917 }
918 if (PLDM_SUCCESS != resp_data->completion_code) {
919 // Return the CC directly without decoding the rest of the payload
920 return PLDM_SUCCESS;
921 }
922
923 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
924 return PLDM_ERROR_INVALID_LENGTH;
925 }
926
927 rc = pldm_msgbuf_extract(buf,
928 resp_data->downstream_device_update_supported);
929 if (rc) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930930 return pldm_xlate_errno(rc);
Chris Wang4c1f2c72024-03-21 17:09:44 +0800931 }
932
933 if (!is_downstream_device_update_support_valid(
934 resp_data->downstream_device_update_supported)) {
935 return PLDM_ERROR_INVALID_DATA;
936 }
937
938 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
939 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
940 pldm_msgbuf_extract(buf, resp_data->capabilities.value);
941
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930942 rc = pldm_msgbuf_destroy_consumed(buf);
943 if (rc) {
944 pldm_xlate_errno(rc);
945 }
946
947 return PLDM_SUCCESS;
Chris Wang4c1f2c72024-03-21 17:09:44 +0800948}
949
Chris Wang458475a2024-03-26 17:59:19 +0800950LIBPLDM_ABI_TESTING
951int encode_query_downstream_identifiers_req(
952 uint8_t instance_id, uint32_t data_transfer_handle,
953 enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg,
954 size_t payload_length)
955{
956 struct pldm_msgbuf _buf;
957 struct pldm_msgbuf *buf = &_buf;
958 int rc;
959
960 if (msg == NULL) {
961 return PLDM_ERROR_INVALID_DATA;
962 }
963
964 if (!is_transfer_operation_flag_valid(transfer_operation_flag)) {
965 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
966 }
967
968 struct pldm_header_info header = { 0 };
969 header.instance = instance_id;
970 header.msg_type = PLDM_REQUEST;
971 header.pldm_type = PLDM_FWUP;
972 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
973 rc = pack_pldm_header(&header, &(msg->hdr));
974 if (rc) {
975 return rc;
976 }
977
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930978 rc = pldm_msgbuf_init_errno(buf,
979 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
980 msg->payload, payload_length);
Chris Wang458475a2024-03-26 17:59:19 +0800981 if (rc) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930982 return pldm_xlate_errno(rc);
Chris Wang458475a2024-03-26 17:59:19 +0800983 }
984
985 pldm_msgbuf_insert(buf, data_transfer_handle);
986 // Data correctness has been verified, cast it to 1-byte data directly.
987 pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag);
988
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930989 rc = pldm_msgbuf_destroy(buf);
990 if (rc) {
991 return pldm_xlate_errno(rc);
992 }
993
994 return PLDM_SUCCESS;
Chris Wang458475a2024-03-26 17:59:19 +0800995}
996
997LIBPLDM_ABI_TESTING
998int decode_query_downstream_identifiers_resp(
999 const struct pldm_msg *msg, size_t payload_length,
1000 struct pldm_query_downstream_identifiers_resp *resp_data,
1001 struct variable_field *downstream_devices)
1002{
1003 struct pldm_msgbuf _buf;
1004 struct pldm_msgbuf *buf = &_buf;
1005 int rc = PLDM_ERROR;
1006
1007 if (msg == NULL || resp_data == NULL || downstream_devices == NULL ||
1008 !payload_length) {
1009 return PLDM_ERROR_INVALID_DATA;
1010 }
1011
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301012 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1013 msg->payload, payload_length);
Chris Wang458475a2024-03-26 17:59:19 +08001014 if (rc) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301015 return pldm_xlate_errno(rc);
Chris Wang458475a2024-03-26 17:59:19 +08001016 }
1017
1018 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1019 if (rc) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301020 return pldm_xlate_errno(rc);
Chris Wang458475a2024-03-26 17:59:19 +08001021 }
1022 if (PLDM_SUCCESS != resp_data->completion_code) {
1023 return PLDM_SUCCESS;
1024 }
1025
1026 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
1027 return PLDM_ERROR_INVALID_LENGTH;
1028 }
1029
1030 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1031 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1032
1033 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
1034 if (rc) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301035 return pldm_xlate_errno(rc);
Chris Wang458475a2024-03-26 17:59:19 +08001036 }
1037
1038 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1039 rc = pldm_msgbuf_span_required(buf,
1040 resp_data->downstream_devices_length,
1041 (void **)&downstream_devices->ptr);
1042 if (rc) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301043 return pldm_xlate_errno(rc);
Chris Wang458475a2024-03-26 17:59:19 +08001044 }
1045 downstream_devices->length = resp_data->downstream_devices_length;
1046
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301047 rc = pldm_msgbuf_destroy(buf);
1048 if (rc) {
1049 return pldm_xlate_errno(rc);
1050 }
1051
1052 return PLDM_SUCCESS;
Chris Wang458475a2024-03-26 17:59:19 +08001053}
1054
Chris Wangb6ef35b2024-07-03 09:35:42 +08001055LIBPLDM_ABI_TESTING
1056int encode_get_downstream_firmware_params_req(
1057 uint8_t instance_id, uint32_t data_transfer_handle,
1058 enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg,
1059 size_t payload_length)
1060{
1061 struct pldm_msgbuf _buf;
1062 struct pldm_msgbuf *buf = &_buf;
1063 int rc;
1064
1065 if (msg == NULL) {
1066 return -EINVAL;
1067 }
1068
1069 rc = pldm_msgbuf_init_errno(
1070 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_REQ_BYTES,
1071 msg->payload, payload_length);
1072 if (rc < 0) {
1073 return rc;
1074 }
1075
1076 if (!is_transfer_operation_flag_valid(transfer_operation_flag)) {
1077 return -EBADMSG;
1078 }
1079
1080 struct pldm_header_info header = { 0 };
1081 header.instance = instance_id;
1082 header.msg_type = PLDM_REQUEST;
1083 header.pldm_type = PLDM_FWUP;
1084 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1085 rc = pack_pldm_header_errno(&header, &msg->hdr);
1086 if (rc < 0) {
1087 return rc;
1088 }
1089
1090 pldm_msgbuf_insert(buf, data_transfer_handle);
1091 // Data correctness has been verified, cast it to 1-byte data directly.
1092 pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag);
1093
1094 return pldm_msgbuf_destroy(buf);
1095}
1096
1097LIBPLDM_ABI_TESTING
1098int decode_get_downstream_firmware_params_resp(
1099 const struct pldm_msg *msg, size_t payload_length,
1100 struct pldm_get_downstream_firmware_params_resp *resp_data,
1101 struct variable_field *downstream_device_param_table)
1102{
1103 struct pldm_msgbuf _buf;
1104 struct pldm_msgbuf *buf = &_buf;
1105 int rc;
1106
1107 if (msg == NULL || resp_data == NULL ||
1108 downstream_device_param_table == NULL) {
1109 return -EINVAL;
1110 }
1111
1112 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1113 msg->payload, payload_length);
1114 if (rc < 0) {
1115 return rc;
1116 }
1117
1118 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1119 if (rc < 0) {
1120 return rc;
1121 }
1122 if (PLDM_SUCCESS != resp_data->completion_code) {
1123 return 0;
1124 }
1125
1126 if (payload_length < PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_RESP_MIN_LEN) {
1127 return -EBADMSG;
1128 }
1129
1130 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1131 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1132 pldm_msgbuf_extract(buf,
1133 resp_data->fdp_capabilities_during_update.value);
1134 pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1135
1136 return pldm_msgbuf_span_remaining(
1137 buf, (void **)&downstream_device_param_table->ptr,
1138 &downstream_device_param_table->length);
1139}
1140
1141LIBPLDM_ABI_TESTING
1142int decode_downstream_device_parameter_table_entry(
1143 struct variable_field *data,
1144 struct pldm_downstream_device_parameter_entry *entry,
1145 struct variable_field *versions)
1146{
1147 struct pldm_msgbuf _buf;
1148 struct pldm_msgbuf *buf = &_buf;
1149 void *cursor = NULL;
1150 size_t remaining;
1151 int rc;
1152
1153 if (data == NULL || entry == NULL || versions == NULL) {
1154 return -EINVAL;
1155 }
1156
1157 rc = pldm_msgbuf_init_errno(
1158 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETER_ENTRY_MIN_LEN, data->ptr,
1159 data->length);
1160 if (rc < 0) {
1161 return rc;
1162 }
1163
1164 pldm_msgbuf_extract(buf, entry->downstream_device_index);
1165 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1166 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1167 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1168 if (rc < 0) {
1169 return rc;
1170 }
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001171 rc = pldm_msgbuf_extract_array(buf,
1172 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1173 entry->active_comp_release_date,
1174 sizeof(entry->active_comp_release_date));
1175 if (rc < 0) {
1176 return rc;
1177 }
1178
Chris Wangb6ef35b2024-07-03 09:35:42 +08001179 // Fill the last byte with NULL character
1180 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1181 '\0';
1182
1183 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1184 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1185 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1186 if (rc < 0) {
1187 return rc;
1188 }
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001189
1190 rc = pldm_msgbuf_extract_array(
1191 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1192 entry->pending_comp_release_date,
1193 sizeof(entry->pending_comp_release_date));
1194 if (rc < 0) {
1195 return rc;
1196 }
1197
Chris Wangb6ef35b2024-07-03 09:35:42 +08001198 // Fill the last byte with NULL character
1199 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1200 '\0';
1201
1202 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1203 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
1204 const size_t versions_len = entry->active_comp_ver_str_len +
1205 entry->pending_comp_ver_str_len;
1206 rc = pldm_msgbuf_span_required(buf, versions_len,
1207 (void **)&versions->ptr);
1208 if (rc < 0) {
1209 return rc;
1210 }
1211 versions->length = versions_len;
1212
1213 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1214 if (rc < 0) {
1215 return rc;
1216 }
1217
1218 data->ptr = cursor;
1219 data->length = remaining;
1220
1221 return 0;
1222}
1223
1224LIBPLDM_ABI_TESTING
1225int decode_downstream_device_parameter_table_entry_versions(
1226 const struct variable_field *versions,
1227 struct pldm_downstream_device_parameter_entry *entry, char *active,
Andrew Jefferya9892492024-10-03 14:07:17 +09301228 size_t active_len, char *pending, size_t pending_len)
Chris Wangb6ef35b2024-07-03 09:35:42 +08001229{
1230 struct pldm_msgbuf _buf;
1231 struct pldm_msgbuf *buf = &_buf;
1232 int rc;
1233
1234 if (versions == NULL || versions->ptr == NULL || !versions->length ||
1235 entry == NULL || active == NULL || pending == NULL) {
1236 return -EINVAL;
1237 }
1238
Andrew Jefferya9892492024-10-03 14:07:17 +09301239 if (!active_len || active_len - 1 < entry->active_comp_ver_str_len) {
1240 return -EOVERFLOW;
1241 }
1242
1243 if (!pending_len || pending_len - 1 < entry->pending_comp_ver_str_len) {
1244 return -EOVERFLOW;
1245 }
1246
Chris Wangb6ef35b2024-07-03 09:35:42 +08001247 /* This API should be called after decode_downstream_device_parameter_table_entry
1248 * has successfully decoded the entry, assume the entry data is valid here.
1249 */
1250 const size_t versions_len = entry->active_comp_ver_str_len +
1251 entry->pending_comp_ver_str_len;
1252 rc = pldm_msgbuf_init_errno(buf, versions_len, versions->ptr,
1253 versions->length);
1254 if (rc < 0) {
1255 return rc;
1256 }
1257
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001258 rc = pldm_msgbuf_extract_array(buf, entry->active_comp_ver_str_len,
Andrew Jefferya9892492024-10-03 14:07:17 +09301259 active, active_len);
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001260 if (rc < 0) {
1261 return rc;
1262 }
1263
Chris Wangb6ef35b2024-07-03 09:35:42 +08001264 active[entry->active_comp_ver_str_len] = '\0';
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001265 rc = pldm_msgbuf_extract_array(buf, entry->pending_comp_ver_str_len,
Andrew Jefferya9892492024-10-03 14:07:17 +09301266 pending, pending_len);
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001267 if (rc < 0) {
1268 return rc;
1269 }
1270
Chris Wangb6ef35b2024-07-03 09:35:42 +08001271 pending[entry->pending_comp_ver_str_len] = '\0';
1272
1273 entry->active_comp_ver_str = active;
1274 entry->pending_comp_ver_str = pending;
1275
1276 return pldm_msgbuf_destroy_consumed(buf);
1277}
1278
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301279LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301280int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1281 uint16_t num_of_comp,
1282 uint8_t max_outstanding_transfer_req,
1283 uint16_t pkg_data_len,
1284 uint8_t comp_image_set_ver_str_type,
1285 uint8_t comp_image_set_ver_str_len,
1286 const struct variable_field *comp_img_set_ver_str,
1287 struct pldm_msg *msg, size_t payload_length)
1288{
1289 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
1290 msg == NULL) {
1291 return PLDM_ERROR_INVALID_DATA;
1292 }
1293
1294 if (payload_length != sizeof(struct pldm_request_update_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301295 comp_img_set_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301296 return PLDM_ERROR_INVALID_LENGTH;
1297 }
1298
1299 if ((comp_image_set_ver_str_len == 0) ||
1300 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
1301 return PLDM_ERROR_INVALID_DATA;
1302 }
1303
1304 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
1305 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
1306 return PLDM_ERROR_INVALID_DATA;
1307 }
1308
1309 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
1310 return PLDM_ERROR_INVALID_DATA;
1311 }
1312
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301313 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301314 header.instance = instance_id;
1315 header.msg_type = PLDM_REQUEST;
1316 header.pldm_type = PLDM_FWUP;
1317 header.command = PLDM_REQUEST_UPDATE;
1318 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1319 if (rc) {
1320 return rc;
1321 }
1322
1323 struct pldm_request_update_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301324 (struct pldm_request_update_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301325
1326 request->max_transfer_size = htole32(max_transfer_size);
1327 request->num_of_comp = htole16(num_of_comp);
1328 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
1329 request->pkg_data_len = htole16(pkg_data_len);
1330 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
1331 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
1332
1333 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
1334 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
1335
1336 return PLDM_SUCCESS;
1337}
1338
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301339LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301340int decode_request_update_resp(const struct pldm_msg *msg,
1341 size_t payload_length, uint8_t *completion_code,
1342 uint16_t *fd_meta_data_len,
1343 uint8_t *fd_will_send_pkg_data)
1344{
1345 if (msg == NULL || completion_code == NULL ||
1346 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
1347 !payload_length) {
1348 return PLDM_ERROR_INVALID_DATA;
1349 }
1350
1351 *completion_code = msg->payload[0];
1352 if (*completion_code != PLDM_SUCCESS) {
1353 return PLDM_SUCCESS;
1354 }
1355
1356 if (payload_length != sizeof(struct pldm_request_update_resp)) {
1357 return PLDM_ERROR_INVALID_LENGTH;
1358 }
1359
1360 struct pldm_request_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301361 (struct pldm_request_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301362
1363 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
1364 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1365
1366 return PLDM_SUCCESS;
1367}
1368
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301369LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301370int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1371 uint16_t comp_classification,
1372 uint16_t comp_identifier,
1373 uint8_t comp_classification_index,
1374 uint32_t comp_comparison_stamp,
1375 uint8_t comp_ver_str_type,
1376 uint8_t comp_ver_str_len,
1377 const struct variable_field *comp_ver_str,
1378 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301379{
1380 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1381 return PLDM_ERROR_INVALID_DATA;
1382 }
1383
1384 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301385 comp_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301386 return PLDM_ERROR_INVALID_LENGTH;
1387 }
1388
1389 if ((comp_ver_str_len == 0) ||
1390 (comp_ver_str_len != comp_ver_str->length)) {
1391 return PLDM_ERROR_INVALID_DATA;
1392 }
1393
1394 if (!is_transfer_flag_valid(transfer_flag)) {
1395 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1396 }
1397
1398 if (!is_string_type_valid(comp_ver_str_type)) {
1399 return PLDM_ERROR_INVALID_DATA;
1400 }
1401
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301402 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301403 header.instance = instance_id;
1404 header.msg_type = PLDM_REQUEST;
1405 header.pldm_type = PLDM_FWUP;
1406 header.command = PLDM_PASS_COMPONENT_TABLE;
1407 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1408 if (rc) {
1409 return rc;
1410 }
1411
1412 struct pldm_pass_component_table_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301413 (struct pldm_pass_component_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301414
1415 request->transfer_flag = transfer_flag;
1416 request->comp_classification = htole16(comp_classification);
1417 request->comp_identifier = htole16(comp_identifier);
1418 request->comp_classification_index = comp_classification_index;
1419 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1420 request->comp_ver_str_type = comp_ver_str_type;
1421 request->comp_ver_str_len = comp_ver_str_len;
1422
1423 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1424 comp_ver_str->ptr, comp_ver_str->length);
1425
1426 return PLDM_SUCCESS;
1427}
1428
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301429LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301430int decode_pass_component_table_resp(const struct pldm_msg *msg,
1431 const size_t payload_length,
1432 uint8_t *completion_code,
1433 uint8_t *comp_resp,
1434 uint8_t *comp_resp_code)
1435{
1436 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1437 comp_resp_code == NULL || !payload_length) {
1438 return PLDM_ERROR_INVALID_DATA;
1439 }
1440
1441 *completion_code = msg->payload[0];
1442 if (*completion_code != PLDM_SUCCESS) {
1443 return PLDM_SUCCESS;
1444 }
1445
1446 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1447 return PLDM_ERROR_INVALID_LENGTH;
1448 }
1449
1450 struct pldm_pass_component_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301451 (struct pldm_pass_component_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301452
1453 if (!is_comp_resp_valid(response->comp_resp)) {
1454 return PLDM_ERROR_INVALID_DATA;
1455 }
1456
1457 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1458 return PLDM_ERROR_INVALID_DATA;
1459 }
1460
1461 *comp_resp = response->comp_resp;
1462 *comp_resp_code = response->comp_resp_code;
1463
1464 return PLDM_SUCCESS;
1465}
1466
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301467LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301468int encode_update_component_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301469 uint8_t instance_id, uint16_t comp_classification,
1470 uint16_t comp_identifier, uint8_t comp_classification_index,
1471 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1472 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1473 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1474 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301475{
1476 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1477 return PLDM_ERROR_INVALID_DATA;
1478 }
1479
1480 if (payload_length !=
1481 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1482 return PLDM_ERROR_INVALID_LENGTH;
1483 }
1484
1485 if (!comp_image_size) {
1486 return PLDM_ERROR_INVALID_DATA;
1487 }
1488
1489 if ((comp_ver_str_len == 0) ||
1490 (comp_ver_str_len != comp_ver_str->length)) {
1491 return PLDM_ERROR_INVALID_DATA;
1492 }
1493
1494 if (!is_string_type_valid(comp_ver_str_type)) {
1495 return PLDM_ERROR_INVALID_DATA;
1496 }
1497
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301498 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301499 header.instance = instance_id;
1500 header.msg_type = PLDM_REQUEST;
1501 header.pldm_type = PLDM_FWUP;
1502 header.command = PLDM_UPDATE_COMPONENT;
1503 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1504 if (rc) {
1505 return rc;
1506 }
1507
1508 struct pldm_update_component_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301509 (struct pldm_update_component_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301510
1511 request->comp_classification = htole16(comp_classification);
1512 request->comp_identifier = htole16(comp_identifier);
1513 request->comp_classification_index = comp_classification_index;
1514 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1515 request->comp_image_size = htole32(comp_image_size);
1516 request->update_option_flags.value = htole32(update_option_flags.value);
1517 request->comp_ver_str_type = comp_ver_str_type;
1518 request->comp_ver_str_len = comp_ver_str_len;
1519
1520 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1521 comp_ver_str->ptr, comp_ver_str->length);
1522
1523 return PLDM_SUCCESS;
1524}
1525
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301526LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301527int decode_update_component_resp(const struct pldm_msg *msg,
1528 size_t payload_length,
1529 uint8_t *completion_code,
1530 uint8_t *comp_compatibility_resp,
1531 uint8_t *comp_compatibility_resp_code,
1532 bitfield32_t *update_option_flags_enabled,
1533 uint16_t *time_before_req_fw_data)
1534{
1535 if (msg == NULL || completion_code == NULL ||
1536 comp_compatibility_resp == NULL ||
1537 comp_compatibility_resp_code == NULL ||
1538 update_option_flags_enabled == NULL ||
1539 time_before_req_fw_data == NULL || !payload_length) {
1540 return PLDM_ERROR_INVALID_DATA;
1541 }
1542
1543 *completion_code = msg->payload[0];
1544 if (*completion_code != PLDM_SUCCESS) {
1545 return PLDM_SUCCESS;
1546 }
1547
1548 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1549 return PLDM_ERROR_INVALID_LENGTH;
1550 }
1551
1552 struct pldm_update_component_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301553 (struct pldm_update_component_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301554
1555 if (!is_comp_compatibility_resp_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301556 response->comp_compatibility_resp)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301557 return PLDM_ERROR_INVALID_DATA;
1558 }
1559
1560 if (!is_comp_compatibility_resp_code_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301561 response->comp_compatibility_resp_code)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301562 return PLDM_ERROR_INVALID_DATA;
1563 }
1564
1565 *comp_compatibility_resp = response->comp_compatibility_resp;
1566 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1567 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301568 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301569 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1570
1571 return PLDM_SUCCESS;
1572}
1573
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301574LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301575int decode_request_firmware_data_req(const struct pldm_msg *msg,
1576 size_t payload_length, uint32_t *offset,
1577 uint32_t *length)
1578{
1579 if (msg == NULL || offset == NULL || length == NULL) {
1580 return PLDM_ERROR_INVALID_DATA;
1581 }
1582 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1583 return PLDM_ERROR_INVALID_LENGTH;
1584 }
1585 struct pldm_request_firmware_data_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301586 (struct pldm_request_firmware_data_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301587 *offset = le32toh(request->offset);
1588 *length = le32toh(request->length);
1589
1590 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1591 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1592 }
1593
1594 return PLDM_SUCCESS;
1595}
1596
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301597LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301598int encode_request_firmware_data_resp(uint8_t instance_id,
1599 uint8_t completion_code,
1600 struct pldm_msg *msg,
1601 size_t payload_length)
1602{
1603 if (msg == NULL || !payload_length) {
1604 return PLDM_ERROR_INVALID_DATA;
1605 }
1606
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301607 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301608 header.instance = instance_id;
1609 header.msg_type = PLDM_RESPONSE;
1610 header.pldm_type = PLDM_FWUP;
1611 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1612 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1613 if (rc) {
1614 return rc;
1615 }
1616
1617 msg->payload[0] = completion_code;
1618
1619 return PLDM_SUCCESS;
1620}
1621
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301622LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301623int decode_transfer_complete_req(const struct pldm_msg *msg,
1624 size_t payload_length,
1625 uint8_t *transfer_result)
1626{
1627 if (msg == NULL || transfer_result == NULL) {
1628 return PLDM_ERROR_INVALID_DATA;
1629 }
1630
1631 if (payload_length != sizeof(*transfer_result)) {
1632 return PLDM_ERROR_INVALID_LENGTH;
1633 }
1634
1635 *transfer_result = msg->payload[0];
1636 return PLDM_SUCCESS;
1637}
1638
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301639LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301640int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1641 struct pldm_msg *msg, size_t payload_length)
1642{
1643 if (msg == NULL) {
1644 return PLDM_ERROR_INVALID_DATA;
1645 }
1646
1647 if (payload_length != sizeof(completion_code)) {
1648 return PLDM_ERROR_INVALID_LENGTH;
1649 }
1650
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301651 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301652 header.instance = instance_id;
1653 header.msg_type = PLDM_RESPONSE;
1654 header.pldm_type = PLDM_FWUP;
1655 header.command = PLDM_TRANSFER_COMPLETE;
1656 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1657 if (rc) {
1658 return rc;
1659 }
1660
1661 msg->payload[0] = completion_code;
1662
1663 return PLDM_SUCCESS;
1664}
1665
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301666LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301667int decode_verify_complete_req(const struct pldm_msg *msg,
1668 size_t payload_length, uint8_t *verify_result)
1669{
1670 if (msg == NULL || verify_result == NULL) {
1671 return PLDM_ERROR_INVALID_DATA;
1672 }
1673
1674 if (payload_length != sizeof(*verify_result)) {
1675 return PLDM_ERROR_INVALID_LENGTH;
1676 }
1677
1678 *verify_result = msg->payload[0];
1679 return PLDM_SUCCESS;
1680}
1681
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301682LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301683int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1684 struct pldm_msg *msg, size_t payload_length)
1685{
1686 if (msg == NULL) {
1687 return PLDM_ERROR_INVALID_DATA;
1688 }
1689
1690 if (payload_length != sizeof(completion_code)) {
1691 return PLDM_ERROR_INVALID_LENGTH;
1692 }
1693
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301694 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301695 header.instance = instance_id;
1696 header.msg_type = PLDM_RESPONSE;
1697 header.pldm_type = PLDM_FWUP;
1698 header.command = PLDM_VERIFY_COMPLETE;
1699 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1700 if (rc) {
1701 return rc;
1702 }
1703
1704 msg->payload[0] = completion_code;
1705
1706 return PLDM_SUCCESS;
1707}
1708
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301709LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301710int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
1711 uint8_t *apply_result,
1712 bitfield16_t *comp_activation_methods_modification)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301713{
1714 if (msg == NULL || apply_result == NULL ||
1715 comp_activation_methods_modification == NULL) {
1716 return PLDM_ERROR_INVALID_DATA;
1717 }
1718
1719 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1720 return PLDM_ERROR_INVALID_LENGTH;
1721 }
1722
1723 struct pldm_apply_complete_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301724 (struct pldm_apply_complete_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301725
1726 *apply_result = request->apply_result;
1727 comp_activation_methods_modification->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301728 le16toh(request->comp_activation_methods_modification.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301729
1730 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1731 comp_activation_methods_modification->value) {
1732 return PLDM_ERROR_INVALID_DATA;
1733 }
1734
1735 return PLDM_SUCCESS;
1736}
1737
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301738LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301739int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1740 struct pldm_msg *msg, size_t payload_length)
1741{
1742 if (msg == NULL) {
1743 return PLDM_ERROR_INVALID_DATA;
1744 }
1745
1746 if (payload_length != sizeof(completion_code)) {
1747 return PLDM_ERROR_INVALID_LENGTH;
1748 }
1749
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301750 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301751 header.instance = instance_id;
1752 header.msg_type = PLDM_RESPONSE;
1753 header.pldm_type = PLDM_FWUP;
1754 header.command = PLDM_APPLY_COMPLETE;
1755 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1756 if (rc) {
1757 return rc;
1758 }
1759
1760 msg->payload[0] = completion_code;
1761
1762 return PLDM_SUCCESS;
1763}
1764
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301765LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301766int encode_activate_firmware_req(uint8_t instance_id,
1767 bool8_t self_contained_activation_req,
1768 struct pldm_msg *msg, size_t payload_length)
1769{
1770 if (msg == NULL) {
1771 return PLDM_ERROR_INVALID_DATA;
1772 }
1773
1774 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1775 return PLDM_ERROR_INVALID_LENGTH;
1776 }
1777
1778 if (!is_self_contained_activation_req_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301779 self_contained_activation_req)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301780 return PLDM_ERROR_INVALID_DATA;
1781 }
1782
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301783 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301784 header.instance = instance_id;
1785 header.msg_type = PLDM_REQUEST;
1786 header.pldm_type = PLDM_FWUP;
1787 header.command = PLDM_ACTIVATE_FIRMWARE;
1788 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1789 if (rc) {
1790 return rc;
1791 }
1792
1793 struct pldm_activate_firmware_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301794 (struct pldm_activate_firmware_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301795
1796 request->self_contained_activation_req = self_contained_activation_req;
1797
1798 return PLDM_SUCCESS;
1799}
1800
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301801LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301802int decode_activate_firmware_resp(const struct pldm_msg *msg,
1803 size_t payload_length,
1804 uint8_t *completion_code,
1805 uint16_t *estimated_time_activation)
1806{
1807 if (msg == NULL || completion_code == NULL ||
1808 estimated_time_activation == NULL || !payload_length) {
1809 return PLDM_ERROR_INVALID_DATA;
1810 }
1811
1812 *completion_code = msg->payload[0];
1813 if (*completion_code != PLDM_SUCCESS) {
1814 return PLDM_SUCCESS;
1815 }
1816
1817 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1818 return PLDM_ERROR_INVALID_LENGTH;
1819 }
1820
1821 struct pldm_activate_firmware_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301822 (struct pldm_activate_firmware_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301823
1824 *estimated_time_activation =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301825 le16toh(response->estimated_time_activation);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301826
1827 return PLDM_SUCCESS;
1828}
1829
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301830LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301831int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1832 size_t payload_length)
1833{
1834 if (msg == NULL) {
1835 return PLDM_ERROR_INVALID_DATA;
1836 }
1837
1838 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1839 return PLDM_ERROR_INVALID_LENGTH;
1840 }
1841
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301842 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301843 header.instance = instance_id;
1844 header.msg_type = PLDM_REQUEST;
1845 header.pldm_type = PLDM_FWUP;
1846 header.command = PLDM_GET_STATUS;
1847 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1848 if (rc) {
1849 return rc;
1850 }
1851
1852 return PLDM_SUCCESS;
1853}
1854
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301855LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301856int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1857 uint8_t *completion_code, uint8_t *current_state,
1858 uint8_t *previous_state, uint8_t *aux_state,
1859 uint8_t *aux_state_status, uint8_t *progress_percent,
1860 uint8_t *reason_code,
1861 bitfield32_t *update_option_flags_enabled)
1862{
1863 if (msg == NULL || completion_code == NULL || current_state == NULL ||
1864 previous_state == NULL || aux_state == NULL ||
1865 aux_state_status == NULL || progress_percent == NULL ||
1866 reason_code == NULL || update_option_flags_enabled == NULL ||
1867 !payload_length) {
1868 return PLDM_ERROR_INVALID_DATA;
1869 }
1870
1871 *completion_code = msg->payload[0];
1872 if (*completion_code != PLDM_SUCCESS) {
1873 return PLDM_SUCCESS;
1874 }
1875
1876 if (payload_length != sizeof(struct pldm_get_status_resp)) {
1877 return PLDM_ERROR_INVALID_LENGTH;
1878 }
1879 struct pldm_get_status_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301880 (struct pldm_get_status_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301881
1882 if (!is_state_valid(response->current_state)) {
1883 return PLDM_ERROR_INVALID_DATA;
1884 }
1885 if (!is_state_valid(response->previous_state)) {
1886 return PLDM_ERROR_INVALID_DATA;
1887 }
1888 if (!is_aux_state_valid(response->aux_state)) {
1889 return PLDM_ERROR_INVALID_DATA;
1890 }
1891 if (!is_aux_state_status_valid(response->aux_state_status)) {
1892 return PLDM_ERROR_INVALID_DATA;
1893 }
1894 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1895 return PLDM_ERROR_INVALID_DATA;
1896 }
1897 if (!is_reason_code_valid(response->reason_code)) {
1898 return PLDM_ERROR_INVALID_DATA;
1899 }
1900
1901 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1902 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1903 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1904 if (response->aux_state !=
1905 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1906 return PLDM_ERROR_INVALID_DATA;
1907 }
1908 }
1909
1910 *current_state = response->current_state;
1911 *previous_state = response->previous_state;
1912 *aux_state = response->aux_state;
1913 *aux_state_status = response->aux_state_status;
1914 *progress_percent = response->progress_percent;
1915 *reason_code = response->reason_code;
1916 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301917 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301918
1919 return PLDM_SUCCESS;
1920}
1921
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301922LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301923int encode_cancel_update_component_req(uint8_t instance_id,
1924 struct pldm_msg *msg,
1925 size_t payload_length)
1926{
1927 if (msg == NULL) {
1928 return PLDM_ERROR_INVALID_DATA;
1929 }
1930
1931 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1932 return PLDM_ERROR_INVALID_LENGTH;
1933 }
1934
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301935 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301936 header.instance = instance_id;
1937 header.msg_type = PLDM_REQUEST;
1938 header.pldm_type = PLDM_FWUP;
1939 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
1940 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1941 if (rc) {
1942 return rc;
1943 }
1944
1945 return PLDM_SUCCESS;
1946}
1947
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301948LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301949int decode_cancel_update_component_resp(const struct pldm_msg *msg,
1950 size_t payload_length,
1951 uint8_t *completion_code)
1952{
1953 if (msg == NULL || completion_code == NULL) {
1954 return PLDM_ERROR_INVALID_DATA;
1955 }
1956
1957 if (payload_length != sizeof(*completion_code)) {
1958 return PLDM_ERROR_INVALID_LENGTH;
1959 }
1960
1961 *completion_code = msg->payload[0];
1962 return PLDM_SUCCESS;
1963}
1964
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301965LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301966int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
1967 size_t payload_length)
1968{
1969 if (msg == NULL) {
1970 return PLDM_ERROR_INVALID_DATA;
1971 }
1972
1973 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
1974 return PLDM_ERROR_INVALID_LENGTH;
1975 }
1976
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301977 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301978 header.instance = instance_id;
1979 header.msg_type = PLDM_REQUEST;
1980 header.pldm_type = PLDM_FWUP;
1981 header.command = PLDM_CANCEL_UPDATE;
1982 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1983 if (rc) {
1984 return rc;
1985 }
1986
1987 return PLDM_SUCCESS;
1988}
1989
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301990LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301991int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
1992 uint8_t *completion_code,
1993 bool8_t *non_functioning_component_indication,
1994 bitfield64_t *non_functioning_component_bitmap)
1995{
1996 if (msg == NULL || completion_code == NULL ||
1997 non_functioning_component_indication == NULL ||
1998 non_functioning_component_bitmap == NULL || !payload_length) {
1999 return PLDM_ERROR_INVALID_DATA;
2000 }
2001
2002 *completion_code = msg->payload[0];
2003 if (*completion_code != PLDM_SUCCESS) {
2004 return PLDM_SUCCESS;
2005 }
2006
2007 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
2008 return PLDM_ERROR_INVALID_LENGTH;
2009 }
2010 struct pldm_cancel_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302011 (struct pldm_cancel_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302012
2013 if (!is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302014 response->non_functioning_component_indication)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09302015 return PLDM_ERROR_INVALID_DATA;
2016 }
2017
2018 *non_functioning_component_indication =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302019 response->non_functioning_component_indication;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302020
2021 if (*non_functioning_component_indication) {
2022 non_functioning_component_bitmap->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302023 le64toh(response->non_functioning_component_bitmap);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302024 }
2025
2026 return PLDM_SUCCESS;
2027}