blob: ed1816d580e33e14690f1113bfb6ff79554edff6 [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Chris Wang4c1f2c72024-03-21 17:09:44 +08002#include "msgbuf.h"
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10303#include <libpldm/firmware_update.h>
4#include <libpldm/utils.h>
5
Andrew Jeffery9c766792022-08-10 23:12:49 +09306#include <endian.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05307#include <stdbool.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09308#include <string.h>
9
10/** @brief Check whether string type value is valid
11 *
12 * @return true if string type value is valid, false if not
13 */
14static bool is_string_type_valid(uint8_t string_type)
15{
16 switch (string_type) {
17 case PLDM_STR_TYPE_UNKNOWN:
18 return false;
19 case PLDM_STR_TYPE_ASCII:
20 case PLDM_STR_TYPE_UTF_8:
21 case PLDM_STR_TYPE_UTF_16:
22 case PLDM_STR_TYPE_UTF_16LE:
23 case PLDM_STR_TYPE_UTF_16BE:
24 return true;
25 default:
26 return false;
27 }
28}
29
30/** @brief Return the length of the descriptor type described in firmware update
31 * specification
32 *
33 * @return length of the descriptor type if descriptor type is valid else
34 * return 0
35 */
36static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
37{
38 switch (descriptor_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093039 case PLDM_FWUP_PCI_VENDOR_ID:
40 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
41 case PLDM_FWUP_IANA_ENTERPRISE_ID:
42 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
43 case PLDM_FWUP_UUID:
44 return PLDM_FWUP_UUID_LENGTH;
45 case PLDM_FWUP_PNP_VENDOR_ID:
46 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
47 case PLDM_FWUP_ACPI_VENDOR_ID:
48 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
49 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
50 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
51 case PLDM_FWUP_SCSI_VENDOR_ID:
52 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
53 case PLDM_FWUP_PCI_DEVICE_ID:
54 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
55 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
56 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
57 case PLDM_FWUP_PCI_SUBSYSTEM_ID:
58 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
59 case PLDM_FWUP_PCI_REVISION_ID:
60 return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
61 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
62 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
63 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
64 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
65 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
66 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
67 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
68 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
69 case PLDM_FWUP_SCSI_PRODUCT_ID:
70 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
71 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
72 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
73 default:
74 return 0;
75 }
76}
77
Chris Wang4c1f2c72024-03-21 17:09:44 +080078static bool is_downstream_device_update_support_valid(uint8_t resp)
79{
80 switch (resp) {
81 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
82 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
83 return true;
84 default:
85 return false;
86 }
87}
88
Andrew Jeffery9c766792022-08-10 23:12:49 +093089/** @brief Check whether ComponentResponse is valid
90 *
91 * @return true if ComponentResponse is valid, false if not
92 */
93static bool is_comp_resp_valid(uint8_t comp_resp)
94{
95 switch (comp_resp) {
96 case PLDM_CR_COMP_CAN_BE_UPDATED:
97 case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
98 return true;
99
100 default:
101 return false;
102 }
103}
104
105/** @brief Check whether ComponentResponseCode is valid
106 *
107 * @return true if ComponentResponseCode is valid, false if not
108 */
109static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
110{
111 switch (comp_resp_code) {
112 case PLDM_CRC_COMP_CAN_BE_UPDATED:
113 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
114 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
115 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
116 case PLDM_CRC_COMP_CONFLICT:
117 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
118 case PLDM_CRC_COMP_NOT_SUPPORTED:
119 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
120 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
121 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
122 case PLDM_CRC_COMP_VER_STR_IDENTICAL:
123 case PLDM_CRC_COMP_VER_STR_LOWER:
124 return true;
125
126 default:
127 if (comp_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930128 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930129 comp_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930130 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930131 return true;
132 }
133 return false;
134 }
135}
136
137/** @brief Check whether ComponentCompatibilityResponse is valid
138 *
139 * @return true if ComponentCompatibilityResponse is valid, false if not
140 */
141static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
142{
143 switch (comp_compatibility_resp) {
144 case PLDM_CCR_COMP_CAN_BE_UPDATED:
145 case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
146 return true;
147
148 default:
149 return false;
150 }
151}
152
153/** @brief Check whether ComponentCompatibilityResponse Code is valid
154 *
155 * @return true if ComponentCompatibilityResponse Code is valid, false if not
156 */
157static bool
158is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
159{
160 switch (comp_compatibility_resp_code) {
161 case PLDM_CCRC_NO_RESPONSE_CODE:
162 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
163 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
164 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
165 case PLDM_CCRC_COMP_CONFLICT:
166 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
167 case PLDM_CCRC_COMP_NOT_SUPPORTED:
168 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
169 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
170 case PLDM_CCRC_COMP_INFO_NO_MATCH:
171 case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
172 case PLDM_CCRC_COMP_VER_STR_LOWER:
173 return true;
174
175 default:
176 if (comp_compatibility_resp_code >=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930177 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
Andrew Jeffery9c766792022-08-10 23:12:49 +0930178 comp_compatibility_resp_code <=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930179 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930180 return true;
181 }
182 return false;
183 }
184}
185
186/** @brief Check whether SelfContainedActivationRequest is valid
187 *
188 * @return true if SelfContainedActivationRequest is valid, false if not
189 */
190static bool
191is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
192{
193 switch (self_contained_activation_req) {
194 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
195 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
196 return true;
197
198 default:
199 return false;
200 }
201}
202
203/** @brief Check if current or previous status in GetStatus command response is
204 * valid
205 *
206 * @param[in] state - current or previous different state machine state of
207 * the FD
208 * @return true if state is valid, false if not
209 */
210static bool is_state_valid(uint8_t state)
211{
212 switch (state) {
213 case PLDM_FD_STATE_IDLE:
214 case PLDM_FD_STATE_LEARN_COMPONENTS:
215 case PLDM_FD_STATE_READY_XFER:
216 case PLDM_FD_STATE_DOWNLOAD:
217 case PLDM_FD_STATE_VERIFY:
218 case PLDM_FD_STATE_APPLY:
219 case PLDM_FD_STATE_ACTIVATE:
220 return true;
221
222 default:
223 return false;
224 }
225}
226
227/** @brief Check if aux state in GetStatus command response is valid
228 *
229 * @param[in] aux_state - provides additional information to the UA to describe
230 * the current operation state of the FD/FDP
231 *
232 * @return true if aux state is valid, false if not
233 */
234static bool is_aux_state_valid(uint8_t aux_state)
235{
236 switch (aux_state) {
237 case PLDM_FD_OPERATION_IN_PROGRESS:
238 case PLDM_FD_OPERATION_SUCCESSFUL:
239 case PLDM_FD_OPERATION_FAILED:
240 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
241 return true;
242
243 default:
244 return false;
245 }
246}
247
248/** @brief Check if aux state status in GetStatus command response is valid
249 *
250 * @param[in] aux_state_status - aux state status
251 *
252 * @return true if aux state status is valid, false if not
253 */
254static bool is_aux_state_status_valid(uint8_t aux_state_status)
255{
256 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
257 aux_state_status == PLDM_FD_TIMEOUT ||
Andrew Jeffery67f7ed92023-04-05 14:00:00 +0930258 aux_state_status == PLDM_FD_GENERIC_ERROR ||
259 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
260 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930261 return true;
262 }
263
264 return false;
265}
266
267/** @brief Check if reason code in GetStatus command response is valid
268 *
269 * @param[in] reason_code - provides the reason for why the current state
270 * entered the IDLE state
271 *
272 * @return true if reason code is valid, false if not
273 */
274static bool is_reason_code_valid(uint8_t reason_code)
275{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930276 switch (reason_code) {
277 case PLDM_FD_INITIALIZATION:
278 case PLDM_FD_ACTIVATE_FW:
279 case PLDM_FD_CANCEL_UPDATE:
280 case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
281 case PLDM_FD_TIMEOUT_READY_XFER:
282 case PLDM_FD_TIMEOUT_DOWNLOAD:
283 case PLDM_FD_TIMEOUT_VERIFY:
284 case PLDM_FD_TIMEOUT_APPLY:
285 return true;
286
287 default:
288 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
289 return true;
290 }
291 return false;
292 }
293}
294
295/** @brief Check if non functioning component indication in CancelUpdate
296 * response is valid
297 *
298 * @return true if non functioning component indication is valid, false if not
299 */
300static bool is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930301 bool8_t non_functioning_component_indication)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930302{
303 switch (non_functioning_component_indication) {
304 case PLDM_FWUP_COMPONENTS_FUNCTIONING:
305 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
306 return true;
307
308 default:
309 return false;
310 }
311}
312
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930313LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930314int decode_pldm_package_header_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930315 const uint8_t *data, size_t length,
316 struct pldm_package_header_information *package_header_info,
317 struct variable_field *package_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930318{
319 if (data == NULL || package_header_info == NULL ||
320 package_version_str == NULL) {
321 return PLDM_ERROR_INVALID_DATA;
322 }
323
324 if (length < sizeof(struct pldm_package_header_information)) {
325 return PLDM_ERROR_INVALID_LENGTH;
326 }
327
328 struct pldm_package_header_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930329 (struct pldm_package_header_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930330
331 if (!is_string_type_valid(data_header->package_version_string_type) ||
332 (data_header->package_version_string_length == 0)) {
333 return PLDM_ERROR_INVALID_DATA;
334 }
335
336 if (length < sizeof(struct pldm_package_header_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930337 data_header->package_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930338 return PLDM_ERROR_INVALID_LENGTH;
339 }
340
341 if ((data_header->component_bitmap_bit_length %
342 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
343 return PLDM_ERROR_INVALID_DATA;
344 }
345
346 memcpy(package_header_info->uuid, data_header->uuid,
347 sizeof(data_header->uuid));
348 package_header_info->package_header_format_version =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930349 data_header->package_header_format_version;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930350 package_header_info->package_header_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930351 le16toh(data_header->package_header_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930352 memcpy(package_header_info->package_release_date_time,
353 data_header->package_release_date_time,
354 sizeof(data_header->package_release_date_time));
355 package_header_info->component_bitmap_bit_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930356 le16toh(data_header->component_bitmap_bit_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930357 package_header_info->package_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930358 data_header->package_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930359 package_header_info->package_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930360 data_header->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930361 package_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930362 data + sizeof(struct pldm_package_header_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930363 package_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930364 package_header_info->package_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930365
366 return PLDM_SUCCESS;
367}
368
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930369LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930370int decode_firmware_device_id_record(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930371 const uint8_t *data, size_t length,
372 uint16_t component_bitmap_bit_length,
373 struct pldm_firmware_device_id_record *fw_device_id_record,
374 struct variable_field *applicable_components,
375 struct variable_field *comp_image_set_version_str,
376 struct variable_field *record_descriptors,
377 struct variable_field *fw_device_pkg_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930378{
379 if (data == NULL || fw_device_id_record == NULL ||
380 applicable_components == NULL ||
381 comp_image_set_version_str == NULL || record_descriptors == NULL ||
382 fw_device_pkg_data == NULL) {
383 return PLDM_ERROR_INVALID_DATA;
384 }
385
386 if (length < sizeof(struct pldm_firmware_device_id_record)) {
387 return PLDM_ERROR_INVALID_LENGTH;
388 }
389
390 if ((component_bitmap_bit_length %
391 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
392 return PLDM_ERROR_INVALID_DATA;
393 }
394
395 struct pldm_firmware_device_id_record *data_record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930396 (struct pldm_firmware_device_id_record *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930397
398 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930399 data_record->comp_image_set_version_string_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930400 (data_record->comp_image_set_version_string_length == 0)) {
401 return PLDM_ERROR_INVALID_DATA;
402 }
403
404 fw_device_id_record->record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930405 le16toh(data_record->record_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930406 fw_device_id_record->descriptor_count = data_record->descriptor_count;
407 fw_device_id_record->device_update_option_flags.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930408 le32toh(data_record->device_update_option_flags.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930409 fw_device_id_record->comp_image_set_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930410 data_record->comp_image_set_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930411 fw_device_id_record->comp_image_set_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930412 data_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930413 fw_device_id_record->fw_device_pkg_data_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930414 le16toh(data_record->fw_device_pkg_data_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930415
416 if (length < fw_device_id_record->record_length) {
417 return PLDM_ERROR_INVALID_LENGTH;
418 }
419
420 uint16_t applicable_components_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930421 component_bitmap_bit_length /
422 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930423 uint16_t calc_min_record_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930424 sizeof(struct pldm_firmware_device_id_record) +
425 applicable_components_length +
426 data_record->comp_image_set_version_string_length +
427 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
428 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930429
430 if (fw_device_id_record->record_length < calc_min_record_length) {
431 return PLDM_ERROR_INVALID_LENGTH;
432 }
433
434 applicable_components->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930435 data + sizeof(struct pldm_firmware_device_id_record);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930436 applicable_components->length = applicable_components_length;
437
438 comp_image_set_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930439 applicable_components->ptr + applicable_components->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930440 comp_image_set_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930441 fw_device_id_record->comp_image_set_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930442
443 record_descriptors->ptr = comp_image_set_version_str->ptr +
444 comp_image_set_version_str->length;
445 record_descriptors->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930446 fw_device_id_record->record_length -
447 sizeof(struct pldm_firmware_device_id_record) -
448 applicable_components_length -
449 fw_device_id_record->comp_image_set_version_string_length -
450 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930451
452 if (fw_device_id_record->fw_device_pkg_data_length) {
453 fw_device_pkg_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930454 record_descriptors->ptr + record_descriptors->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930455 fw_device_pkg_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930456 fw_device_id_record->fw_device_pkg_data_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930457 }
458
459 return PLDM_SUCCESS;
460}
461
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930462LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930463int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
464 uint16_t *descriptor_type,
465 struct variable_field *descriptor_data)
466{
467 uint16_t descriptor_length = 0;
468
469 if (data == NULL || descriptor_type == NULL ||
470 descriptor_data == NULL) {
471 return PLDM_ERROR_INVALID_DATA;
472 }
473
474 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
475 return PLDM_ERROR_INVALID_LENGTH;
476 }
477
478 struct pldm_descriptor_tlv *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930479 (struct pldm_descriptor_tlv *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930480
481 *descriptor_type = le16toh(entry->descriptor_type);
482 descriptor_length = le16toh(entry->descriptor_length);
483 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
484 if (descriptor_length !=
485 get_descriptor_type_length(*descriptor_type)) {
486 return PLDM_ERROR_INVALID_LENGTH;
487 }
488 }
489
490 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
491 descriptor_length)) {
492 return PLDM_ERROR_INVALID_LENGTH;
493 }
494
495 descriptor_data->ptr = entry->descriptor_data;
496 descriptor_data->length = descriptor_length;
497
498 return PLDM_SUCCESS;
499}
500
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930501LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930502int decode_vendor_defined_descriptor_value(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930503 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
504 struct variable_field *descriptor_title_str,
505 struct variable_field *descriptor_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930506{
507 if (data == NULL || descriptor_title_str_type == NULL ||
508 descriptor_title_str == NULL || descriptor_data == NULL) {
509 return PLDM_ERROR_INVALID_DATA;
510 }
511
512 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
513 return PLDM_ERROR_INVALID_LENGTH;
514 }
515
516 struct pldm_vendor_defined_descriptor_title_data *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930517 (struct pldm_vendor_defined_descriptor_title_data *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930518 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930519 entry->vendor_defined_descriptor_title_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930520 (entry->vendor_defined_descriptor_title_str_len == 0)) {
521 return PLDM_ERROR_INVALID_DATA;
522 }
523
524 // Assuming atleast 1 byte of VendorDefinedDescriptorData
525 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
526 entry->vendor_defined_descriptor_title_str_len)) {
527 return PLDM_ERROR_INVALID_LENGTH;
528 }
529
530 *descriptor_title_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930531 entry->vendor_defined_descriptor_title_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930532 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
533 descriptor_title_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930534 entry->vendor_defined_descriptor_title_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930535
536 descriptor_data->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930537 descriptor_title_str->ptr + descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930538 descriptor_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930539 length -
540 sizeof(entry->vendor_defined_descriptor_title_str_type) -
541 sizeof(entry->vendor_defined_descriptor_title_str_len) -
542 descriptor_title_str->length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930543
544 return PLDM_SUCCESS;
545}
546
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930547LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930548int decode_pldm_comp_image_info(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930549 const uint8_t *data, size_t length,
550 struct pldm_component_image_information *pldm_comp_image_info,
551 struct variable_field *comp_version_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930552{
553 if (data == NULL || pldm_comp_image_info == NULL ||
554 comp_version_str == NULL) {
555 return PLDM_ERROR_INVALID_DATA;
556 }
557
558 if (length < sizeof(struct pldm_component_image_information)) {
559 return PLDM_ERROR_INVALID_LENGTH;
560 }
561
562 struct pldm_component_image_information *data_header =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930563 (struct pldm_component_image_information *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930564
565 if (!is_string_type_valid(data_header->comp_version_string_type) ||
566 (data_header->comp_version_string_length == 0)) {
567 return PLDM_ERROR_INVALID_DATA;
568 }
569
570 if (length < sizeof(struct pldm_component_image_information) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930571 data_header->comp_version_string_length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930572 return PLDM_ERROR_INVALID_LENGTH;
573 }
574
575 pldm_comp_image_info->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930576 le16toh(data_header->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930577 pldm_comp_image_info->comp_identifier =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930578 le16toh(data_header->comp_identifier);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930579 pldm_comp_image_info->comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930580 le32toh(data_header->comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930581 pldm_comp_image_info->comp_options.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930582 le16toh(data_header->comp_options.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930583 pldm_comp_image_info->requested_comp_activation_method.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930584 le16toh(data_header->requested_comp_activation_method.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930585 pldm_comp_image_info->comp_location_offset =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930586 le32toh(data_header->comp_location_offset);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930587 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
588 pldm_comp_image_info->comp_version_string_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930589 data_header->comp_version_string_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930590 pldm_comp_image_info->comp_version_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930591 data_header->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930592
593 if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
594 pldm_comp_image_info->comp_comparison_stamp !=
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930595 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930596 return PLDM_ERROR_INVALID_DATA;
597 }
598
599 if (pldm_comp_image_info->comp_location_offset == 0 ||
600 pldm_comp_image_info->comp_size == 0) {
601 return PLDM_ERROR_INVALID_DATA;
602 }
603
604 comp_version_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930605 data + sizeof(struct pldm_component_image_information);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930606 comp_version_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930607 pldm_comp_image_info->comp_version_string_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930608
609 return PLDM_SUCCESS;
610}
611
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930612LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930613int encode_query_device_identifiers_req(uint8_t instance_id,
614 size_t payload_length,
615 struct pldm_msg *msg)
616{
617 if (msg == NULL) {
618 return PLDM_ERROR_INVALID_DATA;
619 }
620
621 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
622 return PLDM_ERROR_INVALID_LENGTH;
623 }
624
625 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
626 PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
627}
628
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930629LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930630int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
631 size_t payload_length,
632 uint8_t *completion_code,
633 uint32_t *device_identifiers_len,
634 uint8_t *descriptor_count,
635 uint8_t **descriptor_data)
636{
637 if (msg == NULL || completion_code == NULL ||
638 device_identifiers_len == NULL || descriptor_count == NULL ||
639 descriptor_data == NULL) {
640 return PLDM_ERROR_INVALID_DATA;
641 }
642
643 *completion_code = msg->payload[0];
644 if (PLDM_SUCCESS != *completion_code) {
645 return PLDM_SUCCESS;
646 }
647
648 if (payload_length <
649 sizeof(struct pldm_query_device_identifiers_resp)) {
650 return PLDM_ERROR_INVALID_LENGTH;
651 }
652
653 struct pldm_query_device_identifiers_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930654 (struct pldm_query_device_identifiers_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930655 *device_identifiers_len = le32toh(response->device_identifiers_len);
656
657 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
658 return PLDM_ERROR_INVALID_LENGTH;
659 }
660
661 if (payload_length !=
662 sizeof(struct pldm_query_device_identifiers_resp) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930663 *device_identifiers_len) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930664 return PLDM_ERROR_INVALID_LENGTH;
665 }
666 *descriptor_count = response->descriptor_count;
667
668 if (*descriptor_count == 0) {
669 return PLDM_ERROR_INVALID_DATA;
670 }
671 *descriptor_data =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930672 (uint8_t *)(msg->payload +
673 sizeof(struct pldm_query_device_identifiers_resp));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930674 return PLDM_SUCCESS;
675}
676
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930677LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930678int encode_get_firmware_parameters_req(uint8_t instance_id,
679 size_t payload_length,
680 struct pldm_msg *msg)
681{
682 if (msg == NULL) {
683 return PLDM_ERROR_INVALID_DATA;
684 }
685
686 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
687 return PLDM_ERROR_INVALID_LENGTH;
688 }
689
690 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
691 PLDM_GET_FIRMWARE_PARAMETERS, msg);
692}
693
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930694LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930695int decode_get_firmware_parameters_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930696 const struct pldm_msg *msg, size_t payload_length,
697 struct pldm_get_firmware_parameters_resp *resp_data,
698 struct variable_field *active_comp_image_set_ver_str,
699 struct variable_field *pending_comp_image_set_ver_str,
700 struct variable_field *comp_parameter_table)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930701{
702 if (msg == NULL || resp_data == NULL ||
703 active_comp_image_set_ver_str == NULL ||
704 pending_comp_image_set_ver_str == NULL ||
705 comp_parameter_table == NULL || !payload_length) {
706 return PLDM_ERROR_INVALID_DATA;
707 }
708
709 resp_data->completion_code = msg->payload[0];
710 if (PLDM_SUCCESS != resp_data->completion_code) {
711 return PLDM_SUCCESS;
712 }
713
714 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
715 return PLDM_ERROR_INVALID_LENGTH;
716 }
717
718 struct pldm_get_firmware_parameters_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930719 (struct pldm_get_firmware_parameters_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930720
721 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930722 response->active_comp_image_set_ver_str_type) ||
Andrew Jeffery9c766792022-08-10 23:12:49 +0930723 (response->active_comp_image_set_ver_str_len == 0)) {
724 return PLDM_ERROR_INVALID_DATA;
725 }
726
727 if (response->pending_comp_image_set_ver_str_len == 0) {
728 if (response->pending_comp_image_set_ver_str_type !=
729 PLDM_STR_TYPE_UNKNOWN) {
730 return PLDM_ERROR_INVALID_DATA;
731 }
732 } else {
733 if (!is_string_type_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930734 response->pending_comp_image_set_ver_str_type)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930735 return PLDM_ERROR_INVALID_DATA;
736 }
737 }
738
739 size_t partial_response_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930740 sizeof(struct pldm_get_firmware_parameters_resp) +
741 response->active_comp_image_set_ver_str_len +
742 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930743
744 if (payload_length < partial_response_length) {
745 return PLDM_ERROR_INVALID_LENGTH;
746 }
747
748 resp_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930749 le32toh(response->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930750 resp_data->comp_count = le16toh(response->comp_count);
751 resp_data->active_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930752 response->active_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930753 resp_data->active_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930754 response->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930755 resp_data->pending_comp_image_set_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930756 response->pending_comp_image_set_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930757 resp_data->pending_comp_image_set_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930758 response->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930759
760 active_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930761 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930762 active_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930763 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930764
765 if (resp_data->pending_comp_image_set_ver_str_len != 0) {
766 pending_comp_image_set_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930767 msg->payload +
768 sizeof(struct pldm_get_firmware_parameters_resp) +
769 resp_data->active_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930770 pending_comp_image_set_ver_str->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930771 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930772 } else {
773 pending_comp_image_set_ver_str->ptr = NULL;
774 pending_comp_image_set_ver_str->length = 0;
775 }
776
777 if (payload_length > partial_response_length && resp_data->comp_count) {
778 comp_parameter_table->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930779 msg->payload +
780 sizeof(struct pldm_get_firmware_parameters_resp) +
781 resp_data->active_comp_image_set_ver_str_len +
782 resp_data->pending_comp_image_set_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930783 comp_parameter_table->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930784 payload_length - partial_response_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930785 } else {
786 comp_parameter_table->ptr = NULL;
787 comp_parameter_table->length = 0;
788 }
789
790 return PLDM_SUCCESS;
791}
792
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930793LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930794int decode_get_firmware_parameters_resp_comp_entry(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930795 const uint8_t *data, size_t length,
796 struct pldm_component_parameter_entry *component_data,
797 struct variable_field *active_comp_ver_str,
798 struct variable_field *pending_comp_ver_str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930799{
800 if (data == NULL || component_data == NULL ||
801 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
802 return PLDM_ERROR_INVALID_DATA;
803 }
804
805 if (length < sizeof(struct pldm_component_parameter_entry)) {
806 return PLDM_ERROR_INVALID_LENGTH;
807 }
808
809 struct pldm_component_parameter_entry *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930810 (struct pldm_component_parameter_entry *)(data);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930811
812 size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
813 entry->active_comp_ver_str_len +
814 entry->pending_comp_ver_str_len;
815
816 if (length < entry_length) {
817 return PLDM_ERROR_INVALID_LENGTH;
818 }
819
820 component_data->comp_classification =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930821 le16toh(entry->comp_classification);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930822 component_data->comp_identifier = le16toh(entry->comp_identifier);
823 component_data->comp_classification_index =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930824 entry->comp_classification_index;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930825 component_data->active_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930826 le32toh(entry->active_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930827 component_data->active_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930828 entry->active_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930829 component_data->active_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930830 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930831 memcpy(component_data->active_comp_release_date,
832 entry->active_comp_release_date,
833 sizeof(entry->active_comp_release_date));
834 component_data->pending_comp_comparison_stamp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930835 le32toh(entry->pending_comp_comparison_stamp);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930836 component_data->pending_comp_ver_str_type =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930837 entry->pending_comp_ver_str_type;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930838 component_data->pending_comp_ver_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930839 entry->pending_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930840 memcpy(component_data->pending_comp_release_date,
841 entry->pending_comp_release_date,
842 sizeof(entry->pending_comp_release_date));
843 component_data->comp_activation_methods.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930844 le16toh(entry->comp_activation_methods.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930845 component_data->capabilities_during_update.value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930846 le32toh(entry->capabilities_during_update.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930847
848 if (entry->active_comp_ver_str_len != 0) {
849 active_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930850 data + sizeof(struct pldm_component_parameter_entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930851 active_comp_ver_str->length = entry->active_comp_ver_str_len;
852 } else {
853 active_comp_ver_str->ptr = NULL;
854 active_comp_ver_str->length = 0;
855 }
856
857 if (entry->pending_comp_ver_str_len != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930858 pending_comp_ver_str->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930859 data + sizeof(struct pldm_component_parameter_entry) +
860 entry->active_comp_ver_str_len;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930861 pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
862 } else {
863 pending_comp_ver_str->ptr = NULL;
864 pending_comp_ver_str->length = 0;
865 }
866 return PLDM_SUCCESS;
867}
868
Chris Wang4c1f2c72024-03-21 17:09:44 +0800869LIBPLDM_ABI_TESTING
870int encode_query_downstream_devices_req(uint8_t instance_id,
871 struct pldm_msg *msg)
872{
873 if (msg == NULL) {
874 return PLDM_ERROR_INVALID_DATA;
875 }
876
877 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
878 PLDM_QUERY_DOWNSTREAM_DEVICES, msg);
879}
880
881LIBPLDM_ABI_TESTING
882int decode_query_downstream_devices_resp(
883 const struct pldm_msg *msg, size_t payload_length,
884 struct pldm_query_downstream_devices_resp *resp_data)
885{
886 struct pldm_msgbuf _buf;
887 struct pldm_msgbuf *buf = &_buf;
888 int rc;
889
890 if (msg == NULL || resp_data == NULL || !payload_length) {
891 return PLDM_ERROR_INVALID_DATA;
892 }
893
894 rc = pldm_msgbuf_init(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
895 msg->payload, payload_length);
896 if (rc) {
897 return rc;
898 }
899
900 rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
901 if (rc) {
902 return rc;
903 }
904 if (PLDM_SUCCESS != resp_data->completion_code) {
905 // Return the CC directly without decoding the rest of the payload
906 return PLDM_SUCCESS;
907 }
908
909 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
910 return PLDM_ERROR_INVALID_LENGTH;
911 }
912
913 rc = pldm_msgbuf_extract(buf,
914 resp_data->downstream_device_update_supported);
915 if (rc) {
916 return rc;
917 }
918
919 if (!is_downstream_device_update_support_valid(
920 resp_data->downstream_device_update_supported)) {
921 return PLDM_ERROR_INVALID_DATA;
922 }
923
924 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
925 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
926 pldm_msgbuf_extract(buf, resp_data->capabilities.value);
927
928 return pldm_msgbuf_destroy_consumed(buf);
929}
930
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930931LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930932int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
933 uint16_t num_of_comp,
934 uint8_t max_outstanding_transfer_req,
935 uint16_t pkg_data_len,
936 uint8_t comp_image_set_ver_str_type,
937 uint8_t comp_image_set_ver_str_len,
938 const struct variable_field *comp_img_set_ver_str,
939 struct pldm_msg *msg, size_t payload_length)
940{
941 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
942 msg == NULL) {
943 return PLDM_ERROR_INVALID_DATA;
944 }
945
946 if (payload_length != sizeof(struct pldm_request_update_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930947 comp_img_set_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930948 return PLDM_ERROR_INVALID_LENGTH;
949 }
950
951 if ((comp_image_set_ver_str_len == 0) ||
952 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
953 return PLDM_ERROR_INVALID_DATA;
954 }
955
956 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
957 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
958 return PLDM_ERROR_INVALID_DATA;
959 }
960
961 if (!is_string_type_valid(comp_image_set_ver_str_type)) {
962 return PLDM_ERROR_INVALID_DATA;
963 }
964
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930965 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930966 header.instance = instance_id;
967 header.msg_type = PLDM_REQUEST;
968 header.pldm_type = PLDM_FWUP;
969 header.command = PLDM_REQUEST_UPDATE;
970 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
971 if (rc) {
972 return rc;
973 }
974
975 struct pldm_request_update_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930976 (struct pldm_request_update_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930977
978 request->max_transfer_size = htole32(max_transfer_size);
979 request->num_of_comp = htole16(num_of_comp);
980 request->max_outstanding_transfer_req = max_outstanding_transfer_req;
981 request->pkg_data_len = htole16(pkg_data_len);
982 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
983 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
984
985 memcpy(msg->payload + sizeof(struct pldm_request_update_req),
986 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
987
988 return PLDM_SUCCESS;
989}
990
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930991LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930992int decode_request_update_resp(const struct pldm_msg *msg,
993 size_t payload_length, uint8_t *completion_code,
994 uint16_t *fd_meta_data_len,
995 uint8_t *fd_will_send_pkg_data)
996{
997 if (msg == NULL || completion_code == NULL ||
998 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
999 !payload_length) {
1000 return PLDM_ERROR_INVALID_DATA;
1001 }
1002
1003 *completion_code = msg->payload[0];
1004 if (*completion_code != PLDM_SUCCESS) {
1005 return PLDM_SUCCESS;
1006 }
1007
1008 if (payload_length != sizeof(struct pldm_request_update_resp)) {
1009 return PLDM_ERROR_INVALID_LENGTH;
1010 }
1011
1012 struct pldm_request_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301013 (struct pldm_request_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301014
1015 *fd_meta_data_len = le16toh(response->fd_meta_data_len);
1016 *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1017
1018 return PLDM_SUCCESS;
1019}
1020
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301021LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301022int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1023 uint16_t comp_classification,
1024 uint16_t comp_identifier,
1025 uint8_t comp_classification_index,
1026 uint32_t comp_comparison_stamp,
1027 uint8_t comp_ver_str_type,
1028 uint8_t comp_ver_str_len,
1029 const struct variable_field *comp_ver_str,
1030 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301031{
1032 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1033 return PLDM_ERROR_INVALID_DATA;
1034 }
1035
1036 if (payload_length != sizeof(struct pldm_pass_component_table_req) +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301037 comp_ver_str->length) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301038 return PLDM_ERROR_INVALID_LENGTH;
1039 }
1040
1041 if ((comp_ver_str_len == 0) ||
1042 (comp_ver_str_len != comp_ver_str->length)) {
1043 return PLDM_ERROR_INVALID_DATA;
1044 }
1045
1046 if (!is_transfer_flag_valid(transfer_flag)) {
1047 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1048 }
1049
1050 if (!is_string_type_valid(comp_ver_str_type)) {
1051 return PLDM_ERROR_INVALID_DATA;
1052 }
1053
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301054 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301055 header.instance = instance_id;
1056 header.msg_type = PLDM_REQUEST;
1057 header.pldm_type = PLDM_FWUP;
1058 header.command = PLDM_PASS_COMPONENT_TABLE;
1059 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1060 if (rc) {
1061 return rc;
1062 }
1063
1064 struct pldm_pass_component_table_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301065 (struct pldm_pass_component_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301066
1067 request->transfer_flag = transfer_flag;
1068 request->comp_classification = htole16(comp_classification);
1069 request->comp_identifier = htole16(comp_identifier);
1070 request->comp_classification_index = comp_classification_index;
1071 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1072 request->comp_ver_str_type = comp_ver_str_type;
1073 request->comp_ver_str_len = comp_ver_str_len;
1074
1075 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1076 comp_ver_str->ptr, comp_ver_str->length);
1077
1078 return PLDM_SUCCESS;
1079}
1080
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301081LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301082int decode_pass_component_table_resp(const struct pldm_msg *msg,
1083 const size_t payload_length,
1084 uint8_t *completion_code,
1085 uint8_t *comp_resp,
1086 uint8_t *comp_resp_code)
1087{
1088 if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1089 comp_resp_code == NULL || !payload_length) {
1090 return PLDM_ERROR_INVALID_DATA;
1091 }
1092
1093 *completion_code = msg->payload[0];
1094 if (*completion_code != PLDM_SUCCESS) {
1095 return PLDM_SUCCESS;
1096 }
1097
1098 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1099 return PLDM_ERROR_INVALID_LENGTH;
1100 }
1101
1102 struct pldm_pass_component_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301103 (struct pldm_pass_component_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301104
1105 if (!is_comp_resp_valid(response->comp_resp)) {
1106 return PLDM_ERROR_INVALID_DATA;
1107 }
1108
1109 if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1110 return PLDM_ERROR_INVALID_DATA;
1111 }
1112
1113 *comp_resp = response->comp_resp;
1114 *comp_resp_code = response->comp_resp_code;
1115
1116 return PLDM_SUCCESS;
1117}
1118
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301119LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301120int encode_update_component_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301121 uint8_t instance_id, uint16_t comp_classification,
1122 uint16_t comp_identifier, uint8_t comp_classification_index,
1123 uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1124 bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1125 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1126 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301127{
1128 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1129 return PLDM_ERROR_INVALID_DATA;
1130 }
1131
1132 if (payload_length !=
1133 sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1134 return PLDM_ERROR_INVALID_LENGTH;
1135 }
1136
1137 if (!comp_image_size) {
1138 return PLDM_ERROR_INVALID_DATA;
1139 }
1140
1141 if ((comp_ver_str_len == 0) ||
1142 (comp_ver_str_len != comp_ver_str->length)) {
1143 return PLDM_ERROR_INVALID_DATA;
1144 }
1145
1146 if (!is_string_type_valid(comp_ver_str_type)) {
1147 return PLDM_ERROR_INVALID_DATA;
1148 }
1149
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301150 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301151 header.instance = instance_id;
1152 header.msg_type = PLDM_REQUEST;
1153 header.pldm_type = PLDM_FWUP;
1154 header.command = PLDM_UPDATE_COMPONENT;
1155 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1156 if (rc) {
1157 return rc;
1158 }
1159
1160 struct pldm_update_component_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301161 (struct pldm_update_component_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301162
1163 request->comp_classification = htole16(comp_classification);
1164 request->comp_identifier = htole16(comp_identifier);
1165 request->comp_classification_index = comp_classification_index;
1166 request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1167 request->comp_image_size = htole32(comp_image_size);
1168 request->update_option_flags.value = htole32(update_option_flags.value);
1169 request->comp_ver_str_type = comp_ver_str_type;
1170 request->comp_ver_str_len = comp_ver_str_len;
1171
1172 memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1173 comp_ver_str->ptr, comp_ver_str->length);
1174
1175 return PLDM_SUCCESS;
1176}
1177
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301178LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301179int decode_update_component_resp(const struct pldm_msg *msg,
1180 size_t payload_length,
1181 uint8_t *completion_code,
1182 uint8_t *comp_compatibility_resp,
1183 uint8_t *comp_compatibility_resp_code,
1184 bitfield32_t *update_option_flags_enabled,
1185 uint16_t *time_before_req_fw_data)
1186{
1187 if (msg == NULL || completion_code == NULL ||
1188 comp_compatibility_resp == NULL ||
1189 comp_compatibility_resp_code == NULL ||
1190 update_option_flags_enabled == NULL ||
1191 time_before_req_fw_data == NULL || !payload_length) {
1192 return PLDM_ERROR_INVALID_DATA;
1193 }
1194
1195 *completion_code = msg->payload[0];
1196 if (*completion_code != PLDM_SUCCESS) {
1197 return PLDM_SUCCESS;
1198 }
1199
1200 if (payload_length != sizeof(struct pldm_update_component_resp)) {
1201 return PLDM_ERROR_INVALID_LENGTH;
1202 }
1203
1204 struct pldm_update_component_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301205 (struct pldm_update_component_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301206
1207 if (!is_comp_compatibility_resp_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301208 response->comp_compatibility_resp)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301209 return PLDM_ERROR_INVALID_DATA;
1210 }
1211
1212 if (!is_comp_compatibility_resp_code_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301213 response->comp_compatibility_resp_code)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301214 return PLDM_ERROR_INVALID_DATA;
1215 }
1216
1217 *comp_compatibility_resp = response->comp_compatibility_resp;
1218 *comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1219 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301220 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301221 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1222
1223 return PLDM_SUCCESS;
1224}
1225
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301226LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301227int decode_request_firmware_data_req(const struct pldm_msg *msg,
1228 size_t payload_length, uint32_t *offset,
1229 uint32_t *length)
1230{
1231 if (msg == NULL || offset == NULL || length == NULL) {
1232 return PLDM_ERROR_INVALID_DATA;
1233 }
1234 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1235 return PLDM_ERROR_INVALID_LENGTH;
1236 }
1237 struct pldm_request_firmware_data_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301238 (struct pldm_request_firmware_data_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301239 *offset = le32toh(request->offset);
1240 *length = le32toh(request->length);
1241
1242 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1243 return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1244 }
1245
1246 return PLDM_SUCCESS;
1247}
1248
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301249LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301250int encode_request_firmware_data_resp(uint8_t instance_id,
1251 uint8_t completion_code,
1252 struct pldm_msg *msg,
1253 size_t payload_length)
1254{
1255 if (msg == NULL || !payload_length) {
1256 return PLDM_ERROR_INVALID_DATA;
1257 }
1258
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301259 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301260 header.instance = instance_id;
1261 header.msg_type = PLDM_RESPONSE;
1262 header.pldm_type = PLDM_FWUP;
1263 header.command = PLDM_REQUEST_FIRMWARE_DATA;
1264 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1265 if (rc) {
1266 return rc;
1267 }
1268
1269 msg->payload[0] = completion_code;
1270
1271 return PLDM_SUCCESS;
1272}
1273
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301274LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301275int decode_transfer_complete_req(const struct pldm_msg *msg,
1276 size_t payload_length,
1277 uint8_t *transfer_result)
1278{
1279 if (msg == NULL || transfer_result == NULL) {
1280 return PLDM_ERROR_INVALID_DATA;
1281 }
1282
1283 if (payload_length != sizeof(*transfer_result)) {
1284 return PLDM_ERROR_INVALID_LENGTH;
1285 }
1286
1287 *transfer_result = msg->payload[0];
1288 return PLDM_SUCCESS;
1289}
1290
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301291LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301292int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1293 struct pldm_msg *msg, size_t payload_length)
1294{
1295 if (msg == NULL) {
1296 return PLDM_ERROR_INVALID_DATA;
1297 }
1298
1299 if (payload_length != sizeof(completion_code)) {
1300 return PLDM_ERROR_INVALID_LENGTH;
1301 }
1302
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301303 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301304 header.instance = instance_id;
1305 header.msg_type = PLDM_RESPONSE;
1306 header.pldm_type = PLDM_FWUP;
1307 header.command = PLDM_TRANSFER_COMPLETE;
1308 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1309 if (rc) {
1310 return rc;
1311 }
1312
1313 msg->payload[0] = completion_code;
1314
1315 return PLDM_SUCCESS;
1316}
1317
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301318LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301319int decode_verify_complete_req(const struct pldm_msg *msg,
1320 size_t payload_length, uint8_t *verify_result)
1321{
1322 if (msg == NULL || verify_result == NULL) {
1323 return PLDM_ERROR_INVALID_DATA;
1324 }
1325
1326 if (payload_length != sizeof(*verify_result)) {
1327 return PLDM_ERROR_INVALID_LENGTH;
1328 }
1329
1330 *verify_result = msg->payload[0];
1331 return PLDM_SUCCESS;
1332}
1333
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301334LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301335int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1336 struct pldm_msg *msg, size_t payload_length)
1337{
1338 if (msg == NULL) {
1339 return PLDM_ERROR_INVALID_DATA;
1340 }
1341
1342 if (payload_length != sizeof(completion_code)) {
1343 return PLDM_ERROR_INVALID_LENGTH;
1344 }
1345
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301346 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301347 header.instance = instance_id;
1348 header.msg_type = PLDM_RESPONSE;
1349 header.pldm_type = PLDM_FWUP;
1350 header.command = PLDM_VERIFY_COMPLETE;
1351 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1352 if (rc) {
1353 return rc;
1354 }
1355
1356 msg->payload[0] = completion_code;
1357
1358 return PLDM_SUCCESS;
1359}
1360
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301361LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301362int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
1363 uint8_t *apply_result,
1364 bitfield16_t *comp_activation_methods_modification)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301365{
1366 if (msg == NULL || apply_result == NULL ||
1367 comp_activation_methods_modification == NULL) {
1368 return PLDM_ERROR_INVALID_DATA;
1369 }
1370
1371 if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1372 return PLDM_ERROR_INVALID_LENGTH;
1373 }
1374
1375 struct pldm_apply_complete_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301376 (struct pldm_apply_complete_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301377
1378 *apply_result = request->apply_result;
1379 comp_activation_methods_modification->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301380 le16toh(request->comp_activation_methods_modification.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301381
1382 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1383 comp_activation_methods_modification->value) {
1384 return PLDM_ERROR_INVALID_DATA;
1385 }
1386
1387 return PLDM_SUCCESS;
1388}
1389
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301390LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301391int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1392 struct pldm_msg *msg, size_t payload_length)
1393{
1394 if (msg == NULL) {
1395 return PLDM_ERROR_INVALID_DATA;
1396 }
1397
1398 if (payload_length != sizeof(completion_code)) {
1399 return PLDM_ERROR_INVALID_LENGTH;
1400 }
1401
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301402 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301403 header.instance = instance_id;
1404 header.msg_type = PLDM_RESPONSE;
1405 header.pldm_type = PLDM_FWUP;
1406 header.command = PLDM_APPLY_COMPLETE;
1407 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1408 if (rc) {
1409 return rc;
1410 }
1411
1412 msg->payload[0] = completion_code;
1413
1414 return PLDM_SUCCESS;
1415}
1416
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301417LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301418int encode_activate_firmware_req(uint8_t instance_id,
1419 bool8_t self_contained_activation_req,
1420 struct pldm_msg *msg, size_t payload_length)
1421{
1422 if (msg == NULL) {
1423 return PLDM_ERROR_INVALID_DATA;
1424 }
1425
1426 if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1427 return PLDM_ERROR_INVALID_LENGTH;
1428 }
1429
1430 if (!is_self_contained_activation_req_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301431 self_contained_activation_req)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301432 return PLDM_ERROR_INVALID_DATA;
1433 }
1434
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301435 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301436 header.instance = instance_id;
1437 header.msg_type = PLDM_REQUEST;
1438 header.pldm_type = PLDM_FWUP;
1439 header.command = PLDM_ACTIVATE_FIRMWARE;
1440 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1441 if (rc) {
1442 return rc;
1443 }
1444
1445 struct pldm_activate_firmware_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301446 (struct pldm_activate_firmware_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301447
1448 request->self_contained_activation_req = self_contained_activation_req;
1449
1450 return PLDM_SUCCESS;
1451}
1452
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301453LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301454int decode_activate_firmware_resp(const struct pldm_msg *msg,
1455 size_t payload_length,
1456 uint8_t *completion_code,
1457 uint16_t *estimated_time_activation)
1458{
1459 if (msg == NULL || completion_code == NULL ||
1460 estimated_time_activation == NULL || !payload_length) {
1461 return PLDM_ERROR_INVALID_DATA;
1462 }
1463
1464 *completion_code = msg->payload[0];
1465 if (*completion_code != PLDM_SUCCESS) {
1466 return PLDM_SUCCESS;
1467 }
1468
1469 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1470 return PLDM_ERROR_INVALID_LENGTH;
1471 }
1472
1473 struct pldm_activate_firmware_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301474 (struct pldm_activate_firmware_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301475
1476 *estimated_time_activation =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301477 le16toh(response->estimated_time_activation);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301478
1479 return PLDM_SUCCESS;
1480}
1481
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301482LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301483int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1484 size_t payload_length)
1485{
1486 if (msg == NULL) {
1487 return PLDM_ERROR_INVALID_DATA;
1488 }
1489
1490 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1491 return PLDM_ERROR_INVALID_LENGTH;
1492 }
1493
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301494 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301495 header.instance = instance_id;
1496 header.msg_type = PLDM_REQUEST;
1497 header.pldm_type = PLDM_FWUP;
1498 header.command = PLDM_GET_STATUS;
1499 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1500 if (rc) {
1501 return rc;
1502 }
1503
1504 return PLDM_SUCCESS;
1505}
1506
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301507LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301508int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1509 uint8_t *completion_code, uint8_t *current_state,
1510 uint8_t *previous_state, uint8_t *aux_state,
1511 uint8_t *aux_state_status, uint8_t *progress_percent,
1512 uint8_t *reason_code,
1513 bitfield32_t *update_option_flags_enabled)
1514{
1515 if (msg == NULL || completion_code == NULL || current_state == NULL ||
1516 previous_state == NULL || aux_state == NULL ||
1517 aux_state_status == NULL || progress_percent == NULL ||
1518 reason_code == NULL || update_option_flags_enabled == NULL ||
1519 !payload_length) {
1520 return PLDM_ERROR_INVALID_DATA;
1521 }
1522
1523 *completion_code = msg->payload[0];
1524 if (*completion_code != PLDM_SUCCESS) {
1525 return PLDM_SUCCESS;
1526 }
1527
1528 if (payload_length != sizeof(struct pldm_get_status_resp)) {
1529 return PLDM_ERROR_INVALID_LENGTH;
1530 }
1531 struct pldm_get_status_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301532 (struct pldm_get_status_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301533
1534 if (!is_state_valid(response->current_state)) {
1535 return PLDM_ERROR_INVALID_DATA;
1536 }
1537 if (!is_state_valid(response->previous_state)) {
1538 return PLDM_ERROR_INVALID_DATA;
1539 }
1540 if (!is_aux_state_valid(response->aux_state)) {
1541 return PLDM_ERROR_INVALID_DATA;
1542 }
1543 if (!is_aux_state_status_valid(response->aux_state_status)) {
1544 return PLDM_ERROR_INVALID_DATA;
1545 }
1546 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1547 return PLDM_ERROR_INVALID_DATA;
1548 }
1549 if (!is_reason_code_valid(response->reason_code)) {
1550 return PLDM_ERROR_INVALID_DATA;
1551 }
1552
1553 if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1554 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1555 (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1556 if (response->aux_state !=
1557 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1558 return PLDM_ERROR_INVALID_DATA;
1559 }
1560 }
1561
1562 *current_state = response->current_state;
1563 *previous_state = response->previous_state;
1564 *aux_state = response->aux_state;
1565 *aux_state_status = response->aux_state_status;
1566 *progress_percent = response->progress_percent;
1567 *reason_code = response->reason_code;
1568 update_option_flags_enabled->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301569 le32toh(response->update_option_flags_enabled.value);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301570
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_cancel_update_component_req(uint8_t instance_id,
1576 struct pldm_msg *msg,
1577 size_t payload_length)
1578{
1579 if (msg == NULL) {
1580 return PLDM_ERROR_INVALID_DATA;
1581 }
1582
1583 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1584 return PLDM_ERROR_INVALID_LENGTH;
1585 }
1586
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301587 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301588 header.instance = instance_id;
1589 header.msg_type = PLDM_REQUEST;
1590 header.pldm_type = PLDM_FWUP;
1591 header.command = PLDM_CANCEL_UPDATE_COMPONENT;
1592 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1593 if (rc) {
1594 return rc;
1595 }
1596
1597 return PLDM_SUCCESS;
1598}
1599
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301600LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301601int decode_cancel_update_component_resp(const struct pldm_msg *msg,
1602 size_t payload_length,
1603 uint8_t *completion_code)
1604{
1605 if (msg == NULL || completion_code == NULL) {
1606 return PLDM_ERROR_INVALID_DATA;
1607 }
1608
1609 if (payload_length != sizeof(*completion_code)) {
1610 return PLDM_ERROR_INVALID_LENGTH;
1611 }
1612
1613 *completion_code = msg->payload[0];
1614 return PLDM_SUCCESS;
1615}
1616
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301617LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301618int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
1619 size_t payload_length)
1620{
1621 if (msg == NULL) {
1622 return PLDM_ERROR_INVALID_DATA;
1623 }
1624
1625 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
1626 return PLDM_ERROR_INVALID_LENGTH;
1627 }
1628
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301629 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +09301630 header.instance = instance_id;
1631 header.msg_type = PLDM_REQUEST;
1632 header.pldm_type = PLDM_FWUP;
1633 header.command = PLDM_CANCEL_UPDATE;
1634 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1635 if (rc) {
1636 return rc;
1637 }
1638
1639 return PLDM_SUCCESS;
1640}
1641
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301642LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301643int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
1644 uint8_t *completion_code,
1645 bool8_t *non_functioning_component_indication,
1646 bitfield64_t *non_functioning_component_bitmap)
1647{
1648 if (msg == NULL || completion_code == NULL ||
1649 non_functioning_component_indication == NULL ||
1650 non_functioning_component_bitmap == NULL || !payload_length) {
1651 return PLDM_ERROR_INVALID_DATA;
1652 }
1653
1654 *completion_code = msg->payload[0];
1655 if (*completion_code != PLDM_SUCCESS) {
1656 return PLDM_SUCCESS;
1657 }
1658
1659 if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
1660 return PLDM_ERROR_INVALID_LENGTH;
1661 }
1662 struct pldm_cancel_update_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301663 (struct pldm_cancel_update_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301664
1665 if (!is_non_functioning_component_indication_valid(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301666 response->non_functioning_component_indication)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301667 return PLDM_ERROR_INVALID_DATA;
1668 }
1669
1670 *non_functioning_component_indication =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301671 response->non_functioning_component_indication;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301672
1673 if (*non_functioning_component_indication) {
1674 non_functioning_component_bitmap->value =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301675 le64toh(response->non_functioning_component_bitmap);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301676 }
1677
1678 return PLDM_SUCCESS;
1679}