blob: c21c118a76603522760abef9f8b438c5b0d0f8ad [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09302#include "api.h"
Chris Wangb6ef35b2024-07-03 09:35:42 +08003#include "dsp/base.h"
Chris Wang4c1f2c72024-03-21 17:09:44 +08004#include "msgbuf.h"
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10305#include <libpldm/firmware_update.h>
6#include <libpldm/utils.h>
7
Andrew Jeffery9c766792022-08-10 23:12:49 +09308#include <endian.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05309#include <stdbool.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +093010#include <string.h>
11
12/** @brief Check whether string type value is valid
13 *
14 * @return true if string type value is valid, false if not
15 */
16static bool is_string_type_valid(uint8_t string_type)
17{
18 switch (string_type) {
19 case PLDM_STR_TYPE_UNKNOWN:
20 return false;
21 case PLDM_STR_TYPE_ASCII:
22 case PLDM_STR_TYPE_UTF_8:
23 case PLDM_STR_TYPE_UTF_16:
24 case PLDM_STR_TYPE_UTF_16LE:
25 case PLDM_STR_TYPE_UTF_16BE:
26 return true;
27 default:
28 return false;
29 }
30}
31
32/** @brief Return the length of the descriptor type described in firmware update
33 * specification
34 *
35 * @return length of the descriptor type if descriptor type is valid else
36 * return 0
37 */
38static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
39{
40 switch (descriptor_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093041 case PLDM_FWUP_PCI_VENDOR_ID:
42 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
43 case PLDM_FWUP_IANA_ENTERPRISE_ID:
44 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
45 case PLDM_FWUP_UUID:
46 return PLDM_FWUP_UUID_LENGTH;
47 case PLDM_FWUP_PNP_VENDOR_ID:
48 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
49 case PLDM_FWUP_ACPI_VENDOR_ID:
50 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
51 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
52 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
53 case PLDM_FWUP_SCSI_VENDOR_ID:
54 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
55 case PLDM_FWUP_PCI_DEVICE_ID:
56 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
57 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
58 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
59 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
60 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
61 case PLDM_FWUP_PCI_REVISION_ID:
62 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
63 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
64 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
65 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
66 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
67 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
68 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
69 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
70 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
71 case PLDM_FWUP_SCSI_PRODUCT_ID:
72 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
73 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
74 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
75 default:
76 return 0;
77 }
78}
79
Chris Wang4c1f2c72024-03-21 17:09:44 +080080static bool is_downstream_device_update_support_valid(uint8_t resp)
81{
82 switch (resp) {
83 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
84 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
85 return true;
86 default:
87 return false;
88 }
89}
90
Chris Wang458475a2024-03-26 17:59:19 +080091static bool
92is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)
93{
94 switch (transfer_op_flag) {
95 case PLDM_GET_NEXTPART:
96 case PLDM_GET_FIRSTPART:
97 return true;
98 default:
99 return false;
100 }
101}
102
Andrew Jeffery9c766792022-08-10 23:12:49 +0930103/** @brief Check whether ComponentResponse is valid
104 *
105 * @return true if ComponentResponse is valid, false if not
106 */
107static bool is_comp_resp_valid(uint8_t comp_resp)
108{
109 switch (comp_resp) {
110 case PLDM_CR_COMP_CAN_BE_UPDATED:
111 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
112 return true;
113
114 default:
115 return false;
116 }
117}
118
119/** @brief Check whether ComponentResponseCode is valid
120 *
121 * @return true if ComponentResponseCode is valid, false if not
122 */
123static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
124{
125 switch (comp_resp_code) {
126 case PLDM_CRC_COMP_CAN_BE_UPDATED:
127 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
128 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
129 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
130 case PLDM_CRC_COMP_CONFLICT:
131 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
132 case PLDM_CRC_COMP_NOT_SUPPORTED:
133 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
134 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
135 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
136 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
137 case PLDM_CRC_COMP_VER_STR_LOWER:
138 return true;
139
140 default:
141 if (comp_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930142 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930143 comp_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930144 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930145 return true;
146 }
147 return false;
148 }
149}
150
151/** @brief Check whether ComponentCompatibilityResponse is valid
152 *
153 * @return true if ComponentCompatibilityResponse is valid, false if not
154 */
155static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
156{
157 switch (comp_compatibility_resp) {
158 case PLDM_CCR_COMP_CAN_BE_UPDATED:
159 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
160 return true;
161
162 default:
163 return false;
164 }
165}
166
167/** @brief Check whether ComponentCompatibilityResponse Code is valid
168 *
169 * @return true if ComponentCompatibilityResponse Code is valid, false if not
170 */
171static bool
172is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
173{
174 switch (comp_compatibility_resp_code) {
175 case PLDM_CCRC_NO_RESPONSE_CODE:
176 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
177 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
178 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
179 case PLDM_CCRC_COMP_CONFLICT:
180 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
181 case PLDM_CCRC_COMP_NOT_SUPPORTED:
182 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
183 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
184 case PLDM_CCRC_COMP_INFO_NO_MATCH:
185 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
186 case PLDM_CCRC_COMP_VER_STR_LOWER:
187 return true;
188
189 default:
190 if (comp_compatibility_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930191 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930192 comp_compatibility_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930193 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930194 return true;
195 }
196 return false;
197 }
198}
199
200/** @brief Check whether SelfContainedActivationRequest is valid
201 *
202 * @return true if SelfContainedActivationRequest is valid, false if not
203 */
204static bool
205is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
206{
207 switch (self_contained_activation_req) {
208 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
209 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
210 return true;
211
212 default:
213 return false;
214 }
215}
216
217/** @brief Check if current or previous status in GetStatus command response is
218 * valid
219 *
220 * @param[in] state - current or previous different state machine state of
221 * the FD
222 * @return true if state is valid, false if not
223 */
224static bool is_state_valid(uint8_t state)
225{
226 switch (state) {
227 case PLDM_FD_STATE_IDLE:
228 case PLDM_FD_STATE_LEARN_COMPONENTS:
229 case PLDM_FD_STATE_READY_XFER:
230 case PLDM_FD_STATE_DOWNLOAD:
231 case PLDM_FD_STATE_VERIFY:
232 case PLDM_FD_STATE_APPLY:
233 case PLDM_FD_STATE_ACTIVATE:
234 return true;
235
236 default:
237 return false;
238 }
239}
240
241/** @brief Check if aux state in GetStatus command response is valid
242 *
243 * @param[in] aux_state - provides additional information to the UA to describe
244 * the current operation state of the FD/FDP
245 *
246 * @return true if aux state is valid, false if not
247 */
248static bool is_aux_state_valid(uint8_t aux_state)
249{
250 switch (aux_state) {
251 case PLDM_FD_OPERATION_IN_PROGRESS:
252 case PLDM_FD_OPERATION_SUCCESSFUL:
253 case PLDM_FD_OPERATION_FAILED:
254 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
255 return true;
256
257 default:
258 return false;
259 }
260}
261
262/** @brief Check if aux state status in GetStatus command response is valid
263 *
264 * @param[in] aux_state_status - aux state status
265 *
266 * @return true if aux state status is valid, false if not
267 */
268static bool is_aux_state_status_valid(uint8_t aux_state_status)
269{
270 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
271 aux_state_status == PLDM_FD_TIMEOUT ||
Andrew Jeffery67f7ed92023-04-05 14:00:00 +0930272 aux_state_status == PLDM_FD_GENERIC_ERROR ||
273 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
274 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930275 return true;
276 }
277
278 return false;
279}
280
281/** @brief Check if reason code in GetStatus command response is valid
282 *
283 * @param[in] reason_code - provides the reason for why the current state
284 * entered the IDLE state
285 *
286 * @return true if reason code is valid, false if not
287 */
288static bool is_reason_code_valid(uint8_t reason_code)
289{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930290 switch (reason_code) {
291 case PLDM_FD_INITIALIZATION:
292 case PLDM_FD_ACTIVATE_FW:
293 case PLDM_FD_CANCEL_UPDATE:
294 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
295 case PLDM_FD_TIMEOUT_READY_XFER:
296 case PLDM_FD_TIMEOUT_DOWNLOAD:
297 case PLDM_FD_TIMEOUT_VERIFY:
298 case PLDM_FD_TIMEOUT_APPLY:
299 return true;
300
301 default:
302 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
303 return true;
304 }
305 return false;
306 }
307}
308
309/** @brief Check if non functioning component indication in CancelUpdate
310 * response is valid
311 *
312 * @return true if non functioning component indication is valid, false if not
313 */
314static bool is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930315 bool8_t non_functioning_component_indication)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930316{
317 switch (non_functioning_component_indication) {
318 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
319 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
320 return true;
321
322 default:
323 return false;
324 }
325}
326
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930327LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930328int decode_pldm_package_header_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930329 const uint8_t *data, size_t length,
330 struct pldm_package_header_information *package_header_info,
331 struct variable_field *package_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930332{
333 if (data == NULL || package_header_info == NULL ||
334 package_version_str == NULL) {
335 return PLDM_ERROR_INVALID_DATA;
336 }
337
338 if (length < sizeof(struct pldm_package_header_information)) {
339 return PLDM_ERROR_INVALID_LENGTH;
340 }
341
342 struct pldm_package_header_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930343 (struct pldm_package_header_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930344
345 if (!is_string_type_valid(data_header->package_version_string_type) ||
346 (data_header->package_version_string_length == 0)) {
347 return PLDM_ERROR_INVALID_DATA;
348 }
349
350 if (length < sizeof(struct pldm_package_header_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930351 data_header->package_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930352 return PLDM_ERROR_INVALID_LENGTH;
353 }
354
355 if ((data_header->component_bitmap_bit_length %
356 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
357 return PLDM_ERROR_INVALID_DATA;
358 }
359
360 memcpy(package_header_info->uuid, data_header->uuid,
361 sizeof(data_header->uuid));
362 package_header_info->package_header_format_version =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930363 data_header->package_header_format_version;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930364 package_header_info->package_header_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930365 le16toh(data_header->package_header_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930366 memcpy(package_header_info->package_release_date_time,
367 data_header->package_release_date_time,
368 sizeof(data_header->package_release_date_time));
369 package_header_info->component_bitmap_bit_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930370 le16toh(data_header->component_bitmap_bit_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930371 package_header_info->package_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930372 data_header->package_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930373 package_header_info->package_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930374 data_header->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930375 package_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930376 data + sizeof(struct pldm_package_header_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930377 package_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930378 package_header_info->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930379
380 return PLDM_SUCCESS;
381}
382
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930383LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930384int decode_firmware_device_id_record(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930385 const uint8_t *data, size_t length,
386 uint16_t component_bitmap_bit_length,
387 struct pldm_firmware_device_id_record *fw_device_id_record,
388 struct variable_field *applicable_components,
389 struct variable_field *comp_image_set_version_str,
390 struct variable_field *record_descriptors,
391 struct variable_field *fw_device_pkg_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930392{
393 if (data == NULL || fw_device_id_record == NULL ||
394 applicable_components == NULL ||
395 comp_image_set_version_str == NULL || record_descriptors == NULL ||
396 fw_device_pkg_data == NULL) {
397 return PLDM_ERROR_INVALID_DATA;
398 }
399
400 if (length < sizeof(struct pldm_firmware_device_id_record)) {
401 return PLDM_ERROR_INVALID_LENGTH;
402 }
403
404 if ((component_bitmap_bit_length %
405 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
406 return PLDM_ERROR_INVALID_DATA;
407 }
408
409 struct pldm_firmware_device_id_record *data_record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930410 (struct pldm_firmware_device_id_record *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930411
412 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930413 data_record->comp_image_set_version_string_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930414 (data_record->comp_image_set_version_string_length == 0)) {
415 return PLDM_ERROR_INVALID_DATA;
416 }
417
418 fw_device_id_record->record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930419 le16toh(data_record->record_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930420 fw_device_id_record->descriptor_count = data_record->descriptor_count;
421 fw_device_id_record->device_update_option_flags.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930422 le32toh(data_record->device_update_option_flags.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930423 fw_device_id_record->comp_image_set_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930424 data_record->comp_image_set_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930425 fw_device_id_record->comp_image_set_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930426 data_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930427 fw_device_id_record->fw_device_pkg_data_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930428 le16toh(data_record->fw_device_pkg_data_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930429
430 if (length < fw_device_id_record->record_length) {
431 return PLDM_ERROR_INVALID_LENGTH;
432 }
433
434 uint16_t applicable_components_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930435 component_bitmap_bit_length /
436 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930437 uint16_t calc_min_record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930438 sizeof(struct pldm_firmware_device_id_record) +
439 applicable_components_length +
440 data_record->comp_image_set_version_string_length +
441 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
442 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930443
444 if (fw_device_id_record->record_length < calc_min_record_length) {
445 return PLDM_ERROR_INVALID_LENGTH;
446 }
447
448 applicable_components->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930449 data + sizeof(struct pldm_firmware_device_id_record);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930450 applicable_components->length = applicable_components_length;
451
452 comp_image_set_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930453 applicable_components->ptr + applicable_components->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930454 comp_image_set_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930455 fw_device_id_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930456
457 record_descriptors->ptr = comp_image_set_version_str->ptr +
458 comp_image_set_version_str->length;
459 record_descriptors->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930460 fw_device_id_record->record_length -
461 sizeof(struct pldm_firmware_device_id_record) -
462 applicable_components_length -
463 fw_device_id_record->comp_image_set_version_string_length -
464 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930465
466 if (fw_device_id_record->fw_device_pkg_data_length) {
467 fw_device_pkg_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930468 record_descriptors->ptr + record_descriptors->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930469 fw_device_pkg_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930470 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930471 }
472
473 return PLDM_SUCCESS;
474}
475
Andrew Jeffery3a2c6582024-11-07 16:30:36 +1030476LIBPLDM_ABI_TESTING
477int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter,
478 struct pldm_descriptor *desc)
479{
480 struct pldm_msgbuf _buf;
481 struct pldm_msgbuf *buf = &_buf;
482 int rc;
483
484 if (!iter || !iter->field || !desc) {
485 return -EINVAL;
486 }
487
488 rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN,
489 iter->field->ptr, iter->field->length);
490 if (rc) {
491 return rc;
492 }
493
494 pldm_msgbuf_extract(buf, desc->descriptor_type);
495 rc = pldm_msgbuf_extract(buf, desc->descriptor_length);
496 if (rc) {
497 return rc;
498 }
499
500 desc->descriptor_data = NULL;
501 pldm_msgbuf_span_required(buf, desc->descriptor_length,
502 (void **)&desc->descriptor_data);
503 iter->field->ptr = NULL;
504 pldm_msgbuf_span_remaining(buf, (void **)&iter->field->ptr,
505 &iter->field->length);
506
507 return pldm_msgbuf_destroy(buf);
508}
509
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930510LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930511int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
512 uint16_t *descriptor_type,
513 struct variable_field *descriptor_data)
514{
515 uint16_t descriptor_length = 0;
516
517 if (data == NULL || descriptor_type == NULL ||
518 descriptor_data == NULL) {
519 return PLDM_ERROR_INVALID_DATA;
520 }
521
522 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
523 return PLDM_ERROR_INVALID_LENGTH;
524 }
525
526 struct pldm_descriptor_tlv *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930527 (struct pldm_descriptor_tlv *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930528
529 *descriptor_type = le16toh(entry->descriptor_type);
530 descriptor_length = le16toh(entry->descriptor_length);
531 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
532 if (descriptor_length !=
533 get_descriptor_type_length(*descriptor_type)) {
534 return PLDM_ERROR_INVALID_LENGTH;
535 }
536 }
537
538 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
539 descriptor_length)) {
540 return PLDM_ERROR_INVALID_LENGTH;
541 }
542
543 descriptor_data->ptr = entry->descriptor_data;
544 descriptor_data->length = descriptor_length;
545
546 return PLDM_SUCCESS;
547}
548
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930549LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930550int decode_vendor_defined_descriptor_value(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930551 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
552 struct variable_field *descriptor_title_str,
553 struct variable_field *descriptor_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930554{
555 if (data == NULL || descriptor_title_str_type == NULL ||
556 descriptor_title_str == NULL || descriptor_data == NULL) {
557 return PLDM_ERROR_INVALID_DATA;
558 }
559
560 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
561 return PLDM_ERROR_INVALID_LENGTH;
562 }
563
564 struct pldm_vendor_defined_descriptor_title_data *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930565 (struct pldm_vendor_defined_descriptor_title_data *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930566 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930567 entry->vendor_defined_descriptor_title_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930568 (entry->vendor_defined_descriptor_title_str_len == 0)) {
569 return PLDM_ERROR_INVALID_DATA;
570 }
571
Manojkiran Eda9e3a5d42024-06-17 16:06:42 +0530572 // Assuming at least 1 byte of VendorDefinedDescriptorData
Andrew Jeffery9c766792022-08-10 23:12:49 +0930573 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
574 entry->vendor_defined_descriptor_title_str_len)) {
575 return PLDM_ERROR_INVALID_LENGTH;
576 }
577
578 *descriptor_title_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930579 entry->vendor_defined_descriptor_title_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930580 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
581 descriptor_title_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930582 entry->vendor_defined_descriptor_title_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930583
584 descriptor_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930585 descriptor_title_str->ptr + descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930586 descriptor_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930587 length -
588 sizeof(entry->vendor_defined_descriptor_title_str_type) -
589 sizeof(entry->vendor_defined_descriptor_title_str_len) -
590 descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930591
592 return PLDM_SUCCESS;
593}
594
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930595LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930596int decode_pldm_comp_image_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930597 const uint8_t *data, size_t length,
598 struct pldm_component_image_information *pldm_comp_image_info,
599 struct variable_field *comp_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930600{
601 if (data == NULL || pldm_comp_image_info == NULL ||
602 comp_version_str == NULL) {
603 return PLDM_ERROR_INVALID_DATA;
604 }
605
606 if (length < sizeof(struct pldm_component_image_information)) {
607 return PLDM_ERROR_INVALID_LENGTH;
608 }
609
610 struct pldm_component_image_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930611 (struct pldm_component_image_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930612
613 if (!is_string_type_valid(data_header->comp_version_string_type) ||
614 (data_header->comp_version_string_length == 0)) {
615 return PLDM_ERROR_INVALID_DATA;
616 }
617
618 if (length < sizeof(struct pldm_component_image_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930619 data_header->comp_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930620 return PLDM_ERROR_INVALID_LENGTH;
621 }
622
623 pldm_comp_image_info->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930624 le16toh(data_header->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930625 pldm_comp_image_info->comp_identifier =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930626 le16toh(data_header->comp_identifier);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930627 pldm_comp_image_info->comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930628 le32toh(data_header->comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930629 pldm_comp_image_info->comp_options.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930630 le16toh(data_header->comp_options.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930631 pldm_comp_image_info->requested_comp_activation_method.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930632 le16toh(data_header->requested_comp_activation_method.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930633 pldm_comp_image_info->comp_location_offset =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930634 le32toh(data_header->comp_location_offset);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930635 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
636 pldm_comp_image_info->comp_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930637 data_header->comp_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930638 pldm_comp_image_info->comp_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930639 data_header->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930640
641 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
642 pldm_comp_image_info->comp_comparison_stamp !=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930643 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930644 return PLDM_ERROR_INVALID_DATA;
645 }
646
647 if (pldm_comp_image_info->comp_location_offset == 0 ||
648 pldm_comp_image_info->comp_size == 0) {
649 return PLDM_ERROR_INVALID_DATA;
650 }
651
652 comp_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930653 data + sizeof(struct pldm_component_image_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930654 comp_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930655 pldm_comp_image_info->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930656
657 return PLDM_SUCCESS;
658}
659
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930660LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930661int encode_query_device_identifiers_req(uint8_t instance_id,
662 size_t payload_length,
663 struct pldm_msg *msg)
664{
665 if (msg == NULL) {
666 return PLDM_ERROR_INVALID_DATA;
667 }
668
669 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
670 return PLDM_ERROR_INVALID_LENGTH;
671 }
672
673 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
674 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
675}
676
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930677LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930678int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
679 size_t payload_length,
680 uint8_t *completion_code,
681 uint32_t *device_identifiers_len,
682 uint8_t *descriptor_count,
683 uint8_t **descriptor_data)
684{
685 if (msg == NULL || completion_code == NULL ||
686 device_identifiers_len == NULL || descriptor_count == NULL ||
687 descriptor_data == NULL) {
688 return PLDM_ERROR_INVALID_DATA;
689 }
690
691 *completion_code = msg->payload[0];
692 if (PLDM_SUCCESS != *completion_code) {
693 return PLDM_SUCCESS;
694 }
695
696 if (payload_length <
697 sizeof(struct pldm_query_device_identifiers_resp)) {
698 return PLDM_ERROR_INVALID_LENGTH;
699 }
700
701 struct pldm_query_device_identifiers_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930702 (struct pldm_query_device_identifiers_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930703 *device_identifiers_len = le32toh(response->device_identifiers_len);
704
705 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
706 return PLDM_ERROR_INVALID_LENGTH;
707 }
708
709 if (payload_length !=
710 sizeof(struct pldm_query_device_identifiers_resp) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930711 *device_identifiers_len) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930712 return PLDM_ERROR_INVALID_LENGTH;
713 }
714 *descriptor_count = response->descriptor_count;
715
716 if (*descriptor_count == 0) {
717 return PLDM_ERROR_INVALID_DATA;
718 }
719 *descriptor_data =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930720 (uint8_t *)(msg->payload +
721 sizeof(struct pldm_query_device_identifiers_resp));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930722 return PLDM_SUCCESS;
723}
724
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930725LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930726int encode_get_firmware_parameters_req(uint8_t instance_id,
727 size_t payload_length,
728 struct pldm_msg *msg)
729{
730 if (msg == NULL) {
731 return PLDM_ERROR_INVALID_DATA;
732 }
733
734 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
735 return PLDM_ERROR_INVALID_LENGTH;
736 }
737
738 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
739 PLDM_GET_FIRMWARE_PARAMETERS, msg);
740}
741
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930742LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930743int decode_get_firmware_parameters_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930744 const struct pldm_msg *msg, size_t payload_length,
745 struct pldm_get_firmware_parameters_resp *resp_data,
746 struct variable_field *active_comp_image_set_ver_str,
747 struct variable_field *pending_comp_image_set_ver_str,
748 struct variable_field *comp_parameter_table)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930749{
750 if (msg == NULL || resp_data == NULL ||
751 active_comp_image_set_ver_str == NULL ||
752 pending_comp_image_set_ver_str == NULL ||
753 comp_parameter_table == NULL || !payload_length) {
754 return PLDM_ERROR_INVALID_DATA;
755 }
756
757 resp_data->completion_code = msg->payload[0];
758 if (PLDM_SUCCESS != resp_data->completion_code) {
759 return PLDM_SUCCESS;
760 }
761
762 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
763 return PLDM_ERROR_INVALID_LENGTH;
764 }
765
766 struct pldm_get_firmware_parameters_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930767 (struct pldm_get_firmware_parameters_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930768
769 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930770 response->active_comp_image_set_ver_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930771 (response->active_comp_image_set_ver_str_len == 0)) {
772 return PLDM_ERROR_INVALID_DATA;
773 }
774
775 if (response->pending_comp_image_set_ver_str_len == 0) {
776 if (response->pending_comp_image_set_ver_str_type !=
777 PLDM_STR_TYPE_UNKNOWN) {
778 return PLDM_ERROR_INVALID_DATA;
779 }
780 } else {
781 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930782 response->pending_comp_image_set_ver_str_type)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930783 return PLDM_ERROR_INVALID_DATA;
784 }
785 }
786
787 size_t partial_response_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930788 sizeof(struct pldm_get_firmware_parameters_resp) +
789 response->active_comp_image_set_ver_str_len +
790 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930791
792 if (payload_length < partial_response_length) {
793 return PLDM_ERROR_INVALID_LENGTH;
794 }
795
796 resp_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930797 le32toh(response->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930798 resp_data->comp_count = le16toh(response->comp_count);
799 resp_data->active_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930800 response->active_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930801 resp_data->active_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930802 response->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930803 resp_data->pending_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930804 response->pending_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930805 resp_data->pending_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930806 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930807
808 active_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930809 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930810 active_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930811 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930812
813 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
814 pending_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930815 msg->payload +
816 sizeof(struct pldm_get_firmware_parameters_resp) +
817 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930818 pending_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930819 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930820 } else {
821 pending_comp_image_set_ver_str->ptr = NULL;
822 pending_comp_image_set_ver_str->length = 0;
823 }
824
825 if (payload_length > partial_response_length && resp_data->comp_count) {
826 comp_parameter_table->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930827 msg->payload +
828 sizeof(struct pldm_get_firmware_parameters_resp) +
829 resp_data->active_comp_image_set_ver_str_len +
830 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930831 comp_parameter_table->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930832 payload_length - partial_response_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930833 } else {
834 comp_parameter_table->ptr = NULL;
835 comp_parameter_table->length = 0;
836 }
837
838 return PLDM_SUCCESS;
839}
840
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930841LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930842int decode_get_firmware_parameters_resp_comp_entry(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930843 const uint8_t *data, size_t length,
844 struct pldm_component_parameter_entry *component_data,
845 struct variable_field *active_comp_ver_str,
846 struct variable_field *pending_comp_ver_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930847{
848 if (data == NULL || component_data == NULL ||
849 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
850 return PLDM_ERROR_INVALID_DATA;
851 }
852
853 if (length < sizeof(struct pldm_component_parameter_entry)) {
854 return PLDM_ERROR_INVALID_LENGTH;
855 }
856
857 struct pldm_component_parameter_entry *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930858 (struct pldm_component_parameter_entry *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930859
860 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
861 entry->active_comp_ver_str_len +
862 entry->pending_comp_ver_str_len;
863
864 if (length < entry_length) {
865 return PLDM_ERROR_INVALID_LENGTH;
866 }
867
868 component_data->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930869 le16toh(entry->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930870 component_data->comp_identifier = le16toh(entry->comp_identifier);
871 component_data->comp_classification_index =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930872 entry->comp_classification_index;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930873 component_data->active_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930874 le32toh(entry->active_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930875 component_data->active_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930876 entry->active_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930877 component_data->active_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930878 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930879 memcpy(component_data->active_comp_release_date,
880 entry->active_comp_release_date,
881 sizeof(entry->active_comp_release_date));
882 component_data->pending_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930883 le32toh(entry->pending_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930884 component_data->pending_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930885 entry->pending_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930886 component_data->pending_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930887 entry->pending_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930888 memcpy(component_data->pending_comp_release_date,
889 entry->pending_comp_release_date,
890 sizeof(entry->pending_comp_release_date));
891 component_data->comp_activation_methods.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930892 le16toh(entry->comp_activation_methods.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930893 component_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930894 le32toh(entry->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930895
896 if (entry->active_comp_ver_str_len != 0) {
897 active_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930898 data + sizeof(struct pldm_component_parameter_entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930899 active_comp_ver_str->length = entry->active_comp_ver_str_len;
900 } else {
901 active_comp_ver_str->ptr = NULL;
902 active_comp_ver_str->length = 0;
903 }
904
905 if (entry->pending_comp_ver_str_len != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930906 pending_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930907 data + sizeof(struct pldm_component_parameter_entry) +
908 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930909 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
910 } else {
911 pending_comp_ver_str->ptr = NULL;
912 pending_comp_ver_str->length = 0;
913 }
914 return PLDM_SUCCESS;
915}
916
Chris Wang4c1f2c72024-03-21 17:09:44 +0800917LIBPLDM_ABI_TESTING
918int encode_query_downstream_devices_req(uint8_t instance_id,
919 struct pldm_msg *msg)
920{
921 if (msg == NULL) {
Unive Tien71e935c2024-11-25 17:21:43 +0800922 return -EINVAL;
Chris Wang4c1f2c72024-03-21 17:09:44 +0800923 }
924
Unive Tien71e935c2024-11-25 17:21:43 +0800925 return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id,
926 PLDM_FWUP,
927 PLDM_QUERY_DOWNSTREAM_DEVICES,
928 msg);
Chris Wang4c1f2c72024-03-21 17:09:44 +0800929}
930
931LIBPLDM_ABI_TESTING
932int decode_query_downstream_devices_resp(
933 const struct pldm_msg *msg, size_t payload_length,
934 struct pldm_query_downstream_devices_resp *resp_data)
935{
936 struct pldm_msgbuf _buf;
937 struct pldm_msgbuf *buf = &_buf;
938 int rc;
939
940 if (msg == NULL || resp_data == NULL || !payload_length) {
Unive Tien71e935c2024-11-25 17:21:43 +0800941 return -EINVAL;
Chris Wang4c1f2c72024-03-21 17:09:44 +0800942 }
943
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930944 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
945 msg->payload, payload_length);
Chris Wang4c1f2c72024-03-21 17:09:44 +0800946 if (rc) {
947 return rc;
948 }
949
950 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
951 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +0800952 return rc;
Chris Wang4c1f2c72024-03-21 17:09:44 +0800953 }
954 if (PLDM_SUCCESS != resp_data->completion_code) {
955 // Return the CC directly without decoding the rest of the payload
Unive Tien71e935c2024-11-25 17:21:43 +0800956 return 0;
Chris Wang4c1f2c72024-03-21 17:09:44 +0800957 }
958
959 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
Unive Tien71e935c2024-11-25 17:21:43 +0800960 return -EBADMSG;
Chris Wang4c1f2c72024-03-21 17:09:44 +0800961 }
962
963 rc = pldm_msgbuf_extract(buf,
964 resp_data->downstream_device_update_supported);
965 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +0800966 return rc;
Chris Wang4c1f2c72024-03-21 17:09:44 +0800967 }
968
969 if (!is_downstream_device_update_support_valid(
970 resp_data->downstream_device_update_supported)) {
Unive Tien71e935c2024-11-25 17:21:43 +0800971 return -EINVAL;
Chris Wang4c1f2c72024-03-21 17:09:44 +0800972 }
973
974 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
975 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
976 pldm_msgbuf_extract(buf, resp_data->capabilities.value);
977
Unive Tien71e935c2024-11-25 17:21:43 +0800978 return pldm_msgbuf_destroy_consumed(buf);
Chris Wang4c1f2c72024-03-21 17:09:44 +0800979}
980
Chris Wang458475a2024-03-26 17:59:19 +0800981LIBPLDM_ABI_TESTING
982int encode_query_downstream_identifiers_req(
Unive Tiend2f8a7e2024-11-27 10:59:34 +0800983 uint8_t instance_id,
984 const struct pldm_query_downstream_identifiers_req *params_req,
985 struct pldm_msg *msg, size_t payload_length)
Chris Wang458475a2024-03-26 17:59:19 +0800986{
987 struct pldm_msgbuf _buf;
988 struct pldm_msgbuf *buf = &_buf;
989 int rc;
990
Unive Tiend2f8a7e2024-11-27 10:59:34 +0800991 if (!msg || !params_req) {
Unive Tien71e935c2024-11-25 17:21:43 +0800992 return -EINVAL;
Chris Wang458475a2024-03-26 17:59:19 +0800993 }
994
Unive Tiend2f8a7e2024-11-27 10:59:34 +0800995 if (!is_transfer_operation_flag_valid(
996 (enum transfer_op_flag)
997 params_req->transfer_operation_flag)) {
Unive Tien71e935c2024-11-25 17:21:43 +0800998 return -EINVAL;
Chris Wang458475a2024-03-26 17:59:19 +0800999 }
1000
1001 struct pldm_header_info header = { 0 };
1002 header.instance = instance_id;
1003 header.msg_type = PLDM_REQUEST;
1004 header.pldm_type = PLDM_FWUP;
1005 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
Unive Tien71e935c2024-11-25 17:21:43 +08001006 rc = pack_pldm_header_errno(&header, &(msg->hdr));
Chris Wang458475a2024-03-26 17:59:19 +08001007 if (rc) {
1008 return rc;
1009 }
1010
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301011 rc = pldm_msgbuf_init_errno(buf,
1012 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
1013 msg->payload, payload_length);
Chris Wang458475a2024-03-26 17:59:19 +08001014 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001015 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001016 }
1017
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001018 pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
Chris Wang458475a2024-03-26 17:59:19 +08001019 // Data correctness has been verified, cast it to 1-byte data directly.
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001020 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
Chris Wang458475a2024-03-26 17:59:19 +08001021
Unive Tien71e935c2024-11-25 17:21:43 +08001022 return pldm_msgbuf_destroy(buf);
Chris Wang458475a2024-03-26 17:59:19 +08001023}
1024
1025LIBPLDM_ABI_TESTING
1026int decode_query_downstream_identifiers_resp(
1027 const struct pldm_msg *msg, size_t payload_length,
1028 struct pldm_query_downstream_identifiers_resp *resp_data,
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301029 struct pldm_downstream_device_iter *iter)
Chris Wang458475a2024-03-26 17:59:19 +08001030{
1031 struct pldm_msgbuf _buf;
1032 struct pldm_msgbuf *buf = &_buf;
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301033 void *remaining = NULL;
Unive Tien71e935c2024-11-25 17:21:43 +08001034 int rc = 0;
Chris Wang458475a2024-03-26 17:59:19 +08001035
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301036 if (msg == NULL || resp_data == NULL || iter == NULL ||
Chris Wang458475a2024-03-26 17:59:19 +08001037 !payload_length) {
Unive Tien71e935c2024-11-25 17:21:43 +08001038 return -EINVAL;
Chris Wang458475a2024-03-26 17:59:19 +08001039 }
1040
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301041 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1042 msg->payload, payload_length);
Chris Wang458475a2024-03-26 17:59:19 +08001043 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001044 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001045 }
1046
1047 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1048 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001049 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001050 }
1051 if (PLDM_SUCCESS != resp_data->completion_code) {
Unive Tien71e935c2024-11-25 17:21:43 +08001052 return 0;
Chris Wang458475a2024-03-26 17:59:19 +08001053 }
1054
1055 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
Unive Tien71e935c2024-11-25 17:21:43 +08001056 return -EBADMSG;
Chris Wang458475a2024-03-26 17:59:19 +08001057 }
1058
1059 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1060 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1061
1062 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
1063 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001064 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001065 }
1066
1067 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301068 rc = pldm_msgbuf_span_required(
1069 buf, resp_data->downstream_devices_length, &remaining);
Chris Wang458475a2024-03-26 17:59:19 +08001070 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001071 return rc;
Chris Wang458475a2024-03-26 17:59:19 +08001072 }
Chris Wang458475a2024-03-26 17:59:19 +08001073
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301074 rc = pldm_msgbuf_destroy(buf);
1075 if (rc) {
Unive Tien71e935c2024-11-25 17:21:43 +08001076 return rc;
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301077 }
1078
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301079 iter->field.ptr = remaining;
1080 iter->field.length = resp_data->downstream_devices_length;
1081 iter->devs = resp_data->number_of_downstream_devices;
1082
Unive Tien71e935c2024-11-25 17:21:43 +08001083 return 0;
Chris Wang458475a2024-03-26 17:59:19 +08001084}
1085
Chris Wangb6ef35b2024-07-03 09:35:42 +08001086LIBPLDM_ABI_TESTING
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10301087int decode_pldm_downstream_device_from_iter(
1088 struct pldm_downstream_device_iter *iter,
1089 struct pldm_downstream_device *dev)
1090{
1091 struct pldm_msgbuf _buf;
1092 struct pldm_msgbuf *buf = &_buf;
1093 int rc;
1094
1095 if (!iter || !dev) {
1096 return -EINVAL;
1097 }
1098
1099 rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr,
1100 iter->field.length);
1101 if (rc) {
1102 return rc;
1103 }
1104
1105 pldm_msgbuf_extract(buf, dev->downstream_device_index);
1106 pldm_msgbuf_extract(buf, dev->downstream_descriptor_count);
1107 iter->field.ptr = NULL;
1108 pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr,
1109 &iter->field.length);
1110
1111 return pldm_msgbuf_destroy(buf);
1112}
1113
1114LIBPLDM_ABI_TESTING
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301115int encode_get_downstream_firmware_parameters_req(
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001116 uint8_t instance_id,
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301117 const struct pldm_get_downstream_firmware_parameters_req *params_req,
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001118 struct pldm_msg *msg, size_t payload_length)
Chris Wangb6ef35b2024-07-03 09:35:42 +08001119{
1120 struct pldm_msgbuf _buf;
1121 struct pldm_msgbuf *buf = &_buf;
1122 int rc;
1123
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001124 if (!msg || !params_req) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001125 return -EINVAL;
1126 }
1127
1128 rc = pldm_msgbuf_init_errno(
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301129 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES,
Chris Wangb6ef35b2024-07-03 09:35:42 +08001130 msg->payload, payload_length);
1131 if (rc < 0) {
1132 return rc;
1133 }
1134
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001135 if (!is_transfer_operation_flag_valid(
1136 (enum transfer_op_flag)
1137 params_req->transfer_operation_flag)) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001138 return -EBADMSG;
1139 }
1140
1141 struct pldm_header_info header = { 0 };
1142 header.instance = instance_id;
1143 header.msg_type = PLDM_REQUEST;
1144 header.pldm_type = PLDM_FWUP;
1145 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1146 rc = pack_pldm_header_errno(&header, &msg->hdr);
1147 if (rc < 0) {
1148 return rc;
1149 }
1150
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001151 pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001152 // Data correctness has been verified, cast it to 1-byte data directly.
Unive Tiend2f8a7e2024-11-27 10:59:34 +08001153 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
Chris Wangb6ef35b2024-07-03 09:35:42 +08001154
1155 return pldm_msgbuf_destroy(buf);
1156}
1157
1158LIBPLDM_ABI_TESTING
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301159int decode_get_downstream_firmware_parameters_resp(
Chris Wangb6ef35b2024-07-03 09:35:42 +08001160 const struct pldm_msg *msg, size_t payload_length,
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301161 struct pldm_get_downstream_firmware_parameters_resp *resp_data,
Chris Wangb6ef35b2024-07-03 09:35:42 +08001162 struct variable_field *downstream_device_param_table)
1163{
1164 struct pldm_msgbuf _buf;
1165 struct pldm_msgbuf *buf = &_buf;
1166 int rc;
1167
1168 if (msg == NULL || resp_data == NULL ||
1169 downstream_device_param_table == NULL) {
1170 return -EINVAL;
1171 }
1172
1173 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1174 msg->payload, payload_length);
1175 if (rc < 0) {
1176 return rc;
1177 }
1178
1179 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1180 if (rc < 0) {
1181 return rc;
1182 }
1183 if (PLDM_SUCCESS != resp_data->completion_code) {
1184 return 0;
1185 }
1186
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301187 if (payload_length <
1188 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) {
Chris Wangb6ef35b2024-07-03 09:35:42 +08001189 return -EBADMSG;
1190 }
1191
1192 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1193 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1194 pldm_msgbuf_extract(buf,
1195 resp_data->fdp_capabilities_during_update.value);
1196 pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1197
1198 return pldm_msgbuf_span_remaining(
1199 buf, (void **)&downstream_device_param_table->ptr,
1200 &downstream_device_param_table->length);
1201}
1202
1203LIBPLDM_ABI_TESTING
1204int decode_downstream_device_parameter_table_entry(
1205 struct variable_field *data,
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301206 struct pldm_downstream_device_parameters_entry *entry,
Chris Wangb6ef35b2024-07-03 09:35:42 +08001207 struct variable_field *versions)
1208{
1209 struct pldm_msgbuf _buf;
1210 struct pldm_msgbuf *buf = &_buf;
1211 void *cursor = NULL;
1212 size_t remaining;
1213 int rc;
1214
1215 if (data == NULL || entry == NULL || versions == NULL) {
1216 return -EINVAL;
1217 }
1218
1219 rc = pldm_msgbuf_init_errno(
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301220 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN, data->ptr,
Chris Wangb6ef35b2024-07-03 09:35:42 +08001221 data->length);
1222 if (rc < 0) {
1223 return rc;
1224 }
1225
1226 pldm_msgbuf_extract(buf, entry->downstream_device_index);
1227 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1228 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1229 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1230 if (rc < 0) {
1231 return rc;
1232 }
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001233 rc = pldm_msgbuf_extract_array(buf,
1234 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1235 entry->active_comp_release_date,
1236 sizeof(entry->active_comp_release_date));
1237 if (rc < 0) {
1238 return rc;
1239 }
1240
Chris Wangb6ef35b2024-07-03 09:35:42 +08001241 // Fill the last byte with NULL character
1242 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1243 '\0';
1244
1245 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1246 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1247 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1248 if (rc < 0) {
1249 return rc;
1250 }
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001251
1252 rc = pldm_msgbuf_extract_array(
1253 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1254 entry->pending_comp_release_date,
1255 sizeof(entry->pending_comp_release_date));
1256 if (rc < 0) {
1257 return rc;
1258 }
1259
Chris Wangb6ef35b2024-07-03 09:35:42 +08001260 // Fill the last byte with NULL character
1261 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1262 '\0';
1263
1264 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1265 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
1266 const size_t versions_len = entry->active_comp_ver_str_len +
1267 entry->pending_comp_ver_str_len;
1268 rc = pldm_msgbuf_span_required(buf, versions_len,
1269 (void **)&versions->ptr);
1270 if (rc < 0) {
1271 return rc;
1272 }
1273 versions->length = versions_len;
1274
1275 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1276 if (rc < 0) {
1277 return rc;
1278 }
1279
1280 data->ptr = cursor;
1281 data->length = remaining;
1282
1283 return 0;
1284}
1285
1286LIBPLDM_ABI_TESTING
1287int decode_downstream_device_parameter_table_entry_versions(
1288 const struct variable_field *versions,
Andrew Jeffery6a97b792024-12-09 13:46:51 +10301289 struct pldm_downstream_device_parameters_entry *entry, char *active,
Andrew Jefferya9892492024-10-03 14:07:17 +09301290 size_t active_len, char *pending, size_t pending_len)
Chris Wangb6ef35b2024-07-03 09:35:42 +08001291{
1292 struct pldm_msgbuf _buf;
1293 struct pldm_msgbuf *buf = &_buf;
1294 int rc;
1295
1296 if (versions == NULL || versions->ptr == NULL || !versions->length ||
1297 entry == NULL || active == NULL || pending == NULL) {
1298 return -EINVAL;
1299 }
1300
Andrew Jefferya9892492024-10-03 14:07:17 +09301301 if (!active_len || active_len - 1 < entry->active_comp_ver_str_len) {
1302 return -EOVERFLOW;
1303 }
1304
1305 if (!pending_len || pending_len - 1 < entry->pending_comp_ver_str_len) {
1306 return -EOVERFLOW;
1307 }
1308
Chris Wangb6ef35b2024-07-03 09:35:42 +08001309 /* This API should be called after decode_downstream_device_parameter_table_entry
1310 * has successfully decoded the entry, assume the entry data is valid here.
1311 */
1312 const size_t versions_len = entry->active_comp_ver_str_len +
1313 entry->pending_comp_ver_str_len;
1314 rc = pldm_msgbuf_init_errno(buf, versions_len, versions->ptr,
1315 versions->length);
1316 if (rc < 0) {
1317 return rc;
1318 }
1319
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001320 rc = pldm_msgbuf_extract_array(buf, entry->active_comp_ver_str_len,
Andrew Jefferya9892492024-10-03 14:07:17 +09301321 active, active_len);
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001322 if (rc < 0) {
1323 return rc;
1324 }
1325
Chris Wangb6ef35b2024-07-03 09:35:42 +08001326 active[entry->active_comp_ver_str_len] = '\0';
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001327 rc = pldm_msgbuf_extract_array(buf, entry->pending_comp_ver_str_len,
Andrew Jefferya9892492024-10-03 14:07:17 +09301328 pending, pending_len);
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001329 if (rc < 0) {
1330 return rc;
1331 }
1332
Chris Wangb6ef35b2024-07-03 09:35:42 +08001333 pending[entry->pending_comp_ver_str_len] = '\0';
1334
1335 entry->active_comp_ver_str = active;
1336 entry->pending_comp_ver_str = pending;
1337
1338 return pldm_msgbuf_destroy_consumed(buf);
1339}
1340
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301341LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301342int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1343 uint16_t num_of_comp,
1344 uint8_t max_outstanding_transfer_req,
1345 uint16_t pkg_data_len,
1346 uint8_t comp_image_set_ver_str_type,
1347 uint8_t comp_image_set_ver_str_len,
1348 const struct variable_field *comp_img_set_ver_str,
1349 struct pldm_msg *msg, size_t payload_length)
1350{
1351 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
1352 msg == NULL) {
1353 return PLDM_ERROR_INVALID_DATA;
1354 }
1355
1356 if (payload_length != sizeof(struct pldm_request_update_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301357 comp_img_set_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301358 return PLDM_ERROR_INVALID_LENGTH;
1359 }
1360
1361 if ((comp_image_set_ver_str_len == 0) ||
1362 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
1363 return PLDM_ERROR_INVALID_DATA;
1364 }
1365
1366 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
1367 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
1368 return PLDM_ERROR_INVALID_DATA;
1369 }
1370
1371 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
1372 return PLDM_ERROR_INVALID_DATA;
1373 }
1374
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301375 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301376 header.instance = instance_id;
1377 header.msg_type = PLDM_REQUEST;
1378 header.pldm_type = PLDM_FWUP;
1379 header.command = PLDM_REQUEST_UPDATE;
1380 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1381 if (rc) {
1382 return rc;
1383 }
1384
1385 struct pldm_request_update_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301386 (struct pldm_request_update_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301387
1388 request->max_transfer_size = htole32(max_transfer_size);
1389 request->num_of_comp = htole16(num_of_comp);
1390 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
1391 request->pkg_data_len = htole16(pkg_data_len);
1392 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
1393 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
1394
1395 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
1396 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
1397
1398 return PLDM_SUCCESS;
1399}
1400
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301401LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301402int decode_request_update_resp(const struct pldm_msg *msg,
1403 size_t payload_length, uint8_t *completion_code,
1404 uint16_t *fd_meta_data_len,
1405 uint8_t *fd_will_send_pkg_data)
1406{
1407 if (msg == NULL || completion_code == NULL ||
1408 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
1409 !payload_length) {
1410 return PLDM_ERROR_INVALID_DATA;
1411 }
1412
1413 *completion_code = msg->payload[0];
1414 if (*completion_code != PLDM_SUCCESS) {
1415 return PLDM_SUCCESS;
1416 }
1417
1418 if (payload_length != sizeof(struct pldm_request_update_resp)) {
1419 return PLDM_ERROR_INVALID_LENGTH;
1420 }
1421
1422 struct pldm_request_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301423 (struct pldm_request_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301424
1425 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
1426 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1427
1428 return PLDM_SUCCESS;
1429}
1430
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301431LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301432int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1433 uint16_t comp_classification,
1434 uint16_t comp_identifier,
1435 uint8_t comp_classification_index,
1436 uint32_t comp_comparison_stamp,
1437 uint8_t comp_ver_str_type,
1438 uint8_t comp_ver_str_len,
1439 const struct variable_field *comp_ver_str,
1440 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301441{
1442 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1443 return PLDM_ERROR_INVALID_DATA;
1444 }
1445
1446 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301447 comp_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301448 return PLDM_ERROR_INVALID_LENGTH;
1449 }
1450
1451 if ((comp_ver_str_len == 0) ||
1452 (comp_ver_str_len != comp_ver_str->length)) {
1453 return PLDM_ERROR_INVALID_DATA;
1454 }
1455
1456 if (!is_transfer_flag_valid(transfer_flag)) {
1457 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1458 }
1459
1460 if (!is_string_type_valid(comp_ver_str_type)) {
1461 return PLDM_ERROR_INVALID_DATA;
1462 }
1463
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301464 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301465 header.instance = instance_id;
1466 header.msg_type = PLDM_REQUEST;
1467 header.pldm_type = PLDM_FWUP;
1468 header.command = PLDM_PASS_COMPONENT_TABLE;
1469 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1470 if (rc) {
1471 return rc;
1472 }
1473
1474 struct pldm_pass_component_table_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301475 (struct pldm_pass_component_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301476
1477 request->transfer_flag = transfer_flag;
1478 request->comp_classification = htole16(comp_classification);
1479 request->comp_identifier = htole16(comp_identifier);
1480 request->comp_classification_index = comp_classification_index;
1481 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1482 request->comp_ver_str_type = comp_ver_str_type;
1483 request->comp_ver_str_len = comp_ver_str_len;
1484
1485 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1486 comp_ver_str->ptr, comp_ver_str->length);
1487
1488 return PLDM_SUCCESS;
1489}
1490
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301491LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301492int decode_pass_component_table_resp(const struct pldm_msg *msg,
1493 const size_t payload_length,
1494 uint8_t *completion_code,
1495 uint8_t *comp_resp,
1496 uint8_t *comp_resp_code)
1497{
1498 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1499 comp_resp_code == NULL || !payload_length) {
1500 return PLDM_ERROR_INVALID_DATA;
1501 }
1502
1503 *completion_code = msg->payload[0];
1504 if (*completion_code != PLDM_SUCCESS) {
1505 return PLDM_SUCCESS;
1506 }
1507
1508 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1509 return PLDM_ERROR_INVALID_LENGTH;
1510 }
1511
1512 struct pldm_pass_component_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301513 (struct pldm_pass_component_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301514
1515 if (!is_comp_resp_valid(response->comp_resp)) {
1516 return PLDM_ERROR_INVALID_DATA;
1517 }
1518
1519 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1520 return PLDM_ERROR_INVALID_DATA;
1521 }
1522
1523 *comp_resp = response->comp_resp;
1524 *comp_resp_code = response->comp_resp_code;
1525
1526 return PLDM_SUCCESS;
1527}
1528
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301529LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301530int encode_update_component_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301531 uint8_t instance_id, uint16_t comp_classification,
1532 uint16_t comp_identifier, uint8_t comp_classification_index,
1533 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1534 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1535 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1536 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301537{
1538 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1539 return PLDM_ERROR_INVALID_DATA;
1540 }
1541
1542 if (payload_length !=
1543 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1544 return PLDM_ERROR_INVALID_LENGTH;
1545 }
1546
1547 if (!comp_image_size) {
1548 return PLDM_ERROR_INVALID_DATA;
1549 }
1550
1551 if ((comp_ver_str_len == 0) ||
1552 (comp_ver_str_len != comp_ver_str->length)) {
1553 return PLDM_ERROR_INVALID_DATA;
1554 }
1555
1556 if (!is_string_type_valid(comp_ver_str_type)) {
1557 return PLDM_ERROR_INVALID_DATA;
1558 }
1559
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301560 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301561 header.instance = instance_id;
1562 header.msg_type = PLDM_REQUEST;
1563 header.pldm_type = PLDM_FWUP;
1564 header.command = PLDM_UPDATE_COMPONENT;
1565 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1566 if (rc) {
1567 return rc;
1568 }
1569
1570 struct pldm_update_component_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301571 (struct pldm_update_component_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301572
1573 request->comp_classification = htole16(comp_classification);
1574 request->comp_identifier = htole16(comp_identifier);
1575 request->comp_classification_index = comp_classification_index;
1576 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1577 request->comp_image_size = htole32(comp_image_size);
1578 request->update_option_flags.value = htole32(update_option_flags.value);
1579 request->comp_ver_str_type = comp_ver_str_type;
1580 request->comp_ver_str_len = comp_ver_str_len;
1581
1582 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1583 comp_ver_str->ptr, comp_ver_str->length);
1584
1585 return PLDM_SUCCESS;
1586}
1587
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301588LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301589int decode_update_component_resp(const struct pldm_msg *msg,
1590 size_t payload_length,
1591 uint8_t *completion_code,
1592 uint8_t *comp_compatibility_resp,
1593 uint8_t *comp_compatibility_resp_code,
1594 bitfield32_t *update_option_flags_enabled,
1595 uint16_t *time_before_req_fw_data)
1596{
1597 if (msg == NULL || completion_code == NULL ||
1598 comp_compatibility_resp == NULL ||
1599 comp_compatibility_resp_code == NULL ||
1600 update_option_flags_enabled == NULL ||
1601 time_before_req_fw_data == NULL || !payload_length) {
1602 return PLDM_ERROR_INVALID_DATA;
1603 }
1604
1605 *completion_code = msg->payload[0];
1606 if (*completion_code != PLDM_SUCCESS) {
1607 return PLDM_SUCCESS;
1608 }
1609
1610 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1611 return PLDM_ERROR_INVALID_LENGTH;
1612 }
1613
1614 struct pldm_update_component_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301615 (struct pldm_update_component_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301616
1617 if (!is_comp_compatibility_resp_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301618 response->comp_compatibility_resp)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301619 return PLDM_ERROR_INVALID_DATA;
1620 }
1621
1622 if (!is_comp_compatibility_resp_code_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301623 response->comp_compatibility_resp_code)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301624 return PLDM_ERROR_INVALID_DATA;
1625 }
1626
1627 *comp_compatibility_resp = response->comp_compatibility_resp;
1628 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1629 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301630 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301631 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1632
1633 return PLDM_SUCCESS;
1634}
1635
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301636LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301637int decode_request_firmware_data_req(const struct pldm_msg *msg,
1638 size_t payload_length, uint32_t *offset,
1639 uint32_t *length)
1640{
1641 if (msg == NULL || offset == NULL || length == NULL) {
1642 return PLDM_ERROR_INVALID_DATA;
1643 }
1644 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1645 return PLDM_ERROR_INVALID_LENGTH;
1646 }
1647 struct pldm_request_firmware_data_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301648 (struct pldm_request_firmware_data_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301649 *offset = le32toh(request->offset);
1650 *length = le32toh(request->length);
1651
1652 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1653 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1654 }
1655
1656 return PLDM_SUCCESS;
1657}
1658
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301659LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301660int encode_request_firmware_data_resp(uint8_t instance_id,
1661 uint8_t completion_code,
1662 struct pldm_msg *msg,
1663 size_t payload_length)
1664{
1665 if (msg == NULL || !payload_length) {
1666 return PLDM_ERROR_INVALID_DATA;
1667 }
1668
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301669 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301670 header.instance = instance_id;
1671 header.msg_type = PLDM_RESPONSE;
1672 header.pldm_type = PLDM_FWUP;
1673 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1674 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1675 if (rc) {
1676 return rc;
1677 }
1678
1679 msg->payload[0] = completion_code;
1680
1681 return PLDM_SUCCESS;
1682}
1683
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301684LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301685int decode_transfer_complete_req(const struct pldm_msg *msg,
1686 size_t payload_length,
1687 uint8_t *transfer_result)
1688{
1689 if (msg == NULL || transfer_result == NULL) {
1690 return PLDM_ERROR_INVALID_DATA;
1691 }
1692
1693 if (payload_length != sizeof(*transfer_result)) {
1694 return PLDM_ERROR_INVALID_LENGTH;
1695 }
1696
1697 *transfer_result = msg->payload[0];
1698 return PLDM_SUCCESS;
1699}
1700
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301701LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301702int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1703 struct pldm_msg *msg, size_t payload_length)
1704{
1705 if (msg == NULL) {
1706 return PLDM_ERROR_INVALID_DATA;
1707 }
1708
1709 if (payload_length != sizeof(completion_code)) {
1710 return PLDM_ERROR_INVALID_LENGTH;
1711 }
1712
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301713 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301714 header.instance = instance_id;
1715 header.msg_type = PLDM_RESPONSE;
1716 header.pldm_type = PLDM_FWUP;
1717 header.command = PLDM_TRANSFER_COMPLETE;
1718 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1719 if (rc) {
1720 return rc;
1721 }
1722
1723 msg->payload[0] = completion_code;
1724
1725 return PLDM_SUCCESS;
1726}
1727
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301728LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301729int decode_verify_complete_req(const struct pldm_msg *msg,
1730 size_t payload_length, uint8_t *verify_result)
1731{
1732 if (msg == NULL || verify_result == NULL) {
1733 return PLDM_ERROR_INVALID_DATA;
1734 }
1735
1736 if (payload_length != sizeof(*verify_result)) {
1737 return PLDM_ERROR_INVALID_LENGTH;
1738 }
1739
1740 *verify_result = msg->payload[0];
1741 return PLDM_SUCCESS;
1742}
1743
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301744LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301745int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1746 struct pldm_msg *msg, size_t payload_length)
1747{
1748 if (msg == NULL) {
1749 return PLDM_ERROR_INVALID_DATA;
1750 }
1751
1752 if (payload_length != sizeof(completion_code)) {
1753 return PLDM_ERROR_INVALID_LENGTH;
1754 }
1755
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301756 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301757 header.instance = instance_id;
1758 header.msg_type = PLDM_RESPONSE;
1759 header.pldm_type = PLDM_FWUP;
1760 header.command = PLDM_VERIFY_COMPLETE;
1761 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1762 if (rc) {
1763 return rc;
1764 }
1765
1766 msg->payload[0] = completion_code;
1767
1768 return PLDM_SUCCESS;
1769}
1770
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301771LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301772int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
1773 uint8_t *apply_result,
1774 bitfield16_t *comp_activation_methods_modification)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301775{
1776 if (msg == NULL || apply_result == NULL ||
1777 comp_activation_methods_modification == NULL) {
1778 return PLDM_ERROR_INVALID_DATA;
1779 }
1780
1781 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1782 return PLDM_ERROR_INVALID_LENGTH;
1783 }
1784
1785 struct pldm_apply_complete_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301786 (struct pldm_apply_complete_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301787
1788 *apply_result = request->apply_result;
1789 comp_activation_methods_modification->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301790 le16toh(request->comp_activation_methods_modification.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301791
1792 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1793 comp_activation_methods_modification->value) {
1794 return PLDM_ERROR_INVALID_DATA;
1795 }
1796
1797 return PLDM_SUCCESS;
1798}
1799
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301800LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301801int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1802 struct pldm_msg *msg, size_t payload_length)
1803{
1804 if (msg == NULL) {
1805 return PLDM_ERROR_INVALID_DATA;
1806 }
1807
1808 if (payload_length != sizeof(completion_code)) {
1809 return PLDM_ERROR_INVALID_LENGTH;
1810 }
1811
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301812 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301813 header.instance = instance_id;
1814 header.msg_type = PLDM_RESPONSE;
1815 header.pldm_type = PLDM_FWUP;
1816 header.command = PLDM_APPLY_COMPLETE;
1817 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1818 if (rc) {
1819 return rc;
1820 }
1821
1822 msg->payload[0] = completion_code;
1823
1824 return PLDM_SUCCESS;
1825}
1826
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301827LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301828int encode_activate_firmware_req(uint8_t instance_id,
1829 bool8_t self_contained_activation_req,
1830 struct pldm_msg *msg, size_t payload_length)
1831{
1832 if (msg == NULL) {
1833 return PLDM_ERROR_INVALID_DATA;
1834 }
1835
1836 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1837 return PLDM_ERROR_INVALID_LENGTH;
1838 }
1839
1840 if (!is_self_contained_activation_req_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301841 self_contained_activation_req)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301842 return PLDM_ERROR_INVALID_DATA;
1843 }
1844
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301845 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301846 header.instance = instance_id;
1847 header.msg_type = PLDM_REQUEST;
1848 header.pldm_type = PLDM_FWUP;
1849 header.command = PLDM_ACTIVATE_FIRMWARE;
1850 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1851 if (rc) {
1852 return rc;
1853 }
1854
1855 struct pldm_activate_firmware_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301856 (struct pldm_activate_firmware_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301857
1858 request->self_contained_activation_req = self_contained_activation_req;
1859
1860 return PLDM_SUCCESS;
1861}
1862
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301863LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301864int decode_activate_firmware_resp(const struct pldm_msg *msg,
1865 size_t payload_length,
1866 uint8_t *completion_code,
1867 uint16_t *estimated_time_activation)
1868{
1869 if (msg == NULL || completion_code == NULL ||
1870 estimated_time_activation == NULL || !payload_length) {
1871 return PLDM_ERROR_INVALID_DATA;
1872 }
1873
1874 *completion_code = msg->payload[0];
1875 if (*completion_code != PLDM_SUCCESS) {
1876 return PLDM_SUCCESS;
1877 }
1878
1879 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1880 return PLDM_ERROR_INVALID_LENGTH;
1881 }
1882
1883 struct pldm_activate_firmware_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301884 (struct pldm_activate_firmware_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301885
1886 *estimated_time_activation =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301887 le16toh(response->estimated_time_activation);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301888
1889 return PLDM_SUCCESS;
1890}
1891
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301892LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301893int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1894 size_t payload_length)
1895{
1896 if (msg == NULL) {
1897 return PLDM_ERROR_INVALID_DATA;
1898 }
1899
1900 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1901 return PLDM_ERROR_INVALID_LENGTH;
1902 }
1903
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301904 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301905 header.instance = instance_id;
1906 header.msg_type = PLDM_REQUEST;
1907 header.pldm_type = PLDM_FWUP;
1908 header.command = PLDM_GET_STATUS;
1909 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1910 if (rc) {
1911 return rc;
1912 }
1913
1914 return PLDM_SUCCESS;
1915}
1916
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301917LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301918int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1919 uint8_t *completion_code, uint8_t *current_state,
1920 uint8_t *previous_state, uint8_t *aux_state,
1921 uint8_t *aux_state_status, uint8_t *progress_percent,
1922 uint8_t *reason_code,
1923 bitfield32_t *update_option_flags_enabled)
1924{
1925 if (msg == NULL || completion_code == NULL || current_state == NULL ||
1926 previous_state == NULL || aux_state == NULL ||
1927 aux_state_status == NULL || progress_percent == NULL ||
1928 reason_code == NULL || update_option_flags_enabled == NULL ||
1929 !payload_length) {
1930 return PLDM_ERROR_INVALID_DATA;
1931 }
1932
1933 *completion_code = msg->payload[0];
1934 if (*completion_code != PLDM_SUCCESS) {
1935 return PLDM_SUCCESS;
1936 }
1937
1938 if (payload_length != sizeof(struct pldm_get_status_resp)) {
1939 return PLDM_ERROR_INVALID_LENGTH;
1940 }
1941 struct pldm_get_status_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301942 (struct pldm_get_status_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301943
1944 if (!is_state_valid(response->current_state)) {
1945 return PLDM_ERROR_INVALID_DATA;
1946 }
1947 if (!is_state_valid(response->previous_state)) {
1948 return PLDM_ERROR_INVALID_DATA;
1949 }
1950 if (!is_aux_state_valid(response->aux_state)) {
1951 return PLDM_ERROR_INVALID_DATA;
1952 }
1953 if (!is_aux_state_status_valid(response->aux_state_status)) {
1954 return PLDM_ERROR_INVALID_DATA;
1955 }
1956 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1957 return PLDM_ERROR_INVALID_DATA;
1958 }
1959 if (!is_reason_code_valid(response->reason_code)) {
1960 return PLDM_ERROR_INVALID_DATA;
1961 }
1962
1963 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1964 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1965 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1966 if (response->aux_state !=
1967 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1968 return PLDM_ERROR_INVALID_DATA;
1969 }
1970 }
1971
1972 *current_state = response->current_state;
1973 *previous_state = response->previous_state;
1974 *aux_state = response->aux_state;
1975 *aux_state_status = response->aux_state_status;
1976 *progress_percent = response->progress_percent;
1977 *reason_code = response->reason_code;
1978 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301979 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301980
1981 return PLDM_SUCCESS;
1982}
1983
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301984LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301985int encode_cancel_update_component_req(uint8_t instance_id,
1986 struct pldm_msg *msg,
1987 size_t payload_length)
1988{
1989 if (msg == NULL) {
1990 return PLDM_ERROR_INVALID_DATA;
1991 }
1992
1993 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1994 return PLDM_ERROR_INVALID_LENGTH;
1995 }
1996
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301997 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301998 header.instance = instance_id;
1999 header.msg_type = PLDM_REQUEST;
2000 header.pldm_type = PLDM_FWUP;
2001 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
2002 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2003 if (rc) {
2004 return rc;
2005 }
2006
2007 return PLDM_SUCCESS;
2008}
2009
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302010LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302011int decode_cancel_update_component_resp(const struct pldm_msg *msg,
2012 size_t payload_length,
2013 uint8_t *completion_code)
2014{
2015 if (msg == NULL || completion_code == NULL) {
2016 return PLDM_ERROR_INVALID_DATA;
2017 }
2018
2019 if (payload_length != sizeof(*completion_code)) {
2020 return PLDM_ERROR_INVALID_LENGTH;
2021 }
2022
2023 *completion_code = msg->payload[0];
2024 return PLDM_SUCCESS;
2025}
2026
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302027LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302028int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
2029 size_t payload_length)
2030{
2031 if (msg == NULL) {
2032 return PLDM_ERROR_INVALID_DATA;
2033 }
2034
2035 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
2036 return PLDM_ERROR_INVALID_LENGTH;
2037 }
2038
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302039 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09302040 header.instance = instance_id;
2041 header.msg_type = PLDM_REQUEST;
2042 header.pldm_type = PLDM_FWUP;
2043 header.command = PLDM_CANCEL_UPDATE;
2044 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2045 if (rc) {
2046 return rc;
2047 }
2048
2049 return PLDM_SUCCESS;
2050}
2051
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302052LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09302053int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
2054 uint8_t *completion_code,
2055 bool8_t *non_functioning_component_indication,
2056 bitfield64_t *non_functioning_component_bitmap)
2057{
2058 if (msg == NULL || completion_code == NULL ||
2059 non_functioning_component_indication == NULL ||
2060 non_functioning_component_bitmap == NULL || !payload_length) {
2061 return PLDM_ERROR_INVALID_DATA;
2062 }
2063
2064 *completion_code = msg->payload[0];
2065 if (*completion_code != PLDM_SUCCESS) {
2066 return PLDM_SUCCESS;
2067 }
2068
2069 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
2070 return PLDM_ERROR_INVALID_LENGTH;
2071 }
2072 struct pldm_cancel_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302073 (struct pldm_cancel_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302074
2075 if (!is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302076 response->non_functioning_component_indication)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09302077 return PLDM_ERROR_INVALID_DATA;
2078 }
2079
2080 *non_functioning_component_indication =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302081 response->non_functioning_component_indication;
Andrew Jeffery9c766792022-08-10 23:12:49 +09302082
2083 if (*non_functioning_component_indication) {
2084 non_functioning_component_bitmap->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302085 le64toh(response->non_functioning_component_bitmap);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302086 }
2087
2088 return PLDM_SUCCESS;
2089}