blob: 5c571717f84b807cb61e0ae2b21d9da613f35cf1 [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
Matt Johnstoncf9a2df2024-11-07 15:29:29 +080012static_assert(PLDM_FIRMWARE_MAX_STRING <= UINT8_MAX, "too large");
13
Andrew Jeffery9c766792022-08-10 23:12:49 +093014/** @brief Check whether string type value is valid
15 *
16 * @return true if string type value is valid, false if not
17 */
18static bool is_string_type_valid(uint8_t string_type)
19{
20 switch (string_type) {
21 case PLDM_STR_TYPE_UNKNOWN:
22 return false;
23 case PLDM_STR_TYPE_ASCII:
24 case PLDM_STR_TYPE_UTF_8:
25 case PLDM_STR_TYPE_UTF_16:
26 case PLDM_STR_TYPE_UTF_16LE:
27 case PLDM_STR_TYPE_UTF_16BE:
28 return true;
29 default:
30 return false;
31 }
32}
33
34/** @brief Return the length of the descriptor type described in firmware update
35 * specification
36 *
37 * @return length of the descriptor type if descriptor type is valid else
38 * return 0
39 */
40static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
41{
42 switch (descriptor_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093043 case PLDM_FWUP_PCI_VENDOR_ID:
44 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
45 case PLDM_FWUP_IANA_ENTERPRISE_ID:
46 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
47 case PLDM_FWUP_UUID:
48 return PLDM_FWUP_UUID_LENGTH;
49 case PLDM_FWUP_PNP_VENDOR_ID:
50 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
51 case PLDM_FWUP_ACPI_VENDOR_ID:
52 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
53 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
54 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
55 case PLDM_FWUP_SCSI_VENDOR_ID:
56 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
57 case PLDM_FWUP_PCI_DEVICE_ID:
58 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
59 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
60 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
61 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
62 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
63 case PLDM_FWUP_PCI_REVISION_ID:
64 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
65 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
66 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
67 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
68 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
69 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
70 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
71 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
72 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
73 case PLDM_FWUP_SCSI_PRODUCT_ID:
74 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
75 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
76 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
77 default:
78 return 0;
79 }
80}
81
Chris Wang4c1f2c72024-03-21 17:09:44 +080082static bool is_downstream_device_update_support_valid(uint8_t resp)
83{
84 switch (resp) {
85 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
86 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
87 return true;
88 default:
89 return false;
90 }
91}
92
Chris Wang458475a2024-03-26 17:59:19 +080093static bool
94is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)
95{
96 switch (transfer_op_flag) {
97 case PLDM_GET_NEXTPART:
98 case PLDM_GET_FIRSTPART:
99 return true;
100 default:
101 return false;
102 }
103}
104
Andrew Jeffery9c766792022-08-10 23:12:49 +0930105/** @brief Check whether ComponentResponse is valid
106 *
107 * @return true if ComponentResponse is valid, false if not
108 */
109static bool is_comp_resp_valid(uint8_t comp_resp)
110{
111 switch (comp_resp) {
112 case PLDM_CR_COMP_CAN_BE_UPDATED:
113 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
114 return true;
115
116 default:
117 return false;
118 }
119}
120
121/** @brief Check whether ComponentResponseCode is valid
122 *
123 * @return true if ComponentResponseCode is valid, false if not
124 */
125static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
126{
127 switch (comp_resp_code) {
128 case PLDM_CRC_COMP_CAN_BE_UPDATED:
129 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
130 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
131 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
132 case PLDM_CRC_COMP_CONFLICT:
133 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
134 case PLDM_CRC_COMP_NOT_SUPPORTED:
135 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
136 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
137 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
138 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
139 case PLDM_CRC_COMP_VER_STR_LOWER:
140 return true;
141
142 default:
143 if (comp_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930144 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930145 comp_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930146 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930147 return true;
148 }
149 return false;
150 }
151}
152
153/** @brief Check whether ComponentCompatibilityResponse is valid
154 *
155 * @return true if ComponentCompatibilityResponse is valid, false if not
156 */
157static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
158{
159 switch (comp_compatibility_resp) {
160 case PLDM_CCR_COMP_CAN_BE_UPDATED:
161 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
162 return true;
163
164 default:
165 return false;
166 }
167}
168
169/** @brief Check whether ComponentCompatibilityResponse Code is valid
170 *
171 * @return true if ComponentCompatibilityResponse Code is valid, false if not
172 */
173static bool
174is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
175{
176 switch (comp_compatibility_resp_code) {
177 case PLDM_CCRC_NO_RESPONSE_CODE:
178 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
179 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
180 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
181 case PLDM_CCRC_COMP_CONFLICT:
182 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
183 case PLDM_CCRC_COMP_NOT_SUPPORTED:
184 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
185 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
186 case PLDM_CCRC_COMP_INFO_NO_MATCH:
187 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
188 case PLDM_CCRC_COMP_VER_STR_LOWER:
189 return true;
190
191 default:
192 if (comp_compatibility_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930193 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930194 comp_compatibility_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930195 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930196 return true;
197 }
198 return false;
199 }
200}
201
202/** @brief Check whether SelfContainedActivationRequest is valid
203 *
204 * @return true if SelfContainedActivationRequest is valid, false if not
205 */
206static bool
207is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
208{
209 switch (self_contained_activation_req) {
210 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
211 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
212 return true;
213
214 default:
215 return false;
216 }
217}
218
219/** @brief Check if current or previous status in GetStatus command response is
220 * valid
221 *
222 * @param[in] state - current or previous different state machine state of
223 * the FD
224 * @return true if state is valid, false if not
225 */
226static bool is_state_valid(uint8_t state)
227{
228 switch (state) {
229 case PLDM_FD_STATE_IDLE:
230 case PLDM_FD_STATE_LEARN_COMPONENTS:
231 case PLDM_FD_STATE_READY_XFER:
232 case PLDM_FD_STATE_DOWNLOAD:
233 case PLDM_FD_STATE_VERIFY:
234 case PLDM_FD_STATE_APPLY:
235 case PLDM_FD_STATE_ACTIVATE:
236 return true;
237
238 default:
239 return false;
240 }
241}
242
243/** @brief Check if aux state in GetStatus command response is valid
244 *
245 * @param[in] aux_state - provides additional information to the UA to describe
246 * the current operation state of the FD/FDP
247 *
248 * @return true if aux state is valid, false if not
249 */
250static bool is_aux_state_valid(uint8_t aux_state)
251{
252 switch (aux_state) {
253 case PLDM_FD_OPERATION_IN_PROGRESS:
254 case PLDM_FD_OPERATION_SUCCESSFUL:
255 case PLDM_FD_OPERATION_FAILED:
256 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
257 return true;
258
259 default:
260 return false;
261 }
262}
263
264/** @brief Check if aux state status in GetStatus command response is valid
265 *
266 * @param[in] aux_state_status - aux state status
267 *
268 * @return true if aux state status is valid, false if not
269 */
270static bool is_aux_state_status_valid(uint8_t aux_state_status)
271{
272 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
273 aux_state_status == PLDM_FD_TIMEOUT ||
Andrew Jeffery67f7ed92023-04-05 14:00:00 +0930274 aux_state_status == PLDM_FD_GENERIC_ERROR ||
275 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
276 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930277 return true;
278 }
279
280 return false;
281}
282
283/** @brief Check if reason code in GetStatus command response is valid
284 *
285 * @param[in] reason_code - provides the reason for why the current state
286 * entered the IDLE state
287 *
288 * @return true if reason code is valid, false if not
289 */
290static bool is_reason_code_valid(uint8_t reason_code)
291{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930292 switch (reason_code) {
293 case PLDM_FD_INITIALIZATION:
294 case PLDM_FD_ACTIVATE_FW:
295 case PLDM_FD_CANCEL_UPDATE:
296 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
297 case PLDM_FD_TIMEOUT_READY_XFER:
298 case PLDM_FD_TIMEOUT_DOWNLOAD:
299 case PLDM_FD_TIMEOUT_VERIFY:
300 case PLDM_FD_TIMEOUT_APPLY:
301 return true;
302
303 default:
304 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
305 return true;
306 }
307 return false;
308 }
309}
310
311/** @brief Check if non functioning component indication in CancelUpdate
312 * response is valid
313 *
314 * @return true if non functioning component indication is valid, false if not
315 */
316static bool is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930317 bool8_t non_functioning_component_indication)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930318{
319 switch (non_functioning_component_indication) {
320 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
321 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
322 return true;
323
324 default:
325 return false;
326 }
327}
328
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930329LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930330int decode_pldm_package_header_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930331 const uint8_t *data, size_t length,
332 struct pldm_package_header_information *package_header_info,
333 struct variable_field *package_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930334{
335 if (data == NULL || package_header_info == NULL ||
336 package_version_str == NULL) {
337 return PLDM_ERROR_INVALID_DATA;
338 }
339
340 if (length < sizeof(struct pldm_package_header_information)) {
341 return PLDM_ERROR_INVALID_LENGTH;
342 }
343
344 struct pldm_package_header_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930345 (struct pldm_package_header_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930346
347 if (!is_string_type_valid(data_header->package_version_string_type) ||
348 (data_header->package_version_string_length == 0)) {
349 return PLDM_ERROR_INVALID_DATA;
350 }
351
352 if (length < sizeof(struct pldm_package_header_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930353 data_header->package_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930354 return PLDM_ERROR_INVALID_LENGTH;
355 }
356
357 if ((data_header->component_bitmap_bit_length %
358 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
359 return PLDM_ERROR_INVALID_DATA;
360 }
361
362 memcpy(package_header_info->uuid, data_header->uuid,
363 sizeof(data_header->uuid));
364 package_header_info->package_header_format_version =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930365 data_header->package_header_format_version;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930366 package_header_info->package_header_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930367 le16toh(data_header->package_header_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930368 memcpy(package_header_info->package_release_date_time,
369 data_header->package_release_date_time,
370 sizeof(data_header->package_release_date_time));
371 package_header_info->component_bitmap_bit_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930372 le16toh(data_header->component_bitmap_bit_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930373 package_header_info->package_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930374 data_header->package_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930375 package_header_info->package_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930376 data_header->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930377 package_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930378 data + sizeof(struct pldm_package_header_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930379 package_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930380 package_header_info->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930381
382 return PLDM_SUCCESS;
383}
384
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930385LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930386int decode_firmware_device_id_record(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930387 const uint8_t *data, size_t length,
388 uint16_t component_bitmap_bit_length,
389 struct pldm_firmware_device_id_record *fw_device_id_record,
390 struct variable_field *applicable_components,
391 struct variable_field *comp_image_set_version_str,
392 struct variable_field *record_descriptors,
393 struct variable_field *fw_device_pkg_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930394{
395 if (data == NULL || fw_device_id_record == NULL ||
396 applicable_components == NULL ||
397 comp_image_set_version_str == NULL || record_descriptors == NULL ||
398 fw_device_pkg_data == NULL) {
399 return PLDM_ERROR_INVALID_DATA;
400 }
401
402 if (length < sizeof(struct pldm_firmware_device_id_record)) {
403 return PLDM_ERROR_INVALID_LENGTH;
404 }
405
406 if ((component_bitmap_bit_length %
407 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
408 return PLDM_ERROR_INVALID_DATA;
409 }
410
411 struct pldm_firmware_device_id_record *data_record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930412 (struct pldm_firmware_device_id_record *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930413
414 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930415 data_record->comp_image_set_version_string_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930416 (data_record->comp_image_set_version_string_length == 0)) {
417 return PLDM_ERROR_INVALID_DATA;
418 }
419
420 fw_device_id_record->record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930421 le16toh(data_record->record_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930422 fw_device_id_record->descriptor_count = data_record->descriptor_count;
423 fw_device_id_record->device_update_option_flags.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930424 le32toh(data_record->device_update_option_flags.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930425 fw_device_id_record->comp_image_set_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930426 data_record->comp_image_set_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930427 fw_device_id_record->comp_image_set_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930428 data_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930429 fw_device_id_record->fw_device_pkg_data_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930430 le16toh(data_record->fw_device_pkg_data_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930431
432 if (length < fw_device_id_record->record_length) {
433 return PLDM_ERROR_INVALID_LENGTH;
434 }
435
436 uint16_t applicable_components_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930437 component_bitmap_bit_length /
438 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930439 uint16_t calc_min_record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930440 sizeof(struct pldm_firmware_device_id_record) +
441 applicable_components_length +
442 data_record->comp_image_set_version_string_length +
443 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
444 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930445
446 if (fw_device_id_record->record_length < calc_min_record_length) {
447 return PLDM_ERROR_INVALID_LENGTH;
448 }
449
450 applicable_components->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930451 data + sizeof(struct pldm_firmware_device_id_record);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930452 applicable_components->length = applicable_components_length;
453
454 comp_image_set_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930455 applicable_components->ptr + applicable_components->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930456 comp_image_set_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930457 fw_device_id_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930458
459 record_descriptors->ptr = comp_image_set_version_str->ptr +
460 comp_image_set_version_str->length;
461 record_descriptors->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930462 fw_device_id_record->record_length -
463 sizeof(struct pldm_firmware_device_id_record) -
464 applicable_components_length -
465 fw_device_id_record->comp_image_set_version_string_length -
466 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930467
468 if (fw_device_id_record->fw_device_pkg_data_length) {
469 fw_device_pkg_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930470 record_descriptors->ptr + record_descriptors->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930471 fw_device_pkg_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930472 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930473 }
474
475 return PLDM_SUCCESS;
476}
477
Andrew Jeffery3a2c6582024-11-07 16:30:36 +1030478LIBPLDM_ABI_TESTING
479int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter,
480 struct pldm_descriptor *desc)
481{
482 struct pldm_msgbuf _buf;
483 struct pldm_msgbuf *buf = &_buf;
484 int rc;
485
486 if (!iter || !iter->field || !desc) {
487 return -EINVAL;
488 }
489
490 rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN,
491 iter->field->ptr, iter->field->length);
492 if (rc) {
493 return rc;
494 }
495
496 pldm_msgbuf_extract(buf, desc->descriptor_type);
497 rc = pldm_msgbuf_extract(buf, desc->descriptor_length);
498 if (rc) {
499 return rc;
500 }
501
502 desc->descriptor_data = NULL;
503 pldm_msgbuf_span_required(buf, desc->descriptor_length,
504 (void **)&desc->descriptor_data);
505 iter->field->ptr = NULL;
506 pldm_msgbuf_span_remaining(buf, (void **)&iter->field->ptr,
507 &iter->field->length);
508
509 return pldm_msgbuf_destroy(buf);
510}
511
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930512LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930513int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
514 uint16_t *descriptor_type,
515 struct variable_field *descriptor_data)
516{
517 uint16_t descriptor_length = 0;
518
519 if (data == NULL || descriptor_type == NULL ||
520 descriptor_data == NULL) {
521 return PLDM_ERROR_INVALID_DATA;
522 }
523
524 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
525 return PLDM_ERROR_INVALID_LENGTH;
526 }
527
528 struct pldm_descriptor_tlv *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930529 (struct pldm_descriptor_tlv *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930530
531 *descriptor_type = le16toh(entry->descriptor_type);
532 descriptor_length = le16toh(entry->descriptor_length);
533 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
534 if (descriptor_length !=
535 get_descriptor_type_length(*descriptor_type)) {
536 return PLDM_ERROR_INVALID_LENGTH;
537 }
538 }
539
540 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
541 descriptor_length)) {
542 return PLDM_ERROR_INVALID_LENGTH;
543 }
544
545 descriptor_data->ptr = entry->descriptor_data;
546 descriptor_data->length = descriptor_length;
547
548 return PLDM_SUCCESS;
549}
550
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930551LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930552int decode_vendor_defined_descriptor_value(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930553 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
554 struct variable_field *descriptor_title_str,
555 struct variable_field *descriptor_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930556{
557 if (data == NULL || descriptor_title_str_type == NULL ||
558 descriptor_title_str == NULL || descriptor_data == NULL) {
559 return PLDM_ERROR_INVALID_DATA;
560 }
561
562 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
563 return PLDM_ERROR_INVALID_LENGTH;
564 }
565
566 struct pldm_vendor_defined_descriptor_title_data *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930567 (struct pldm_vendor_defined_descriptor_title_data *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930568 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930569 entry->vendor_defined_descriptor_title_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930570 (entry->vendor_defined_descriptor_title_str_len == 0)) {
571 return PLDM_ERROR_INVALID_DATA;
572 }
573
Manojkiran Eda9e3a5d42024-06-17 16:06:42 +0530574 // Assuming at least 1 byte of VendorDefinedDescriptorData
Andrew Jeffery9c766792022-08-10 23:12:49 +0930575 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
576 entry->vendor_defined_descriptor_title_str_len)) {
577 return PLDM_ERROR_INVALID_LENGTH;
578 }
579
580 *descriptor_title_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930581 entry->vendor_defined_descriptor_title_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930582 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
583 descriptor_title_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930584 entry->vendor_defined_descriptor_title_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930585
586 descriptor_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930587 descriptor_title_str->ptr + descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930588 descriptor_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930589 length -
590 sizeof(entry->vendor_defined_descriptor_title_str_type) -
591 sizeof(entry->vendor_defined_descriptor_title_str_len) -
592 descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930593
594 return PLDM_SUCCESS;
595}
596
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930597LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930598int decode_pldm_comp_image_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930599 const uint8_t *data, size_t length,
600 struct pldm_component_image_information *pldm_comp_image_info,
601 struct variable_field *comp_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930602{
603 if (data == NULL || pldm_comp_image_info == NULL ||
604 comp_version_str == NULL) {
605 return PLDM_ERROR_INVALID_DATA;
606 }
607
608 if (length < sizeof(struct pldm_component_image_information)) {
609 return PLDM_ERROR_INVALID_LENGTH;
610 }
611
612 struct pldm_component_image_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930613 (struct pldm_component_image_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930614
615 if (!is_string_type_valid(data_header->comp_version_string_type) ||
616 (data_header->comp_version_string_length == 0)) {
617 return PLDM_ERROR_INVALID_DATA;
618 }
619
620 if (length < sizeof(struct pldm_component_image_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930621 data_header->comp_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930622 return PLDM_ERROR_INVALID_LENGTH;
623 }
624
625 pldm_comp_image_info->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930626 le16toh(data_header->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930627 pldm_comp_image_info->comp_identifier =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930628 le16toh(data_header->comp_identifier);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930629 pldm_comp_image_info->comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930630 le32toh(data_header->comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930631 pldm_comp_image_info->comp_options.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930632 le16toh(data_header->comp_options.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930633 pldm_comp_image_info->requested_comp_activation_method.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930634 le16toh(data_header->requested_comp_activation_method.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930635 pldm_comp_image_info->comp_location_offset =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930636 le32toh(data_header->comp_location_offset);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930637 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
638 pldm_comp_image_info->comp_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930639 data_header->comp_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930640 pldm_comp_image_info->comp_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930641 data_header->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930642
643 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
644 pldm_comp_image_info->comp_comparison_stamp !=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930645 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930646 return PLDM_ERROR_INVALID_DATA;
647 }
648
649 if (pldm_comp_image_info->comp_location_offset == 0 ||
650 pldm_comp_image_info->comp_size == 0) {
651 return PLDM_ERROR_INVALID_DATA;
652 }
653
654 comp_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930655 data + sizeof(struct pldm_component_image_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930656 comp_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930657 pldm_comp_image_info->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930658
659 return PLDM_SUCCESS;
660}
661
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930662LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930663int encode_query_device_identifiers_req(uint8_t instance_id,
664 size_t payload_length,
665 struct pldm_msg *msg)
666{
667 if (msg == NULL) {
668 return PLDM_ERROR_INVALID_DATA;
669 }
670
671 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
672 return PLDM_ERROR_INVALID_LENGTH;
673 }
674
675 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
676 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
677}
678
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930679LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930680int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
681 size_t payload_length,
682 uint8_t *completion_code,
683 uint32_t *device_identifiers_len,
684 uint8_t *descriptor_count,
685 uint8_t **descriptor_data)
686{
687 if (msg == NULL || completion_code == NULL ||
688 device_identifiers_len == NULL || descriptor_count == NULL ||
689 descriptor_data == NULL) {
690 return PLDM_ERROR_INVALID_DATA;
691 }
692
693 *completion_code = msg->payload[0];
694 if (PLDM_SUCCESS != *completion_code) {
695 return PLDM_SUCCESS;
696 }
697
698 if (payload_length <
699 sizeof(struct pldm_query_device_identifiers_resp)) {
700 return PLDM_ERROR_INVALID_LENGTH;
701 }
702
703 struct pldm_query_device_identifiers_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930704 (struct pldm_query_device_identifiers_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930705 *device_identifiers_len = le32toh(response->device_identifiers_len);
706
707 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
708 return PLDM_ERROR_INVALID_LENGTH;
709 }
710
711 if (payload_length !=
712 sizeof(struct pldm_query_device_identifiers_resp) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930713 *device_identifiers_len) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930714 return PLDM_ERROR_INVALID_LENGTH;
715 }
716 *descriptor_count = response->descriptor_count;
717
718 if (*descriptor_count == 0) {
719 return PLDM_ERROR_INVALID_DATA;
720 }
721 *descriptor_data =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930722 (uint8_t *)(msg->payload +
723 sizeof(struct pldm_query_device_identifiers_resp));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930724 return PLDM_SUCCESS;
725}
726
Matt Johnstoncf9a2df2024-11-07 15:29:29 +0800727LIBPLDM_ABI_TESTING
728int encode_query_device_identifiers_resp(
729 uint8_t instance_id, uint8_t descriptor_count,
730 const struct pldm_descriptor *descriptors, struct pldm_msg *msg,
731 size_t *payload_length)
732{
733 int rc;
734 struct pldm_msgbuf _buf;
735 struct pldm_msgbuf *buf = &_buf;
736
737 if (descriptors == NULL || msg == NULL || payload_length == NULL) {
738 return -EINVAL;
739 }
740
741 if (descriptor_count < 1) {
742 return -EINVAL;
743 }
744
745 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
746 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
747 if (rc) {
748 return -EINVAL;
749 }
750
751 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
752 if (rc) {
753 return rc;
754 }
755
756 /* Determine total length */
757 uint32_t device_identifiers_len = 0;
758 for (uint8_t i = 0; i < descriptor_count; i++) {
759 const struct pldm_descriptor *d = &descriptors[i];
760 device_identifiers_len +=
761 2 * sizeof(uint16_t) + d->descriptor_length;
762 }
763
764 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
765 pldm_msgbuf_insert(buf, device_identifiers_len);
766 pldm_msgbuf_insert(buf, descriptor_count);
767
768 for (uint8_t i = 0; i < descriptor_count; i++) {
769 const struct pldm_descriptor *d = &descriptors[i];
770 pldm_msgbuf_insert(buf, d->descriptor_type);
771 pldm_msgbuf_insert(buf, d->descriptor_length);
772 if (d->descriptor_data == NULL) {
773 return -EINVAL;
774 }
775 rc = pldm_msgbuf_insert_array(
776 buf, d->descriptor_length,
777 (const uint8_t *)d->descriptor_data,
778 d->descriptor_length);
779 if (rc) {
780 return rc;
781 }
782 }
783
784 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
785}
786
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930787LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930788int encode_get_firmware_parameters_req(uint8_t instance_id,
789 size_t payload_length,
790 struct pldm_msg *msg)
791{
792 if (msg == NULL) {
793 return PLDM_ERROR_INVALID_DATA;
794 }
795
796 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
797 return PLDM_ERROR_INVALID_LENGTH;
798 }
799
800 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
801 PLDM_GET_FIRMWARE_PARAMETERS, msg);
802}
803
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930804LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930805int decode_get_firmware_parameters_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930806 const struct pldm_msg *msg, size_t payload_length,
807 struct pldm_get_firmware_parameters_resp *resp_data,
808 struct variable_field *active_comp_image_set_ver_str,
809 struct variable_field *pending_comp_image_set_ver_str,
810 struct variable_field *comp_parameter_table)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930811{
812 if (msg == NULL || resp_data == NULL ||
813 active_comp_image_set_ver_str == NULL ||
814 pending_comp_image_set_ver_str == NULL ||
815 comp_parameter_table == NULL || !payload_length) {
816 return PLDM_ERROR_INVALID_DATA;
817 }
818
819 resp_data->completion_code = msg->payload[0];
820 if (PLDM_SUCCESS != resp_data->completion_code) {
821 return PLDM_SUCCESS;
822 }
823
824 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
825 return PLDM_ERROR_INVALID_LENGTH;
826 }
827
828 struct pldm_get_firmware_parameters_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930829 (struct pldm_get_firmware_parameters_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930830
831 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930832 response->active_comp_image_set_ver_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930833 (response->active_comp_image_set_ver_str_len == 0)) {
834 return PLDM_ERROR_INVALID_DATA;
835 }
836
837 if (response->pending_comp_image_set_ver_str_len == 0) {
838 if (response->pending_comp_image_set_ver_str_type !=
839 PLDM_STR_TYPE_UNKNOWN) {
840 return PLDM_ERROR_INVALID_DATA;
841 }
842 } else {
843 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930844 response->pending_comp_image_set_ver_str_type)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930845 return PLDM_ERROR_INVALID_DATA;
846 }
847 }
848
849 size_t partial_response_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930850 sizeof(struct pldm_get_firmware_parameters_resp) +
851 response->active_comp_image_set_ver_str_len +
852 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930853
854 if (payload_length < partial_response_length) {
855 return PLDM_ERROR_INVALID_LENGTH;
856 }
857
858 resp_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930859 le32toh(response->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930860 resp_data->comp_count = le16toh(response->comp_count);
861 resp_data->active_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930862 response->active_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930863 resp_data->active_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930864 response->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930865 resp_data->pending_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930866 response->pending_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930867 resp_data->pending_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930868 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930869
870 active_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930871 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930872 active_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930873 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930874
875 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
876 pending_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930877 msg->payload +
878 sizeof(struct pldm_get_firmware_parameters_resp) +
879 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930880 pending_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930881 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930882 } else {
883 pending_comp_image_set_ver_str->ptr = NULL;
884 pending_comp_image_set_ver_str->length = 0;
885 }
886
887 if (payload_length > partial_response_length && resp_data->comp_count) {
888 comp_parameter_table->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930889 msg->payload +
890 sizeof(struct pldm_get_firmware_parameters_resp) +
891 resp_data->active_comp_image_set_ver_str_len +
892 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930893 comp_parameter_table->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930894 payload_length - partial_response_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930895 } else {
896 comp_parameter_table->ptr = NULL;
897 comp_parameter_table->length = 0;
898 }
899
900 return PLDM_SUCCESS;
901}
902
Matt Johnstoncf9a2df2024-11-07 15:29:29 +0800903LIBPLDM_ABI_TESTING
904int encode_get_firmware_parameters_resp(
905 uint8_t instance_id,
906 const struct pldm_get_firmware_parameters_resp_full *resp_data,
907 struct pldm_msg *msg, size_t *payload_length)
908{
909 int rc;
910 struct pldm_msgbuf _buf;
911 struct pldm_msgbuf *buf = &_buf;
912
913 if (resp_data == NULL || msg == NULL || payload_length == NULL) {
914 return -EINVAL;
915 }
916
917 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
918 PLDM_GET_FIRMWARE_PARAMETERS, msg);
919 if (rc) {
920 return -EINVAL;
921 }
922
923 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
924 if (rc) {
925 return rc;
926 }
927
928 pldm_msgbuf_insert(buf, resp_data->completion_code);
929 pldm_msgbuf_insert(buf, resp_data->capabilities_during_update.value);
930 pldm_msgbuf_insert(buf, resp_data->comp_count);
931 pldm_msgbuf_insert(buf,
932 resp_data->active_comp_image_set_ver_str.str_type);
933 pldm_msgbuf_insert(buf,
934 resp_data->active_comp_image_set_ver_str.str_len);
935 pldm_msgbuf_insert(buf,
936 resp_data->pending_comp_image_set_ver_str.str_type);
937 pldm_msgbuf_insert(buf,
938 resp_data->pending_comp_image_set_ver_str.str_len);
939 /* String data appended */
940 rc = pldm_msgbuf_insert_array(
941 buf, resp_data->active_comp_image_set_ver_str.str_len,
942 resp_data->active_comp_image_set_ver_str.str_data,
943 resp_data->active_comp_image_set_ver_str.str_len);
944 if (rc) {
945 return rc;
946 }
947 rc = pldm_msgbuf_insert_array(
948 buf, resp_data->pending_comp_image_set_ver_str.str_len,
949 resp_data->pending_comp_image_set_ver_str.str_data,
950 resp_data->pending_comp_image_set_ver_str.str_len);
951 if (rc) {
952 return rc;
953 }
954
955 /* Further calls to encode_get_firmware_parameters_resp_comp_entry
956 * will populate the remainder */
957
958 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
959}
960
961LIBPLDM_ABI_TESTING
962int encode_get_firmware_parameters_resp_comp_entry(
963 const struct pldm_component_parameter_entry_full *comp,
964 uint8_t *payload, size_t *payload_length)
965{
966 int rc;
967 struct pldm_msgbuf _buf;
968 struct pldm_msgbuf *buf = &_buf;
969
970 if (comp == NULL || payload == NULL || payload_length == NULL) {
971 return -EINVAL;
972 }
973
974 rc = pldm_msgbuf_init_errno(buf, 0, payload, *payload_length);
975 if (rc) {
976 return rc;
977 }
978
979 pldm_msgbuf_insert(buf, comp->comp_classification);
980 pldm_msgbuf_insert(buf, comp->comp_identifier);
981 pldm_msgbuf_insert(buf, comp->comp_classification_index);
982
983 pldm_msgbuf_insert(buf, comp->active_ver.comparison_stamp);
984 pldm_msgbuf_insert(buf, (uint8_t)comp->active_ver.str.str_type);
985 pldm_msgbuf_insert(buf, comp->active_ver.str.str_len);
986 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
987 comp->active_ver.date,
988 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
989 if (rc) {
990 return rc;
991 }
992
993 pldm_msgbuf_insert(buf, comp->pending_ver.comparison_stamp);
994 pldm_msgbuf_insert(buf, (uint8_t)comp->pending_ver.str.str_type);
995 pldm_msgbuf_insert(buf, comp->pending_ver.str.str_len);
996 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
997 comp->pending_ver.date,
998 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
999 if (rc) {
1000 return rc;
1001 }
1002
1003 pldm_msgbuf_insert(buf, comp->comp_activation_methods.value);
1004 pldm_msgbuf_insert(buf, comp->capabilities_during_update.value);
1005
1006 rc = pldm_msgbuf_insert_array(buf, comp->active_ver.str.str_len,
1007 comp->active_ver.str.str_data,
1008 comp->active_ver.str.str_len);
1009 if (rc) {
1010 return rc;
1011 }
1012 rc = pldm_msgbuf_insert_array(buf, comp->pending_ver.str.str_len,
1013 comp->pending_ver.str.str_data,
1014 comp->pending_ver.str.str_len);
1015 if (rc) {
1016 return rc;
1017 }
1018
1019 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
1020}
1021
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301022LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301023int decode_get_firmware_parameters_resp_comp_entry(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301024 const uint8_t *data, size_t length,
1025 struct pldm_component_parameter_entry *component_data,
1026 struct variable_field *active_comp_ver_str,
1027 struct variable_field *pending_comp_ver_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301028{
1029 if (data == NULL || component_data == NULL ||
1030 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
1031 return PLDM_ERROR_INVALID_DATA;
1032 }
1033
1034 if (length < sizeof(struct pldm_component_parameter_entry)) {
1035 return PLDM_ERROR_INVALID_LENGTH;
1036 }
1037
1038 struct pldm_component_parameter_entry *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301039 (struct pldm_component_parameter_entry *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301040
1041 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
1042 entry->active_comp_ver_str_len +
1043 entry->pending_comp_ver_str_len;
1044
1045 if (length < entry_length) {
1046 return PLDM_ERROR_INVALID_LENGTH;
1047 }
1048
1049 component_data->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301050 le16toh(entry->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301051 component_data->comp_identifier = le16toh(entry->comp_identifier);
1052 component_data->comp_classification_index =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301053 entry->comp_classification_index;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301054 component_data->active_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301055 le32toh(entry->active_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301056 component_data->active_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301057 entry->active_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301058 component_data->active_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301059 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301060 memcpy(component_data->active_comp_release_date,
1061 entry->active_comp_release_date,
1062 sizeof(entry->active_comp_release_date));
1063 component_data->pending_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301064 le32toh(entry->pending_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301065 component_data->pending_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301066 entry->pending_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301067 component_data->pending_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301068 entry->pending_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301069 memcpy(component_data->pending_comp_release_date,
1070 entry->pending_comp_release_date,
1071 sizeof(entry->pending_comp_release_date));
1072 component_data->comp_activation_methods.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301073 le16toh(entry->comp_activation_methods.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301074 component_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301075 le32toh(entry->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301076
1077 if (entry->active_comp_ver_str_len != 0) {
1078 active_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301079 data + sizeof(struct pldm_component_parameter_entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301080 active_comp_ver_str->length = entry->active_comp_ver_str_len;
1081 } else {
1082 active_comp_ver_str->ptr = NULL;
1083 active_comp_ver_str->length = 0;
1084 }
1085
1086 if (entry->pending_comp_ver_str_len != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301087 pending_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301088 data + sizeof(struct pldm_component_parameter_entry) +
1089 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301090 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
1091 } else {
1092 pending_comp_ver_str->ptr = NULL;
1093 pending_comp_ver_str->length = 0;
1094 }
1095 return PLDM_SUCCESS;
1096}
1097
Chris Wang4c1f2c72024-03-21 17:09:44 +08001098LIBPLDM_ABI_TESTING
1099int encode_query_downstream_devices_req(uint8_t instance_id,
1100 struct pldm_msg *msg)
1101{
1102 if (msg == NULL) {
Unive Tien71e935c2024-11-25 17:21:43 +08001103 return -EINVAL;
Chris Wang4c1f2c72024-03-21 17:09:44 +08001104 }
1105
Unive Tien71e935c2024-11-25 17:21:43 +08001106 return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id,
1107 PLDM_FWUP,
1108 PLDM_QUERY_DOWNSTREAM_DEVICES,
1109 msg);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001110}
1111
1112LIBPLDM_ABI_TESTING
1113int decode_query_downstream_devices_resp(
1114 const struct pldm_msg *msg, size_t payload_length,
1115 struct pldm_query_downstream_devices_resp *resp_data)
1116{
1117 struct pldm_msgbuf _buf;
1118 struct pldm_msgbuf *buf = &_buf;
1119 int rc;
1120
1121 if (msg == NULL || resp_data == NULL || !payload_length) {
Unive Tien71e935c2024-11-25 17:21:43 +08001122 return -EINVAL;
Chris Wang4c1f2c72024-03-21 17:09:44 +08001123 }
1124
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301125 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1126 msg->payload, payload_length);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001127 if (rc) {
1128 return rc;
1129 }
1130
1131 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1132 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001133 return rc;
Chris Wang4c1f2c72024-03-21 17:09:44 +08001134 }
1135 if (PLDM_SUCCESS != resp_data->completion_code) {
1136 // Return the CC directly without decoding the rest of the payload
Unive Tien71e935c2024-11-25 17:21:43 +08001137 return 0;
Chris Wang4c1f2c72024-03-21 17:09:44 +08001138 }
1139
1140 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
Unive Tien71e935c2024-11-25 17:21:43 +08001141 return -EBADMSG;
Chris Wang4c1f2c72024-03-21 17:09:44 +08001142 }
1143
1144 rc = pldm_msgbuf_extract(buf,
1145 resp_data->downstream_device_update_supported);
1146 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001147 return rc;
Chris Wang4c1f2c72024-03-21 17:09:44 +08001148 }
1149
1150 if (!is_downstream_device_update_support_valid(
1151 resp_data->downstream_device_update_supported)) {
Unive Tien71e935c2024-11-25 17:21:43 +08001152 return -EINVAL;
Chris Wang4c1f2c72024-03-21 17:09:44 +08001153 }
1154
1155 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1156 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
1157 pldm_msgbuf_extract(buf, resp_data->capabilities.value);
1158
Unive Tien71e935c2024-11-25 17:21:43 +08001159 return pldm_msgbuf_destroy_consumed(buf);
Chris Wang4c1f2c72024-03-21 17:09:44 +08001160}
1161
Chris Wang458475a2024-03-26 17:59:19 +08001162LIBPLDM_ABI_TESTING
1163int encode_query_downstream_identifiers_req(
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001164 uint8_t instance_id,
1165 const struct pldm_query_downstream_identifiers_req *params_req,
1166 struct pldm_msg *msg, size_t payload_length)
Chris Wang458475a2024-03-26 17:59:19 +08001167{
1168 struct pldm_msgbuf _buf;
1169 struct pldm_msgbuf *buf = &_buf;
1170 int rc;
1171
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001172 if (!msg || !params_req) {
Unive Tien71e935c2024-11-25 17:21:43 +08001173 return -EINVAL;
Chris Wang458475a2024-03-26 17:59:19 +08001174 }
1175
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001176 if (!is_transfer_operation_flag_valid(
1177 (enum transfer_op_flag)
1178 params_req->transfer_operation_flag)) {
Unive Tien71e935c2024-11-25 17:21:43 +08001179 return -EINVAL;
Chris Wang458475a2024-03-26 17:59:19 +08001180 }
1181
1182 struct pldm_header_info header = { 0 };
1183 header.instance = instance_id;
1184 header.msg_type = PLDM_REQUEST;
1185 header.pldm_type = PLDM_FWUP;
1186 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
Unive Tien71e935c2024-11-25 17:21:43 +08001187 rc = pack_pldm_header_errno(&header, &(msg->hdr));
Chris Wang458475a2024-03-26 17:59:19 +08001188 if (rc) {
1189 return rc;
1190 }
1191
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301192 rc = pldm_msgbuf_init_errno(buf,
1193 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
1194 msg->payload, payload_length);
Chris Wang458475a2024-03-26 17:59:19 +08001195 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001196 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001197 }
1198
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001199 pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
Chris Wang458475a2024-03-26 17:59:19 +08001200 // Data correctness has been verified, cast it to 1-byte data directly.
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001201 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
Chris Wang458475a2024-03-26 17:59:19 +08001202
Unive Tien71e935c2024-11-25 17:21:43 +08001203 return pldm_msgbuf_destroy(buf);
Chris Wang458475a2024-03-26 17:59:19 +08001204}
1205
1206LIBPLDM_ABI_TESTING
1207int decode_query_downstream_identifiers_resp(
1208 const struct pldm_msg *msg, size_t payload_length,
1209 struct pldm_query_downstream_identifiers_resp *resp_data,
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301210 struct pldm_downstream_device_iter *iter)
Chris Wang458475a2024-03-26 17:59:19 +08001211{
1212 struct pldm_msgbuf _buf;
1213 struct pldm_msgbuf *buf = &_buf;
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301214 void *remaining = NULL;
Unive Tien71e935c2024-11-25 17:21:43 +08001215 int rc = 0;
Chris Wang458475a2024-03-26 17:59:19 +08001216
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301217 if (msg == NULL || resp_data == NULL || iter == NULL ||
Chris Wang458475a2024-03-26 17:59:19 +08001218 !payload_length) {
Unive Tien71e935c2024-11-25 17:21:43 +08001219 return -EINVAL;
Chris Wang458475a2024-03-26 17:59:19 +08001220 }
1221
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301222 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1223 msg->payload, payload_length);
Chris Wang458475a2024-03-26 17:59:19 +08001224 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001225 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001226 }
1227
1228 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1229 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001230 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001231 }
1232 if (PLDM_SUCCESS != resp_data->completion_code) {
Unive Tien71e935c2024-11-25 17:21:43 +08001233 return 0;
Chris Wang458475a2024-03-26 17:59:19 +08001234 }
1235
1236 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
Unive Tien71e935c2024-11-25 17:21:43 +08001237 return -EBADMSG;
Chris Wang458475a2024-03-26 17:59:19 +08001238 }
1239
1240 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1241 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1242
1243 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
1244 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001245 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001246 }
1247
1248 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301249 rc = pldm_msgbuf_span_required(
1250 buf, resp_data->downstream_devices_length, &remaining);
Chris Wang458475a2024-03-26 17:59:19 +08001251 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001252 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001253 }
Chris Wang458475a2024-03-26 17:59:19 +08001254
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301255 rc = pldm_msgbuf_destroy(buf);
1256 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001257 return rc;
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301258 }
1259
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301260 iter->field.ptr = remaining;
1261 iter->field.length = resp_data->downstream_devices_length;
1262 iter->devs = resp_data->number_of_downstream_devices;
1263
Unive Tien71e935c2024-11-25 17:21:43 +08001264 return 0;
Chris Wang458475a2024-03-26 17:59:19 +08001265}
1266
Chris Wangb6ef35b2024-07-03 09:35:42 +08001267LIBPLDM_ABI_TESTING
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301268int decode_pldm_downstream_device_from_iter(
1269 struct pldm_downstream_device_iter *iter,
1270 struct pldm_downstream_device *dev)
1271{
1272 struct pldm_msgbuf _buf;
1273 struct pldm_msgbuf *buf = &_buf;
1274 int rc;
1275
1276 if (!iter || !dev) {
1277 return -EINVAL;
1278 }
1279
1280 rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr,
1281 iter->field.length);
1282 if (rc) {
1283 return rc;
1284 }
1285
1286 pldm_msgbuf_extract(buf, dev->downstream_device_index);
1287 pldm_msgbuf_extract(buf, dev->downstream_descriptor_count);
1288 iter->field.ptr = NULL;
1289 pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr,
1290 &iter->field.length);
1291
1292 return pldm_msgbuf_destroy(buf);
1293}
1294
1295LIBPLDM_ABI_TESTING
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301296int encode_get_downstream_firmware_parameters_req(
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001297 uint8_t instance_id,
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301298 const struct pldm_get_downstream_firmware_parameters_req *params_req,
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001299 struct pldm_msg *msg, size_t payload_length)
Chris Wangb6ef35b2024-07-03 09:35:42 +08001300{
1301 struct pldm_msgbuf _buf;
1302 struct pldm_msgbuf *buf = &_buf;
1303 int rc;
1304
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001305 if (!msg || !params_req) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001306 return -EINVAL;
1307 }
1308
1309 rc = pldm_msgbuf_init_errno(
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301310 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES,
Chris Wangb6ef35b2024-07-03 09:35:42 +08001311 msg->payload, payload_length);
1312 if (rc < 0) {
1313 return rc;
1314 }
1315
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001316 if (!is_transfer_operation_flag_valid(
1317 (enum transfer_op_flag)
1318 params_req->transfer_operation_flag)) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001319 return -EBADMSG;
1320 }
1321
1322 struct pldm_header_info header = { 0 };
1323 header.instance = instance_id;
1324 header.msg_type = PLDM_REQUEST;
1325 header.pldm_type = PLDM_FWUP;
1326 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1327 rc = pack_pldm_header_errno(&header, &msg->hdr);
1328 if (rc < 0) {
1329 return rc;
1330 }
1331
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001332 pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001333 // Data correctness has been verified, cast it to 1-byte data directly.
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001334 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001335
1336 return pldm_msgbuf_destroy(buf);
1337}
1338
1339LIBPLDM_ABI_TESTING
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301340int decode_get_downstream_firmware_parameters_resp(
Chris Wangb6ef35b2024-07-03 09:35:42 +08001341 const struct pldm_msg *msg, size_t payload_length,
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301342 struct pldm_get_downstream_firmware_parameters_resp *resp_data,
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301343 struct pldm_downstream_device_parameters_iter *iter)
Chris Wangb6ef35b2024-07-03 09:35:42 +08001344{
1345 struct pldm_msgbuf _buf;
1346 struct pldm_msgbuf *buf = &_buf;
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301347 void *remaining = NULL;
1348 size_t length;
Chris Wangb6ef35b2024-07-03 09:35:42 +08001349 int rc;
1350
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301351 if (msg == NULL || resp_data == NULL || iter == NULL) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001352 return -EINVAL;
1353 }
1354
1355 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1356 msg->payload, payload_length);
1357 if (rc < 0) {
1358 return rc;
1359 }
1360
1361 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1362 if (rc < 0) {
1363 return rc;
1364 }
1365 if (PLDM_SUCCESS != resp_data->completion_code) {
1366 return 0;
1367 }
1368
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301369 if (payload_length <
1370 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001371 return -EBADMSG;
1372 }
1373
1374 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1375 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1376 pldm_msgbuf_extract(buf,
1377 resp_data->fdp_capabilities_during_update.value);
1378 pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1379
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301380 rc = pldm_msgbuf_span_remaining(buf, &remaining, &length);
1381 if (rc) {
1382 return rc;
1383 }
1384
1385 rc = pldm_msgbuf_destroy(buf);
1386 if (rc) {
1387 return rc;
1388 }
1389
1390 iter->field.ptr = remaining;
1391 iter->field.length = length;
1392 iter->entries = resp_data->downstream_device_count;
1393
1394 return 0;
Chris Wangb6ef35b2024-07-03 09:35:42 +08001395}
1396
1397LIBPLDM_ABI_TESTING
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301398int decode_pldm_downstream_device_parameters_entry_from_iter(
1399 struct pldm_downstream_device_parameters_iter *iter,
1400 struct pldm_downstream_device_parameters_entry *entry)
Chris Wangb6ef35b2024-07-03 09:35:42 +08001401{
1402 struct pldm_msgbuf _buf;
1403 struct pldm_msgbuf *buf = &_buf;
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301404 void *comp_ver_str;
Chris Wangb6ef35b2024-07-03 09:35:42 +08001405 size_t remaining;
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301406 void *cursor;
Chris Wangb6ef35b2024-07-03 09:35:42 +08001407 int rc;
1408
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301409 if (iter == NULL || entry == NULL) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001410 return -EINVAL;
1411 }
1412
1413 rc = pldm_msgbuf_init_errno(
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301414 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN,
1415 iter->field.ptr, iter->field.length);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001416 if (rc < 0) {
1417 return rc;
1418 }
1419
1420 pldm_msgbuf_extract(buf, entry->downstream_device_index);
1421 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1422 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1423 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1424 if (rc < 0) {
1425 return rc;
1426 }
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001427 rc = pldm_msgbuf_extract_array(buf,
1428 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1429 entry->active_comp_release_date,
1430 sizeof(entry->active_comp_release_date));
1431 if (rc < 0) {
1432 return rc;
1433 }
1434
Chris Wangb6ef35b2024-07-03 09:35:42 +08001435 // Fill the last byte with NULL character
1436 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1437 '\0';
1438
1439 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1440 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1441 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1442 if (rc < 0) {
1443 return rc;
1444 }
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001445
1446 rc = pldm_msgbuf_extract_array(
1447 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1448 entry->pending_comp_release_date,
1449 sizeof(entry->pending_comp_release_date));
1450 if (rc < 0) {
1451 return rc;
1452 }
1453
Chris Wangb6ef35b2024-07-03 09:35:42 +08001454 // Fill the last byte with NULL character
1455 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1456 '\0';
1457
1458 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1459 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001460
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301461 comp_ver_str = NULL;
1462 pldm_msgbuf_span_required(buf, entry->active_comp_ver_str_len,
1463 &comp_ver_str);
1464 entry->active_comp_ver_str = comp_ver_str;
1465
1466 comp_ver_str = NULL;
1467 pldm_msgbuf_span_required(buf, entry->pending_comp_ver_str_len,
1468 &comp_ver_str);
1469 entry->pending_comp_ver_str = comp_ver_str;
1470
1471 cursor = NULL;
Chris Wangb6ef35b2024-07-03 09:35:42 +08001472 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1473 if (rc < 0) {
1474 return rc;
1475 }
1476
Andrew Jeffery5a5129b2024-12-04 16:12:40 +10301477 iter->field.ptr = cursor;
1478 iter->field.length = remaining;
Chris Wangb6ef35b2024-07-03 09:35:42 +08001479
1480 return 0;
1481}
1482
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301483LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301484int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1485 uint16_t num_of_comp,
1486 uint8_t max_outstanding_transfer_req,
1487 uint16_t pkg_data_len,
1488 uint8_t comp_image_set_ver_str_type,
1489 uint8_t comp_image_set_ver_str_len,
1490 const struct variable_field *comp_img_set_ver_str,
1491 struct pldm_msg *msg, size_t payload_length)
1492{
1493 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
1494 msg == NULL) {
1495 return PLDM_ERROR_INVALID_DATA;
1496 }
1497
1498 if (payload_length != sizeof(struct pldm_request_update_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301499 comp_img_set_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301500 return PLDM_ERROR_INVALID_LENGTH;
1501 }
1502
1503 if ((comp_image_set_ver_str_len == 0) ||
1504 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
1505 return PLDM_ERROR_INVALID_DATA;
1506 }
1507
1508 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
1509 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
1510 return PLDM_ERROR_INVALID_DATA;
1511 }
1512
1513 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
1514 return PLDM_ERROR_INVALID_DATA;
1515 }
1516
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301517 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301518 header.instance = instance_id;
1519 header.msg_type = PLDM_REQUEST;
1520 header.pldm_type = PLDM_FWUP;
1521 header.command = PLDM_REQUEST_UPDATE;
1522 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1523 if (rc) {
1524 return rc;
1525 }
1526
1527 struct pldm_request_update_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301528 (struct pldm_request_update_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301529
1530 request->max_transfer_size = htole32(max_transfer_size);
1531 request->num_of_comp = htole16(num_of_comp);
1532 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
1533 request->pkg_data_len = htole16(pkg_data_len);
1534 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
1535 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
1536
1537 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
1538 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
1539
1540 return PLDM_SUCCESS;
1541}
1542
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001543LIBPLDM_ABI_TESTING
1544int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length,
1545 struct pldm_request_update_req_full *req)
1546{
1547 int rc;
1548 uint8_t t;
1549 struct pldm_msgbuf _buf;
1550 struct pldm_msgbuf *buf = &_buf;
1551
1552 if (msg == NULL || req == NULL) {
1553 return -EINVAL;
1554 }
1555
1556 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1557 if (rc) {
1558 return rc;
1559 }
1560
1561 pldm_msgbuf_extract(buf, req->max_transfer_size);
1562 pldm_msgbuf_extract(buf, req->num_of_comp);
1563 pldm_msgbuf_extract(buf, req->max_outstanding_transfer_req);
1564 pldm_msgbuf_extract(buf, req->pkg_data_len);
1565 rc = pldm_msgbuf_extract(buf, t);
1566 if (rc) {
1567 return rc;
1568 }
1569 if (t > PLDM_STR_TYPE_UTF_16BE) {
1570 return -EBADMSG;
1571 }
1572 req->image_set_ver.str_type = (enum pldm_firmware_update_string_type)t;
1573 pldm_msgbuf_extract(buf, req->image_set_ver.str_len);
1574 if (rc) {
1575 return rc;
1576 }
1577
1578 rc = pldm_msgbuf_extract_array(buf, req->image_set_ver.str_len,
1579 req->image_set_ver.str_data,
1580 PLDM_FIRMWARE_MAX_STRING);
1581 if (rc) {
1582 return rc;
1583 }
1584
1585 return pldm_msgbuf_destroy_consumed(buf);
1586}
1587
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301588LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301589int decode_request_update_resp(const struct pldm_msg *msg,
1590 size_t payload_length, uint8_t *completion_code,
1591 uint16_t *fd_meta_data_len,
1592 uint8_t *fd_will_send_pkg_data)
1593{
1594 if (msg == NULL || completion_code == NULL ||
1595 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
1596 !payload_length) {
1597 return PLDM_ERROR_INVALID_DATA;
1598 }
1599
1600 *completion_code = msg->payload[0];
1601 if (*completion_code != PLDM_SUCCESS) {
1602 return PLDM_SUCCESS;
1603 }
1604
1605 if (payload_length != sizeof(struct pldm_request_update_resp)) {
1606 return PLDM_ERROR_INVALID_LENGTH;
1607 }
1608
1609 struct pldm_request_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301610 (struct pldm_request_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301611
1612 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
1613 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1614
1615 return PLDM_SUCCESS;
1616}
1617
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001618LIBPLDM_ABI_TESTING
1619int encode_request_update_resp(uint8_t instance_id,
1620 const struct pldm_request_update_resp *resp_data,
1621 struct pldm_msg *msg, size_t *payload_length)
1622{
1623 int rc;
1624 struct pldm_msgbuf _buf;
1625 struct pldm_msgbuf *buf = &_buf;
1626
1627 if (msg == NULL || payload_length == NULL) {
1628 return -EINVAL;
1629 }
1630
1631 struct pldm_header_info header = {
1632 .instance = instance_id,
1633 .msg_type = PLDM_RESPONSE,
1634 .pldm_type = PLDM_FWUP,
1635 .command = PLDM_REQUEST_UPDATE,
1636 };
1637 rc = pack_pldm_header(&header, &(msg->hdr));
1638 if (rc) {
1639 return -EINVAL;
1640 }
1641
1642 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1643 if (rc) {
1644 return rc;
1645 }
1646
1647 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1648 pldm_msgbuf_insert(buf, resp_data->fd_meta_data_len);
1649 pldm_msgbuf_insert(buf, resp_data->fd_will_send_pkg_data);
1650
1651 /* TODO: DSP0267 1.3.0 adds GetPackageDataMaximumTransferSize */
1652
1653 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
1654}
1655
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301656LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301657int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1658 uint16_t comp_classification,
1659 uint16_t comp_identifier,
1660 uint8_t comp_classification_index,
1661 uint32_t comp_comparison_stamp,
1662 uint8_t comp_ver_str_type,
1663 uint8_t comp_ver_str_len,
1664 const struct variable_field *comp_ver_str,
1665 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301666{
1667 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1668 return PLDM_ERROR_INVALID_DATA;
1669 }
1670
1671 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301672 comp_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301673 return PLDM_ERROR_INVALID_LENGTH;
1674 }
1675
1676 if ((comp_ver_str_len == 0) ||
1677 (comp_ver_str_len != comp_ver_str->length)) {
1678 return PLDM_ERROR_INVALID_DATA;
1679 }
1680
1681 if (!is_transfer_flag_valid(transfer_flag)) {
1682 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1683 }
1684
1685 if (!is_string_type_valid(comp_ver_str_type)) {
1686 return PLDM_ERROR_INVALID_DATA;
1687 }
1688
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301689 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301690 header.instance = instance_id;
1691 header.msg_type = PLDM_REQUEST;
1692 header.pldm_type = PLDM_FWUP;
1693 header.command = PLDM_PASS_COMPONENT_TABLE;
1694 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1695 if (rc) {
1696 return rc;
1697 }
1698
1699 struct pldm_pass_component_table_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301700 (struct pldm_pass_component_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301701
1702 request->transfer_flag = transfer_flag;
1703 request->comp_classification = htole16(comp_classification);
1704 request->comp_identifier = htole16(comp_identifier);
1705 request->comp_classification_index = comp_classification_index;
1706 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1707 request->comp_ver_str_type = comp_ver_str_type;
1708 request->comp_ver_str_len = comp_ver_str_len;
1709
1710 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1711 comp_ver_str->ptr, comp_ver_str->length);
1712
1713 return PLDM_SUCCESS;
1714}
1715
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001716LIBPLDM_ABI_TESTING
1717int decode_pass_component_table_req(
1718 const struct pldm_msg *msg, size_t payload_length,
1719 struct pldm_pass_component_table_req_full *pcomp)
1720{
1721 int rc;
1722 uint8_t t;
1723 struct pldm_msgbuf _buf;
1724 struct pldm_msgbuf *buf = &_buf;
1725
1726 if (msg == NULL || pcomp == NULL) {
1727 return -EINVAL;
1728 }
1729
1730 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1731 if (rc) {
1732 return rc;
1733 }
1734
1735 pldm_msgbuf_extract(buf, pcomp->transfer_flag);
1736 pldm_msgbuf_extract(buf, pcomp->comp_classification);
1737 pldm_msgbuf_extract(buf, pcomp->comp_identifier);
1738 pldm_msgbuf_extract(buf, pcomp->comp_classification_index);
1739 pldm_msgbuf_extract(buf, pcomp->comp_comparison_stamp);
1740 rc = pldm_msgbuf_extract(buf, t);
1741 if (rc) {
1742 return rc;
1743 }
1744 if (t > PLDM_STR_TYPE_UTF_16BE) {
1745 return -EBADMSG;
1746 }
1747 pcomp->version.str_type = (enum pldm_firmware_update_string_type)t;
1748 rc = pldm_msgbuf_extract(buf, pcomp->version.str_len);
1749 if (rc) {
1750 return rc;
1751 }
1752 rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len,
1753 pcomp->version.str_data,
1754 PLDM_FIRMWARE_MAX_STRING);
1755 if (rc) {
1756 return rc;
1757 }
1758
1759 return pldm_msgbuf_destroy_consumed(buf);
1760}
1761
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301762LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301763int decode_pass_component_table_resp(const struct pldm_msg *msg,
1764 const size_t payload_length,
1765 uint8_t *completion_code,
1766 uint8_t *comp_resp,
1767 uint8_t *comp_resp_code)
1768{
1769 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1770 comp_resp_code == NULL || !payload_length) {
1771 return PLDM_ERROR_INVALID_DATA;
1772 }
1773
1774 *completion_code = msg->payload[0];
1775 if (*completion_code != PLDM_SUCCESS) {
1776 return PLDM_SUCCESS;
1777 }
1778
1779 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1780 return PLDM_ERROR_INVALID_LENGTH;
1781 }
1782
1783 struct pldm_pass_component_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301784 (struct pldm_pass_component_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301785
1786 if (!is_comp_resp_valid(response->comp_resp)) {
1787 return PLDM_ERROR_INVALID_DATA;
1788 }
1789
1790 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1791 return PLDM_ERROR_INVALID_DATA;
1792 }
1793
1794 *comp_resp = response->comp_resp;
1795 *comp_resp_code = response->comp_resp_code;
1796
1797 return PLDM_SUCCESS;
1798}
1799
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001800LIBPLDM_ABI_TESTING
1801int encode_pass_component_table_resp(
1802 uint8_t instance_id,
1803 const struct pldm_pass_component_table_resp *resp_data,
1804 struct pldm_msg *msg, size_t *payload_length)
1805{
1806 int rc;
1807 struct pldm_msgbuf _buf;
1808 struct pldm_msgbuf *buf = &_buf;
1809
1810 if (msg == NULL || payload_length == NULL) {
1811 return -EINVAL;
1812 }
1813
1814 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
1815 PLDM_PASS_COMPONENT_TABLE, msg);
1816 if (rc) {
1817 return -EINVAL;
1818 }
1819
1820 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1821 if (rc) {
1822 return rc;
1823 }
1824
1825 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1826 pldm_msgbuf_insert(buf, resp_data->comp_resp);
1827 pldm_msgbuf_insert(buf, resp_data->comp_resp_code);
1828
1829 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
1830}
1831
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301832LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301833int encode_update_component_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301834 uint8_t instance_id, uint16_t comp_classification,
1835 uint16_t comp_identifier, uint8_t comp_classification_index,
1836 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1837 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1838 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1839 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301840{
1841 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1842 return PLDM_ERROR_INVALID_DATA;
1843 }
1844
1845 if (payload_length !=
1846 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1847 return PLDM_ERROR_INVALID_LENGTH;
1848 }
1849
1850 if (!comp_image_size) {
1851 return PLDM_ERROR_INVALID_DATA;
1852 }
1853
1854 if ((comp_ver_str_len == 0) ||
1855 (comp_ver_str_len != comp_ver_str->length)) {
1856 return PLDM_ERROR_INVALID_DATA;
1857 }
1858
1859 if (!is_string_type_valid(comp_ver_str_type)) {
1860 return PLDM_ERROR_INVALID_DATA;
1861 }
1862
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301863 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301864 header.instance = instance_id;
1865 header.msg_type = PLDM_REQUEST;
1866 header.pldm_type = PLDM_FWUP;
1867 header.command = PLDM_UPDATE_COMPONENT;
1868 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1869 if (rc) {
1870 return rc;
1871 }
1872
1873 struct pldm_update_component_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301874 (struct pldm_update_component_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301875
1876 request->comp_classification = htole16(comp_classification);
1877 request->comp_identifier = htole16(comp_identifier);
1878 request->comp_classification_index = comp_classification_index;
1879 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1880 request->comp_image_size = htole32(comp_image_size);
1881 request->update_option_flags.value = htole32(update_option_flags.value);
1882 request->comp_ver_str_type = comp_ver_str_type;
1883 request->comp_ver_str_len = comp_ver_str_len;
1884
1885 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1886 comp_ver_str->ptr, comp_ver_str->length);
1887
1888 return PLDM_SUCCESS;
1889}
1890
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001891LIBPLDM_ABI_TESTING
1892int decode_update_component_req(const struct pldm_msg *msg,
1893 size_t payload_length,
1894 struct pldm_update_component_req_full *up)
1895{
1896 int rc;
1897 uint8_t t;
1898 struct pldm_msgbuf _buf;
1899 struct pldm_msgbuf *buf = &_buf;
1900
1901 if (msg == NULL || up == NULL) {
1902 return -EINVAL;
1903 }
1904
1905 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1906 if (rc) {
1907 return rc;
1908 }
1909
1910 pldm_msgbuf_extract(buf, up->comp_classification);
1911 pldm_msgbuf_extract(buf, up->comp_identifier);
1912 pldm_msgbuf_extract(buf, up->comp_classification_index);
1913 pldm_msgbuf_extract(buf, up->comp_comparison_stamp);
1914 pldm_msgbuf_extract(buf, up->comp_image_size);
1915 pldm_msgbuf_extract(buf, up->update_option_flags.value);
1916 rc = pldm_msgbuf_extract(buf, t);
1917 if (rc) {
1918 return rc;
1919 }
1920 if (t > PLDM_STR_TYPE_UTF_16BE) {
1921 return -EBADMSG;
1922 }
1923 up->version.str_type = (enum pldm_firmware_update_string_type)t;
1924 rc = pldm_msgbuf_extract(buf, up->version.str_len);
1925 if (rc) {
1926 return rc;
1927 }
1928 rc = pldm_msgbuf_extract_array(buf, up->version.str_len,
1929 up->version.str_data,
1930 PLDM_FIRMWARE_MAX_STRING);
1931 if (rc) {
1932 return rc;
1933 }
1934
1935 if (buf->remaining != 0) {
1936 return -EINVAL;
1937 }
1938
1939 return 0;
1940}
1941
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301942LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301943int decode_update_component_resp(const struct pldm_msg *msg,
1944 size_t payload_length,
1945 uint8_t *completion_code,
1946 uint8_t *comp_compatibility_resp,
1947 uint8_t *comp_compatibility_resp_code,
1948 bitfield32_t *update_option_flags_enabled,
1949 uint16_t *time_before_req_fw_data)
1950{
1951 if (msg == NULL || completion_code == NULL ||
1952 comp_compatibility_resp == NULL ||
1953 comp_compatibility_resp_code == NULL ||
1954 update_option_flags_enabled == NULL ||
1955 time_before_req_fw_data == NULL || !payload_length) {
1956 return PLDM_ERROR_INVALID_DATA;
1957 }
1958
1959 *completion_code = msg->payload[0];
1960 if (*completion_code != PLDM_SUCCESS) {
1961 return PLDM_SUCCESS;
1962 }
1963
1964 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1965 return PLDM_ERROR_INVALID_LENGTH;
1966 }
1967
1968 struct pldm_update_component_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301969 (struct pldm_update_component_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301970
1971 if (!is_comp_compatibility_resp_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301972 response->comp_compatibility_resp)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301973 return PLDM_ERROR_INVALID_DATA;
1974 }
1975
1976 if (!is_comp_compatibility_resp_code_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301977 response->comp_compatibility_resp_code)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301978 return PLDM_ERROR_INVALID_DATA;
1979 }
1980
1981 *comp_compatibility_resp = response->comp_compatibility_resp;
1982 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1983 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301984 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301985 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1986
1987 return PLDM_SUCCESS;
1988}
1989
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08001990LIBPLDM_ABI_TESTING
1991int encode_update_component_resp(
1992 uint8_t instance_id, const struct pldm_update_component_resp *resp_data,
1993 struct pldm_msg *msg, size_t *payload_length)
1994{
1995 int rc;
1996 struct pldm_msgbuf _buf;
1997 struct pldm_msgbuf *buf = &_buf;
1998
1999 if (msg == NULL || payload_length == NULL) {
2000 return -EINVAL;
2001 }
2002
2003 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2004 PLDM_UPDATE_COMPONENT, msg);
2005 if (rc) {
2006 return -EINVAL;
2007 }
2008
2009 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2010 if (rc) {
2011 return rc;
2012 }
2013
2014 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2015 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp);
2016 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp_code);
2017 pldm_msgbuf_insert(buf, resp_data->update_option_flags_enabled.value);
2018 pldm_msgbuf_insert(buf, resp_data->time_before_req_fw_data);
2019
2020 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2021}
2022
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302023LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302024int decode_request_firmware_data_req(const struct pldm_msg *msg,
2025 size_t payload_length, uint32_t *offset,
2026 uint32_t *length)
2027{
2028 if (msg == NULL || offset == NULL || length == NULL) {
2029 return PLDM_ERROR_INVALID_DATA;
2030 }
2031 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
2032 return PLDM_ERROR_INVALID_LENGTH;
2033 }
2034 struct pldm_request_firmware_data_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302035 (struct pldm_request_firmware_data_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302036 *offset = le32toh(request->offset);
2037 *length = le32toh(request->length);
2038
2039 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
2040 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
2041 }
2042
2043 return PLDM_SUCCESS;
2044}
2045
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002046LIBPLDM_ABI_TESTING
2047int encode_request_firmware_data_req(
2048 uint8_t instance_id,
2049 const struct pldm_request_firmware_data_req *req_params,
2050 struct pldm_msg *msg, size_t *payload_length)
2051{
2052 int rc;
2053 struct pldm_msgbuf _buf;
2054 struct pldm_msgbuf *buf = &_buf;
2055
2056 if (msg == NULL || payload_length == NULL) {
2057 return -EINVAL;
2058 }
2059
2060 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2061 PLDM_REQUEST_FIRMWARE_DATA, msg);
2062 if (rc) {
2063 return -EINVAL;
2064 }
2065
2066 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2067 if (rc) {
2068 return rc;
2069 }
2070
2071 pldm_msgbuf_insert(buf, req_params->offset);
2072 pldm_msgbuf_insert(buf, req_params->length);
2073
2074 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2075}
2076
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302077LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302078int encode_request_firmware_data_resp(uint8_t instance_id,
2079 uint8_t completion_code,
2080 struct pldm_msg *msg,
2081 size_t payload_length)
2082{
2083 if (msg == NULL || !payload_length) {
2084 return PLDM_ERROR_INVALID_DATA;
2085 }
2086
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302087 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302088 header.instance = instance_id;
2089 header.msg_type = PLDM_RESPONSE;
2090 header.pldm_type = PLDM_FWUP;
2091 header.command = PLDM_REQUEST_FIRMWARE_DATA;
2092 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2093 if (rc) {
2094 return rc;
2095 }
2096
2097 msg->payload[0] = completion_code;
2098
2099 return PLDM_SUCCESS;
2100}
2101
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302102LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302103int decode_transfer_complete_req(const struct pldm_msg *msg,
2104 size_t payload_length,
2105 uint8_t *transfer_result)
2106{
2107 if (msg == NULL || transfer_result == NULL) {
2108 return PLDM_ERROR_INVALID_DATA;
2109 }
2110
2111 if (payload_length != sizeof(*transfer_result)) {
2112 return PLDM_ERROR_INVALID_LENGTH;
2113 }
2114
2115 *transfer_result = msg->payload[0];
2116 return PLDM_SUCCESS;
2117}
2118
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002119LIBPLDM_ABI_TESTING
2120int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
2121 struct pldm_msg *msg, size_t *payload_length)
2122{
2123 int rc;
2124 struct pldm_msgbuf _buf;
2125 struct pldm_msgbuf *buf = &_buf;
2126
2127 if (msg == NULL || payload_length == NULL) {
2128 return -EINVAL;
2129 }
2130
2131 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2132 PLDM_TRANSFER_COMPLETE, msg);
2133 if (rc) {
2134 return -EINVAL;
2135 }
2136
2137 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2138 if (rc) {
2139 return rc;
2140 }
2141
2142 rc = pldm_msgbuf_insert(buf, transfer_result);
2143 if (rc) {
2144 return rc;
2145 }
2146
2147 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2148}
2149
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302150LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302151int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
2152 struct pldm_msg *msg, size_t payload_length)
2153{
2154 if (msg == NULL) {
2155 return PLDM_ERROR_INVALID_DATA;
2156 }
2157
2158 if (payload_length != sizeof(completion_code)) {
2159 return PLDM_ERROR_INVALID_LENGTH;
2160 }
2161
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302162 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302163 header.instance = instance_id;
2164 header.msg_type = PLDM_RESPONSE;
2165 header.pldm_type = PLDM_FWUP;
2166 header.command = PLDM_TRANSFER_COMPLETE;
2167 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2168 if (rc) {
2169 return rc;
2170 }
2171
2172 msg->payload[0] = completion_code;
2173
2174 return PLDM_SUCCESS;
2175}
2176
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302177LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302178int decode_verify_complete_req(const struct pldm_msg *msg,
2179 size_t payload_length, uint8_t *verify_result)
2180{
2181 if (msg == NULL || verify_result == NULL) {
2182 return PLDM_ERROR_INVALID_DATA;
2183 }
2184
2185 if (payload_length != sizeof(*verify_result)) {
2186 return PLDM_ERROR_INVALID_LENGTH;
2187 }
2188
2189 *verify_result = msg->payload[0];
2190 return PLDM_SUCCESS;
2191}
2192
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002193LIBPLDM_ABI_TESTING
2194int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
2195 struct pldm_msg *msg, size_t *payload_length)
2196{
2197 int rc;
2198 struct pldm_msgbuf _buf;
2199 struct pldm_msgbuf *buf = &_buf;
2200
2201 if (msg == NULL || payload_length == NULL) {
2202 return -EINVAL;
2203 }
2204
2205 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2206 PLDM_VERIFY_COMPLETE, msg);
2207 if (rc) {
2208 return EINVAL;
2209 }
2210
2211 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2212 if (rc) {
2213 return rc;
2214 }
2215
2216 rc = pldm_msgbuf_insert(buf, verify_result);
2217 if (rc) {
2218 return rc;
2219 }
2220
2221 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2222}
2223
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302224LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302225int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
2226 struct pldm_msg *msg, size_t payload_length)
2227{
2228 if (msg == NULL) {
2229 return PLDM_ERROR_INVALID_DATA;
2230 }
2231
2232 if (payload_length != sizeof(completion_code)) {
2233 return PLDM_ERROR_INVALID_LENGTH;
2234 }
2235
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302236 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302237 header.instance = instance_id;
2238 header.msg_type = PLDM_RESPONSE;
2239 header.pldm_type = PLDM_FWUP;
2240 header.command = PLDM_VERIFY_COMPLETE;
2241 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2242 if (rc) {
2243 return rc;
2244 }
2245
2246 msg->payload[0] = completion_code;
2247
2248 return PLDM_SUCCESS;
2249}
2250
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302251LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302252int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
2253 uint8_t *apply_result,
2254 bitfield16_t *comp_activation_methods_modification)
Andrew Jeffery9c766792022-08-10 23:12:49 +09302255{
2256 if (msg == NULL || apply_result == NULL ||
2257 comp_activation_methods_modification == NULL) {
2258 return PLDM_ERROR_INVALID_DATA;
2259 }
2260
2261 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
2262 return PLDM_ERROR_INVALID_LENGTH;
2263 }
2264
2265 struct pldm_apply_complete_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302266 (struct pldm_apply_complete_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302267
2268 *apply_result = request->apply_result;
2269 comp_activation_methods_modification->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302270 le16toh(request->comp_activation_methods_modification.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302271
2272 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
2273 comp_activation_methods_modification->value) {
2274 return PLDM_ERROR_INVALID_DATA;
2275 }
2276
2277 return PLDM_SUCCESS;
2278}
2279
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002280LIBPLDM_ABI_TESTING
2281int encode_apply_complete_req(uint8_t instance_id,
2282 const struct pldm_apply_complete_req *req_data,
2283 struct pldm_msg *msg, size_t *payload_length)
2284{
2285 int rc;
2286 struct pldm_msgbuf _buf;
2287 struct pldm_msgbuf *buf = &_buf;
2288
2289 if (msg == NULL || payload_length == NULL) {
2290 return -EINVAL;
2291 }
2292
2293 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2294 PLDM_APPLY_COMPLETE, msg);
2295 if (rc) {
2296 return -EINVAL;
2297 }
2298
2299 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2300 if (rc) {
2301 return rc;
2302 }
2303
2304 pldm_msgbuf_insert(buf, req_data->apply_result);
2305 pldm_msgbuf_insert(
2306 buf, req_data->comp_activation_methods_modification.value);
2307
2308 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2309}
2310
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302311LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302312int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
2313 struct pldm_msg *msg, size_t payload_length)
2314{
2315 if (msg == NULL) {
2316 return PLDM_ERROR_INVALID_DATA;
2317 }
2318
2319 if (payload_length != sizeof(completion_code)) {
2320 return PLDM_ERROR_INVALID_LENGTH;
2321 }
2322
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302323 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302324 header.instance = instance_id;
2325 header.msg_type = PLDM_RESPONSE;
2326 header.pldm_type = PLDM_FWUP;
2327 header.command = PLDM_APPLY_COMPLETE;
2328 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2329 if (rc) {
2330 return rc;
2331 }
2332
2333 msg->payload[0] = completion_code;
2334
2335 return PLDM_SUCCESS;
2336}
2337
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002338LIBPLDM_ABI_TESTING
2339int decode_activate_firmware_req(const struct pldm_msg *msg,
2340 size_t payload_length, bool *self_contained)
2341{
2342 int rc;
2343 struct pldm_msgbuf _buf;
2344 struct pldm_msgbuf *buf = &_buf;
2345
2346 if (msg == NULL || self_contained == NULL) {
2347 return -EINVAL;
2348 }
2349
2350 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
2351 if (rc) {
2352 return 0;
2353 }
2354
2355 uint8_t self_contained_u8 = 0;
2356 rc = pldm_msgbuf_extract(buf, self_contained_u8);
2357 if (rc) {
2358 return rc;
2359 }
2360 if (buf->remaining != 0) {
2361 return -EOVERFLOW;
2362 }
2363 *self_contained = (bool)self_contained_u8;
2364 return 0;
2365}
2366
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302367LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302368int encode_activate_firmware_req(uint8_t instance_id,
2369 bool8_t self_contained_activation_req,
2370 struct pldm_msg *msg, size_t payload_length)
2371{
2372 if (msg == NULL) {
2373 return PLDM_ERROR_INVALID_DATA;
2374 }
2375
2376 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
2377 return PLDM_ERROR_INVALID_LENGTH;
2378 }
2379
2380 if (!is_self_contained_activation_req_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302381 self_contained_activation_req)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09302382 return PLDM_ERROR_INVALID_DATA;
2383 }
2384
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302385 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302386 header.instance = instance_id;
2387 header.msg_type = PLDM_REQUEST;
2388 header.pldm_type = PLDM_FWUP;
2389 header.command = PLDM_ACTIVATE_FIRMWARE;
2390 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2391 if (rc) {
2392 return rc;
2393 }
2394
2395 struct pldm_activate_firmware_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302396 (struct pldm_activate_firmware_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302397
2398 request->self_contained_activation_req = self_contained_activation_req;
2399
2400 return PLDM_SUCCESS;
2401}
2402
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302403LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302404int decode_activate_firmware_resp(const struct pldm_msg *msg,
2405 size_t payload_length,
2406 uint8_t *completion_code,
2407 uint16_t *estimated_time_activation)
2408{
2409 if (msg == NULL || completion_code == NULL ||
2410 estimated_time_activation == NULL || !payload_length) {
2411 return PLDM_ERROR_INVALID_DATA;
2412 }
2413
2414 *completion_code = msg->payload[0];
2415 if (*completion_code != PLDM_SUCCESS) {
2416 return PLDM_SUCCESS;
2417 }
2418
2419 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
2420 return PLDM_ERROR_INVALID_LENGTH;
2421 }
2422
2423 struct pldm_activate_firmware_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302424 (struct pldm_activate_firmware_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302425
2426 *estimated_time_activation =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302427 le16toh(response->estimated_time_activation);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302428
2429 return PLDM_SUCCESS;
2430}
2431
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002432LIBPLDM_ABI_TESTING
2433int encode_activate_firmware_resp(
2434 uint8_t instance_id,
2435 const struct pldm_activate_firmware_resp *resp_data,
2436 struct pldm_msg *msg, size_t *payload_length)
2437{
2438 int rc;
2439 struct pldm_msgbuf _buf;
2440 struct pldm_msgbuf *buf = &_buf;
2441
2442 if (msg == NULL || payload_length == NULL) {
2443 return -EINVAL;
2444 }
2445
2446 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2447 PLDM_ACTIVATE_FIRMWARE, msg);
2448 if (rc) {
2449 return -EINVAL;
2450 }
2451
2452 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2453 if (rc) {
2454 return rc;
2455 }
2456
2457 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2458 pldm_msgbuf_insert(buf, resp_data->estimated_time_activation);
2459
2460 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2461}
2462
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302463LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302464int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
2465 size_t payload_length)
2466{
2467 if (msg == NULL) {
2468 return PLDM_ERROR_INVALID_DATA;
2469 }
2470
2471 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
2472 return PLDM_ERROR_INVALID_LENGTH;
2473 }
2474
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302475 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302476 header.instance = instance_id;
2477 header.msg_type = PLDM_REQUEST;
2478 header.pldm_type = PLDM_FWUP;
2479 header.command = PLDM_GET_STATUS;
2480 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2481 if (rc) {
2482 return rc;
2483 }
2484
2485 return PLDM_SUCCESS;
2486}
2487
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302488LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302489int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
2490 uint8_t *completion_code, uint8_t *current_state,
2491 uint8_t *previous_state, uint8_t *aux_state,
2492 uint8_t *aux_state_status, uint8_t *progress_percent,
2493 uint8_t *reason_code,
2494 bitfield32_t *update_option_flags_enabled)
2495{
2496 if (msg == NULL || completion_code == NULL || current_state == NULL ||
2497 previous_state == NULL || aux_state == NULL ||
2498 aux_state_status == NULL || progress_percent == NULL ||
2499 reason_code == NULL || update_option_flags_enabled == NULL ||
2500 !payload_length) {
2501 return PLDM_ERROR_INVALID_DATA;
2502 }
2503
2504 *completion_code = msg->payload[0];
2505 if (*completion_code != PLDM_SUCCESS) {
2506 return PLDM_SUCCESS;
2507 }
2508
2509 if (payload_length != sizeof(struct pldm_get_status_resp)) {
2510 return PLDM_ERROR_INVALID_LENGTH;
2511 }
2512 struct pldm_get_status_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302513 (struct pldm_get_status_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302514
2515 if (!is_state_valid(response->current_state)) {
2516 return PLDM_ERROR_INVALID_DATA;
2517 }
2518 if (!is_state_valid(response->previous_state)) {
2519 return PLDM_ERROR_INVALID_DATA;
2520 }
2521 if (!is_aux_state_valid(response->aux_state)) {
2522 return PLDM_ERROR_INVALID_DATA;
2523 }
2524 if (!is_aux_state_status_valid(response->aux_state_status)) {
2525 return PLDM_ERROR_INVALID_DATA;
2526 }
2527 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
2528 return PLDM_ERROR_INVALID_DATA;
2529 }
2530 if (!is_reason_code_valid(response->reason_code)) {
2531 return PLDM_ERROR_INVALID_DATA;
2532 }
2533
2534 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
2535 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
2536 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
2537 if (response->aux_state !=
2538 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
2539 return PLDM_ERROR_INVALID_DATA;
2540 }
2541 }
2542
2543 *current_state = response->current_state;
2544 *previous_state = response->previous_state;
2545 *aux_state = response->aux_state;
2546 *aux_state_status = response->aux_state_status;
2547 *progress_percent = response->progress_percent;
2548 *reason_code = response->reason_code;
2549 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302550 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302551
2552 return PLDM_SUCCESS;
2553}
2554
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002555LIBPLDM_ABI_TESTING
2556int encode_get_status_resp(uint8_t instance_id,
2557 const struct pldm_get_status_resp *status,
2558 struct pldm_msg *msg, size_t *payload_length)
2559{
2560 int rc;
2561 struct pldm_msgbuf _buf;
2562 struct pldm_msgbuf *buf = &_buf;
2563
2564 if (status == NULL || msg == NULL || payload_length == NULL) {
2565 return -EINVAL;
2566 }
2567
2568 if (status->completion_code != PLDM_SUCCESS) {
2569 return -EINVAL;
2570 }
2571
2572 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2573 PLDM_GET_STATUS, msg);
2574 if (rc) {
2575 return -EINVAL;
2576 }
2577
2578 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2579 if (rc) {
2580 return rc;
2581 }
2582
2583 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2584 pldm_msgbuf_insert(buf, status->current_state);
2585 pldm_msgbuf_insert(buf, status->previous_state);
2586 pldm_msgbuf_insert(buf, status->aux_state);
2587 pldm_msgbuf_insert(buf, status->aux_state_status);
2588 pldm_msgbuf_insert(buf, status->progress_percent);
2589 pldm_msgbuf_insert(buf, status->reason_code);
2590 pldm_msgbuf_insert(buf, status->update_option_flags_enabled.value);
2591
2592 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2593}
2594
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302595LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302596int encode_cancel_update_component_req(uint8_t instance_id,
2597 struct pldm_msg *msg,
2598 size_t payload_length)
2599{
2600 if (msg == NULL) {
2601 return PLDM_ERROR_INVALID_DATA;
2602 }
2603
2604 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
2605 return PLDM_ERROR_INVALID_LENGTH;
2606 }
2607
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302608 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302609 header.instance = instance_id;
2610 header.msg_type = PLDM_REQUEST;
2611 header.pldm_type = PLDM_FWUP;
2612 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
2613 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2614 if (rc) {
2615 return rc;
2616 }
2617
2618 return PLDM_SUCCESS;
2619}
2620
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302621LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302622int decode_cancel_update_component_resp(const struct pldm_msg *msg,
2623 size_t payload_length,
2624 uint8_t *completion_code)
2625{
2626 if (msg == NULL || completion_code == NULL) {
2627 return PLDM_ERROR_INVALID_DATA;
2628 }
2629
2630 if (payload_length != sizeof(*completion_code)) {
2631 return PLDM_ERROR_INVALID_LENGTH;
2632 }
2633
2634 *completion_code = msg->payload[0];
2635 return PLDM_SUCCESS;
2636}
2637
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302638LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302639int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
2640 size_t payload_length)
2641{
2642 if (msg == NULL) {
2643 return PLDM_ERROR_INVALID_DATA;
2644 }
2645
2646 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
2647 return PLDM_ERROR_INVALID_LENGTH;
2648 }
2649
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302650 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302651 header.instance = instance_id;
2652 header.msg_type = PLDM_REQUEST;
2653 header.pldm_type = PLDM_FWUP;
2654 header.command = PLDM_CANCEL_UPDATE;
2655 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2656 if (rc) {
2657 return rc;
2658 }
2659
2660 return PLDM_SUCCESS;
2661}
2662
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302663LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302664int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
2665 uint8_t *completion_code,
2666 bool8_t *non_functioning_component_indication,
2667 bitfield64_t *non_functioning_component_bitmap)
2668{
2669 if (msg == NULL || completion_code == NULL ||
2670 non_functioning_component_indication == NULL ||
2671 non_functioning_component_bitmap == NULL || !payload_length) {
2672 return PLDM_ERROR_INVALID_DATA;
2673 }
2674
2675 *completion_code = msg->payload[0];
2676 if (*completion_code != PLDM_SUCCESS) {
2677 return PLDM_SUCCESS;
2678 }
2679
2680 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
2681 return PLDM_ERROR_INVALID_LENGTH;
2682 }
2683 struct pldm_cancel_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302684 (struct pldm_cancel_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302685
2686 if (!is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302687 response->non_functioning_component_indication)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09302688 return PLDM_ERROR_INVALID_DATA;
2689 }
2690
2691 *non_functioning_component_indication =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302692 response->non_functioning_component_indication;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302693
2694 if (*non_functioning_component_indication) {
2695 non_functioning_component_bitmap->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302696 le64toh(response->non_functioning_component_bitmap);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302697 }
2698
2699 return PLDM_SUCCESS;
2700}
Matt Johnstoncf9a2df2024-11-07 15:29:29 +08002701
2702LIBPLDM_ABI_TESTING
2703int encode_cancel_update_resp(uint8_t instance_id,
2704 const struct pldm_cancel_update_resp *resp_data,
2705 struct pldm_msg *msg, size_t *payload_length)
2706{
2707 int rc;
2708 struct pldm_msgbuf _buf;
2709 struct pldm_msgbuf *buf = &_buf;
2710
2711 if (msg == NULL || payload_length == NULL) {
2712 return -EINVAL;
2713 }
2714
2715 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2716 PLDM_CANCEL_UPDATE, msg);
2717 if (rc) {
2718 return -EINVAL;
2719 }
2720
2721 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2722 if (rc) {
2723 return rc;
2724 }
2725
2726 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2727 pldm_msgbuf_insert(buf,
2728 resp_data->non_functioning_component_indication);
2729 pldm_msgbuf_insert(buf, resp_data->non_functioning_component_bitmap);
2730
2731 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2732}