1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #ifndef FW_UPDATE_H
3 #define FW_UPDATE_H
4 
5 #ifdef __cplusplus
6 extern "C" {
7 #endif
8 
9 #include <libpldm/base.h>
10 #include <libpldm/pldm_types.h>
11 
12 #include "stdbool.h"
13 #include <stddef.h>
14 #include <stdint.h>
15 struct variable_field;
16 
17 #define PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE		 8
18 #define PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP 0xffffffff
19 #define PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES		 0
20 
21 /** @brief Length of QueryDownstreamDevices response defined in DSP0267_1.1.0
22  *  Table 15 - QueryDownstreamDevices command format.
23  *
24  *  1 byte for completion code
25  *  1 byte for downstream device update supported
26  *  2 bytes for number of downstream devices
27  *  2 bytes for max number of downstream devices
28  *  4 bytes for capabilities
29  */
30 #define PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES 10
31 
32 /** @brief Length of QueryDownstreamIdentifiers request defined in DSP0267_1.1.0
33  * 	Table 16 - QueryDownstreamIdentifiers command format.
34  *
35  *  4 bytes for data transfer handle
36  *  1 byte for transfer operation flag
37 */
38 #define PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES 5
39 
40 /** @brief Minimum length of QueryDownstreamIdentifiers response from DSP0267_1.1.0
41  *  if the complement code is success.
42  *
43  *  1 byte for completion code
44  *  4 bytes for next data transfer handle
45  *  1 byte for transfer flag
46  *  4 bytes for downstream devices length
47  *  2 bytes for number of downstream devices
48  */
49 #define PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN 12
50 
51 /** @brief Minimum length of device descriptor, 2 bytes for descriptor type,
52  *         2 bytes for descriptor length and at least 1 byte of descriptor data
53  */
54 #define PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN 5
55 
56 /** @brief Length of GetDownstreamFirmwareParameters request defined in DSP0267_1.1.0
57  *
58  * 4 bytes for Data Transfer Handle
59  * 1 byte for Transfer Operation Flag
60  */
61 #define PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_REQ_BYTES 5
62 
63 /** @brief Minimum length of GetDownstreamFirmwareParameters response from
64  * DSP0267_1.1.0 if the completion code is success.
65  *
66  * 1 byte for completion code
67  * 4 bytes for next data transfer handle
68  * 1 byte for transfer flag
69  * 4 bytes for FDP capabilities during update
70  * 2 bytes for downstream device count
71  */
72 #define PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_RESP_MIN_LEN 12
73 
74 /** @brief Minimum length of DownstreamDeviceParameterTable entry from
75  * DSP0267_1.1.0 table 21 - DownstreamDeviceParameterTable
76  *
77  * 2 bytes for Downstream Device Index
78  * 4 bytes for Active Component Comparison Stamp
79  * 1 byte for Active Component Version String Type
80  * 1 byte for Active Component Version String Length
81  * 8 bytes for Active Component Release Date
82  * 4 bytes for Pending Component Comparison Stamp
83  * 1 byte for Pending Component Version String Type
84  * 1 byte for Pending Component Version String Length
85  * 8 bytes for Pending Component Release Date
86  * 2 bytes for Component Activation Methods
87  * 4 bytes for Capabilities During Update
88  */
89 #define PLDM_DOWNSTREAM_DEVICE_PARAMETER_ENTRY_MIN_LEN 36
90 
91 #define PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES 0
92 #define PLDM_FWUP_BASELINE_TRANSFER_SIZE       32
93 #define PLDM_FWUP_MIN_OUTSTANDING_REQ	       1
94 #define PLDM_GET_STATUS_REQ_BYTES	       0
95 /* Maximum progress percentage value*/
96 #define PLDM_FWUP_MAX_PROGRESS_PERCENT	       0x65
97 #define PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES 0
98 #define PLDM_CANCEL_UPDATE_REQ_BYTES	       0
99 
100 /** @brief PLDM component release data size in bytes defined in DSP0267_1.1.0
101  * Table 14 - ComponentParameterTable and Table 21 - ComponentParameterTable
102  *
103  * The size can be used in `ASCII[8] - ActiveComponentReleaseDate` and
104  * `ASCII[8] - PendingComponentReleaseDate` fields in the tables above.
105  */
106 #define PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN 8
107 
108 /** @brief PLDM Firmware update commands
109  */
110 enum pldm_firmware_update_commands {
111 	PLDM_QUERY_DEVICE_IDENTIFIERS = 0x01,
112 	PLDM_GET_FIRMWARE_PARAMETERS = 0x02,
113 	PLDM_QUERY_DOWNSTREAM_DEVICES = 0x03,
114 	PLDM_QUERY_DOWNSTREAM_IDENTIFIERS = 0x04,
115 	PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS = 0x05,
116 	PLDM_REQUEST_UPDATE = 0x10,
117 	PLDM_PASS_COMPONENT_TABLE = 0x13,
118 	PLDM_UPDATE_COMPONENT = 0x14,
119 	PLDM_REQUEST_FIRMWARE_DATA = 0x15,
120 	PLDM_TRANSFER_COMPLETE = 0x16,
121 	PLDM_VERIFY_COMPLETE = 0x17,
122 	PLDM_APPLY_COMPLETE = 0x18,
123 	PLDM_ACTIVATE_FIRMWARE = 0x1a,
124 	PLDM_GET_STATUS = 0x1b,
125 	PLDM_CANCEL_UPDATE_COMPONENT = 0x1c,
126 	PLDM_CANCEL_UPDATE = 0x1d
127 };
128 
129 /** @brief PLDM Firmware update completion codes
130  */
131 enum pldm_firmware_update_completion_codes {
132 	PLDM_FWUP_NOT_IN_UPDATE_MODE = 0x80,
133 	PLDM_FWUP_ALREADY_IN_UPDATE_MODE = 0x81,
134 	PLDM_FWUP_DATA_OUT_OF_RANGE = 0x82,
135 	PLDM_FWUP_INVALID_TRANSFER_LENGTH = 0x83,
136 	PLDM_FWUP_INVALID_STATE_FOR_COMMAND = 0x84,
137 	PLDM_FWUP_INCOMPLETE_UPDATE = 0x85,
138 	PLDM_FWUP_BUSY_IN_BACKGROUND = 0x86,
139 	PLDM_FWUP_CANCEL_PENDING = 0x87,
140 	PLDM_FWUP_COMMAND_NOT_EXPECTED = 0x88,
141 	PLDM_FWUP_RETRY_REQUEST_FW_DATA = 0x89,
142 	PLDM_FWUP_UNABLE_TO_INITIATE_UPDATE = 0x8a,
143 	PLDM_FWUP_ACTIVATION_NOT_REQUIRED = 0x8b,
144 	PLDM_FWUP_SELF_CONTAINED_ACTIVATION_NOT_PERMITTED = 0x8c,
145 	PLDM_FWUP_NO_DEVICE_METADATA = 0x8d,
146 	PLDM_FWUP_RETRY_REQUEST_UPDATE = 0x8e,
147 	PLDM_FWUP_NO_PACKAGE_DATA = 0x8f,
148 	PLDM_FWUP_INVALID_TRANSFER_HANDLE = 0x90,
149 	PLDM_FWUP_INVALID_TRANSFER_OPERATION_FLAG = 0x91,
150 	PLDM_FWUP_ACTIVATE_PENDING_IMAGE_NOT_PERMITTED = 0x92,
151 	PLDM_FWUP_PACKAGE_DATA_ERROR = 0x93
152 };
153 
154 /** @brief String type values defined in the PLDM firmware update specification
155  */
156 enum pldm_firmware_update_string_type {
157 	PLDM_STR_TYPE_UNKNOWN = 0,
158 	PLDM_STR_TYPE_ASCII = 1,
159 	PLDM_STR_TYPE_UTF_8 = 2,
160 	PLDM_STR_TYPE_UTF_16 = 3,
161 	PLDM_STR_TYPE_UTF_16LE = 4,
162 	PLDM_STR_TYPE_UTF_16BE = 5
163 };
164 
165 /** @brief Descriptor types defined in PLDM firmware update specification
166  */
167 enum pldm_firmware_update_descriptor_types {
168 	PLDM_FWUP_PCI_VENDOR_ID = 0x0000,
169 	PLDM_FWUP_IANA_ENTERPRISE_ID = 0x0001,
170 	PLDM_FWUP_UUID = 0x0002,
171 	PLDM_FWUP_PNP_VENDOR_ID = 0x0003,
172 	PLDM_FWUP_ACPI_VENDOR_ID = 0x0004,
173 	PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID = 0x0005,
174 	PLDM_FWUP_SCSI_VENDOR_ID = 0x0006,
175 	PLDM_FWUP_PCI_DEVICE_ID = 0x0100,
176 	PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID = 0x0101,
177 	PLDM_FWUP_PCI_SUBSYSTEM_ID = 0x0102,
178 	PLDM_FWUP_PCI_REVISION_ID = 0x0103,
179 	PLDM_FWUP_PNP_PRODUCT_IDENTIFIER = 0x0104,
180 	PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER = 0x0105,
181 	PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING = 0x0106,
182 	PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING = 0x0107,
183 	PLDM_FWUP_SCSI_PRODUCT_ID = 0x0108,
184 	PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE = 0x0109,
185 	PLDM_FWUP_VENDOR_DEFINED = 0xffff
186 };
187 
188 /** @brief Descriptor types length defined in PLDM firmware update specification
189  */
190 enum pldm_firmware_update_descriptor_types_length {
191 	PLDM_FWUP_PCI_VENDOR_ID_LENGTH = 2,
192 	PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH = 4,
193 	PLDM_FWUP_UUID_LENGTH = 16,
194 	PLDM_FWUP_PNP_VENDOR_ID_LENGTH = 3,
195 	PLDM_FWUP_ACPI_VENDOR_ID_LENGTH = 4,
196 	PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH = 3,
197 	PLDM_FWUP_SCSI_VENDOR_ID_LENGTH = 8,
198 	PLDM_FWUP_PCI_DEVICE_ID_LENGTH = 2,
199 	PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH = 2,
200 	PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH = 2,
201 	PLDM_FWUP_PCI_REVISION_ID_LENGTH = 1,
202 	PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH = 4,
203 	PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH = 4,
204 	PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH = 40,
205 	PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH = 10,
206 	PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH = 16,
207 	PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH = 4
208 };
209 
210 /** @brief ComponentClassification values defined in firmware update
211  *         specification
212  */
213 enum pldm_component_classification_values {
214 	PLDM_COMP_UNKNOWN = 0x0000,
215 	PLDM_COMP_OTHER = 0x0001,
216 	PLDM_COMP_DRIVER = 0x0002,
217 	PLDM_COMP_CONFIGURATION_SOFTWARE = 0x0003,
218 	PLDM_COMP_APPLICATION_SOFTWARE = 0x0004,
219 	PLDM_COMP_INSTRUMENTATION = 0x0005,
220 	PLDM_COMP_FIRMWARE_OR_BIOS = 0x0006,
221 	PLDM_COMP_DIAGNOSTIC_SOFTWARE = 0x0007,
222 	PLDM_COMP_OPERATING_SYSTEM = 0x0008,
223 	PLDM_COMP_MIDDLEWARE = 0x0009,
224 	PLDM_COMP_FIRMWARE = 0x000a,
225 	PLDM_COMP_BIOS_OR_FCODE = 0x000b,
226 	PLDM_COMP_SUPPORT_OR_SERVICEPACK = 0x000c,
227 	PLDM_COMP_SOFTWARE_BUNDLE = 0x000d,
228 	PLDM_COMP_DOWNSTREAM_DEVICE = 0xffff
229 };
230 
231 /** @brief ComponentActivationMethods is the bit position in the bitfield that
232  *         provides the capability of the FD for firmware activation. Multiple
233  *         activation methods can be supported.
234  */
235 enum pldm_comp_activation_methods {
236 	PLDM_ACTIVATION_AUTOMATIC = 0,
237 	PLDM_ACTIVATION_SELF_CONTAINED = 1,
238 	PLDM_ACTIVATION_MEDIUM_SPECIFIC_RESET = 2,
239 	PLDM_ACTIVATION_SYSTEM_REBOOT = 3,
240 	PLDM_ACTIVATION_DC_POWER_CYCLE = 4,
241 	PLDM_ACTIVATION_AC_POWER_CYCLE = 5,
242 	PLDM_SUPPORTS_ACTIVATE_PENDING_IMAGE = 6,
243 	PLDM_SUPPORTS_ACTIVATE_PENDING_IMAGE_SET = 7
244 };
245 
246 /** @brief ComponentResponse values in the response of PassComponentTable
247  */
248 enum pldm_component_responses {
249 	PLDM_CR_COMP_CAN_BE_UPDATED = 0,
250 	PLDM_CR_COMP_MAY_BE_UPDATEABLE = 1
251 };
252 
253 /** @brief ComponentResponseCode values in the response of PassComponentTable
254  */
255 enum pldm_component_response_codes {
256 	PLDM_CRC_COMP_CAN_BE_UPDATED = 0x00,
257 	PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL = 0x01,
258 	PLDM_CRC_COMP_COMPARISON_STAMP_LOWER = 0x02,
259 	PLDM_CRC_INVALID_COMP_COMPARISON_STAMP = 0x03,
260 	PLDM_CRC_COMP_CONFLICT = 0x04,
261 	PLDM_CRC_COMP_PREREQUISITES_NOT_MET = 0x05,
262 	PLDM_CRC_COMP_NOT_SUPPORTED = 0x06,
263 	PLDM_CRC_COMP_SECURITY_RESTRICTIONS = 0x07,
264 	PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET = 0x08,
265 	PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY = 0x09,
266 	PLDM_CRC_COMP_VER_STR_IDENTICAL = 0x0a,
267 	PLDM_CRC_COMP_VER_STR_LOWER = 0x0b,
268 	PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN = 0xd0,
269 	PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX = 0xef
270 };
271 
272 /** @brief ComponentCompatibilityResponse values in the response of
273  *         UpdateComponent
274  */
275 enum pldm_component_compatibility_responses {
276 	PLDM_CCR_COMP_CAN_BE_UPDATED = 0,
277 	PLDM_CCR_COMP_CANNOT_BE_UPDATED = 1
278 };
279 
280 /** @brief ComponentCompatibilityResponse Code values in the response of
281  *         UpdateComponent
282  */
283 enum pldm_component_compatibility_response_codes {
284 	PLDM_CCRC_NO_RESPONSE_CODE = 0x00,
285 	PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL = 0x01,
286 	PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER = 0x02,
287 	PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP = 0x03,
288 	PLDM_CCRC_COMP_CONFLICT = 0x04,
289 	PLDM_CCRC_COMP_PREREQUISITES_NOT_MET = 0x05,
290 	PLDM_CCRC_COMP_NOT_SUPPORTED = 0x06,
291 	PLDM_CCRC_COMP_SECURITY_RESTRICTIONS = 0x07,
292 	PLDM_CCRC_INCOMPLETE_COMP_IMAGE_SET = 0x08,
293 	PLDM_CCRC_COMP_INFO_NO_MATCH = 0x09,
294 	PLDM_CCRC_COMP_VER_STR_IDENTICAL = 0x0a,
295 	PLDM_CCRC_COMP_VER_STR_LOWER = 0x0b,
296 	PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN = 0xd0,
297 	PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX = 0xef
298 };
299 
300 /** @brief Common error codes in TransferComplete, VerifyComplete and
301  *        ApplyComplete request
302  */
303 enum pldm_firmware_update_common_error_codes {
304 	PLDM_FWUP_TIME_OUT = 0x09,
305 	PLDM_FWUP_GENERIC_ERROR = 0x0a
306 };
307 
308 /** @brief TransferResult values in the request of TransferComplete
309  */
310 enum pldm_firmware_update_transfer_result_values {
311 	PLDM_FWUP_TRANSFER_SUCCESS = 0x00,
312 	PLDM_FWUP_TRANSFER_ERROR_IMAGE_CORRUPT = 0x02,
313 	PLDM_FWUP_TRANSFER_ERROR_VERSION_MISMATCH = 0x02,
314 	PLDM_FWUP_FD_ABORTED_TRANSFER = 0x03,
315 	PLDM_FWUP_FD_ABORTED_TRANSFER_LOW_POWER_STATE = 0x0b,
316 	PLDM_FWUP_FD_ABORTED_TRANSFER_RESET_NEEDED = 0x0c,
317 	PLDM_FWUP_FD_ABORTED_TRANSFER_STORAGE_ISSUE = 0x0d,
318 	PLDM_FWUP_VENDOR_TRANSFER_RESULT_RANGE_MIN = 0x70,
319 	PLDM_FWUP_VENDOR_TRANSFER_RESULT_RANGE_MAX = 0x8f
320 };
321 
322 /**@brief VerifyResult values in the request of VerifyComplete
323  */
324 enum pldm_firmware_update_verify_result_values {
325 	PLDM_FWUP_VERIFY_SUCCESS = 0x00,
326 	PLDM_FWUP_VERIFY_ERROR_VERIFICATION_FAILURE = 0x01,
327 	PLDM_FWUP_VERIFY_ERROR_VERSION_MISMATCH = 0x02,
328 	PLDM_FWUP_VERIFY_FAILED_FD_SECURITY_CHECKS = 0x03,
329 	PLDM_FWUP_VERIFY_ERROR_IMAGE_INCOMPLETE = 0x04,
330 	PLDM_FWUP_VENDOR_VERIFY_RESULT_RANGE_MIN = 0x90,
331 	PLDM_FWUP_VENDOR_VERIFY_RESULT_RANGE_MAX = 0xaf
332 };
333 
334 /**@brief ApplyResult values in the request of ApplyComplete
335  */
336 enum pldm_firmware_update_apply_result_values {
337 	PLDM_FWUP_APPLY_SUCCESS = 0x00,
338 	PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD = 0x01,
339 	PLDM_FWUP_APPLY_FAILURE_MEMORY_ISSUE = 0x02,
340 	PLDM_FWUP_VENDOR_APPLY_RESULT_RANGE_MIN = 0xb0,
341 	PLDM_FWUP_VENDOR_APPLY_RESULT_RANGE_MAX = 0xcf
342 };
343 
344 /** @brief SelfContainedActivationRequest in the request of ActivateFirmware
345  */
346 enum pldm_self_contained_activation_req {
347 	PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS = false,
348 	PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS = true
349 };
350 
351 /** @brief Current state/previous state of the FD or FDP returned in GetStatus
352  *         response
353  */
354 enum pldm_firmware_device_states {
355 	PLDM_FD_STATE_IDLE = 0,
356 	PLDM_FD_STATE_LEARN_COMPONENTS = 1,
357 	PLDM_FD_STATE_READY_XFER = 2,
358 	PLDM_FD_STATE_DOWNLOAD = 3,
359 	PLDM_FD_STATE_VERIFY = 4,
360 	PLDM_FD_STATE_APPLY = 5,
361 	PLDM_FD_STATE_ACTIVATE = 6
362 };
363 
364 /** @brief Firmware device aux state in GetStatus response
365  */
366 enum pldm_get_status_aux_states {
367 	PLDM_FD_OPERATION_IN_PROGRESS = 0,
368 	PLDM_FD_OPERATION_SUCCESSFUL = 1,
369 	PLDM_FD_OPERATION_FAILED = 2,
370 	PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER = 3
371 };
372 
373 /** @brief Firmware device aux state status in GetStatus response
374  */
375 enum pldm_get_status_aux_state_status_values {
376 	PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS = 0x00,
377 	PLDM_FD_TIMEOUT = 0x09,
378 	PLDM_FD_GENERIC_ERROR = 0x0a,
379 	PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START = 0x70,
380 	PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END = 0xef
381 };
382 
383 /** @brief Firmware device reason code in GetStatus response
384  */
385 enum pldm_get_status_reason_code_values {
386 	PLDM_FD_INITIALIZATION = 0,
387 	PLDM_FD_ACTIVATE_FW = 1,
388 	PLDM_FD_CANCEL_UPDATE = 2,
389 	PLDM_FD_TIMEOUT_LEARN_COMPONENT = 3,
390 	PLDM_FD_TIMEOUT_READY_XFER = 4,
391 	PLDM_FD_TIMEOUT_DOWNLOAD = 5,
392 	PLDM_FD_TIMEOUT_VERIFY = 6,
393 	PLDM_FD_TIMEOUT_APPLY = 7,
394 	PLDM_FD_STATUS_VENDOR_DEFINED_MIN = 200,
395 	PLDM_FD_STATUS_VENDOR_DEFINED_MAX = 255
396 };
397 
398 /** @brief Components functional indicator in CancelUpdate response
399  */
400 enum pldm_firmware_update_non_functioning_component_indication {
401 	PLDM_FWUP_COMPONENTS_FUNCTIONING = 0,
402 	PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING = 1
403 };
404 
405 /** @brief Downstream device update supported in QueryDownstreamDevices response
406  *         defined in DSP0267_1.1.0
407 */
408 enum pldm_firmware_update_downstream_device_update_supported {
409 	PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED = 0,
410 	PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED = 1
411 };
412 
413 /** @struct pldm_package_header_information
414  *
415  *  Structure representing fixed part of package header information
416  */
417 struct pldm_package_header_information {
418 	uint8_t uuid[PLDM_FWUP_UUID_LENGTH];
419 	uint8_t package_header_format_version;
420 	uint16_t package_header_size;
421 	uint8_t package_release_date_time[PLDM_TIMESTAMP104_SIZE];
422 	uint16_t component_bitmap_bit_length;
423 	uint8_t package_version_string_type;
424 	uint8_t package_version_string_length;
425 } __attribute__((packed));
426 
427 /** @struct pldm_firmware_device_id_record
428  *
429  *  Structure representing firmware device ID record
430  */
431 struct pldm_firmware_device_id_record {
432 	uint16_t record_length;
433 	uint8_t descriptor_count;
434 	bitfield32_t device_update_option_flags;
435 	uint8_t comp_image_set_version_string_type;
436 	uint8_t comp_image_set_version_string_length;
437 	uint16_t fw_device_pkg_data_length;
438 } __attribute__((packed));
439 
440 /** @struct pldm_descriptor_tlv
441  *
442  *  Structure representing descriptor type, length and value
443  */
444 struct pldm_descriptor_tlv {
445 	uint16_t descriptor_type;
446 	uint16_t descriptor_length;
447 	uint8_t descriptor_data[1];
448 } __attribute__((packed));
449 
450 /** @struct pldm_vendor_defined_descriptor_title_data
451  *
452  *  Structure representing vendor defined descriptor title sections
453  */
454 struct pldm_vendor_defined_descriptor_title_data {
455 	uint8_t vendor_defined_descriptor_title_str_type;
456 	uint8_t vendor_defined_descriptor_title_str_len;
457 	uint8_t vendor_defined_descriptor_title_str[1];
458 } __attribute__((packed));
459 
460 /** @struct pldm_component_image_information
461  *
462  *  Structure representing fixed part of individual component information in
463  *  PLDM firmware update package
464  */
465 struct pldm_component_image_information {
466 	uint16_t comp_classification;
467 	uint16_t comp_identifier;
468 	uint32_t comp_comparison_stamp;
469 	bitfield16_t comp_options;
470 	bitfield16_t requested_comp_activation_method;
471 	uint32_t comp_location_offset;
472 	uint32_t comp_size;
473 	uint8_t comp_version_string_type;
474 	uint8_t comp_version_string_length;
475 } __attribute__((packed));
476 
477 /** @struct pldm_query_device_identifiers_resp
478  *
479  *  Structure representing query device identifiers response.
480  */
481 struct pldm_query_device_identifiers_resp {
482 	uint8_t completion_code;
483 	uint32_t device_identifiers_len;
484 	uint8_t descriptor_count;
485 } __attribute__((packed));
486 
487 /** @struct pldm_get_firmware_parameters_resp
488  *
489  *  Structure representing the fixed part of GetFirmwareParameters response
490  */
491 struct pldm_get_firmware_parameters_resp {
492 	uint8_t completion_code;
493 	bitfield32_t capabilities_during_update;
494 	uint16_t comp_count;
495 	uint8_t active_comp_image_set_ver_str_type;
496 	uint8_t active_comp_image_set_ver_str_len;
497 	uint8_t pending_comp_image_set_ver_str_type;
498 	uint8_t pending_comp_image_set_ver_str_len;
499 } __attribute__((packed));
500 
501 /** @struct pldm_query_downstream_devices_resp
502  *
503  *  Structure representing response of QueryDownstreamDevices.
504  *  The definition can be found Table 15 - QueryDownstreamDevices command format
505  *  in DSP0267_1.1.0
506  */
507 struct pldm_query_downstream_devices_resp {
508 	uint8_t completion_code;
509 	uint8_t downstream_device_update_supported;
510 	uint16_t number_of_downstream_devices;
511 	uint16_t max_number_of_downstream_devices;
512 	bitfield32_t capabilities;
513 };
514 
515 /** @struct pldm_component_parameter_entry
516  *
517  *  Structure representing component parameter table entry.
518  */
519 struct pldm_component_parameter_entry {
520 	uint16_t comp_classification;
521 	uint16_t comp_identifier;
522 	uint8_t comp_classification_index;
523 	uint32_t active_comp_comparison_stamp;
524 	uint8_t active_comp_ver_str_type;
525 	uint8_t active_comp_ver_str_len;
526 	uint8_t active_comp_release_date[8];
527 	uint32_t pending_comp_comparison_stamp;
528 	uint8_t pending_comp_ver_str_type;
529 	uint8_t pending_comp_ver_str_len;
530 	uint8_t pending_comp_release_date[8];
531 	bitfield16_t comp_activation_methods;
532 	bitfield32_t capabilities_during_update;
533 } __attribute__((packed));
534 
535 /** @struct pldm_query_downstream_identifiers_req
536  *
537  *  Structure for QueryDownstreamIdentifiers request defined in Table 16 -
538  *  QueryDownstreamIdentifiers command format in DSP0267_1.1.0
539  */
540 struct pldm_query_downstream_identifiers_req {
541 	uint32_t data_transfer_handle;
542 	uint8_t transfer_operation_flag;
543 };
544 
545 /** @struct pldm_query_downstream_identifiers_resp
546  *
547  *  Structure representing the fixed part of QueryDownstreamIdentifiers response
548  *  defined in Table 16 - QueryDownstreamIdentifiers command format, and
549  *  Table 17 - QueryDownstreamIdentifiers response definition in DSP0267_1.1.0.
550  *
551  *  Squash the two tables into one since the definition of
552  *  Table 17 is `Portion of QueryDownstreamIdentifiers response`
553  */
554 struct pldm_query_downstream_identifiers_resp {
555 	uint8_t completion_code;
556 	uint32_t next_data_transfer_handle;
557 	uint8_t transfer_flag;
558 	uint32_t downstream_devices_length;
559 	uint16_t number_of_downstream_devices;
560 };
561 
562 /** @struct pldm_downstream_device
563  *
564  *  Structure representing downstream device information defined in
565  *  Table 18 - DownstreamDevice definition in DSP0267_1.1.0
566  */
567 struct pldm_downstream_device {
568 	uint16_t downstream_device_index;
569 	uint8_t downstream_descriptor_count;
570 };
571 #define PLDM_DOWNSTREAM_DEVICE_BYTES 3
572 
573 /** @struct pldm_query_downstream_firmware_param_req
574  *
575  *  Structure representing QueryDownstreamFirmwareParameters request
576  */
577 struct pldm_get_downstream_firmware_params_req {
578 	uint32_t data_transfer_handle;
579 	uint8_t transfer_operation_flag;
580 };
581 
582 /** @struct pldm_query_downstream_firmware_param_resp
583  *
584  *  Structure representing the fixed part of QueryDownstreamFirmwareParameters
585  *  response in Table 19 - GetDownstreamFirmwareParameters command format, and
586  *  Table 20 - QueryDownstreamFirmwareParameters response definition in
587  *  DSP0267_1.1.0.
588  *
589  *  Squash the two tables into one since the definition of Table 20 is `Portion
590  *  of GetDownstreamFirmwareParameters response`
591  */
592 struct pldm_get_downstream_firmware_params_resp {
593 	uint8_t completion_code;
594 	uint32_t next_data_transfer_handle;
595 	uint8_t transfer_flag;
596 	bitfield32_t fdp_capabilities_during_update;
597 	uint16_t downstream_device_count;
598 };
599 
600 /** @struct pldm_downstream_device_parameter_entry
601  *
602  *  Structure representing downstream device parameter table entry defined in
603  *  Table 21 - DownstreamDeviceParameterTable in DSP0267_1.1.0
604  *
605  *  Clients should not allocate memory for this struct to decode the response,
606  *  use `pldm_downstream_device_parameter_entry_versions` instead to make sure
607  *  that the active and pending component version strings are copied from the
608  *  message buffer.
609  */
610 struct pldm_downstream_device_parameter_entry {
611 	uint16_t downstream_device_index;
612 	uint32_t active_comp_comparison_stamp;
613 	uint8_t active_comp_ver_str_type;
614 	uint8_t active_comp_ver_str_len;
615 	/* Append 1 bytes for null termination so that it can be used as a
616 	 * Null-terminated string.
617 	 */
618 	char active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN + 1];
619 	uint32_t pending_comp_comparison_stamp;
620 	uint8_t pending_comp_ver_str_type;
621 	uint8_t pending_comp_ver_str_len;
622 	/* Append 1 bytes for null termination so that it can be used as a
623 	 * Null-terminated string.
624 	 */
625 	char pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN + 1];
626 	bitfield16_t comp_activation_methods;
627 	bitfield32_t capabilities_during_update;
628 	const char *active_comp_ver_str;
629 	const char *pending_comp_ver_str;
630 };
631 
632 /** @struct pldm_downstream_device_parameter_entry_versions
633  *
634  *  Structure representing downstream device parameter table entry with
635  *  copies of active and pending component version strings to avoid the
636  *  message buffer is subsequently freed.
637  *
638  *  Clients should allocate memory for this struct then decode the response
639  *  instead of using `pldm_downstream_device_parameter_entry`.
640  */
641 struct pldm_downstream_device_parameter_entry_versions {
642 	struct pldm_downstream_device_parameter_entry entry;
643 	/* The "Length of ComponentVersionString" field is 1 byte, so
644 	 * "ComponentVersionString" can be at most 255 characters, allocate
645 	 * memory for it and append 1 bytes for null termination so that it
646 	 * can be used as a Null-terminated string.
647 	 */
648 	char active_comp_ver_str[UINT8_MAX + 1];
649 	char pending_comp_ver_str[UINT8_MAX + 1];
650 };
651 
652 /** @struct pldm_request_update_req
653  *
654  *  Structure representing fixed part of Request Update request
655  */
656 struct pldm_request_update_req {
657 	uint32_t max_transfer_size;
658 	uint16_t num_of_comp;
659 	uint8_t max_outstanding_transfer_req;
660 	uint16_t pkg_data_len;
661 	uint8_t comp_image_set_ver_str_type;
662 	uint8_t comp_image_set_ver_str_len;
663 } __attribute__((packed));
664 
665 /** @struct pldm_request_update_resp
666  *
667  *  Structure representing Request Update response
668  */
669 struct pldm_request_update_resp {
670 	uint8_t completion_code;
671 	uint16_t fd_meta_data_len;
672 	uint8_t fd_will_send_pkg_data;
673 } __attribute__((packed));
674 
675 /** @struct pldm_pass_component_table_req
676  *
677  *  Structure representing PassComponentTable request
678  */
679 struct pldm_pass_component_table_req {
680 	uint8_t transfer_flag;
681 	uint16_t comp_classification;
682 	uint16_t comp_identifier;
683 	uint8_t comp_classification_index;
684 	uint32_t comp_comparison_stamp;
685 	uint8_t comp_ver_str_type;
686 	uint8_t comp_ver_str_len;
687 } __attribute__((packed));
688 
689 /** @struct pldm_pass_component_table_resp
690  *
691  *  Structure representing PassComponentTable response
692  */
693 struct pldm_pass_component_table_resp {
694 	uint8_t completion_code;
695 	uint8_t comp_resp;
696 	uint8_t comp_resp_code;
697 } __attribute__((packed));
698 
699 /** @struct pldm_update_component_req
700  *
701  *  Structure representing UpdateComponent request
702  */
703 struct pldm_update_component_req {
704 	uint16_t comp_classification;
705 	uint16_t comp_identifier;
706 	uint8_t comp_classification_index;
707 	uint32_t comp_comparison_stamp;
708 	uint32_t comp_image_size;
709 	bitfield32_t update_option_flags;
710 	uint8_t comp_ver_str_type;
711 	uint8_t comp_ver_str_len;
712 } __attribute__((packed));
713 
714 /** @struct pldm_update_component_resp
715  *
716  *  Structure representing UpdateComponent response
717  */
718 struct pldm_update_component_resp {
719 	uint8_t completion_code;
720 	uint8_t comp_compatibility_resp;
721 	uint8_t comp_compatibility_resp_code;
722 	bitfield32_t update_option_flags_enabled;
723 	uint16_t time_before_req_fw_data;
724 } __attribute__((packed));
725 
726 /** @struct pldm_request_firmware_data_req
727  *
728  *  Structure representing RequestFirmwareData request.
729  */
730 struct pldm_request_firmware_data_req {
731 	uint32_t offset;
732 	uint32_t length;
733 } __attribute__((packed));
734 
735 /** @struct pldm_apply_complete_req
736  *
737  *  Structure representing ApplyComplete request.
738  */
739 struct pldm_apply_complete_req {
740 	uint8_t apply_result;
741 	bitfield16_t comp_activation_methods_modification;
742 } __attribute__((packed));
743 
744 /** @struct pldm_activate_firmware_req
745  *
746  *  Structure representing ActivateFirmware request
747  */
748 struct pldm_activate_firmware_req {
749 	bool8_t self_contained_activation_req;
750 } __attribute__((packed));
751 
752 /** @struct activate_firmware_resp
753  *
754  *  Structure representing Activate Firmware response
755  */
756 struct pldm_activate_firmware_resp {
757 	uint8_t completion_code;
758 	uint16_t estimated_time_activation;
759 } __attribute__((packed));
760 
761 /** @struct pldm_get_status_resp
762  *
763  *  Structure representing GetStatus response.
764  */
765 struct pldm_get_status_resp {
766 	uint8_t completion_code;
767 	uint8_t current_state;
768 	uint8_t previous_state;
769 	uint8_t aux_state;
770 	uint8_t aux_state_status;
771 	uint8_t progress_percent;
772 	uint8_t reason_code;
773 	bitfield32_t update_option_flags_enabled;
774 } __attribute__((packed));
775 
776 /** @struct pldm_cancel_update_resp
777  *
778  *  Structure representing CancelUpdate response.
779  */
780 struct pldm_cancel_update_resp {
781 	uint8_t completion_code;
782 	bool8_t non_functioning_component_indication;
783 	uint64_t non_functioning_component_bitmap;
784 } __attribute__((packed));
785 
786 /** @brief Decode the PLDM package header information
787  *
788  *  @param[in] data - pointer to package header information
789  *  @param[in] length - available length in the firmware update package
790  *  @param[out] package_header_info - pointer to fixed part of PLDM package
791  *                                    header information
792  *  @param[out] package_version_str - pointer to package version string
793  *
794  *  @return pldm_completion_codes
795  */
796 int decode_pldm_package_header_info(
797 	const uint8_t *data, size_t length,
798 	struct pldm_package_header_information *package_header_info,
799 	struct variable_field *package_version_str);
800 
801 /** @brief Decode individual firmware device ID record
802  *
803  *  @param[in] data - pointer to firmware device ID record
804  *  @param[in] length - available length in the firmware update package
805  *  @param[in] component_bitmap_bit_length - ComponentBitmapBitLengthfield
806  *                                           parsed from the package header info
807  *  @param[out] fw_device_id_record - pointer to fixed part of firmware device
808  *                                    id record
809  *  @param[out] applicable_components - pointer to ApplicableComponents
810  *  @param[out] comp_image_set_version_str - pointer to
811  *                                           ComponentImageSetVersionString
812  *  @param[out] record_descriptors - pointer to RecordDescriptors
813  *  @param[out] fw_device_pkg_data - pointer to FirmwareDevicePackageData
814  *
815  *  @return pldm_completion_codes
816  */
817 int decode_firmware_device_id_record(
818 	const uint8_t *data, size_t length,
819 	uint16_t component_bitmap_bit_length,
820 	struct pldm_firmware_device_id_record *fw_device_id_record,
821 	struct variable_field *applicable_components,
822 	struct variable_field *comp_image_set_version_str,
823 	struct variable_field *record_descriptors,
824 	struct variable_field *fw_device_pkg_data);
825 
826 /** @brief Decode the record descriptor entries in the firmware update package
827  *         and the Descriptors in the QueryDeviceIDentifiers command
828  *
829  *  @param[in] data - pointer to descriptor entry
830  *  @param[in] length - remaining length of the descriptor data
831  *  @param[out] descriptor_type - pointer to descriptor type
832  *  @param[out] descriptor_data - pointer to descriptor data
833  *
834  *  @return pldm_completion_codes
835  */
836 int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
837 					uint16_t *descriptor_type,
838 					struct variable_field *descriptor_data);
839 
840 /** @brief Decode the vendor defined descriptor value
841  *
842  *  @param[in] data - pointer to vendor defined descriptor value
843  *  @param[in] length - length of the vendor defined descriptor value
844  *  @param[out] descriptor_title_str_type - pointer to vendor defined descriptor
845  *                                          title string type
846  *  @param[out] descriptor_title_str - pointer to vendor defined descriptor
847  *                                     title string
848  *  @param[out] descriptor_data - pointer to vendor defined descriptor data
849  *
850  *  @return pldm_completion_codes
851  */
852 int decode_vendor_defined_descriptor_value(
853 	const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
854 	struct variable_field *descriptor_title_str,
855 	struct variable_field *descriptor_data);
856 
857 /** @brief Decode individual component image information
858  *
859  *  @param[in] data - pointer to component image information
860  *  @param[in] length - available length in the firmware update package
861  *  @param[out] pldm_comp_image_info - pointer to fixed part of component image
862  *                                     information
863  *  @param[out] comp_version_str - pointer to component version string
864  *
865  *  @return pldm_completion_codes
866  */
867 int decode_pldm_comp_image_info(
868 	const uint8_t *data, size_t length,
869 	struct pldm_component_image_information *pldm_comp_image_info,
870 	struct variable_field *comp_version_str);
871 
872 /** @brief Create a PLDM request message for QueryDeviceIdentifiers
873  *
874  *  @param[in] instance_id - Message's instance id
875  *  @param[in] payload_length - Length of the request message payload
876  *  @param[in,out] msg - Message will be written to this
877  *
878  *  @return pldm_completion_codes
879  *
880  *  @note  Caller is responsible for memory alloc and dealloc of param
881  *         'msg.payload'
882  */
883 int encode_query_device_identifiers_req(uint8_t instance_id,
884 					size_t payload_length,
885 					struct pldm_msg *msg);
886 
887 /** @brief Decode QueryDeviceIdentifiers response message
888  *
889  *  @param[in] msg - Response message
890  *  @param[in] payload_length - Length of response message payload
891  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
892  *  @param[out] device_identifiers_len - Pointer to device identifiers length
893  *  @param[out] descriptor_count - Pointer to descriptor count
894  *  @param[out] descriptor_data - Pointer to descriptor data
895  *
896  *  @return pldm_completion_codes
897  */
898 int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
899 					 size_t payload_length,
900 					 uint8_t *completion_code,
901 					 uint32_t *device_identifiers_len,
902 					 uint8_t *descriptor_count,
903 					 uint8_t **descriptor_data);
904 
905 /** @brief Create a PLDM request message for GetFirmwareParameters
906  *
907  *  @param[in] instance_id - Message's instance id
908  *  @param[in] payload_length - Length of the request message payload
909  *  @param[in,out] msg - Message will be written to this
910  *
911  *  @return pldm_completion_codes
912  *
913  *  @note  Caller is responsible for memory alloc and dealloc of param
914  *         'msg.payload'
915  */
916 int encode_get_firmware_parameters_req(uint8_t instance_id,
917 				       size_t payload_length,
918 				       struct pldm_msg *msg);
919 
920 /** @brief Decode GetFirmwareParameters response
921  *
922  *  @param[in] msg - Response message
923  *  @param[in] payload_length - Length of response message payload
924  *  @param[out] resp_data - Pointer to get firmware parameters response
925  *  @param[out] active_comp_image_set_ver_str - Pointer to active component
926  *                                              image set version string
927  *  @param[out] pending_comp_image_set_ver_str - Pointer to pending component
928  *                                               image set version string
929  *  @param[out] comp_parameter_table - Pointer to component parameter table
930  *
931  *  @return pldm_completion_codes
932  */
933 int decode_get_firmware_parameters_resp(
934 	const struct pldm_msg *msg, size_t payload_length,
935 	struct pldm_get_firmware_parameters_resp *resp_data,
936 	struct variable_field *active_comp_image_set_ver_str,
937 	struct variable_field *pending_comp_image_set_ver_str,
938 	struct variable_field *comp_parameter_table);
939 
940 /** @brief Decode component entries in the component parameter table which is
941  *         part of the response of GetFirmwareParameters command
942  *
943  *  @param[in] data - Component entry
944  *  @param[in] length - Length of component entry
945  *  @param[out] component_data - Pointer to component parameter table
946  *  @param[out] active_comp_ver_str - Pointer to active component version string
947  *  @param[out] pending_comp_ver_str - Pointer to pending component version
948  *                                     string
949  *
950  *  @return pldm_completion_codes
951  */
952 int decode_get_firmware_parameters_resp_comp_entry(
953 	const uint8_t *data, size_t length,
954 	struct pldm_component_parameter_entry *component_data,
955 	struct variable_field *active_comp_ver_str,
956 	struct variable_field *pending_comp_ver_str);
957 
958 /** @brief Create a PLDM request message for QueryDownstreamDevices
959  *
960  *  @param[in] instance_id - Message's instance id
961  *  @param[out] msg - Message will be written to this
962  *
963  *  @return pldm_completion_codes
964  *
965  *  @note  Caller is responsible for memory alloc and dealloc of param
966  *         'msg.payload'
967  */
968 int encode_query_downstream_devices_req(uint8_t instance_id,
969 					struct pldm_msg *msg);
970 
971 /**
972  * @brief Decodes the response message for Querying Downstream Devices.
973  *
974  * @param[in] msg The PLDM message to decode.
975  * @param[in] payload_length The length of the message payload.
976  * @param[out] resp_data Pointer to the structure to store the decoded response data.
977  * @return pldm_completion_codes
978  *
979  * @note  Caller is responsible for memory alloc and dealloc of param
980  *         'msg.payload'
981  */
982 int decode_query_downstream_devices_resp(
983 	const struct pldm_msg *msg, size_t payload_length,
984 	struct pldm_query_downstream_devices_resp *resp_data);
985 
986 /**
987  * @brief Encodes a request message for Query Downstream Identifiers.
988  *
989  * @param[in] instance_id The instance ID of the PLDM entity.
990  * @param[in] data_transfer_handle The handle for the data transfer.
991  * @param[in] transfer_operation_flag The flag indicating the transfer operation.
992  * @param[out] msg Pointer to the PLDM message structure to store the encoded message.
993  * @param[in] payload_length The length of the payload.
994  * @return pldm_completion_codes
995  *
996  * @note Caller is responsible for memory alloc and dealloc of param
997  *        'msg.payload'
998  */
999 int encode_query_downstream_identifiers_req(
1000 	uint8_t instance_id, uint32_t data_transfer_handle,
1001 	enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg,
1002 	size_t payload_length);
1003 
1004 /**
1005  * @brief Decodes the response message for Querying Downstream Identifiers.
1006  * @param[in] msg The PLDM message to decode.
1007  * @param[in] payload_length The length of the message payload.
1008  * @param[out] resp_data Pointer to the decoded response data.
1009  * @param[out] downstream_devices Pointer to the downstream devices.
1010  * @return pldm_completion_codes
1011  *
1012  * @note Caller is responsible for memory alloc and dealloc of pointer params
1013  */
1014 int decode_query_downstream_identifiers_resp(
1015 	const struct pldm_msg *msg, size_t payload_length,
1016 	struct pldm_query_downstream_identifiers_resp *resp_data,
1017 	struct variable_field *downstream_devices);
1018 
1019 /**
1020  * @brief Encodes request message for Get Downstream Firmware Parameters.
1021  *
1022  * @param[in] instance_id - The instance ID of the PLDM entity.
1023  * @param[in] data_transfer_handle - The handle for the data transfer.
1024  * @param[in] transfer_operation_flag - The flag indicating the transfer operation.
1025  * @param[in,out] msg - A pointer to the PLDM message structure to store the encoded message.
1026  * @param[in] payload_length - The length of the payload.
1027  *
1028  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1029  *         are not allocated, -EOVERFLOW if the payload length is not enough
1030  *         to encode the message, -EBADMSG if the message is not valid.
1031  *
1032  * @note Caller is responsible for memory alloc and dealloc of param
1033  *        'msg.payload'
1034  */
1035 int encode_get_downstream_firmware_params_req(
1036 	uint8_t instance_id, uint32_t data_transfer_handle,
1037 	enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg,
1038 	size_t payload_length);
1039 
1040 /**
1041  * @brief Decode response message for Get Downstream Firmware Parameters
1042  *
1043  * @param[in] msg - The PLDM message to decode
1044  * @param[in] payload_length - The length of the message payload
1045  * @param[out] resp_data - Pointer to the structure to store the decoded response data
1046  * @param[out] downstream_device_param_table - Pointer to the variable field structure
1047  *                                           to store the decoded downstream device
1048  *                                           parameter table
1049  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1050  *         are not allocated, -EOVERFLOW if the payload length is not enough
1051  *         to decode the message, -EBADMSG if the message is not valid.
1052  *
1053  * @note Caller is responsible for memory alloc and dealloc of param
1054  *        'resp_data' and 'downstream_device_param_table'
1055  */
1056 int decode_get_downstream_firmware_params_resp(
1057 	const struct pldm_msg *msg, size_t payload_length,
1058 	struct pldm_get_downstream_firmware_params_resp *resp_data,
1059 	struct variable_field *downstream_device_param_table);
1060 
1061 /**
1062  * @brief Decode the next downstream device parameter table entry
1063  *
1064  * @param[in,out] data - A variable field covering the table entries in the
1065  *                       response message data. @p data is updated to point to
1066  *                       the remaining entries once the current entry has been
1067  *                       decoded.
1068 
1069  * @param[out] entry - The struct object into which the current table entry will
1070  *                     be decoded
1071 
1072  * @param[out] versions - A variable field covering the active and
1073  *                        pending component version strings in the
1074  *                        response message data. The component version
1075  *                        strings can be decoded into @p entry using
1076  *                        decode_downstream_device_parameter_table_entry_versions()
1077  *
1078  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1079  *         are not allocated, -EOVERFLOW if the payload length is not enough
1080  *         to decode the entry.
1081  *
1082  * @note Caller is responsible for memory alloc and dealloc of param
1083  * 	  'entry', 'active_comp_ver_str' and 'pending_comp_ver_str'
1084  */
1085 int decode_downstream_device_parameter_table_entry(
1086 	struct variable_field *data,
1087 	struct pldm_downstream_device_parameter_entry *entry,
1088 	struct variable_field *versions);
1089 
1090 /**
1091  * @brief Decode the downstream device parameter table entry versions
1092  *
1093  * @param[in] versions - pointer to version strings raw data
1094  * @param[in,out] entry - pointer to the decoded downstream device parameter table entry
1095  * @param[out] active - pointer to active component version string, the object pointed-to
1096  *                      must be at least as large as `entry->active_comp_ver_str_len + 1`
1097  * @param[out] pending - pointer to pending component version string, the object pointed-to
1098  *                      must be at least as large as `entry->pending_comp_ver_str_len + 1`
1099  *
1100  * @note Caller is responsible for memory alloc and dealloc of all the params,
1101  *    and the param `entry` should be the instance which has successfully decoded
1102  *    by `decode_downstream_device_parameter_table_entry()`.
1103  *
1104  */
1105 int decode_downstream_device_parameter_table_entry_versions(
1106 	const struct variable_field *versions,
1107 	struct pldm_downstream_device_parameter_entry *entry, char *active,
1108 	char *pending);
1109 
1110 /** @brief Create PLDM request message for RequestUpdate
1111  *
1112  *  @param[in] instance_id - Message's instance id
1113  *  @param[in] max_transfer_size - Maximum size of the variable payload allowed
1114  *                                 to be requested via RequestFirmwareData
1115  *                                 command
1116  *  @param[in] num_of_comp - Total number of components that will be passed to
1117  *                           the FD during the update
1118  *  @param[in] max_outstanding_transfer_req - Total number of outstanding
1119  * 											  RequestFirmwareData
1120  * commands that can be sent by the FD
1121  *  @param[in] pkg_data_len - Value of the FirmwareDevicePackageDataLength field
1122  *                            present in firmware package header
1123  *  @param[in] comp_image_set_ver_str_type - StringType of
1124  *                                           ComponentImageSetVersionString
1125  *  @param[in] comp_image_set_ver_str_len - The length of the
1126  *                                          ComponentImageSetVersionString
1127  *  @param[in] comp_img_set_ver_str - Component Image Set version information
1128  *  @param[in,out] msg - Message will be written to this
1129  *  @param[in] payload_length - Length of request message payload
1130  *
1131  *  @return pldm_completion_codes
1132  *
1133  *  @note Caller is responsible for memory alloc and dealloc of param
1134  *        'msg.payload'
1135  */
1136 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1137 			      uint16_t num_of_comp,
1138 			      uint8_t max_outstanding_transfer_req,
1139 			      uint16_t pkg_data_len,
1140 			      uint8_t comp_image_set_ver_str_type,
1141 			      uint8_t comp_image_set_ver_str_len,
1142 			      const struct variable_field *comp_img_set_ver_str,
1143 			      struct pldm_msg *msg, size_t payload_length);
1144 
1145 /** @brief Decode a RequestUpdate response message
1146  *
1147  *  @param[in] msg - Response message
1148  *  @param[in] payload_length - Length of response message payload
1149  *  @param[out] completion_code - Pointer to hold the completion code
1150  *  @param[out] fd_meta_data_len - Pointer to hold the length of FD metadata
1151  *  @param[out] fd_will_send_pkg_data - Pointer to hold information whether FD
1152  *                                      will send GetPackageData command
1153  *  @return pldm_completion_codes
1154  */
1155 int decode_request_update_resp(const struct pldm_msg *msg,
1156 			       size_t payload_length, uint8_t *completion_code,
1157 			       uint16_t *fd_meta_data_len,
1158 			       uint8_t *fd_will_send_pkg_data);
1159 
1160 /** @brief Create PLDM request message for PassComponentTable
1161  *
1162  *  @param[in] instance_id - Message's instance id
1163  *  @param[in] transfer_flag - TransferFlag
1164  *  @param[in] comp_classification - ComponentClassification
1165  *  @param[in] comp_identifier - ComponentIdentifier
1166  *  @param[in] comp_classification_index - ComponentClassificationIndex
1167  *  @param[in] comp_comparison_stamp - ComponentComparisonStamp
1168  *  @param[in] comp_ver_str_type - ComponentVersionStringType
1169  *  @param[in] comp_ver_str_len - ComponentVersionStringLength
1170  *  @param[in] comp_ver_str - ComponentVersionString
1171  *  @param[in,out] msg - Message will be written to this
1172  *  @param[in] payload_length - Length of request message payload
1173  *                              information
1174  *
1175  *  @return pldm_completion_codes
1176  *
1177  *  @note  Caller is responsible for memory alloc and dealloc of param
1178  *         'msg.payload'
1179  */
1180 int encode_pass_component_table_req(
1181 	uint8_t instance_id, uint8_t transfer_flag,
1182 	uint16_t comp_classification, uint16_t comp_identifier,
1183 	uint8_t comp_classification_index, uint32_t comp_comparison_stamp,
1184 	uint8_t comp_ver_str_type, uint8_t comp_ver_str_len,
1185 	const struct variable_field *comp_ver_str, struct pldm_msg *msg,
1186 	size_t payload_length);
1187 
1188 /** @brief Decode PassComponentTable response message
1189  *
1190  *  @param[in] msg - Response message
1191  *  @param[in] payload_length - Length of response message payload
1192  *  @param[out] completion_code - Pointer to hold completion code
1193  *  @param[out] comp_resp - Pointer to hold component response
1194  *  @param[out] comp_resp_code - Pointer to hold component response code
1195  *
1196  *  @return pldm_completion_codes
1197  */
1198 int decode_pass_component_table_resp(const struct pldm_msg *msg,
1199 				     size_t payload_length,
1200 				     uint8_t *completion_code,
1201 				     uint8_t *comp_resp,
1202 				     uint8_t *comp_resp_code);
1203 
1204 /** @brief Create PLDM request message for UpdateComponent
1205  *
1206  *  @param[in] instance_id - Message's instance id
1207  *  @param[in] comp_classification - ComponentClassification
1208  *  @param[in] comp_identifier - ComponentIdentifier
1209  *  @param[in] comp_classification_index - ComponentClassificationIndex
1210  *  @param[in] comp_comparison_stamp - ComponentComparisonStamp
1211  *  @param[in] comp_image_size - ComponentImageSize
1212  *  @param[in] update_option_flags - UpdateOptionFlags
1213  *  @param[in] comp_ver_str_type - ComponentVersionStringType
1214  *  @param[in] comp_ver_str_len - ComponentVersionStringLength
1215  *  @param[in] comp_ver_str - ComponentVersionString
1216  *  @param[in,out] msg - Message will be written to this
1217  *  @param[in] payload_length - Length of request message payload
1218  *                              information
1219  *
1220  *  @return pldm_completion_codes
1221  *
1222  *  @note  Caller is responsible for memory alloc and dealloc of param
1223  *         'msg.payload'
1224  */
1225 int encode_update_component_req(
1226 	uint8_t instance_id, uint16_t comp_classification,
1227 	uint16_t comp_identifier, uint8_t comp_classification_index,
1228 	uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1229 	bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1230 	uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1231 	struct pldm_msg *msg, size_t payload_length);
1232 
1233 /** @brief Decode UpdateComponent response message
1234  *
1235  *  @param[in] msg - Response message
1236  *  @param[in] payload_length - Length of response message payload
1237  *  @param[out] completion_code - Pointer to hold completion code
1238  *  @param[out] comp_compatibility_resp - Pointer to hold component
1239  *                                        compatibility response
1240  *  @param[out] comp_compatibility_resp_code - Pointer to hold component
1241  *                                             compatibility response code
1242  *  @param[out] update_option_flags_enabled - Pointer to hold
1243  *                                            UpdateOptionsFlagEnabled
1244  *  @param[out] time_before_req_fw_data - Pointer to hold the estimated time
1245  *                                        before sending RequestFirmwareData
1246  *
1247  *  @return pldm_completion_codes
1248  */
1249 int decode_update_component_resp(const struct pldm_msg *msg,
1250 				 size_t payload_length,
1251 				 uint8_t *completion_code,
1252 				 uint8_t *comp_compatibility_resp,
1253 				 uint8_t *comp_compatibility_resp_code,
1254 				 bitfield32_t *update_option_flags_enabled,
1255 				 uint16_t *time_before_req_fw_data);
1256 
1257 /** @brief Decode RequestFirmwareData request message
1258  *
1259  *	@param[in] msg - Request message
1260  *	@param[in] payload_length - Length of request message payload
1261  *	@param[out] offset - Pointer to hold offset
1262  *	@param[out] length - Pointer to hold the size of the component image
1263  *                       segment requested by the FD/FDP
1264  *
1265  *	@return pldm_completion_codes
1266  */
1267 int decode_request_firmware_data_req(const struct pldm_msg *msg,
1268 				     size_t payload_length, uint32_t *offset,
1269 				     uint32_t *length);
1270 
1271 /** @brief Create PLDM response message for RequestFirmwareData
1272  *
1273  *  The ComponentImagePortion is not encoded in the PLDM response message
1274  *  by encode_request_firmware_data_resp to avoid an additional copy. Populating
1275  *  ComponentImagePortion in the PLDM response message is handled by the user
1276  *  of this API. The payload_length validation considers only the
1277  *  CompletionCode.
1278  *
1279  *	@param[in] instance_id - Message's instance id
1280  *	@param[in] completion_code - CompletionCode
1281  *	@param[in,out] msg - Message will be written to this
1282  *  @param[in] payload_length - Length of response message payload
1283  *
1284  *	@return pldm_completion_codes
1285  *
1286  *	@note  Caller is responsible for memory alloc and dealloc of param
1287  *		   'msg.payload'
1288  */
1289 int encode_request_firmware_data_resp(uint8_t instance_id,
1290 				      uint8_t completion_code,
1291 				      struct pldm_msg *msg,
1292 				      size_t payload_length);
1293 
1294 /** @brief Decode TransferComplete request message
1295  *
1296  *  @param[in] msg - Request message
1297  *  @param[in] payload_length - Length of request message payload
1298  *  @param[out] transfer_result - Pointer to hold TransferResult
1299  *
1300  *  @return pldm_completion_codes
1301  */
1302 int decode_transfer_complete_req(const struct pldm_msg *msg,
1303 				 size_t payload_length,
1304 				 uint8_t *transfer_result);
1305 
1306 /** @brief Create PLDM response message for TransferComplete
1307  *
1308  *  @param[in] instance_id - Message's instance id
1309  *  @param[in] completion_code - CompletionCode
1310  *  @param[in,out] msg - Message will be written to this
1311  *  @param[in] payload_length - Length of response message payload
1312  *
1313  *  @return pldm_completion_codes
1314  *
1315  *  @note  Caller is responsible for memory alloc and dealloc of param
1316  *         'msg.payload'
1317  */
1318 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1319 				  struct pldm_msg *msg, size_t payload_length);
1320 
1321 /** @brief Decode VerifyComplete request message
1322  *
1323  *  @param[in] msg - Request message
1324  *  @param[in] payload_length - Length of request message payload
1325  *  @param[in] verify_result - Pointer to hold VerifyResult
1326  *
1327  *  @return pldm_completion_codes
1328  */
1329 int decode_verify_complete_req(const struct pldm_msg *msg,
1330 			       size_t payload_length, uint8_t *verify_result);
1331 
1332 /** @brief Create PLDM response message for VerifyComplete
1333  *
1334  *  @param[in] instance_id - Message's instance id
1335  *  @param[in] completion_code - CompletionCode
1336  *  @param[in,out] msg - Message will be written to this
1337  *  @param[in] payload_length - Length of response message payload
1338  *
1339  *  @return pldm_completion_codes
1340  *
1341  *  @note  Caller is responsible for memory alloc and dealloc of param
1342  *         'msg.payload'
1343  */
1344 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1345 				struct pldm_msg *msg, size_t payload_length);
1346 
1347 /** @brief Decode ApplyComplete request message
1348  *
1349  *  @param[in] msg - Request message
1350  *  @param[in] payload_length - Length of request message payload
1351  *  @param[in] apply_result - Pointer to hold ApplyResult
1352  *  @param[in] comp_activation_methods_modification - Pointer to hold the
1353  *                                        ComponentActivationMethodsModification
1354  *
1355  *  @return pldm_completion_codes
1356  */
1357 int decode_apply_complete_req(
1358 	const struct pldm_msg *msg, size_t payload_length,
1359 	uint8_t *apply_result,
1360 	bitfield16_t *comp_activation_methods_modification);
1361 
1362 /** @brief Create PLDM response message for ApplyComplete
1363  *
1364  *  @param[in] instance_id - Message's instance id
1365  *  @param[in] completion_code - CompletionCode
1366  *  @param[in,out] msg - Message will be written to this
1367  *  @param[in] payload_length - Length of response message payload
1368  *
1369  *  @return pldm_completion_codes
1370  *
1371  *  @note Caller is responsible for memory alloc and dealloc of param
1372  *        'msg.payload'
1373  */
1374 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1375 			       struct pldm_msg *msg, size_t payload_length);
1376 
1377 /** @brief Create PLDM request message for ActivateFirmware
1378  *
1379  *  @param[in] instance_id - Message's instance id
1380  *  @param[in] self_contained_activation_req SelfContainedActivationRequest
1381  *  @param[in,out] msg - Message will be written to this
1382  *  @param[in] payload_length - Length of request message payload
1383  *
1384  *  @return pldm_completion_codes
1385  *
1386  *  @note  Caller is responsible for memory alloc and dealloc of param
1387  *         'msg.payload'
1388  */
1389 int encode_activate_firmware_req(uint8_t instance_id,
1390 				 bool8_t self_contained_activation_req,
1391 				 struct pldm_msg *msg, size_t payload_length);
1392 
1393 /** @brief Decode ActivateFirmware response message
1394  *
1395  *  @param[in] msg - Response message
1396  *  @param[in] payload_length - Length of response message payload
1397  *  @param[out] completion_code - Pointer to hold CompletionCode
1398  *  @param[out] estimated_time_activation - Pointer to hold
1399  *                                       EstimatedTimeForSelfContainedActivation
1400  *
1401  *  @return pldm_completion_codes
1402  */
1403 int decode_activate_firmware_resp(const struct pldm_msg *msg,
1404 				  size_t payload_length,
1405 				  uint8_t *completion_code,
1406 				  uint16_t *estimated_time_activation);
1407 
1408 /** @brief Create PLDM request message for GetStatus
1409  *
1410  *  @param[in] instance_id - Message's instance id
1411  *  @param[in,out] msg - Message will be written to this
1412  *  @param[in] payload_length - Length of request message payload
1413  *
1414  *  @return pldm_completion_codes
1415  *
1416  *  @note Caller is responsible for memory alloc and dealloc of param
1417  *        'msg.payload'
1418  */
1419 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1420 			  size_t payload_length);
1421 
1422 /** @brief Decode GetStatus response message
1423  *
1424  *  @param[in] msg - Response message
1425  *  @param[in] payload_length - Length of response message payload
1426  *  @param[out] completion_code - Pointer to completion code
1427  *  @param[out] current_state - Pointer to current state machine state
1428  *  @param[out] previous_state - Pointer to previous different state machine
1429  *                               state
1430  *  @param[out] aux_state - Pointer to current operation state of FD/FDP
1431  *  @param[out] aux_state_status - Pointer to aux state status
1432  *  @param[out] progress_percent - Pointer to progress percentage
1433  *  @param[out] reason_code - Pointer to reason for entering current state
1434  *  @param[out] update_option_flags_enabled - Pointer to update option flags
1435  *                                            enabled
1436  *
1437  *  @return pldm_completion_codes
1438  */
1439 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1440 			   uint8_t *completion_code, uint8_t *current_state,
1441 			   uint8_t *previous_state, uint8_t *aux_state,
1442 			   uint8_t *aux_state_status, uint8_t *progress_percent,
1443 			   uint8_t *reason_code,
1444 			   bitfield32_t *update_option_flags_enabled);
1445 
1446 /** @brief Create PLDM request message for CancelUpdateComponent
1447  *
1448  *  @param[in] instance_id - Message's instance id
1449  *  @param[in,out] msg - Message will be written to this
1450  *  @param[in] payload_length - Length of request message payload
1451  *
1452  *  @return pldm_completion_codes
1453  *
1454  *  @note  Caller is responsible for memory alloc and dealloc of param
1455  *         'msg.payload'
1456  */
1457 int encode_cancel_update_component_req(uint8_t instance_id,
1458 				       struct pldm_msg *msg,
1459 				       size_t payload_length);
1460 
1461 /** @brief Decode CancelUpdateComponent response message
1462  *
1463  *  @param[in] msg - Response message
1464  *  @param[in] payload_length - Length of response message payload
1465  *  @param[out] completion_code - Pointer to the completion code
1466  *
1467  *  @return pldm_completion_codes
1468  */
1469 int decode_cancel_update_component_resp(const struct pldm_msg *msg,
1470 					size_t payload_length,
1471 					uint8_t *completion_code);
1472 
1473 /** @brief Create PLDM request message for CancelUpdate
1474  *
1475  *	@param[in] instance_id - Message's instance id
1476  *	@param[in,out] msg - Message will be written to this
1477  *  @param[in] payload_length - Length of request message payload
1478  *
1479  *	@return pldm_completion_codes
1480  *
1481  *	@note  Caller is responsible for memory alloc and dealloc of param
1482  *         'msg.payload'
1483  */
1484 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
1485 			     size_t payload_length);
1486 
1487 /** @brief Decode CancelUpdate response message
1488  *
1489  *	@param[in] msg - Response message
1490  *  @param[in] payload_length - Length of response message payload
1491  *	@param[out] completion_code - Pointer to completion code
1492  *	@param[out] non_functioning_component_indication - Pointer to non
1493 						       functioning
1494  *                                                     component indication
1495  *	@param[out] non_functioning_component_bitmap - Pointer to non
1496  functioning
1497  *                                                 component bitmap
1498  *
1499  *	@return pldm_completion_codes
1500  */
1501 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
1502 			      uint8_t *completion_code,
1503 			      bool8_t *non_functioning_component_indication,
1504 			      bitfield64_t *non_functioning_component_bitmap);
1505 
1506 #ifdef __cplusplus
1507 }
1508 #endif
1509 
1510 #endif // End of FW_UPDATE_H
1511