blob: 61bb9535bc42460d1e4c4a439600e30443e4e482 [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Chris Wangb6ef35b2024-07-03 09:35:42 +08002#include "dsp/base.h"
Chris Wang4c1f2c72024-03-21 17:09:44 +08003#include "msgbuf.h"
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10304#include <libpldm/firmware_update.h>
5#include <libpldm/utils.h>
6
Andrew Jeffery9c766792022-08-10 23:12:49 +09307#include <endian.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05308#include <stdbool.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09309#include <string.h>
10
11/** @brief Check whether string type value is valid
12 *
13 * @return true if string type value is valid, false if not
14 */
15static bool is_string_type_valid(uint8_t string_type)
16{
17 switch (string_type) {
18 case PLDM_STR_TYPE_UNKNOWN:
19 return false;
20 case PLDM_STR_TYPE_ASCII:
21 case PLDM_STR_TYPE_UTF_8:
22 case PLDM_STR_TYPE_UTF_16:
23 case PLDM_STR_TYPE_UTF_16LE:
24 case PLDM_STR_TYPE_UTF_16BE:
25 return true;
26 default:
27 return false;
28 }
29}
30
31/** @brief Return the length of the descriptor type described in firmware update
32 * specification
33 *
34 * @return length of the descriptor type if descriptor type is valid else
35 * return 0
36 */
37static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
38{
39 switch (descriptor_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093040 case PLDM_FWUP_PCI_VENDOR_ID:
41 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
42 case PLDM_FWUP_IANA_ENTERPRISE_ID:
43 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
44 case PLDM_FWUP_UUID:
45 return PLDM_FWUP_UUID_LENGTH;
46 case PLDM_FWUP_PNP_VENDOR_ID:
47 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
48 case PLDM_FWUP_ACPI_VENDOR_ID:
49 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
50 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
51 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
52 case PLDM_FWUP_SCSI_VENDOR_ID:
53 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
54 case PLDM_FWUP_PCI_DEVICE_ID:
55 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
56 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
57 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
58 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
59 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
60 case PLDM_FWUP_PCI_REVISION_ID:
61 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
62 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
63 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
64 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
65 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
66 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
67 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
68 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
69 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
70 case PLDM_FWUP_SCSI_PRODUCT_ID:
71 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
72 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
73 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
74 default:
75 return 0;
76 }
77}
78
Chris Wang4c1f2c72024-03-21 17:09:44 +080079static bool is_downstream_device_update_support_valid(uint8_t resp)
80{
81 switch (resp) {
82 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
83 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
84 return true;
85 default:
86 return false;
87 }
88}
89
Chris Wang458475a2024-03-26 17:59:19 +080090static bool
91is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)
92{
93 switch (transfer_op_flag) {
94 case PLDM_GET_NEXTPART:
95 case PLDM_GET_FIRSTPART:
96 return true;
97 default:
98 return false;
99 }
100}
101
Andrew Jeffery9c766792022-08-10 23:12:49 +0930102/** @brief Check whether ComponentResponse is valid
103 *
104 * @return true if ComponentResponse is valid, false if not
105 */
106static bool is_comp_resp_valid(uint8_t comp_resp)
107{
108 switch (comp_resp) {
109 case PLDM_CR_COMP_CAN_BE_UPDATED:
110 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
111 return true;
112
113 default:
114 return false;
115 }
116}
117
118/** @brief Check whether ComponentResponseCode is valid
119 *
120 * @return true if ComponentResponseCode is valid, false if not
121 */
122static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
123{
124 switch (comp_resp_code) {
125 case PLDM_CRC_COMP_CAN_BE_UPDATED:
126 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
127 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
128 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
129 case PLDM_CRC_COMP_CONFLICT:
130 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
131 case PLDM_CRC_COMP_NOT_SUPPORTED:
132 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
133 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
134 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
135 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
136 case PLDM_CRC_COMP_VER_STR_LOWER:
137 return true;
138
139 default:
140 if (comp_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930141 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930142 comp_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930143 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930144 return true;
145 }
146 return false;
147 }
148}
149
150/** @brief Check whether ComponentCompatibilityResponse is valid
151 *
152 * @return true if ComponentCompatibilityResponse is valid, false if not
153 */
154static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
155{
156 switch (comp_compatibility_resp) {
157 case PLDM_CCR_COMP_CAN_BE_UPDATED:
158 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
159 return true;
160
161 default:
162 return false;
163 }
164}
165
166/** @brief Check whether ComponentCompatibilityResponse Code is valid
167 *
168 * @return true if ComponentCompatibilityResponse Code is valid, false if not
169 */
170static bool
171is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
172{
173 switch (comp_compatibility_resp_code) {
174 case PLDM_CCRC_NO_RESPONSE_CODE:
175 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
176 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
177 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
178 case PLDM_CCRC_COMP_CONFLICT:
179 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
180 case PLDM_CCRC_COMP_NOT_SUPPORTED:
181 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
182 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
183 case PLDM_CCRC_COMP_INFO_NO_MATCH:
184 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
185 case PLDM_CCRC_COMP_VER_STR_LOWER:
186 return true;
187
188 default:
189 if (comp_compatibility_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930190 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930191 comp_compatibility_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930192 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930193 return true;
194 }
195 return false;
196 }
197}
198
199/** @brief Check whether SelfContainedActivationRequest is valid
200 *
201 * @return true if SelfContainedActivationRequest is valid, false if not
202 */
203static bool
204is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
205{
206 switch (self_contained_activation_req) {
207 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
208 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
209 return true;
210
211 default:
212 return false;
213 }
214}
215
216/** @brief Check if current or previous status in GetStatus command response is
217 * valid
218 *
219 * @param[in] state - current or previous different state machine state of
220 * the FD
221 * @return true if state is valid, false if not
222 */
223static bool is_state_valid(uint8_t state)
224{
225 switch (state) {
226 case PLDM_FD_STATE_IDLE:
227 case PLDM_FD_STATE_LEARN_COMPONENTS:
228 case PLDM_FD_STATE_READY_XFER:
229 case PLDM_FD_STATE_DOWNLOAD:
230 case PLDM_FD_STATE_VERIFY:
231 case PLDM_FD_STATE_APPLY:
232 case PLDM_FD_STATE_ACTIVATE:
233 return true;
234
235 default:
236 return false;
237 }
238}
239
240/** @brief Check if aux state in GetStatus command response is valid
241 *
242 * @param[in] aux_state - provides additional information to the UA to describe
243 * the current operation state of the FD/FDP
244 *
245 * @return true if aux state is valid, false if not
246 */
247static bool is_aux_state_valid(uint8_t aux_state)
248{
249 switch (aux_state) {
250 case PLDM_FD_OPERATION_IN_PROGRESS:
251 case PLDM_FD_OPERATION_SUCCESSFUL:
252 case PLDM_FD_OPERATION_FAILED:
253 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
254 return true;
255
256 default:
257 return false;
258 }
259}
260
261/** @brief Check if aux state status in GetStatus command response is valid
262 *
263 * @param[in] aux_state_status - aux state status
264 *
265 * @return true if aux state status is valid, false if not
266 */
267static bool is_aux_state_status_valid(uint8_t aux_state_status)
268{
269 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
270 aux_state_status == PLDM_FD_TIMEOUT ||
Andrew Jeffery67f7ed92023-04-05 14:00:00 +0930271 aux_state_status == PLDM_FD_GENERIC_ERROR ||
272 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
273 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930274 return true;
275 }
276
277 return false;
278}
279
280/** @brief Check if reason code in GetStatus command response is valid
281 *
282 * @param[in] reason_code - provides the reason for why the current state
283 * entered the IDLE state
284 *
285 * @return true if reason code is valid, false if not
286 */
287static bool is_reason_code_valid(uint8_t reason_code)
288{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930289 switch (reason_code) {
290 case PLDM_FD_INITIALIZATION:
291 case PLDM_FD_ACTIVATE_FW:
292 case PLDM_FD_CANCEL_UPDATE:
293 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
294 case PLDM_FD_TIMEOUT_READY_XFER:
295 case PLDM_FD_TIMEOUT_DOWNLOAD:
296 case PLDM_FD_TIMEOUT_VERIFY:
297 case PLDM_FD_TIMEOUT_APPLY:
298 return true;
299
300 default:
301 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
302 return true;
303 }
304 return false;
305 }
306}
307
308/** @brief Check if non functioning component indication in CancelUpdate
309 * response is valid
310 *
311 * @return true if non functioning component indication is valid, false if not
312 */
313static bool is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930314 bool8_t non_functioning_component_indication)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930315{
316 switch (non_functioning_component_indication) {
317 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
318 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
319 return true;
320
321 default:
322 return false;
323 }
324}
325
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930326LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930327int decode_pldm_package_header_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930328 const uint8_t *data, size_t length,
329 struct pldm_package_header_information *package_header_info,
330 struct variable_field *package_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930331{
332 if (data == NULL || package_header_info == NULL ||
333 package_version_str == NULL) {
334 return PLDM_ERROR_INVALID_DATA;
335 }
336
337 if (length < sizeof(struct pldm_package_header_information)) {
338 return PLDM_ERROR_INVALID_LENGTH;
339 }
340
341 struct pldm_package_header_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930342 (struct pldm_package_header_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930343
344 if (!is_string_type_valid(data_header->package_version_string_type) ||
345 (data_header->package_version_string_length == 0)) {
346 return PLDM_ERROR_INVALID_DATA;
347 }
348
349 if (length < sizeof(struct pldm_package_header_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930350 data_header->package_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930351 return PLDM_ERROR_INVALID_LENGTH;
352 }
353
354 if ((data_header->component_bitmap_bit_length %
355 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
356 return PLDM_ERROR_INVALID_DATA;
357 }
358
359 memcpy(package_header_info->uuid, data_header->uuid,
360 sizeof(data_header->uuid));
361 package_header_info->package_header_format_version =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930362 data_header->package_header_format_version;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930363 package_header_info->package_header_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930364 le16toh(data_header->package_header_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930365 memcpy(package_header_info->package_release_date_time,
366 data_header->package_release_date_time,
367 sizeof(data_header->package_release_date_time));
368 package_header_info->component_bitmap_bit_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930369 le16toh(data_header->component_bitmap_bit_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930370 package_header_info->package_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930371 data_header->package_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930372 package_header_info->package_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930373 data_header->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930374 package_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930375 data + sizeof(struct pldm_package_header_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930376 package_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930377 package_header_info->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930378
379 return PLDM_SUCCESS;
380}
381
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930382LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930383int decode_firmware_device_id_record(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930384 const uint8_t *data, size_t length,
385 uint16_t component_bitmap_bit_length,
386 struct pldm_firmware_device_id_record *fw_device_id_record,
387 struct variable_field *applicable_components,
388 struct variable_field *comp_image_set_version_str,
389 struct variable_field *record_descriptors,
390 struct variable_field *fw_device_pkg_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930391{
392 if (data == NULL || fw_device_id_record == NULL ||
393 applicable_components == NULL ||
394 comp_image_set_version_str == NULL || record_descriptors == NULL ||
395 fw_device_pkg_data == NULL) {
396 return PLDM_ERROR_INVALID_DATA;
397 }
398
399 if (length < sizeof(struct pldm_firmware_device_id_record)) {
400 return PLDM_ERROR_INVALID_LENGTH;
401 }
402
403 if ((component_bitmap_bit_length %
404 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
405 return PLDM_ERROR_INVALID_DATA;
406 }
407
408 struct pldm_firmware_device_id_record *data_record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930409 (struct pldm_firmware_device_id_record *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930410
411 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930412 data_record->comp_image_set_version_string_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930413 (data_record->comp_image_set_version_string_length == 0)) {
414 return PLDM_ERROR_INVALID_DATA;
415 }
416
417 fw_device_id_record->record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930418 le16toh(data_record->record_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930419 fw_device_id_record->descriptor_count = data_record->descriptor_count;
420 fw_device_id_record->device_update_option_flags.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930421 le32toh(data_record->device_update_option_flags.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930422 fw_device_id_record->comp_image_set_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930423 data_record->comp_image_set_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930424 fw_device_id_record->comp_image_set_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930425 data_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930426 fw_device_id_record->fw_device_pkg_data_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930427 le16toh(data_record->fw_device_pkg_data_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930428
429 if (length < fw_device_id_record->record_length) {
430 return PLDM_ERROR_INVALID_LENGTH;
431 }
432
433 uint16_t applicable_components_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930434 component_bitmap_bit_length /
435 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930436 uint16_t calc_min_record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930437 sizeof(struct pldm_firmware_device_id_record) +
438 applicable_components_length +
439 data_record->comp_image_set_version_string_length +
440 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
441 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930442
443 if (fw_device_id_record->record_length < calc_min_record_length) {
444 return PLDM_ERROR_INVALID_LENGTH;
445 }
446
447 applicable_components->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930448 data + sizeof(struct pldm_firmware_device_id_record);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930449 applicable_components->length = applicable_components_length;
450
451 comp_image_set_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930452 applicable_components->ptr + applicable_components->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930453 comp_image_set_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930454 fw_device_id_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930455
456 record_descriptors->ptr = comp_image_set_version_str->ptr +
457 comp_image_set_version_str->length;
458 record_descriptors->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930459 fw_device_id_record->record_length -
460 sizeof(struct pldm_firmware_device_id_record) -
461 applicable_components_length -
462 fw_device_id_record->comp_image_set_version_string_length -
463 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930464
465 if (fw_device_id_record->fw_device_pkg_data_length) {
466 fw_device_pkg_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930467 record_descriptors->ptr + record_descriptors->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930468 fw_device_pkg_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930469 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930470 }
471
472 return PLDM_SUCCESS;
473}
474
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930475LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930476int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
477 uint16_t *descriptor_type,
478 struct variable_field *descriptor_data)
479{
480 uint16_t descriptor_length = 0;
481
482 if (data == NULL || descriptor_type == NULL ||
483 descriptor_data == NULL) {
484 return PLDM_ERROR_INVALID_DATA;
485 }
486
487 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
488 return PLDM_ERROR_INVALID_LENGTH;
489 }
490
491 struct pldm_descriptor_tlv *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930492 (struct pldm_descriptor_tlv *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930493
494 *descriptor_type = le16toh(entry->descriptor_type);
495 descriptor_length = le16toh(entry->descriptor_length);
496 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
497 if (descriptor_length !=
498 get_descriptor_type_length(*descriptor_type)) {
499 return PLDM_ERROR_INVALID_LENGTH;
500 }
501 }
502
503 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
504 descriptor_length)) {
505 return PLDM_ERROR_INVALID_LENGTH;
506 }
507
508 descriptor_data->ptr = entry->descriptor_data;
509 descriptor_data->length = descriptor_length;
510
511 return PLDM_SUCCESS;
512}
513
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930514LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930515int decode_vendor_defined_descriptor_value(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930516 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
517 struct variable_field *descriptor_title_str,
518 struct variable_field *descriptor_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930519{
520 if (data == NULL || descriptor_title_str_type == NULL ||
521 descriptor_title_str == NULL || descriptor_data == NULL) {
522 return PLDM_ERROR_INVALID_DATA;
523 }
524
525 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
526 return PLDM_ERROR_INVALID_LENGTH;
527 }
528
529 struct pldm_vendor_defined_descriptor_title_data *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930530 (struct pldm_vendor_defined_descriptor_title_data *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930531 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930532 entry->vendor_defined_descriptor_title_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930533 (entry->vendor_defined_descriptor_title_str_len == 0)) {
534 return PLDM_ERROR_INVALID_DATA;
535 }
536
Manojkiran Eda9e3a5d42024-06-17 16:06:42 +0530537 // Assuming at least 1 byte of VendorDefinedDescriptorData
Andrew Jeffery9c766792022-08-10 23:12:49 +0930538 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
539 entry->vendor_defined_descriptor_title_str_len)) {
540 return PLDM_ERROR_INVALID_LENGTH;
541 }
542
543 *descriptor_title_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930544 entry->vendor_defined_descriptor_title_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930545 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
546 descriptor_title_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930547 entry->vendor_defined_descriptor_title_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930548
549 descriptor_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930550 descriptor_title_str->ptr + descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930551 descriptor_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930552 length -
553 sizeof(entry->vendor_defined_descriptor_title_str_type) -
554 sizeof(entry->vendor_defined_descriptor_title_str_len) -
555 descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930556
557 return PLDM_SUCCESS;
558}
559
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930560LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930561int decode_pldm_comp_image_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930562 const uint8_t *data, size_t length,
563 struct pldm_component_image_information *pldm_comp_image_info,
564 struct variable_field *comp_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930565{
566 if (data == NULL || pldm_comp_image_info == NULL ||
567 comp_version_str == NULL) {
568 return PLDM_ERROR_INVALID_DATA;
569 }
570
571 if (length < sizeof(struct pldm_component_image_information)) {
572 return PLDM_ERROR_INVALID_LENGTH;
573 }
574
575 struct pldm_component_image_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930576 (struct pldm_component_image_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930577
578 if (!is_string_type_valid(data_header->comp_version_string_type) ||
579 (data_header->comp_version_string_length == 0)) {
580 return PLDM_ERROR_INVALID_DATA;
581 }
582
583 if (length < sizeof(struct pldm_component_image_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930584 data_header->comp_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930585 return PLDM_ERROR_INVALID_LENGTH;
586 }
587
588 pldm_comp_image_info->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930589 le16toh(data_header->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930590 pldm_comp_image_info->comp_identifier =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930591 le16toh(data_header->comp_identifier);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930592 pldm_comp_image_info->comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930593 le32toh(data_header->comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930594 pldm_comp_image_info->comp_options.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930595 le16toh(data_header->comp_options.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930596 pldm_comp_image_info->requested_comp_activation_method.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930597 le16toh(data_header->requested_comp_activation_method.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930598 pldm_comp_image_info->comp_location_offset =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930599 le32toh(data_header->comp_location_offset);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930600 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
601 pldm_comp_image_info->comp_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930602 data_header->comp_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930603 pldm_comp_image_info->comp_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930604 data_header->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930605
606 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
607 pldm_comp_image_info->comp_comparison_stamp !=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930608 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930609 return PLDM_ERROR_INVALID_DATA;
610 }
611
612 if (pldm_comp_image_info->comp_location_offset == 0 ||
613 pldm_comp_image_info->comp_size == 0) {
614 return PLDM_ERROR_INVALID_DATA;
615 }
616
617 comp_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930618 data + sizeof(struct pldm_component_image_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930619 comp_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930620 pldm_comp_image_info->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930621
622 return PLDM_SUCCESS;
623}
624
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930625LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930626int encode_query_device_identifiers_req(uint8_t instance_id,
627 size_t payload_length,
628 struct pldm_msg *msg)
629{
630 if (msg == NULL) {
631 return PLDM_ERROR_INVALID_DATA;
632 }
633
634 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
635 return PLDM_ERROR_INVALID_LENGTH;
636 }
637
638 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
639 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
640}
641
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930642LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930643int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
644 size_t payload_length,
645 uint8_t *completion_code,
646 uint32_t *device_identifiers_len,
647 uint8_t *descriptor_count,
648 uint8_t **descriptor_data)
649{
650 if (msg == NULL || completion_code == NULL ||
651 device_identifiers_len == NULL || descriptor_count == NULL ||
652 descriptor_data == NULL) {
653 return PLDM_ERROR_INVALID_DATA;
654 }
655
656 *completion_code = msg->payload[0];
657 if (PLDM_SUCCESS != *completion_code) {
658 return PLDM_SUCCESS;
659 }
660
661 if (payload_length <
662 sizeof(struct pldm_query_device_identifiers_resp)) {
663 return PLDM_ERROR_INVALID_LENGTH;
664 }
665
666 struct pldm_query_device_identifiers_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930667 (struct pldm_query_device_identifiers_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930668 *device_identifiers_len = le32toh(response->device_identifiers_len);
669
670 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
671 return PLDM_ERROR_INVALID_LENGTH;
672 }
673
674 if (payload_length !=
675 sizeof(struct pldm_query_device_identifiers_resp) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930676 *device_identifiers_len) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930677 return PLDM_ERROR_INVALID_LENGTH;
678 }
679 *descriptor_count = response->descriptor_count;
680
681 if (*descriptor_count == 0) {
682 return PLDM_ERROR_INVALID_DATA;
683 }
684 *descriptor_data =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930685 (uint8_t *)(msg->payload +
686 sizeof(struct pldm_query_device_identifiers_resp));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930687 return PLDM_SUCCESS;
688}
689
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930690LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930691int encode_get_firmware_parameters_req(uint8_t instance_id,
692 size_t payload_length,
693 struct pldm_msg *msg)
694{
695 if (msg == NULL) {
696 return PLDM_ERROR_INVALID_DATA;
697 }
698
699 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
700 return PLDM_ERROR_INVALID_LENGTH;
701 }
702
703 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
704 PLDM_GET_FIRMWARE_PARAMETERS, msg);
705}
706
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930707LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930708int decode_get_firmware_parameters_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930709 const struct pldm_msg *msg, size_t payload_length,
710 struct pldm_get_firmware_parameters_resp *resp_data,
711 struct variable_field *active_comp_image_set_ver_str,
712 struct variable_field *pending_comp_image_set_ver_str,
713 struct variable_field *comp_parameter_table)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930714{
715 if (msg == NULL || resp_data == NULL ||
716 active_comp_image_set_ver_str == NULL ||
717 pending_comp_image_set_ver_str == NULL ||
718 comp_parameter_table == NULL || !payload_length) {
719 return PLDM_ERROR_INVALID_DATA;
720 }
721
722 resp_data->completion_code = msg->payload[0];
723 if (PLDM_SUCCESS != resp_data->completion_code) {
724 return PLDM_SUCCESS;
725 }
726
727 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
728 return PLDM_ERROR_INVALID_LENGTH;
729 }
730
731 struct pldm_get_firmware_parameters_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930732 (struct pldm_get_firmware_parameters_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930733
734 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930735 response->active_comp_image_set_ver_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930736 (response->active_comp_image_set_ver_str_len == 0)) {
737 return PLDM_ERROR_INVALID_DATA;
738 }
739
740 if (response->pending_comp_image_set_ver_str_len == 0) {
741 if (response->pending_comp_image_set_ver_str_type !=
742 PLDM_STR_TYPE_UNKNOWN) {
743 return PLDM_ERROR_INVALID_DATA;
744 }
745 } else {
746 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930747 response->pending_comp_image_set_ver_str_type)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930748 return PLDM_ERROR_INVALID_DATA;
749 }
750 }
751
752 size_t partial_response_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930753 sizeof(struct pldm_get_firmware_parameters_resp) +
754 response->active_comp_image_set_ver_str_len +
755 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930756
757 if (payload_length < partial_response_length) {
758 return PLDM_ERROR_INVALID_LENGTH;
759 }
760
761 resp_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930762 le32toh(response->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930763 resp_data->comp_count = le16toh(response->comp_count);
764 resp_data->active_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930765 response->active_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930766 resp_data->active_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930767 response->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930768 resp_data->pending_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930769 response->pending_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930770 resp_data->pending_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930771 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930772
773 active_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930774 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930775 active_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930776 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930777
778 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
779 pending_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930780 msg->payload +
781 sizeof(struct pldm_get_firmware_parameters_resp) +
782 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930783 pending_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930784 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930785 } else {
786 pending_comp_image_set_ver_str->ptr = NULL;
787 pending_comp_image_set_ver_str->length = 0;
788 }
789
790 if (payload_length > partial_response_length && resp_data->comp_count) {
791 comp_parameter_table->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930792 msg->payload +
793 sizeof(struct pldm_get_firmware_parameters_resp) +
794 resp_data->active_comp_image_set_ver_str_len +
795 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930796 comp_parameter_table->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930797 payload_length - partial_response_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930798 } else {
799 comp_parameter_table->ptr = NULL;
800 comp_parameter_table->length = 0;
801 }
802
803 return PLDM_SUCCESS;
804}
805
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930806LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930807int decode_get_firmware_parameters_resp_comp_entry(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930808 const uint8_t *data, size_t length,
809 struct pldm_component_parameter_entry *component_data,
810 struct variable_field *active_comp_ver_str,
811 struct variable_field *pending_comp_ver_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930812{
813 if (data == NULL || component_data == NULL ||
814 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
815 return PLDM_ERROR_INVALID_DATA;
816 }
817
818 if (length < sizeof(struct pldm_component_parameter_entry)) {
819 return PLDM_ERROR_INVALID_LENGTH;
820 }
821
822 struct pldm_component_parameter_entry *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930823 (struct pldm_component_parameter_entry *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930824
825 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
826 entry->active_comp_ver_str_len +
827 entry->pending_comp_ver_str_len;
828
829 if (length < entry_length) {
830 return PLDM_ERROR_INVALID_LENGTH;
831 }
832
833 component_data->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930834 le16toh(entry->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930835 component_data->comp_identifier = le16toh(entry->comp_identifier);
836 component_data->comp_classification_index =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930837 entry->comp_classification_index;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930838 component_data->active_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930839 le32toh(entry->active_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930840 component_data->active_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930841 entry->active_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930842 component_data->active_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930843 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930844 memcpy(component_data->active_comp_release_date,
845 entry->active_comp_release_date,
846 sizeof(entry->active_comp_release_date));
847 component_data->pending_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930848 le32toh(entry->pending_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930849 component_data->pending_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930850 entry->pending_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930851 component_data->pending_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930852 entry->pending_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930853 memcpy(component_data->pending_comp_release_date,
854 entry->pending_comp_release_date,
855 sizeof(entry->pending_comp_release_date));
856 component_data->comp_activation_methods.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930857 le16toh(entry->comp_activation_methods.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930858 component_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930859 le32toh(entry->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930860
861 if (entry->active_comp_ver_str_len != 0) {
862 active_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930863 data + sizeof(struct pldm_component_parameter_entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930864 active_comp_ver_str->length = entry->active_comp_ver_str_len;
865 } else {
866 active_comp_ver_str->ptr = NULL;
867 active_comp_ver_str->length = 0;
868 }
869
870 if (entry->pending_comp_ver_str_len != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930871 pending_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930872 data + sizeof(struct pldm_component_parameter_entry) +
873 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930874 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
875 } else {
876 pending_comp_ver_str->ptr = NULL;
877 pending_comp_ver_str->length = 0;
878 }
879 return PLDM_SUCCESS;
880}
881
Chris Wang4c1f2c72024-03-21 17:09:44 +0800882LIBPLDM_ABI_TESTING
883int encode_query_downstream_devices_req(uint8_t instance_id,
884 struct pldm_msg *msg)
885{
886 if (msg == NULL) {
887 return PLDM_ERROR_INVALID_DATA;
888 }
889
890 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
891 PLDM_QUERY_DOWNSTREAM_DEVICES, msg);
892}
893
894LIBPLDM_ABI_TESTING
895int decode_query_downstream_devices_resp(
896 const struct pldm_msg *msg, size_t payload_length,
897 struct pldm_query_downstream_devices_resp *resp_data)
898{
899 struct pldm_msgbuf _buf;
900 struct pldm_msgbuf *buf = &_buf;
901 int rc;
902
903 if (msg == NULL || resp_data == NULL || !payload_length) {
904 return PLDM_ERROR_INVALID_DATA;
905 }
906
Andrew Jefferyc8df31c2024-05-21 16:47:43 +0930907 rc = pldm_msgbuf_init_cc(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
908 msg->payload, payload_length);
Chris Wang4c1f2c72024-03-21 17:09:44 +0800909 if (rc) {
910 return rc;
911 }
912
913 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
914 if (rc) {
915 return rc;
916 }
917 if (PLDM_SUCCESS != resp_data->completion_code) {
918 // Return the CC directly without decoding the rest of the payload
919 return PLDM_SUCCESS;
920 }
921
922 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
923 return PLDM_ERROR_INVALID_LENGTH;
924 }
925
926 rc = pldm_msgbuf_extract(buf,
927 resp_data->downstream_device_update_supported);
928 if (rc) {
929 return rc;
930 }
931
932 if (!is_downstream_device_update_support_valid(
933 resp_data->downstream_device_update_supported)) {
934 return PLDM_ERROR_INVALID_DATA;
935 }
936
937 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
938 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
939 pldm_msgbuf_extract(buf, resp_data->capabilities.value);
940
941 return pldm_msgbuf_destroy_consumed(buf);
942}
943
Chris Wang458475a2024-03-26 17:59:19 +0800944LIBPLDM_ABI_TESTING
945int encode_query_downstream_identifiers_req(
946 uint8_t instance_id, uint32_t data_transfer_handle,
947 enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg,
948 size_t payload_length)
949{
950 struct pldm_msgbuf _buf;
951 struct pldm_msgbuf *buf = &_buf;
952 int rc;
953
954 if (msg == NULL) {
955 return PLDM_ERROR_INVALID_DATA;
956 }
957
958 if (!is_transfer_operation_flag_valid(transfer_operation_flag)) {
959 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
960 }
961
962 struct pldm_header_info header = { 0 };
963 header.instance = instance_id;
964 header.msg_type = PLDM_REQUEST;
965 header.pldm_type = PLDM_FWUP;
966 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
967 rc = pack_pldm_header(&header, &(msg->hdr));
968 if (rc) {
969 return rc;
970 }
971
Andrew Jefferyc8df31c2024-05-21 16:47:43 +0930972 rc = pldm_msgbuf_init_cc(buf,
973 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
974 msg->payload, payload_length);
Chris Wang458475a2024-03-26 17:59:19 +0800975 if (rc) {
976 return rc;
977 }
978
979 pldm_msgbuf_insert(buf, data_transfer_handle);
980 // Data correctness has been verified, cast it to 1-byte data directly.
981 pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag);
982
983 return pldm_msgbuf_destroy(buf);
984}
985
986LIBPLDM_ABI_TESTING
987int decode_query_downstream_identifiers_resp(
988 const struct pldm_msg *msg, size_t payload_length,
989 struct pldm_query_downstream_identifiers_resp *resp_data,
990 struct variable_field *downstream_devices)
991{
992 struct pldm_msgbuf _buf;
993 struct pldm_msgbuf *buf = &_buf;
994 int rc = PLDM_ERROR;
995
996 if (msg == NULL || resp_data == NULL || downstream_devices == NULL ||
997 !payload_length) {
998 return PLDM_ERROR_INVALID_DATA;
999 }
1000
Andrew Jefferyc8df31c2024-05-21 16:47:43 +09301001 rc = pldm_msgbuf_init_cc(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1002 msg->payload, payload_length);
Chris Wang458475a2024-03-26 17:59:19 +08001003 if (rc) {
1004 return rc;
1005 }
1006
1007 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1008 if (rc) {
1009 return rc;
1010 }
1011 if (PLDM_SUCCESS != resp_data->completion_code) {
1012 return PLDM_SUCCESS;
1013 }
1014
1015 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
1016 return PLDM_ERROR_INVALID_LENGTH;
1017 }
1018
1019 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1020 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1021
1022 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
1023 if (rc) {
1024 return rc;
1025 }
1026
1027 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1028 rc = pldm_msgbuf_span_required(buf,
1029 resp_data->downstream_devices_length,
1030 (void **)&downstream_devices->ptr);
1031 if (rc) {
1032 return rc;
1033 }
1034 downstream_devices->length = resp_data->downstream_devices_length;
1035
1036 return pldm_msgbuf_destroy(buf);
1037}
1038
Chris Wangb6ef35b2024-07-03 09:35:42 +08001039LIBPLDM_ABI_TESTING
1040int encode_get_downstream_firmware_params_req(
1041 uint8_t instance_id, uint32_t data_transfer_handle,
1042 enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg,
1043 size_t payload_length)
1044{
1045 struct pldm_msgbuf _buf;
1046 struct pldm_msgbuf *buf = &_buf;
1047 int rc;
1048
1049 if (msg == NULL) {
1050 return -EINVAL;
1051 }
1052
1053 rc = pldm_msgbuf_init_errno(
1054 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_REQ_BYTES,
1055 msg->payload, payload_length);
1056 if (rc < 0) {
1057 return rc;
1058 }
1059
1060 if (!is_transfer_operation_flag_valid(transfer_operation_flag)) {
1061 return -EBADMSG;
1062 }
1063
1064 struct pldm_header_info header = { 0 };
1065 header.instance = instance_id;
1066 header.msg_type = PLDM_REQUEST;
1067 header.pldm_type = PLDM_FWUP;
1068 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1069 rc = pack_pldm_header_errno(&header, &msg->hdr);
1070 if (rc < 0) {
1071 return rc;
1072 }
1073
1074 pldm_msgbuf_insert(buf, data_transfer_handle);
1075 // Data correctness has been verified, cast it to 1-byte data directly.
1076 pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag);
1077
1078 return pldm_msgbuf_destroy(buf);
1079}
1080
1081LIBPLDM_ABI_TESTING
1082int decode_get_downstream_firmware_params_resp(
1083 const struct pldm_msg *msg, size_t payload_length,
1084 struct pldm_get_downstream_firmware_params_resp *resp_data,
1085 struct variable_field *downstream_device_param_table)
1086{
1087 struct pldm_msgbuf _buf;
1088 struct pldm_msgbuf *buf = &_buf;
1089 int rc;
1090
1091 if (msg == NULL || resp_data == NULL ||
1092 downstream_device_param_table == NULL) {
1093 return -EINVAL;
1094 }
1095
1096 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1097 msg->payload, payload_length);
1098 if (rc < 0) {
1099 return rc;
1100 }
1101
1102 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1103 if (rc < 0) {
1104 return rc;
1105 }
1106 if (PLDM_SUCCESS != resp_data->completion_code) {
1107 return 0;
1108 }
1109
1110 if (payload_length < PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_RESP_MIN_LEN) {
1111 return -EBADMSG;
1112 }
1113
1114 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1115 pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1116 pldm_msgbuf_extract(buf,
1117 resp_data->fdp_capabilities_during_update.value);
1118 pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1119
1120 return pldm_msgbuf_span_remaining(
1121 buf, (void **)&downstream_device_param_table->ptr,
1122 &downstream_device_param_table->length);
1123}
1124
1125LIBPLDM_ABI_TESTING
1126int decode_downstream_device_parameter_table_entry(
1127 struct variable_field *data,
1128 struct pldm_downstream_device_parameter_entry *entry,
1129 struct variable_field *versions)
1130{
1131 struct pldm_msgbuf _buf;
1132 struct pldm_msgbuf *buf = &_buf;
1133 void *cursor = NULL;
1134 size_t remaining;
1135 int rc;
1136
1137 if (data == NULL || entry == NULL || versions == NULL) {
1138 return -EINVAL;
1139 }
1140
1141 rc = pldm_msgbuf_init_errno(
1142 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETER_ENTRY_MIN_LEN, data->ptr,
1143 data->length);
1144 if (rc < 0) {
1145 return rc;
1146 }
1147
1148 pldm_msgbuf_extract(buf, entry->downstream_device_index);
1149 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1150 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1151 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1152 if (rc < 0) {
1153 return rc;
1154 }
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001155 rc = pldm_msgbuf_extract_array(buf,
1156 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1157 entry->active_comp_release_date,
1158 sizeof(entry->active_comp_release_date));
1159 if (rc < 0) {
1160 return rc;
1161 }
1162
Chris Wangb6ef35b2024-07-03 09:35:42 +08001163 // Fill the last byte with NULL character
1164 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1165 '\0';
1166
1167 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1168 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1169 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1170 if (rc < 0) {
1171 return rc;
1172 }
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001173
1174 rc = pldm_msgbuf_extract_array(
1175 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1176 entry->pending_comp_release_date,
1177 sizeof(entry->pending_comp_release_date));
1178 if (rc < 0) {
1179 return rc;
1180 }
1181
Chris Wangb6ef35b2024-07-03 09:35:42 +08001182 // Fill the last byte with NULL character
1183 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1184 '\0';
1185
1186 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1187 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
1188 const size_t versions_len = entry->active_comp_ver_str_len +
1189 entry->pending_comp_ver_str_len;
1190 rc = pldm_msgbuf_span_required(buf, versions_len,
1191 (void **)&versions->ptr);
1192 if (rc < 0) {
1193 return rc;
1194 }
1195 versions->length = versions_len;
1196
1197 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1198 if (rc < 0) {
1199 return rc;
1200 }
1201
1202 data->ptr = cursor;
1203 data->length = remaining;
1204
1205 return 0;
1206}
1207
1208LIBPLDM_ABI_TESTING
1209int decode_downstream_device_parameter_table_entry_versions(
1210 const struct variable_field *versions,
1211 struct pldm_downstream_device_parameter_entry *entry, char *active,
1212 char *pending)
1213{
1214 struct pldm_msgbuf _buf;
1215 struct pldm_msgbuf *buf = &_buf;
1216 int rc;
1217
1218 if (versions == NULL || versions->ptr == NULL || !versions->length ||
1219 entry == NULL || active == NULL || pending == NULL) {
1220 return -EINVAL;
1221 }
1222
1223 /* This API should be called after decode_downstream_device_parameter_table_entry
1224 * has successfully decoded the entry, assume the entry data is valid here.
1225 */
1226 const size_t versions_len = entry->active_comp_ver_str_len +
1227 entry->pending_comp_ver_str_len;
1228 rc = pldm_msgbuf_init_errno(buf, versions_len, versions->ptr,
1229 versions->length);
1230 if (rc < 0) {
1231 return rc;
1232 }
1233
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001234 rc = pldm_msgbuf_extract_array(buf, entry->active_comp_ver_str_len,
1235 active, entry->active_comp_ver_str_len);
1236 if (rc < 0) {
1237 return rc;
1238 }
1239
Chris Wangb6ef35b2024-07-03 09:35:42 +08001240 active[entry->active_comp_ver_str_len] = '\0';
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001241 rc = pldm_msgbuf_extract_array(buf, entry->pending_comp_ver_str_len,
1242 pending,
1243 entry->pending_comp_ver_str_len);
1244 if (rc < 0) {
1245 return rc;
1246 }
1247
Chris Wangb6ef35b2024-07-03 09:35:42 +08001248 pending[entry->pending_comp_ver_str_len] = '\0';
1249
1250 entry->active_comp_ver_str = active;
1251 entry->pending_comp_ver_str = pending;
1252
1253 return pldm_msgbuf_destroy_consumed(buf);
1254}
1255
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301256LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301257int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1258 uint16_t num_of_comp,
1259 uint8_t max_outstanding_transfer_req,
1260 uint16_t pkg_data_len,
1261 uint8_t comp_image_set_ver_str_type,
1262 uint8_t comp_image_set_ver_str_len,
1263 const struct variable_field *comp_img_set_ver_str,
1264 struct pldm_msg *msg, size_t payload_length)
1265{
1266 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
1267 msg == NULL) {
1268 return PLDM_ERROR_INVALID_DATA;
1269 }
1270
1271 if (payload_length != sizeof(struct pldm_request_update_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301272 comp_img_set_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301273 return PLDM_ERROR_INVALID_LENGTH;
1274 }
1275
1276 if ((comp_image_set_ver_str_len == 0) ||
1277 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
1278 return PLDM_ERROR_INVALID_DATA;
1279 }
1280
1281 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
1282 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
1283 return PLDM_ERROR_INVALID_DATA;
1284 }
1285
1286 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
1287 return PLDM_ERROR_INVALID_DATA;
1288 }
1289
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301290 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301291 header.instance = instance_id;
1292 header.msg_type = PLDM_REQUEST;
1293 header.pldm_type = PLDM_FWUP;
1294 header.command = PLDM_REQUEST_UPDATE;
1295 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1296 if (rc) {
1297 return rc;
1298 }
1299
1300 struct pldm_request_update_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301301 (struct pldm_request_update_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301302
1303 request->max_transfer_size = htole32(max_transfer_size);
1304 request->num_of_comp = htole16(num_of_comp);
1305 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
1306 request->pkg_data_len = htole16(pkg_data_len);
1307 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
1308 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
1309
1310 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
1311 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
1312
1313 return PLDM_SUCCESS;
1314}
1315
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301316LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301317int decode_request_update_resp(const struct pldm_msg *msg,
1318 size_t payload_length, uint8_t *completion_code,
1319 uint16_t *fd_meta_data_len,
1320 uint8_t *fd_will_send_pkg_data)
1321{
1322 if (msg == NULL || completion_code == NULL ||
1323 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
1324 !payload_length) {
1325 return PLDM_ERROR_INVALID_DATA;
1326 }
1327
1328 *completion_code = msg->payload[0];
1329 if (*completion_code != PLDM_SUCCESS) {
1330 return PLDM_SUCCESS;
1331 }
1332
1333 if (payload_length != sizeof(struct pldm_request_update_resp)) {
1334 return PLDM_ERROR_INVALID_LENGTH;
1335 }
1336
1337 struct pldm_request_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301338 (struct pldm_request_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301339
1340 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
1341 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1342
1343 return PLDM_SUCCESS;
1344}
1345
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301346LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301347int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1348 uint16_t comp_classification,
1349 uint16_t comp_identifier,
1350 uint8_t comp_classification_index,
1351 uint32_t comp_comparison_stamp,
1352 uint8_t comp_ver_str_type,
1353 uint8_t comp_ver_str_len,
1354 const struct variable_field *comp_ver_str,
1355 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301356{
1357 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1358 return PLDM_ERROR_INVALID_DATA;
1359 }
1360
1361 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301362 comp_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301363 return PLDM_ERROR_INVALID_LENGTH;
1364 }
1365
1366 if ((comp_ver_str_len == 0) ||
1367 (comp_ver_str_len != comp_ver_str->length)) {
1368 return PLDM_ERROR_INVALID_DATA;
1369 }
1370
1371 if (!is_transfer_flag_valid(transfer_flag)) {
1372 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1373 }
1374
1375 if (!is_string_type_valid(comp_ver_str_type)) {
1376 return PLDM_ERROR_INVALID_DATA;
1377 }
1378
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301379 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301380 header.instance = instance_id;
1381 header.msg_type = PLDM_REQUEST;
1382 header.pldm_type = PLDM_FWUP;
1383 header.command = PLDM_PASS_COMPONENT_TABLE;
1384 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1385 if (rc) {
1386 return rc;
1387 }
1388
1389 struct pldm_pass_component_table_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301390 (struct pldm_pass_component_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301391
1392 request->transfer_flag = transfer_flag;
1393 request->comp_classification = htole16(comp_classification);
1394 request->comp_identifier = htole16(comp_identifier);
1395 request->comp_classification_index = comp_classification_index;
1396 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1397 request->comp_ver_str_type = comp_ver_str_type;
1398 request->comp_ver_str_len = comp_ver_str_len;
1399
1400 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1401 comp_ver_str->ptr, comp_ver_str->length);
1402
1403 return PLDM_SUCCESS;
1404}
1405
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301406LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301407int decode_pass_component_table_resp(const struct pldm_msg *msg,
1408 const size_t payload_length,
1409 uint8_t *completion_code,
1410 uint8_t *comp_resp,
1411 uint8_t *comp_resp_code)
1412{
1413 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1414 comp_resp_code == NULL || !payload_length) {
1415 return PLDM_ERROR_INVALID_DATA;
1416 }
1417
1418 *completion_code = msg->payload[0];
1419 if (*completion_code != PLDM_SUCCESS) {
1420 return PLDM_SUCCESS;
1421 }
1422
1423 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1424 return PLDM_ERROR_INVALID_LENGTH;
1425 }
1426
1427 struct pldm_pass_component_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301428 (struct pldm_pass_component_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301429
1430 if (!is_comp_resp_valid(response->comp_resp)) {
1431 return PLDM_ERROR_INVALID_DATA;
1432 }
1433
1434 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1435 return PLDM_ERROR_INVALID_DATA;
1436 }
1437
1438 *comp_resp = response->comp_resp;
1439 *comp_resp_code = response->comp_resp_code;
1440
1441 return PLDM_SUCCESS;
1442}
1443
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301444LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301445int encode_update_component_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301446 uint8_t instance_id, uint16_t comp_classification,
1447 uint16_t comp_identifier, uint8_t comp_classification_index,
1448 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1449 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1450 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1451 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301452{
1453 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1454 return PLDM_ERROR_INVALID_DATA;
1455 }
1456
1457 if (payload_length !=
1458 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1459 return PLDM_ERROR_INVALID_LENGTH;
1460 }
1461
1462 if (!comp_image_size) {
1463 return PLDM_ERROR_INVALID_DATA;
1464 }
1465
1466 if ((comp_ver_str_len == 0) ||
1467 (comp_ver_str_len != comp_ver_str->length)) {
1468 return PLDM_ERROR_INVALID_DATA;
1469 }
1470
1471 if (!is_string_type_valid(comp_ver_str_type)) {
1472 return PLDM_ERROR_INVALID_DATA;
1473 }
1474
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301475 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301476 header.instance = instance_id;
1477 header.msg_type = PLDM_REQUEST;
1478 header.pldm_type = PLDM_FWUP;
1479 header.command = PLDM_UPDATE_COMPONENT;
1480 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1481 if (rc) {
1482 return rc;
1483 }
1484
1485 struct pldm_update_component_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301486 (struct pldm_update_component_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301487
1488 request->comp_classification = htole16(comp_classification);
1489 request->comp_identifier = htole16(comp_identifier);
1490 request->comp_classification_index = comp_classification_index;
1491 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1492 request->comp_image_size = htole32(comp_image_size);
1493 request->update_option_flags.value = htole32(update_option_flags.value);
1494 request->comp_ver_str_type = comp_ver_str_type;
1495 request->comp_ver_str_len = comp_ver_str_len;
1496
1497 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1498 comp_ver_str->ptr, comp_ver_str->length);
1499
1500 return PLDM_SUCCESS;
1501}
1502
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301503LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301504int decode_update_component_resp(const struct pldm_msg *msg,
1505 size_t payload_length,
1506 uint8_t *completion_code,
1507 uint8_t *comp_compatibility_resp,
1508 uint8_t *comp_compatibility_resp_code,
1509 bitfield32_t *update_option_flags_enabled,
1510 uint16_t *time_before_req_fw_data)
1511{
1512 if (msg == NULL || completion_code == NULL ||
1513 comp_compatibility_resp == NULL ||
1514 comp_compatibility_resp_code == NULL ||
1515 update_option_flags_enabled == NULL ||
1516 time_before_req_fw_data == NULL || !payload_length) {
1517 return PLDM_ERROR_INVALID_DATA;
1518 }
1519
1520 *completion_code = msg->payload[0];
1521 if (*completion_code != PLDM_SUCCESS) {
1522 return PLDM_SUCCESS;
1523 }
1524
1525 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1526 return PLDM_ERROR_INVALID_LENGTH;
1527 }
1528
1529 struct pldm_update_component_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301530 (struct pldm_update_component_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301531
1532 if (!is_comp_compatibility_resp_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301533 response->comp_compatibility_resp)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301534 return PLDM_ERROR_INVALID_DATA;
1535 }
1536
1537 if (!is_comp_compatibility_resp_code_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301538 response->comp_compatibility_resp_code)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301539 return PLDM_ERROR_INVALID_DATA;
1540 }
1541
1542 *comp_compatibility_resp = response->comp_compatibility_resp;
1543 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1544 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301545 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301546 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1547
1548 return PLDM_SUCCESS;
1549}
1550
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301551LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301552int decode_request_firmware_data_req(const struct pldm_msg *msg,
1553 size_t payload_length, uint32_t *offset,
1554 uint32_t *length)
1555{
1556 if (msg == NULL || offset == NULL || length == NULL) {
1557 return PLDM_ERROR_INVALID_DATA;
1558 }
1559 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1560 return PLDM_ERROR_INVALID_LENGTH;
1561 }
1562 struct pldm_request_firmware_data_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301563 (struct pldm_request_firmware_data_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301564 *offset = le32toh(request->offset);
1565 *length = le32toh(request->length);
1566
1567 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1568 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1569 }
1570
1571 return PLDM_SUCCESS;
1572}
1573
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301574LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301575int encode_request_firmware_data_resp(uint8_t instance_id,
1576 uint8_t completion_code,
1577 struct pldm_msg *msg,
1578 size_t payload_length)
1579{
1580 if (msg == NULL || !payload_length) {
1581 return PLDM_ERROR_INVALID_DATA;
1582 }
1583
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301584 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301585 header.instance = instance_id;
1586 header.msg_type = PLDM_RESPONSE;
1587 header.pldm_type = PLDM_FWUP;
1588 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1589 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1590 if (rc) {
1591 return rc;
1592 }
1593
1594 msg->payload[0] = completion_code;
1595
1596 return PLDM_SUCCESS;
1597}
1598
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301599LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301600int decode_transfer_complete_req(const struct pldm_msg *msg,
1601 size_t payload_length,
1602 uint8_t *transfer_result)
1603{
1604 if (msg == NULL || transfer_result == NULL) {
1605 return PLDM_ERROR_INVALID_DATA;
1606 }
1607
1608 if (payload_length != sizeof(*transfer_result)) {
1609 return PLDM_ERROR_INVALID_LENGTH;
1610 }
1611
1612 *transfer_result = msg->payload[0];
1613 return PLDM_SUCCESS;
1614}
1615
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301616LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301617int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1618 struct pldm_msg *msg, size_t payload_length)
1619{
1620 if (msg == NULL) {
1621 return PLDM_ERROR_INVALID_DATA;
1622 }
1623
1624 if (payload_length != sizeof(completion_code)) {
1625 return PLDM_ERROR_INVALID_LENGTH;
1626 }
1627
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301628 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301629 header.instance = instance_id;
1630 header.msg_type = PLDM_RESPONSE;
1631 header.pldm_type = PLDM_FWUP;
1632 header.command = PLDM_TRANSFER_COMPLETE;
1633 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1634 if (rc) {
1635 return rc;
1636 }
1637
1638 msg->payload[0] = completion_code;
1639
1640 return PLDM_SUCCESS;
1641}
1642
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301643LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301644int decode_verify_complete_req(const struct pldm_msg *msg,
1645 size_t payload_length, uint8_t *verify_result)
1646{
1647 if (msg == NULL || verify_result == NULL) {
1648 return PLDM_ERROR_INVALID_DATA;
1649 }
1650
1651 if (payload_length != sizeof(*verify_result)) {
1652 return PLDM_ERROR_INVALID_LENGTH;
1653 }
1654
1655 *verify_result = msg->payload[0];
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_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1661 struct pldm_msg *msg, size_t payload_length)
1662{
1663 if (msg == NULL) {
1664 return PLDM_ERROR_INVALID_DATA;
1665 }
1666
1667 if (payload_length != sizeof(completion_code)) {
1668 return PLDM_ERROR_INVALID_LENGTH;
1669 }
1670
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301671 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301672 header.instance = instance_id;
1673 header.msg_type = PLDM_RESPONSE;
1674 header.pldm_type = PLDM_FWUP;
1675 header.command = PLDM_VERIFY_COMPLETE;
1676 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1677 if (rc) {
1678 return rc;
1679 }
1680
1681 msg->payload[0] = completion_code;
1682
1683 return PLDM_SUCCESS;
1684}
1685
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301686LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301687int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
1688 uint8_t *apply_result,
1689 bitfield16_t *comp_activation_methods_modification)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301690{
1691 if (msg == NULL || apply_result == NULL ||
1692 comp_activation_methods_modification == NULL) {
1693 return PLDM_ERROR_INVALID_DATA;
1694 }
1695
1696 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1697 return PLDM_ERROR_INVALID_LENGTH;
1698 }
1699
1700 struct pldm_apply_complete_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301701 (struct pldm_apply_complete_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301702
1703 *apply_result = request->apply_result;
1704 comp_activation_methods_modification->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301705 le16toh(request->comp_activation_methods_modification.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301706
1707 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1708 comp_activation_methods_modification->value) {
1709 return PLDM_ERROR_INVALID_DATA;
1710 }
1711
1712 return PLDM_SUCCESS;
1713}
1714
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301715LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301716int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1717 struct pldm_msg *msg, size_t payload_length)
1718{
1719 if (msg == NULL) {
1720 return PLDM_ERROR_INVALID_DATA;
1721 }
1722
1723 if (payload_length != sizeof(completion_code)) {
1724 return PLDM_ERROR_INVALID_LENGTH;
1725 }
1726
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301727 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301728 header.instance = instance_id;
1729 header.msg_type = PLDM_RESPONSE;
1730 header.pldm_type = PLDM_FWUP;
1731 header.command = PLDM_APPLY_COMPLETE;
1732 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1733 if (rc) {
1734 return rc;
1735 }
1736
1737 msg->payload[0] = completion_code;
1738
1739 return PLDM_SUCCESS;
1740}
1741
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301742LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301743int encode_activate_firmware_req(uint8_t instance_id,
1744 bool8_t self_contained_activation_req,
1745 struct pldm_msg *msg, size_t payload_length)
1746{
1747 if (msg == NULL) {
1748 return PLDM_ERROR_INVALID_DATA;
1749 }
1750
1751 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1752 return PLDM_ERROR_INVALID_LENGTH;
1753 }
1754
1755 if (!is_self_contained_activation_req_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301756 self_contained_activation_req)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301757 return PLDM_ERROR_INVALID_DATA;
1758 }
1759
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301760 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301761 header.instance = instance_id;
1762 header.msg_type = PLDM_REQUEST;
1763 header.pldm_type = PLDM_FWUP;
1764 header.command = PLDM_ACTIVATE_FIRMWARE;
1765 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1766 if (rc) {
1767 return rc;
1768 }
1769
1770 struct pldm_activate_firmware_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301771 (struct pldm_activate_firmware_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301772
1773 request->self_contained_activation_req = self_contained_activation_req;
1774
1775 return PLDM_SUCCESS;
1776}
1777
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301778LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301779int decode_activate_firmware_resp(const struct pldm_msg *msg,
1780 size_t payload_length,
1781 uint8_t *completion_code,
1782 uint16_t *estimated_time_activation)
1783{
1784 if (msg == NULL || completion_code == NULL ||
1785 estimated_time_activation == NULL || !payload_length) {
1786 return PLDM_ERROR_INVALID_DATA;
1787 }
1788
1789 *completion_code = msg->payload[0];
1790 if (*completion_code != PLDM_SUCCESS) {
1791 return PLDM_SUCCESS;
1792 }
1793
1794 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1795 return PLDM_ERROR_INVALID_LENGTH;
1796 }
1797
1798 struct pldm_activate_firmware_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301799 (struct pldm_activate_firmware_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301800
1801 *estimated_time_activation =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301802 le16toh(response->estimated_time_activation);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301803
1804 return PLDM_SUCCESS;
1805}
1806
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301807LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301808int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1809 size_t payload_length)
1810{
1811 if (msg == NULL) {
1812 return PLDM_ERROR_INVALID_DATA;
1813 }
1814
1815 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1816 return PLDM_ERROR_INVALID_LENGTH;
1817 }
1818
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301819 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301820 header.instance = instance_id;
1821 header.msg_type = PLDM_REQUEST;
1822 header.pldm_type = PLDM_FWUP;
1823 header.command = PLDM_GET_STATUS;
1824 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1825 if (rc) {
1826 return rc;
1827 }
1828
1829 return PLDM_SUCCESS;
1830}
1831
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301832LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301833int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1834 uint8_t *completion_code, uint8_t *current_state,
1835 uint8_t *previous_state, uint8_t *aux_state,
1836 uint8_t *aux_state_status, uint8_t *progress_percent,
1837 uint8_t *reason_code,
1838 bitfield32_t *update_option_flags_enabled)
1839{
1840 if (msg == NULL || completion_code == NULL || current_state == NULL ||
1841 previous_state == NULL || aux_state == NULL ||
1842 aux_state_status == NULL || progress_percent == NULL ||
1843 reason_code == NULL || update_option_flags_enabled == NULL ||
1844 !payload_length) {
1845 return PLDM_ERROR_INVALID_DATA;
1846 }
1847
1848 *completion_code = msg->payload[0];
1849 if (*completion_code != PLDM_SUCCESS) {
1850 return PLDM_SUCCESS;
1851 }
1852
1853 if (payload_length != sizeof(struct pldm_get_status_resp)) {
1854 return PLDM_ERROR_INVALID_LENGTH;
1855 }
1856 struct pldm_get_status_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301857 (struct pldm_get_status_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301858
1859 if (!is_state_valid(response->current_state)) {
1860 return PLDM_ERROR_INVALID_DATA;
1861 }
1862 if (!is_state_valid(response->previous_state)) {
1863 return PLDM_ERROR_INVALID_DATA;
1864 }
1865 if (!is_aux_state_valid(response->aux_state)) {
1866 return PLDM_ERROR_INVALID_DATA;
1867 }
1868 if (!is_aux_state_status_valid(response->aux_state_status)) {
1869 return PLDM_ERROR_INVALID_DATA;
1870 }
1871 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1872 return PLDM_ERROR_INVALID_DATA;
1873 }
1874 if (!is_reason_code_valid(response->reason_code)) {
1875 return PLDM_ERROR_INVALID_DATA;
1876 }
1877
1878 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1879 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1880 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1881 if (response->aux_state !=
1882 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1883 return PLDM_ERROR_INVALID_DATA;
1884 }
1885 }
1886
1887 *current_state = response->current_state;
1888 *previous_state = response->previous_state;
1889 *aux_state = response->aux_state;
1890 *aux_state_status = response->aux_state_status;
1891 *progress_percent = response->progress_percent;
1892 *reason_code = response->reason_code;
1893 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301894 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301895
1896 return PLDM_SUCCESS;
1897}
1898
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301899LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301900int encode_cancel_update_component_req(uint8_t instance_id,
1901 struct pldm_msg *msg,
1902 size_t payload_length)
1903{
1904 if (msg == NULL) {
1905 return PLDM_ERROR_INVALID_DATA;
1906 }
1907
1908 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1909 return PLDM_ERROR_INVALID_LENGTH;
1910 }
1911
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301912 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301913 header.instance = instance_id;
1914 header.msg_type = PLDM_REQUEST;
1915 header.pldm_type = PLDM_FWUP;
1916 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
1917 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1918 if (rc) {
1919 return rc;
1920 }
1921
1922 return PLDM_SUCCESS;
1923}
1924
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301925LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301926int decode_cancel_update_component_resp(const struct pldm_msg *msg,
1927 size_t payload_length,
1928 uint8_t *completion_code)
1929{
1930 if (msg == NULL || completion_code == NULL) {
1931 return PLDM_ERROR_INVALID_DATA;
1932 }
1933
1934 if (payload_length != sizeof(*completion_code)) {
1935 return PLDM_ERROR_INVALID_LENGTH;
1936 }
1937
1938 *completion_code = msg->payload[0];
1939 return PLDM_SUCCESS;
1940}
1941
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301942LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301943int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
1944 size_t payload_length)
1945{
1946 if (msg == NULL) {
1947 return PLDM_ERROR_INVALID_DATA;
1948 }
1949
1950 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
1951 return PLDM_ERROR_INVALID_LENGTH;
1952 }
1953
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301954 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301955 header.instance = instance_id;
1956 header.msg_type = PLDM_REQUEST;
1957 header.pldm_type = PLDM_FWUP;
1958 header.command = PLDM_CANCEL_UPDATE;
1959 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1960 if (rc) {
1961 return rc;
1962 }
1963
1964 return PLDM_SUCCESS;
1965}
1966
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301967LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301968int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
1969 uint8_t *completion_code,
1970 bool8_t *non_functioning_component_indication,
1971 bitfield64_t *non_functioning_component_bitmap)
1972{
1973 if (msg == NULL || completion_code == NULL ||
1974 non_functioning_component_indication == NULL ||
1975 non_functioning_component_bitmap == NULL || !payload_length) {
1976 return PLDM_ERROR_INVALID_DATA;
1977 }
1978
1979 *completion_code = msg->payload[0];
1980 if (*completion_code != PLDM_SUCCESS) {
1981 return PLDM_SUCCESS;
1982 }
1983
1984 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
1985 return PLDM_ERROR_INVALID_LENGTH;
1986 }
1987 struct pldm_cancel_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301988 (struct pldm_cancel_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301989
1990 if (!is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301991 response->non_functioning_component_indication)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301992 return PLDM_ERROR_INVALID_DATA;
1993 }
1994
1995 *non_functioning_component_indication =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301996 response->non_functioning_component_indication;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301997
1998 if (*non_functioning_component_indication) {
1999 non_functioning_component_bitmap->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09302000 le64toh(response->non_functioning_component_bitmap);
Andrew Jeffery9c766792022-08-10 23:12:49 +09302001 }
2002
2003 return PLDM_SUCCESS;
2004}