blob: 80310b22d213f0ca1d2748d1a2797c3efc78d910 [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 }
1155 pldm_msgbuf_extract_array(buf, entry->active_comp_release_date,
1156 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1157 // Fill the last byte with NULL character
1158 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1159 '\0';
1160
1161 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1162 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1163 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1164 if (rc < 0) {
1165 return rc;
1166 }
1167 pldm_msgbuf_extract_array(buf, entry->pending_comp_release_date,
1168 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1169 // Fill the last byte with NULL character
1170 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1171 '\0';
1172
1173 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1174 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
1175 const size_t versions_len = entry->active_comp_ver_str_len +
1176 entry->pending_comp_ver_str_len;
1177 rc = pldm_msgbuf_span_required(buf, versions_len,
1178 (void **)&versions->ptr);
1179 if (rc < 0) {
1180 return rc;
1181 }
1182 versions->length = versions_len;
1183
1184 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1185 if (rc < 0) {
1186 return rc;
1187 }
1188
1189 data->ptr = cursor;
1190 data->length = remaining;
1191
1192 return 0;
1193}
1194
1195LIBPLDM_ABI_TESTING
1196int decode_downstream_device_parameter_table_entry_versions(
1197 const struct variable_field *versions,
1198 struct pldm_downstream_device_parameter_entry *entry, char *active,
1199 char *pending)
1200{
1201 struct pldm_msgbuf _buf;
1202 struct pldm_msgbuf *buf = &_buf;
1203 int rc;
1204
1205 if (versions == NULL || versions->ptr == NULL || !versions->length ||
1206 entry == NULL || active == NULL || pending == NULL) {
1207 return -EINVAL;
1208 }
1209
1210 /* This API should be called after decode_downstream_device_parameter_table_entry
1211 * has successfully decoded the entry, assume the entry data is valid here.
1212 */
1213 const size_t versions_len = entry->active_comp_ver_str_len +
1214 entry->pending_comp_ver_str_len;
1215 rc = pldm_msgbuf_init_errno(buf, versions_len, versions->ptr,
1216 versions->length);
1217 if (rc < 0) {
1218 return rc;
1219 }
1220
1221 pldm_msgbuf_extract_array(buf, active, entry->active_comp_ver_str_len);
1222 active[entry->active_comp_ver_str_len] = '\0';
1223 pldm_msgbuf_extract_array(buf, pending,
1224 entry->pending_comp_ver_str_len);
1225 pending[entry->pending_comp_ver_str_len] = '\0';
1226
1227 entry->active_comp_ver_str = active;
1228 entry->pending_comp_ver_str = pending;
1229
1230 return pldm_msgbuf_destroy_consumed(buf);
1231}
1232
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301233LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301234int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1235 uint16_t num_of_comp,
1236 uint8_t max_outstanding_transfer_req,
1237 uint16_t pkg_data_len,
1238 uint8_t comp_image_set_ver_str_type,
1239 uint8_t comp_image_set_ver_str_len,
1240 const struct variable_field *comp_img_set_ver_str,
1241 struct pldm_msg *msg, size_t payload_length)
1242{
1243 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
1244 msg == NULL) {
1245 return PLDM_ERROR_INVALID_DATA;
1246 }
1247
1248 if (payload_length != sizeof(struct pldm_request_update_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301249 comp_img_set_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301250 return PLDM_ERROR_INVALID_LENGTH;
1251 }
1252
1253 if ((comp_image_set_ver_str_len == 0) ||
1254 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
1255 return PLDM_ERROR_INVALID_DATA;
1256 }
1257
1258 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
1259 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
1260 return PLDM_ERROR_INVALID_DATA;
1261 }
1262
1263 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
1264 return PLDM_ERROR_INVALID_DATA;
1265 }
1266
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301267 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301268 header.instance = instance_id;
1269 header.msg_type = PLDM_REQUEST;
1270 header.pldm_type = PLDM_FWUP;
1271 header.command = PLDM_REQUEST_UPDATE;
1272 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1273 if (rc) {
1274 return rc;
1275 }
1276
1277 struct pldm_request_update_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301278 (struct pldm_request_update_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301279
1280 request->max_transfer_size = htole32(max_transfer_size);
1281 request->num_of_comp = htole16(num_of_comp);
1282 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
1283 request->pkg_data_len = htole16(pkg_data_len);
1284 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
1285 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
1286
1287 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
1288 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
1289
1290 return PLDM_SUCCESS;
1291}
1292
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301293LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301294int decode_request_update_resp(const struct pldm_msg *msg,
1295 size_t payload_length, uint8_t *completion_code,
1296 uint16_t *fd_meta_data_len,
1297 uint8_t *fd_will_send_pkg_data)
1298{
1299 if (msg == NULL || completion_code == NULL ||
1300 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
1301 !payload_length) {
1302 return PLDM_ERROR_INVALID_DATA;
1303 }
1304
1305 *completion_code = msg->payload[0];
1306 if (*completion_code != PLDM_SUCCESS) {
1307 return PLDM_SUCCESS;
1308 }
1309
1310 if (payload_length != sizeof(struct pldm_request_update_resp)) {
1311 return PLDM_ERROR_INVALID_LENGTH;
1312 }
1313
1314 struct pldm_request_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301315 (struct pldm_request_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301316
1317 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
1318 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1319
1320 return PLDM_SUCCESS;
1321}
1322
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301323LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301324int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1325 uint16_t comp_classification,
1326 uint16_t comp_identifier,
1327 uint8_t comp_classification_index,
1328 uint32_t comp_comparison_stamp,
1329 uint8_t comp_ver_str_type,
1330 uint8_t comp_ver_str_len,
1331 const struct variable_field *comp_ver_str,
1332 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301333{
1334 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1335 return PLDM_ERROR_INVALID_DATA;
1336 }
1337
1338 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301339 comp_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301340 return PLDM_ERROR_INVALID_LENGTH;
1341 }
1342
1343 if ((comp_ver_str_len == 0) ||
1344 (comp_ver_str_len != comp_ver_str->length)) {
1345 return PLDM_ERROR_INVALID_DATA;
1346 }
1347
1348 if (!is_transfer_flag_valid(transfer_flag)) {
1349 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1350 }
1351
1352 if (!is_string_type_valid(comp_ver_str_type)) {
1353 return PLDM_ERROR_INVALID_DATA;
1354 }
1355
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301356 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301357 header.instance = instance_id;
1358 header.msg_type = PLDM_REQUEST;
1359 header.pldm_type = PLDM_FWUP;
1360 header.command = PLDM_PASS_COMPONENT_TABLE;
1361 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1362 if (rc) {
1363 return rc;
1364 }
1365
1366 struct pldm_pass_component_table_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301367 (struct pldm_pass_component_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301368
1369 request->transfer_flag = transfer_flag;
1370 request->comp_classification = htole16(comp_classification);
1371 request->comp_identifier = htole16(comp_identifier);
1372 request->comp_classification_index = comp_classification_index;
1373 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1374 request->comp_ver_str_type = comp_ver_str_type;
1375 request->comp_ver_str_len = comp_ver_str_len;
1376
1377 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1378 comp_ver_str->ptr, comp_ver_str->length);
1379
1380 return PLDM_SUCCESS;
1381}
1382
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301383LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301384int decode_pass_component_table_resp(const struct pldm_msg *msg,
1385 const size_t payload_length,
1386 uint8_t *completion_code,
1387 uint8_t *comp_resp,
1388 uint8_t *comp_resp_code)
1389{
1390 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1391 comp_resp_code == NULL || !payload_length) {
1392 return PLDM_ERROR_INVALID_DATA;
1393 }
1394
1395 *completion_code = msg->payload[0];
1396 if (*completion_code != PLDM_SUCCESS) {
1397 return PLDM_SUCCESS;
1398 }
1399
1400 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1401 return PLDM_ERROR_INVALID_LENGTH;
1402 }
1403
1404 struct pldm_pass_component_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301405 (struct pldm_pass_component_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301406
1407 if (!is_comp_resp_valid(response->comp_resp)) {
1408 return PLDM_ERROR_INVALID_DATA;
1409 }
1410
1411 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1412 return PLDM_ERROR_INVALID_DATA;
1413 }
1414
1415 *comp_resp = response->comp_resp;
1416 *comp_resp_code = response->comp_resp_code;
1417
1418 return PLDM_SUCCESS;
1419}
1420
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301421LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301422int encode_update_component_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301423 uint8_t instance_id, uint16_t comp_classification,
1424 uint16_t comp_identifier, uint8_t comp_classification_index,
1425 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1426 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1427 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1428 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301429{
1430 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1431 return PLDM_ERROR_INVALID_DATA;
1432 }
1433
1434 if (payload_length !=
1435 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1436 return PLDM_ERROR_INVALID_LENGTH;
1437 }
1438
1439 if (!comp_image_size) {
1440 return PLDM_ERROR_INVALID_DATA;
1441 }
1442
1443 if ((comp_ver_str_len == 0) ||
1444 (comp_ver_str_len != comp_ver_str->length)) {
1445 return PLDM_ERROR_INVALID_DATA;
1446 }
1447
1448 if (!is_string_type_valid(comp_ver_str_type)) {
1449 return PLDM_ERROR_INVALID_DATA;
1450 }
1451
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301452 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301453 header.instance = instance_id;
1454 header.msg_type = PLDM_REQUEST;
1455 header.pldm_type = PLDM_FWUP;
1456 header.command = PLDM_UPDATE_COMPONENT;
1457 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1458 if (rc) {
1459 return rc;
1460 }
1461
1462 struct pldm_update_component_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301463 (struct pldm_update_component_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301464
1465 request->comp_classification = htole16(comp_classification);
1466 request->comp_identifier = htole16(comp_identifier);
1467 request->comp_classification_index = comp_classification_index;
1468 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1469 request->comp_image_size = htole32(comp_image_size);
1470 request->update_option_flags.value = htole32(update_option_flags.value);
1471 request->comp_ver_str_type = comp_ver_str_type;
1472 request->comp_ver_str_len = comp_ver_str_len;
1473
1474 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1475 comp_ver_str->ptr, comp_ver_str->length);
1476
1477 return PLDM_SUCCESS;
1478}
1479
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301480LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301481int decode_update_component_resp(const struct pldm_msg *msg,
1482 size_t payload_length,
1483 uint8_t *completion_code,
1484 uint8_t *comp_compatibility_resp,
1485 uint8_t *comp_compatibility_resp_code,
1486 bitfield32_t *update_option_flags_enabled,
1487 uint16_t *time_before_req_fw_data)
1488{
1489 if (msg == NULL || completion_code == NULL ||
1490 comp_compatibility_resp == NULL ||
1491 comp_compatibility_resp_code == NULL ||
1492 update_option_flags_enabled == NULL ||
1493 time_before_req_fw_data == NULL || !payload_length) {
1494 return PLDM_ERROR_INVALID_DATA;
1495 }
1496
1497 *completion_code = msg->payload[0];
1498 if (*completion_code != PLDM_SUCCESS) {
1499 return PLDM_SUCCESS;
1500 }
1501
1502 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1503 return PLDM_ERROR_INVALID_LENGTH;
1504 }
1505
1506 struct pldm_update_component_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301507 (struct pldm_update_component_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301508
1509 if (!is_comp_compatibility_resp_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301510 response->comp_compatibility_resp)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301511 return PLDM_ERROR_INVALID_DATA;
1512 }
1513
1514 if (!is_comp_compatibility_resp_code_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301515 response->comp_compatibility_resp_code)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301516 return PLDM_ERROR_INVALID_DATA;
1517 }
1518
1519 *comp_compatibility_resp = response->comp_compatibility_resp;
1520 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1521 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301522 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301523 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1524
1525 return PLDM_SUCCESS;
1526}
1527
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301528LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301529int decode_request_firmware_data_req(const struct pldm_msg *msg,
1530 size_t payload_length, uint32_t *offset,
1531 uint32_t *length)
1532{
1533 if (msg == NULL || offset == NULL || length == NULL) {
1534 return PLDM_ERROR_INVALID_DATA;
1535 }
1536 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1537 return PLDM_ERROR_INVALID_LENGTH;
1538 }
1539 struct pldm_request_firmware_data_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301540 (struct pldm_request_firmware_data_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301541 *offset = le32toh(request->offset);
1542 *length = le32toh(request->length);
1543
1544 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1545 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1546 }
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 encode_request_firmware_data_resp(uint8_t instance_id,
1553 uint8_t completion_code,
1554 struct pldm_msg *msg,
1555 size_t payload_length)
1556{
1557 if (msg == NULL || !payload_length) {
1558 return PLDM_ERROR_INVALID_DATA;
1559 }
1560
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301561 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301562 header.instance = instance_id;
1563 header.msg_type = PLDM_RESPONSE;
1564 header.pldm_type = PLDM_FWUP;
1565 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1566 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1567 if (rc) {
1568 return rc;
1569 }
1570
1571 msg->payload[0] = completion_code;
1572
1573 return PLDM_SUCCESS;
1574}
1575
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301576LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301577int decode_transfer_complete_req(const struct pldm_msg *msg,
1578 size_t payload_length,
1579 uint8_t *transfer_result)
1580{
1581 if (msg == NULL || transfer_result == NULL) {
1582 return PLDM_ERROR_INVALID_DATA;
1583 }
1584
1585 if (payload_length != sizeof(*transfer_result)) {
1586 return PLDM_ERROR_INVALID_LENGTH;
1587 }
1588
1589 *transfer_result = msg->payload[0];
1590 return PLDM_SUCCESS;
1591}
1592
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301593LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301594int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1595 struct pldm_msg *msg, size_t payload_length)
1596{
1597 if (msg == NULL) {
1598 return PLDM_ERROR_INVALID_DATA;
1599 }
1600
1601 if (payload_length != sizeof(completion_code)) {
1602 return PLDM_ERROR_INVALID_LENGTH;
1603 }
1604
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301605 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301606 header.instance = instance_id;
1607 header.msg_type = PLDM_RESPONSE;
1608 header.pldm_type = PLDM_FWUP;
1609 header.command = PLDM_TRANSFER_COMPLETE;
1610 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1611 if (rc) {
1612 return rc;
1613 }
1614
1615 msg->payload[0] = completion_code;
1616
1617 return PLDM_SUCCESS;
1618}
1619
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301620LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301621int decode_verify_complete_req(const struct pldm_msg *msg,
1622 size_t payload_length, uint8_t *verify_result)
1623{
1624 if (msg == NULL || verify_result == NULL) {
1625 return PLDM_ERROR_INVALID_DATA;
1626 }
1627
1628 if (payload_length != sizeof(*verify_result)) {
1629 return PLDM_ERROR_INVALID_LENGTH;
1630 }
1631
1632 *verify_result = msg->payload[0];
1633 return PLDM_SUCCESS;
1634}
1635
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301636LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301637int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1638 struct pldm_msg *msg, size_t payload_length)
1639{
1640 if (msg == NULL) {
1641 return PLDM_ERROR_INVALID_DATA;
1642 }
1643
1644 if (payload_length != sizeof(completion_code)) {
1645 return PLDM_ERROR_INVALID_LENGTH;
1646 }
1647
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301648 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301649 header.instance = instance_id;
1650 header.msg_type = PLDM_RESPONSE;
1651 header.pldm_type = PLDM_FWUP;
1652 header.command = PLDM_VERIFY_COMPLETE;
1653 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1654 if (rc) {
1655 return rc;
1656 }
1657
1658 msg->payload[0] = completion_code;
1659
1660 return PLDM_SUCCESS;
1661}
1662
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301663LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301664int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
1665 uint8_t *apply_result,
1666 bitfield16_t *comp_activation_methods_modification)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301667{
1668 if (msg == NULL || apply_result == NULL ||
1669 comp_activation_methods_modification == NULL) {
1670 return PLDM_ERROR_INVALID_DATA;
1671 }
1672
1673 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1674 return PLDM_ERROR_INVALID_LENGTH;
1675 }
1676
1677 struct pldm_apply_complete_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301678 (struct pldm_apply_complete_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301679
1680 *apply_result = request->apply_result;
1681 comp_activation_methods_modification->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301682 le16toh(request->comp_activation_methods_modification.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301683
1684 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1685 comp_activation_methods_modification->value) {
1686 return PLDM_ERROR_INVALID_DATA;
1687 }
1688
1689 return PLDM_SUCCESS;
1690}
1691
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301692LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301693int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1694 struct pldm_msg *msg, size_t payload_length)
1695{
1696 if (msg == NULL) {
1697 return PLDM_ERROR_INVALID_DATA;
1698 }
1699
1700 if (payload_length != sizeof(completion_code)) {
1701 return PLDM_ERROR_INVALID_LENGTH;
1702 }
1703
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301704 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301705 header.instance = instance_id;
1706 header.msg_type = PLDM_RESPONSE;
1707 header.pldm_type = PLDM_FWUP;
1708 header.command = PLDM_APPLY_COMPLETE;
1709 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1710 if (rc) {
1711 return rc;
1712 }
1713
1714 msg->payload[0] = completion_code;
1715
1716 return PLDM_SUCCESS;
1717}
1718
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301719LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301720int encode_activate_firmware_req(uint8_t instance_id,
1721 bool8_t self_contained_activation_req,
1722 struct pldm_msg *msg, size_t payload_length)
1723{
1724 if (msg == NULL) {
1725 return PLDM_ERROR_INVALID_DATA;
1726 }
1727
1728 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1729 return PLDM_ERROR_INVALID_LENGTH;
1730 }
1731
1732 if (!is_self_contained_activation_req_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301733 self_contained_activation_req)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301734 return PLDM_ERROR_INVALID_DATA;
1735 }
1736
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301737 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301738 header.instance = instance_id;
1739 header.msg_type = PLDM_REQUEST;
1740 header.pldm_type = PLDM_FWUP;
1741 header.command = PLDM_ACTIVATE_FIRMWARE;
1742 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1743 if (rc) {
1744 return rc;
1745 }
1746
1747 struct pldm_activate_firmware_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301748 (struct pldm_activate_firmware_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301749
1750 request->self_contained_activation_req = self_contained_activation_req;
1751
1752 return PLDM_SUCCESS;
1753}
1754
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301755LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301756int decode_activate_firmware_resp(const struct pldm_msg *msg,
1757 size_t payload_length,
1758 uint8_t *completion_code,
1759 uint16_t *estimated_time_activation)
1760{
1761 if (msg == NULL || completion_code == NULL ||
1762 estimated_time_activation == NULL || !payload_length) {
1763 return PLDM_ERROR_INVALID_DATA;
1764 }
1765
1766 *completion_code = msg->payload[0];
1767 if (*completion_code != PLDM_SUCCESS) {
1768 return PLDM_SUCCESS;
1769 }
1770
1771 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1772 return PLDM_ERROR_INVALID_LENGTH;
1773 }
1774
1775 struct pldm_activate_firmware_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301776 (struct pldm_activate_firmware_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301777
1778 *estimated_time_activation =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301779 le16toh(response->estimated_time_activation);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301780
1781 return PLDM_SUCCESS;
1782}
1783
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301784LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301785int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1786 size_t payload_length)
1787{
1788 if (msg == NULL) {
1789 return PLDM_ERROR_INVALID_DATA;
1790 }
1791
1792 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1793 return PLDM_ERROR_INVALID_LENGTH;
1794 }
1795
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301796 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301797 header.instance = instance_id;
1798 header.msg_type = PLDM_REQUEST;
1799 header.pldm_type = PLDM_FWUP;
1800 header.command = PLDM_GET_STATUS;
1801 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1802 if (rc) {
1803 return rc;
1804 }
1805
1806 return PLDM_SUCCESS;
1807}
1808
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301809LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301810int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1811 uint8_t *completion_code, uint8_t *current_state,
1812 uint8_t *previous_state, uint8_t *aux_state,
1813 uint8_t *aux_state_status, uint8_t *progress_percent,
1814 uint8_t *reason_code,
1815 bitfield32_t *update_option_flags_enabled)
1816{
1817 if (msg == NULL || completion_code == NULL || current_state == NULL ||
1818 previous_state == NULL || aux_state == NULL ||
1819 aux_state_status == NULL || progress_percent == NULL ||
1820 reason_code == NULL || update_option_flags_enabled == NULL ||
1821 !payload_length) {
1822 return PLDM_ERROR_INVALID_DATA;
1823 }
1824
1825 *completion_code = msg->payload[0];
1826 if (*completion_code != PLDM_SUCCESS) {
1827 return PLDM_SUCCESS;
1828 }
1829
1830 if (payload_length != sizeof(struct pldm_get_status_resp)) {
1831 return PLDM_ERROR_INVALID_LENGTH;
1832 }
1833 struct pldm_get_status_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301834 (struct pldm_get_status_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301835
1836 if (!is_state_valid(response->current_state)) {
1837 return PLDM_ERROR_INVALID_DATA;
1838 }
1839 if (!is_state_valid(response->previous_state)) {
1840 return PLDM_ERROR_INVALID_DATA;
1841 }
1842 if (!is_aux_state_valid(response->aux_state)) {
1843 return PLDM_ERROR_INVALID_DATA;
1844 }
1845 if (!is_aux_state_status_valid(response->aux_state_status)) {
1846 return PLDM_ERROR_INVALID_DATA;
1847 }
1848 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1849 return PLDM_ERROR_INVALID_DATA;
1850 }
1851 if (!is_reason_code_valid(response->reason_code)) {
1852 return PLDM_ERROR_INVALID_DATA;
1853 }
1854
1855 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1856 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1857 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1858 if (response->aux_state !=
1859 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1860 return PLDM_ERROR_INVALID_DATA;
1861 }
1862 }
1863
1864 *current_state = response->current_state;
1865 *previous_state = response->previous_state;
1866 *aux_state = response->aux_state;
1867 *aux_state_status = response->aux_state_status;
1868 *progress_percent = response->progress_percent;
1869 *reason_code = response->reason_code;
1870 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301871 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301872
1873 return PLDM_SUCCESS;
1874}
1875
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301876LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301877int encode_cancel_update_component_req(uint8_t instance_id,
1878 struct pldm_msg *msg,
1879 size_t payload_length)
1880{
1881 if (msg == NULL) {
1882 return PLDM_ERROR_INVALID_DATA;
1883 }
1884
1885 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1886 return PLDM_ERROR_INVALID_LENGTH;
1887 }
1888
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301889 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301890 header.instance = instance_id;
1891 header.msg_type = PLDM_REQUEST;
1892 header.pldm_type = PLDM_FWUP;
1893 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
1894 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1895 if (rc) {
1896 return rc;
1897 }
1898
1899 return PLDM_SUCCESS;
1900}
1901
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301902LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301903int decode_cancel_update_component_resp(const struct pldm_msg *msg,
1904 size_t payload_length,
1905 uint8_t *completion_code)
1906{
1907 if (msg == NULL || completion_code == NULL) {
1908 return PLDM_ERROR_INVALID_DATA;
1909 }
1910
1911 if (payload_length != sizeof(*completion_code)) {
1912 return PLDM_ERROR_INVALID_LENGTH;
1913 }
1914
1915 *completion_code = msg->payload[0];
1916 return PLDM_SUCCESS;
1917}
1918
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301919LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301920int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
1921 size_t payload_length)
1922{
1923 if (msg == NULL) {
1924 return PLDM_ERROR_INVALID_DATA;
1925 }
1926
1927 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
1928 return PLDM_ERROR_INVALID_LENGTH;
1929 }
1930
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301931 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301932 header.instance = instance_id;
1933 header.msg_type = PLDM_REQUEST;
1934 header.pldm_type = PLDM_FWUP;
1935 header.command = PLDM_CANCEL_UPDATE;
1936 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1937 if (rc) {
1938 return rc;
1939 }
1940
1941 return PLDM_SUCCESS;
1942}
1943
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301944LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301945int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
1946 uint8_t *completion_code,
1947 bool8_t *non_functioning_component_indication,
1948 bitfield64_t *non_functioning_component_bitmap)
1949{
1950 if (msg == NULL || completion_code == NULL ||
1951 non_functioning_component_indication == NULL ||
1952 non_functioning_component_bitmap == NULL || !payload_length) {
1953 return PLDM_ERROR_INVALID_DATA;
1954 }
1955
1956 *completion_code = msg->payload[0];
1957 if (*completion_code != PLDM_SUCCESS) {
1958 return PLDM_SUCCESS;
1959 }
1960
1961 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
1962 return PLDM_ERROR_INVALID_LENGTH;
1963 }
1964 struct pldm_cancel_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301965 (struct pldm_cancel_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301966
1967 if (!is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301968 response->non_functioning_component_indication)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301969 return PLDM_ERROR_INVALID_DATA;
1970 }
1971
1972 *non_functioning_component_indication =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301973 response->non_functioning_component_indication;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301974
1975 if (*non_functioning_component_indication) {
1976 non_functioning_component_bitmap->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301977 le64toh(response->non_functioning_component_bitmap);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301978 }
1979
1980 return PLDM_SUCCESS;
1981}