xref: /openbmc/libpldm/include/libpldm/firmware_update.h (revision 33ff135a3a086aa1e8c8dc9293a405f39520adae)
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 "compiler.h"
10 
11 #include <libpldm/api.h>
12 #include <libpldm/base.h>
13 #include <libpldm/pldm_types.h>
14 #include <libpldm/utils.h>
15 
16 #include <assert.h>
17 #include <stdbool.h>
18 #include <stddef.h>
19 #include <stdint.h>
20 
21 #define PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE		 8
22 #define PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP 0xffffffff
23 #define PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES		 0
24 
25 /** @brief Length of QueryDownstreamDevices response defined in DSP0267_1.1.0
26  *  Table 15 - QueryDownstreamDevices command format.
27  *
28  *  1 byte for completion code
29  *  1 byte for downstream device update supported
30  *  2 bytes for number of downstream devices
31  *  2 bytes for max number of downstream devices
32  *  4 bytes for capabilities
33  */
34 #define PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES 10
35 
36 /** @brief Length of QueryDownstreamIdentifiers request defined in DSP0267_1.1.0
37  * 	Table 16 - QueryDownstreamIdentifiers command format.
38  *
39  *  4 bytes for data transfer handle
40  *  1 byte for transfer operation flag
41 */
42 #define PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES 5
43 
44 /** @brief Minimum length of QueryDownstreamIdentifiers response from DSP0267_1.1.0
45  *  if the complement code is success.
46  *
47  *  1 byte for completion code
48  *  4 bytes for next data transfer handle
49  *  1 byte for transfer flag
50  *  4 bytes for downstream devices length
51  *  2 bytes for number of downstream devices
52  */
53 #define PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN 12
54 
55 /** @brief Minimum length of device descriptor, 2 bytes for descriptor type,
56  *         2 bytes for descriptor length and at least 1 byte of descriptor data
57  */
58 #define PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN 5
59 
60 /** @brief Length of GetDownstreamFirmwareParameters request defined in DSP0267_1.1.0
61  *
62  * 4 bytes for Data Transfer Handle
63  * 1 byte for Transfer Operation Flag
64  */
65 #define PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES 5
66 
67 /** @brief Minimum length of GetDownstreamFirmwareParameters response from
68  * DSP0267_1.1.0 if the completion code is success.
69  *
70  * 1 byte for completion code
71  * 4 bytes for next data transfer handle
72  * 1 byte for transfer flag
73  * 4 bytes for FDP capabilities during update
74  * 2 bytes for downstream device count
75  */
76 #define PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN 12
77 
78 /** @brief Minimum length of DownstreamDeviceParameterTable entry from
79  * DSP0267_1.1.0 table 21 - DownstreamDeviceParameterTable
80  *
81  * 2 bytes for Downstream Device Index
82  * 4 bytes for Active Component Comparison Stamp
83  * 1 byte for Active Component Version String Type
84  * 1 byte for Active Component Version String Length
85  * 8 bytes for Active Component Release Date
86  * 4 bytes for Pending Component Comparison Stamp
87  * 1 byte for Pending Component Version String Type
88  * 1 byte for Pending Component Version String Length
89  * 8 bytes for Pending Component Release Date
90  * 2 bytes for Component Activation Methods
91  * 4 bytes for Capabilities During Update
92  */
93 #define PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN 36
94 
95 #define PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES 0
96 #define PLDM_FWUP_BASELINE_TRANSFER_SIZE       32
97 #define PLDM_FWUP_MIN_OUTSTANDING_REQ	       1
98 #define PLDM_GET_STATUS_REQ_BYTES	       0
99 /* Maximum progress percentage value*/
100 #define PLDM_FWUP_MAX_PROGRESS_PERCENT	       0x65
101 #define PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES 0
102 #define PLDM_CANCEL_UPDATE_REQ_BYTES	       0
103 
104 /** @brief PLDM component release data size in bytes defined in DSP0267_1.1.0
105  * Table 14 - ComponentParameterTable and Table 21 - ComponentParameterTable
106  *
107  * The size can be used in `ASCII[8] - ActiveComponentReleaseDate` and
108  * `ASCII[8] - PendingComponentReleaseDate` fields in the tables above.
109  */
110 #define PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN 8
111 
112 /** @brief PLDM Firmware update commands
113  */
114 enum pldm_firmware_update_commands {
115 	PLDM_QUERY_DEVICE_IDENTIFIERS = 0x01,
116 	PLDM_GET_FIRMWARE_PARAMETERS = 0x02,
117 	PLDM_QUERY_DOWNSTREAM_DEVICES = 0x03,
118 	PLDM_QUERY_DOWNSTREAM_IDENTIFIERS = 0x04,
119 	PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS = 0x05,
120 	PLDM_REQUEST_UPDATE = 0x10,
121 	PLDM_PASS_COMPONENT_TABLE = 0x13,
122 	PLDM_UPDATE_COMPONENT = 0x14,
123 	PLDM_REQUEST_FIRMWARE_DATA = 0x15,
124 	PLDM_TRANSFER_COMPLETE = 0x16,
125 	PLDM_VERIFY_COMPLETE = 0x17,
126 	PLDM_APPLY_COMPLETE = 0x18,
127 	PLDM_GET_META_DATA = 0x19,
128 	PLDM_ACTIVATE_FIRMWARE = 0x1a,
129 	PLDM_GET_STATUS = 0x1b,
130 	PLDM_CANCEL_UPDATE_COMPONENT = 0x1c,
131 	PLDM_CANCEL_UPDATE = 0x1d,
132 	PLDM_ACTIVATE_PENDING_COMPONENT_IMAGE_SET = 0x1e,
133 	PLDM_ACTIVATE_PENDING_COMPONENT_IMAGE = 0x1f,
134 	PLDM_REQUEST_DOWNSTREAM_DEVICE_UPDATE = 0x20,
135 	PLDM_GET_COMPONENT_OPAQUE_DATA = 0x21,
136 	PLDM_UPTATE_SECURITY_REVISION = 0x22
137 };
138 
139 /** @brief PLDM Firmware update completion codes
140  */
141 enum pldm_firmware_update_completion_codes {
142 	PLDM_FWUP_NOT_IN_UPDATE_MODE = 0x80,
143 	PLDM_FWUP_ALREADY_IN_UPDATE_MODE = 0x81,
144 	PLDM_FWUP_DATA_OUT_OF_RANGE = 0x82,
145 	PLDM_FWUP_INVALID_TRANSFER_LENGTH = 0x83,
146 	PLDM_FWUP_INVALID_STATE_FOR_COMMAND = 0x84,
147 	PLDM_FWUP_INCOMPLETE_UPDATE = 0x85,
148 	PLDM_FWUP_BUSY_IN_BACKGROUND = 0x86,
149 	PLDM_FWUP_CANCEL_PENDING = 0x87,
150 	PLDM_FWUP_COMMAND_NOT_EXPECTED = 0x88,
151 	PLDM_FWUP_RETRY_REQUEST_FW_DATA = 0x89,
152 	PLDM_FWUP_UNABLE_TO_INITIATE_UPDATE = 0x8a,
153 	PLDM_FWUP_ACTIVATION_NOT_REQUIRED = 0x8b,
154 	PLDM_FWUP_SELF_CONTAINED_ACTIVATION_NOT_PERMITTED = 0x8c,
155 	PLDM_FWUP_NO_DEVICE_METADATA = 0x8d,
156 	PLDM_FWUP_RETRY_REQUEST_UPDATE = 0x8e,
157 	PLDM_FWUP_NO_PACKAGE_DATA = 0x8f,
158 	PLDM_FWUP_INVALID_TRANSFER_HANDLE = 0x90,
159 	PLDM_FWUP_INVALID_TRANSFER_OPERATION_FLAG = 0x91,
160 	PLDM_FWUP_ACTIVATE_PENDING_IMAGE_NOT_PERMITTED = 0x92,
161 	PLDM_FWUP_PACKAGE_DATA_ERROR = 0x93
162 };
163 
164 /** @brief String type values defined in the PLDM firmware update specification
165  */
166 enum pldm_firmware_update_string_type {
167 	PLDM_STR_TYPE_UNKNOWN = 0,
168 	PLDM_STR_TYPE_ASCII = 1,
169 	PLDM_STR_TYPE_UTF_8 = 2,
170 	PLDM_STR_TYPE_UTF_16 = 3,
171 	PLDM_STR_TYPE_UTF_16LE = 4,
172 	PLDM_STR_TYPE_UTF_16BE = 5
173 };
174 
175 /** @brief Descriptor types defined in PLDM firmware update specification
176  */
177 enum pldm_firmware_update_descriptor_types {
178 	PLDM_FWUP_PCI_VENDOR_ID = 0x0000,
179 	PLDM_FWUP_IANA_ENTERPRISE_ID = 0x0001,
180 	PLDM_FWUP_UUID = 0x0002,
181 	PLDM_FWUP_PNP_VENDOR_ID = 0x0003,
182 	PLDM_FWUP_ACPI_VENDOR_ID = 0x0004,
183 	PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID = 0x0005,
184 	PLDM_FWUP_SCSI_VENDOR_ID = 0x0006,
185 	PLDM_FWUP_PCI_DEVICE_ID = 0x0100,
186 	PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID = 0x0101,
187 	PLDM_FWUP_PCI_SUBSYSTEM_ID = 0x0102,
188 	PLDM_FWUP_PCI_REVISION_ID = 0x0103,
189 	PLDM_FWUP_PNP_PRODUCT_IDENTIFIER = 0x0104,
190 	PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER = 0x0105,
191 	PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING = 0x0106,
192 	PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING = 0x0107,
193 	PLDM_FWUP_SCSI_PRODUCT_ID = 0x0108,
194 	PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE = 0x0109,
195 	PLDM_FWUP_VENDOR_DEFINED = 0xffff
196 };
197 
198 /** @brief Descriptor types length defined in PLDM firmware update specification
199  */
200 enum pldm_firmware_update_descriptor_types_length {
201 	PLDM_FWUP_PCI_VENDOR_ID_LENGTH = 2,
202 	PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH = 4,
203 	PLDM_FWUP_UUID_LENGTH = 16,
204 	PLDM_FWUP_PNP_VENDOR_ID_LENGTH = 3,
205 	PLDM_FWUP_ACPI_VENDOR_ID_LENGTH = 4,
206 	PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH = 3,
207 	PLDM_FWUP_SCSI_VENDOR_ID_LENGTH = 8,
208 	PLDM_FWUP_PCI_DEVICE_ID_LENGTH = 2,
209 	PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH = 2,
210 	PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH = 2,
211 	PLDM_FWUP_PCI_REVISION_ID_LENGTH = 1,
212 	PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH = 4,
213 	PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH = 4,
214 	PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH = 40,
215 	PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH = 10,
216 	PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH = 16,
217 	PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH = 4
218 };
219 
220 /** @brief ComponentClassification values defined in firmware update
221  *         specification
222  */
223 enum pldm_component_classification_values {
224 	PLDM_COMP_UNKNOWN = 0x0000,
225 	PLDM_COMP_OTHER = 0x0001,
226 	PLDM_COMP_DRIVER = 0x0002,
227 	PLDM_COMP_CONFIGURATION_SOFTWARE = 0x0003,
228 	PLDM_COMP_APPLICATION_SOFTWARE = 0x0004,
229 	PLDM_COMP_INSTRUMENTATION = 0x0005,
230 	PLDM_COMP_FIRMWARE_OR_BIOS = 0x0006,
231 	PLDM_COMP_DIAGNOSTIC_SOFTWARE = 0x0007,
232 	PLDM_COMP_OPERATING_SYSTEM = 0x0008,
233 	PLDM_COMP_MIDDLEWARE = 0x0009,
234 	PLDM_COMP_FIRMWARE = 0x000a,
235 	PLDM_COMP_BIOS_OR_FCODE = 0x000b,
236 	PLDM_COMP_SUPPORT_OR_SERVICEPACK = 0x000c,
237 	PLDM_COMP_SOFTWARE_BUNDLE = 0x000d,
238 	PLDM_COMP_DOWNSTREAM_DEVICE = 0xffff
239 };
240 
241 /** @brief ComponentActivationMethods is the bit position in the bitfield that
242  *         provides the capability of the FD for firmware activation. Multiple
243  *         activation methods can be supported.
244  */
245 enum pldm_comp_activation_methods {
246 	PLDM_ACTIVATION_AUTOMATIC = 0,
247 	PLDM_ACTIVATION_SELF_CONTAINED = 1,
248 	PLDM_ACTIVATION_MEDIUM_SPECIFIC_RESET = 2,
249 	PLDM_ACTIVATION_SYSTEM_REBOOT = 3,
250 	PLDM_ACTIVATION_DC_POWER_CYCLE = 4,
251 	PLDM_ACTIVATION_AC_POWER_CYCLE = 5,
252 	PLDM_SUPPORTS_ACTIVATE_PENDING_IMAGE = 6,
253 	PLDM_SUPPORTS_ACTIVATE_PENDING_IMAGE_SET = 7
254 };
255 
256 /** @brief ComponentResponse values in the response of PassComponentTable
257  */
258 enum pldm_component_responses {
259 	PLDM_CR_COMP_CAN_BE_UPDATED = 0,
260 	PLDM_CR_COMP_MAY_BE_UPDATEABLE = 1
261 };
262 
263 /** @brief ComponentResponseCode values in the response of PassComponentTable
264  */
265 enum pldm_component_response_codes {
266 	PLDM_CRC_COMP_CAN_BE_UPDATED = 0x00,
267 	PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL = 0x01,
268 	PLDM_CRC_COMP_COMPARISON_STAMP_LOWER = 0x02,
269 	PLDM_CRC_INVALID_COMP_COMPARISON_STAMP = 0x03,
270 	PLDM_CRC_COMP_CONFLICT = 0x04,
271 	PLDM_CRC_COMP_PREREQUISITES_NOT_MET = 0x05,
272 	PLDM_CRC_COMP_NOT_SUPPORTED = 0x06,
273 	PLDM_CRC_COMP_SECURITY_RESTRICTIONS = 0x07,
274 	PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET = 0x08,
275 	PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY = 0x09,
276 	PLDM_CRC_COMP_VER_STR_IDENTICAL = 0x0a,
277 	PLDM_CRC_COMP_VER_STR_LOWER = 0x0b,
278 	PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN = 0xd0,
279 	PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX = 0xef
280 };
281 
282 /** @brief ComponentCompatibilityResponse values in the response of
283  *         UpdateComponent
284  */
285 enum pldm_component_compatibility_responses {
286 	PLDM_CCR_COMP_CAN_BE_UPDATED = 0,
287 	PLDM_CCR_COMP_CANNOT_BE_UPDATED = 1
288 };
289 
290 /** @brief ComponentCompatibilityResponse Code values in the response of
291  *         UpdateComponent
292  */
293 enum pldm_component_compatibility_response_codes {
294 	PLDM_CCRC_NO_RESPONSE_CODE = 0x00,
295 	PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL = 0x01,
296 	PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER = 0x02,
297 	PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP = 0x03,
298 	PLDM_CCRC_COMP_CONFLICT = 0x04,
299 	PLDM_CCRC_COMP_PREREQUISITES_NOT_MET = 0x05,
300 	PLDM_CCRC_COMP_NOT_SUPPORTED = 0x06,
301 	PLDM_CCRC_COMP_SECURITY_RESTRICTIONS = 0x07,
302 	PLDM_CCRC_INCOMPLETE_COMP_IMAGE_SET = 0x08,
303 	PLDM_CCRC_COMP_INFO_NO_MATCH = 0x09,
304 	PLDM_CCRC_COMP_VER_STR_IDENTICAL = 0x0a,
305 	PLDM_CCRC_COMP_VER_STR_LOWER = 0x0b,
306 	PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN = 0xd0,
307 	PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX = 0xef
308 };
309 
310 /** @brief Common error codes in TransferComplete, VerifyComplete and
311  *        ApplyComplete request
312  */
313 enum pldm_firmware_update_common_error_codes {
314 	PLDM_FWUP_TIME_OUT = 0x09,
315 	PLDM_FWUP_GENERIC_ERROR = 0x0a
316 };
317 
318 /** @brief TransferResult values in the request of TransferComplete
319  */
320 enum pldm_firmware_update_transfer_result_values {
321 	PLDM_FWUP_TRANSFER_SUCCESS = 0x00,
322 	PLDM_FWUP_TRANSFER_ERROR_IMAGE_CORRUPT = 0x02,
323 	PLDM_FWUP_TRANSFER_ERROR_VERSION_MISMATCH = 0x02,
324 	PLDM_FWUP_FD_ABORTED_TRANSFER = 0x03,
325 	PLDM_FWUP_FD_ABORTED_TRANSFER_LOW_POWER_STATE = 0x0b,
326 	PLDM_FWUP_FD_ABORTED_TRANSFER_RESET_NEEDED = 0x0c,
327 	PLDM_FWUP_FD_ABORTED_TRANSFER_STORAGE_ISSUE = 0x0d,
328 	PLDM_FWUP_VENDOR_TRANSFER_RESULT_RANGE_MIN = 0x70,
329 	PLDM_FWUP_VENDOR_TRANSFER_RESULT_RANGE_MAX = 0x8f
330 };
331 
332 /**@brief VerifyResult values in the request of VerifyComplete
333  */
334 enum pldm_firmware_update_verify_result_values {
335 	PLDM_FWUP_VERIFY_SUCCESS = 0x00,
336 	PLDM_FWUP_VERIFY_ERROR_VERIFICATION_FAILURE = 0x01,
337 	PLDM_FWUP_VERIFY_ERROR_VERSION_MISMATCH = 0x02,
338 	PLDM_FWUP_VERIFY_FAILED_FD_SECURITY_CHECKS = 0x03,
339 	PLDM_FWUP_VERIFY_ERROR_IMAGE_INCOMPLETE = 0x04,
340 	PLDM_FWUP_VENDOR_VERIFY_RESULT_RANGE_MIN = 0x90,
341 	PLDM_FWUP_VENDOR_VERIFY_RESULT_RANGE_MAX = 0xaf
342 };
343 
344 /**@brief ApplyResult values in the request of ApplyComplete
345  */
346 enum pldm_firmware_update_apply_result_values {
347 	PLDM_FWUP_APPLY_SUCCESS = 0x00,
348 	PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD = 0x01,
349 	PLDM_FWUP_APPLY_FAILURE_MEMORY_ISSUE = 0x02,
350 	PLDM_FWUP_VENDOR_APPLY_RESULT_RANGE_MIN = 0xb0,
351 	PLDM_FWUP_VENDOR_APPLY_RESULT_RANGE_MAX = 0xcf
352 };
353 
354 /** @brief SelfContainedActivationRequest in the request of ActivateFirmware
355  */
356 enum pldm_self_contained_activation_req {
357 	PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS = false,
358 	PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS = true
359 };
360 
361 /** @brief Current state/previous state of the FD or FDP returned in GetStatus
362  *         response
363  */
364 enum pldm_firmware_device_states {
365 	PLDM_FD_STATE_IDLE = 0,
366 	PLDM_FD_STATE_LEARN_COMPONENTS = 1,
367 	PLDM_FD_STATE_READY_XFER = 2,
368 	PLDM_FD_STATE_DOWNLOAD = 3,
369 	PLDM_FD_STATE_VERIFY = 4,
370 	PLDM_FD_STATE_APPLY = 5,
371 	PLDM_FD_STATE_ACTIVATE = 6
372 };
373 
374 /** @brief Firmware device aux state in GetStatus response
375  */
376 enum pldm_get_status_aux_states {
377 	PLDM_FD_OPERATION_IN_PROGRESS = 0,
378 	PLDM_FD_OPERATION_SUCCESSFUL = 1,
379 	PLDM_FD_OPERATION_FAILED = 2,
380 	PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER = 3
381 };
382 
383 /** @brief Firmware device aux state status in GetStatus response
384  */
385 enum pldm_get_status_aux_state_status_values {
386 	PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS = 0x00,
387 	PLDM_FD_TIMEOUT = 0x09,
388 	PLDM_FD_GENERIC_ERROR = 0x0a,
389 	PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START = 0x70,
390 	PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END = 0xef
391 };
392 
393 /** @brief Firmware device reason code in GetStatus response
394  */
395 enum pldm_get_status_reason_code_values {
396 	PLDM_FD_INITIALIZATION = 0,
397 	PLDM_FD_ACTIVATE_FW = 1,
398 	PLDM_FD_CANCEL_UPDATE = 2,
399 	PLDM_FD_TIMEOUT_LEARN_COMPONENT = 3,
400 	PLDM_FD_TIMEOUT_READY_XFER = 4,
401 	PLDM_FD_TIMEOUT_DOWNLOAD = 5,
402 	PLDM_FD_TIMEOUT_VERIFY = 6,
403 	PLDM_FD_TIMEOUT_APPLY = 7,
404 	PLDM_FD_STATUS_VENDOR_DEFINED_MIN = 200,
405 	PLDM_FD_STATUS_VENDOR_DEFINED_MAX = 255
406 };
407 
408 /** @brief Components functional indicator in CancelUpdate response
409  */
410 enum pldm_firmware_update_non_functioning_component_indication {
411 	PLDM_FWUP_COMPONENTS_FUNCTIONING = 0,
412 	PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING = 1
413 };
414 
415 /** @brief Downstream device update supported in QueryDownstreamDevices response
416  *         defined in DSP0267_1.1.0
417 */
418 enum pldm_firmware_update_downstream_device_update_supported {
419 	PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED = 0,
420 	PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED = 1
421 };
422 
423 /* An arbitrary limit, for static storage */
424 #define PLDM_FIRMWARE_MAX_STRING 64
425 
426 /** @struct pldm_firmware_string
427  *
428  *  A fixed maximum length PLDM firmware string
429 */
430 struct pldm_firmware_string {
431 	enum pldm_firmware_update_string_type str_type;
432 	uint8_t str_len;
433 	uint8_t str_data[PLDM_FIRMWARE_MAX_STRING];
434 };
435 
436 /** @struct pldm_firmware_version
437  *
438  *  A PLDM component version
439 */
440 struct pldm_firmware_version {
441 	uint32_t comparison_stamp;
442 	struct pldm_firmware_string str;
443 	uint8_t date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN];
444 };
445 
446 /** @struct pldm_package_header_information
447  *
448  *  Structure representing fixed part of package header information
449  */
450 struct pldm_package_header_information {
451 	uint8_t uuid[PLDM_FWUP_UUID_LENGTH];
452 	uint8_t package_header_format_version;
453 	uint16_t package_header_size;
454 	uint8_t package_release_date_time[PLDM_TIMESTAMP104_SIZE];
455 	uint16_t component_bitmap_bit_length;
456 	uint8_t package_version_string_type;
457 	uint8_t package_version_string_length;
458 } __attribute__((packed));
459 
460 /** @struct pldm_firmware_device_id_record
461  *
462  *  Structure representing firmware device ID record
463  */
464 struct pldm_firmware_device_id_record {
465 	uint16_t record_length;
466 	uint8_t descriptor_count;
467 	bitfield32_t device_update_option_flags;
468 	uint8_t comp_image_set_version_string_type;
469 	uint8_t comp_image_set_version_string_length;
470 	uint16_t fw_device_pkg_data_length;
471 } __attribute__((packed));
472 
473 /** @struct pldm_descriptor_tlv
474  *
475  *  Structure representing descriptor type, length and value
476  */
477 struct pldm_descriptor_tlv {
478 	uint16_t descriptor_type;
479 	uint16_t descriptor_length;
480 	uint8_t descriptor_data[1];
481 } __attribute__((packed));
482 
483 /** @struct pldm_vendor_defined_descriptor_title_data
484  *
485  *  Structure representing vendor defined descriptor title sections
486  */
487 struct pldm_vendor_defined_descriptor_title_data {
488 	uint8_t vendor_defined_descriptor_title_str_type;
489 	uint8_t vendor_defined_descriptor_title_str_len;
490 	uint8_t vendor_defined_descriptor_title_str[1];
491 } __attribute__((packed));
492 
493 /** @struct pldm_component_image_information
494  *
495  *  Structure representing fixed part of individual component information in
496  *  PLDM firmware update package
497  */
498 struct pldm_component_image_information {
499 	uint16_t comp_classification;
500 	uint16_t comp_identifier;
501 	uint32_t comp_comparison_stamp;
502 	bitfield16_t comp_options;
503 	bitfield16_t requested_comp_activation_method;
504 	uint32_t comp_location_offset;
505 	uint32_t comp_size;
506 	uint8_t comp_version_string_type;
507 	uint8_t comp_version_string_length;
508 } __attribute__((packed));
509 
510 /** @struct pldm_query_device_identifiers_resp
511  *
512  *  Structure representing query device identifiers response.
513  */
514 struct pldm_query_device_identifiers_resp {
515 	uint8_t completion_code;
516 	uint32_t device_identifiers_len;
517 	uint8_t descriptor_count;
518 } __attribute__((packed));
519 
520 /** @struct pldm_get_firmware_parameters_resp
521  *
522  *  Structure representing the fixed part of GetFirmwareParameters response
523  */
524 struct pldm_get_firmware_parameters_resp {
525 	uint8_t completion_code;
526 	bitfield32_t capabilities_during_update;
527 	uint16_t comp_count;
528 	uint8_t active_comp_image_set_ver_str_type;
529 	uint8_t active_comp_image_set_ver_str_len;
530 	uint8_t pending_comp_image_set_ver_str_type;
531 	uint8_t pending_comp_image_set_ver_str_len;
532 } __attribute__((packed));
533 
534 /** @struct pldm_get_firmware_parameters_resp_full
535  *
536  *  Structure representing a full GetFirmwareParameters response
537  */
538 struct pldm_get_firmware_parameters_resp_full {
539 	uint8_t completion_code;
540 	bitfield32_t capabilities_during_update;
541 	uint16_t comp_count;
542 	struct pldm_firmware_string active_comp_image_set_ver_str;
543 	struct pldm_firmware_string pending_comp_image_set_ver_str;
544 };
545 
546 /** @struct pldm_query_downstream_devices_resp
547  *
548  *  Structure representing response of QueryDownstreamDevices.
549  *  The definition can be found Table 15 - QueryDownstreamDevices command format
550  *  in DSP0267_1.1.0
551  */
552 struct pldm_query_downstream_devices_resp {
553 	uint8_t completion_code;
554 	uint8_t downstream_device_update_supported;
555 	uint16_t number_of_downstream_devices;
556 	uint16_t max_number_of_downstream_devices;
557 	bitfield32_t capabilities;
558 };
559 
560 /** @struct pldm_component_parameter_entry
561  *
562  *  Structure representing component parameter table entry, as wire format.
563  */
564 struct pldm_component_parameter_entry {
565 	uint16_t comp_classification;
566 	uint16_t comp_identifier;
567 	uint8_t comp_classification_index;
568 	uint32_t active_comp_comparison_stamp;
569 	uint8_t active_comp_ver_str_type;
570 	uint8_t active_comp_ver_str_len;
571 	uint8_t active_comp_release_date[8];
572 	uint32_t pending_comp_comparison_stamp;
573 	uint8_t pending_comp_ver_str_type;
574 	uint8_t pending_comp_ver_str_len;
575 	uint8_t pending_comp_release_date[8];
576 	bitfield16_t comp_activation_methods;
577 	bitfield32_t capabilities_during_update;
578 } __attribute__((packed));
579 
580 /** @struct pldm_component_parameter_entry_full
581  *
582  *  Structure representing component parameter table entry.
583  *  This is non-packed (contrast with struct pldm_component_parameter_entry),
584  *  with version strings included.
585  */
586 struct pldm_component_parameter_entry_full {
587 	uint16_t comp_classification;
588 	uint16_t comp_identifier;
589 	uint8_t comp_classification_index;
590 
591 	struct pldm_firmware_version active_ver;
592 	struct pldm_firmware_version pending_ver;
593 
594 	bitfield16_t comp_activation_methods;
595 	bitfield32_t capabilities_during_update;
596 };
597 
598 /** @struct pldm_query_downstream_identifiers_req
599  *
600  *  Structure for QueryDownstreamIdentifiers request defined in Table 16 -
601  *  QueryDownstreamIdentifiers command format in DSP0267_1.1.0
602  */
603 struct pldm_query_downstream_identifiers_req {
604 	uint32_t data_transfer_handle;
605 	uint8_t transfer_operation_flag;
606 };
607 
608 /** @struct pldm_query_downstream_identifiers_resp
609  *
610  *  Structure representing the fixed part of QueryDownstreamIdentifiers response
611  *  defined in Table 16 - QueryDownstreamIdentifiers command format, and
612  *  Table 17 - QueryDownstreamIdentifiers response definition in DSP0267_1.1.0.
613  *
614  *  Squash the two tables into one since the definition of
615  *  Table 17 is `Portion of QueryDownstreamIdentifiers response`
616  */
617 struct pldm_query_downstream_identifiers_resp {
618 	uint8_t completion_code;
619 	uint32_t next_data_transfer_handle;
620 	uint8_t transfer_flag;
621 	uint32_t downstream_devices_length;
622 	uint16_t number_of_downstream_devices;
623 };
624 
625 /** @struct pldm_downstream_device
626  *
627  *  Structure representing downstream device information defined in
628  *  Table 18 - DownstreamDevice definition in DSP0267_1.1.0
629  */
630 struct pldm_downstream_device {
631 	uint16_t downstream_device_index;
632 	uint8_t downstream_descriptor_count;
633 };
634 #define PLDM_DOWNSTREAM_DEVICE_BYTES 3
635 
636 struct pldm_downstream_device_iter {
637 	struct variable_field field;
638 	size_t devs;
639 };
640 
641 LIBPLDM_ITERATOR
pldm_downstream_device_iter_end(const struct pldm_downstream_device_iter * iter)642 bool pldm_downstream_device_iter_end(
643 	const struct pldm_downstream_device_iter *iter)
644 {
645 	return !iter->devs;
646 }
647 
648 LIBPLDM_ITERATOR
pldm_downstream_device_iter_next(struct pldm_downstream_device_iter * iter)649 bool pldm_downstream_device_iter_next(struct pldm_downstream_device_iter *iter)
650 {
651 	if (!iter->devs) {
652 		return false;
653 	}
654 
655 	iter->devs--;
656 	return true;
657 }
658 
659 int decode_pldm_downstream_device_from_iter(
660 	struct pldm_downstream_device_iter *iter,
661 	struct pldm_downstream_device *dev);
662 
663 /** @brief Iterate downstream devices in QueryDownstreamIdentifiers response
664  *
665  * @param devs The @ref "struct pldm_downstream_device_iter" lvalue used as the
666  *                  out-value from the corresponding call to @ref
667  *                  decode_query_downstream_identifiers_resp
668  * @param dev The @ref "struct pldm_downstream_device" lvalue into which the
669  *            next device instance should be decoded.
670  * @param rc An lvalue of type int into which the return code from the decoding
671  *           will be placed.
672  *
673  * Example use of the macro is as follows:
674  *
675  * @code
676  * struct pldm_query_downstream_identifiers_resp resp;
677  * struct pldm_downstream_device_iter devs;
678  * struct pldm_downstream_device dev;
679  * int rc;
680  *
681  * rc = decode_query_downstream_identifiers_resp(..., &resp, &devs);
682  * if (rc) {
683  *     // Handle any error from decoding fixed-portion of response
684  * }
685  *
686  * foreach_pldm_downstream_device(devs, dev, rc) {
687  *     // Do something with each decoded device placed in `dev`
688  * }
689  *
690  * if (rc) {
691  *     // Handle any decoding error while iterating variable-length set of
692  *     // devices
693  * }
694  * @endcode
695  */
696 #define foreach_pldm_downstream_device(devs, dev, rc)                          \
697 	for ((rc) = 0; (!pldm_downstream_device_iter_end(&(devs)) &&           \
698 			!((rc) = decode_pldm_downstream_device_from_iter(      \
699 				  &(devs), &(dev))));                          \
700 	     pldm_downstream_device_iter_next(&(devs)))
701 
702 /** @struct pldm_descriptor
703  *
704  * Structure representing a type-length-value descriptor as defined in Table 7 -
705  * Descriptor Definition.
706  *
707  * Member values are always host-endian. When decoding messages, the
708  * descriptor_data member points into the message buffer.
709  */
710 struct pldm_descriptor {
711 	uint16_t descriptor_type;
712 	uint16_t descriptor_length;
713 	const void *descriptor_data;
714 };
715 
716 struct pldm_descriptor_iter {
717 	struct variable_field *field;
718 	size_t count;
719 };
720 
721 LIBPLDM_ITERATOR
pldm_downstream_device_descriptor_iter_init(struct pldm_downstream_device_iter * devs,const struct pldm_downstream_device * dev)722 struct pldm_descriptor_iter pldm_downstream_device_descriptor_iter_init(
723 	struct pldm_downstream_device_iter *devs,
724 	const struct pldm_downstream_device *dev)
725 {
726 	struct pldm_descriptor_iter iter = { &devs->field,
727 					     dev->downstream_descriptor_count };
728 	return iter;
729 }
730 
731 LIBPLDM_ITERATOR
pldm_descriptor_iter_end(const struct pldm_descriptor_iter * iter)732 bool pldm_descriptor_iter_end(const struct pldm_descriptor_iter *iter)
733 {
734 	return !iter->count;
735 }
736 
737 LIBPLDM_ITERATOR
pldm_descriptor_iter_next(struct pldm_descriptor_iter * iter)738 bool pldm_descriptor_iter_next(struct pldm_descriptor_iter *iter)
739 {
740 	if (!iter->count) {
741 		return false;
742 	}
743 
744 	iter->count--;
745 	return true;
746 }
747 
748 int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter,
749 				     struct pldm_descriptor *desc);
750 
751 /** @brief Iterate a downstream device's descriptors in a
752  *         QueryDownstreamIdentifiers response
753  *
754  * @param devs The @ref "struct pldm_downstream_device_iter" lvalue used as the
755  *                  out-value from the corresponding call to @ref
756  *                  decode_query_downstream_identifiers_resp
757  * @param dev The @ref "struct pldm_downstream_device" lvalue over whose
758  *            descriptors to iterate
759  * @param desc The @ref "struct pldm_descriptor" lvalue into which the next
760  *             descriptor instance should be decoded
761  * @param rc An lvalue of type int into which the return code from the decoding
762  *           will be placed
763  *
764  * Example use of the macro is as follows:
765  *
766  * @code
767  * struct pldm_query_downstream_identifiers_resp resp;
768  * struct pldm_downstream_device_iter devs;
769  * struct pldm_downstream_device dev;
770  * int rc;
771  *
772  * rc = decode_query_downstream_identifiers_resp(..., &resp, &devs);
773  * if (rc) {
774  *     // Handle any error from decoding fixed-portion of response
775  * }
776  *
777  * foreach_pldm_downstream_device(devs, dev, rc) {
778  *     struct pldm_descriptor desc;
779  *
780  *     foreach_pldm_downstream_device_descriptor(devs, dev, desc, rc) {
781  *         // Do something with each decoded descriptor placed in `desc`
782  *     }
783  *
784  *     if (rc) {
785  *         // Handle any decoding error while iterating on the variable-length
786  *         // set of descriptors
787  *     }
788  * }
789  *
790  * if (rc) {
791  *     // Handle any decoding error while iterating variable-length set of
792  *     // devices
793  * }
794  * @endcode
795  */
796 #define foreach_pldm_downstream_device_descriptor(devs, dev, desc, rc)         \
797 	for (struct pldm_descriptor_iter desc##_iter =                         \
798 		     ((rc) = 0, pldm_downstream_device_descriptor_iter_init(   \
799 					&(devs), &(dev)));                     \
800 	     (!pldm_descriptor_iter_end(&(desc##_iter)) &&                     \
801 	      !((rc) = decode_pldm_descriptor_from_iter(&(desc##_iter),        \
802 							&(desc))));            \
803 	     pldm_descriptor_iter_next(&(desc##_iter)))
804 
805 /** @struct pldm_query_downstream_firmware_param_req
806  *
807  *  Structure representing QueryDownstreamFirmwareParameters request
808  */
809 struct pldm_get_downstream_firmware_parameters_req {
810 	uint32_t data_transfer_handle;
811 	uint8_t transfer_operation_flag;
812 };
813 
814 /** @struct pldm_get_downstream_firmware_parameters_resp
815  *
816  *  Structure representing the fixed part of QueryDownstreamFirmwareParameters
817  *  response in Table 19 - GetDownstreamFirmwareParameters command format, and
818  *  Table 20 - QueryDownstreamFirmwareParameters response definition in
819  *  DSP0267_1.1.0.
820  *
821  *  Squash the two tables into one since the definition of Table 20 is `Portion
822  *  of GetDownstreamFirmwareParameters response`
823  */
824 struct pldm_get_downstream_firmware_parameters_resp {
825 	uint8_t completion_code;
826 	uint32_t next_data_transfer_handle;
827 	uint8_t transfer_flag;
828 	bitfield32_t fdp_capabilities_during_update;
829 	uint16_t downstream_device_count;
830 };
831 
832 /** @struct pldm_downstream_device_parameters_entry
833  *
834  *  Structure representing downstream device parameter table entry defined in
835  *  Table 21 - DownstreamDeviceParameterTable in DSP0267_1.1.0
836  *
837  *  Clients should not allocate memory for this struct to decode the response,
838  *  use `pldm_downstream_device_parameter_entry_versions` instead to make sure
839  *  that the active and pending component version strings are copied from the
840  *  message buffer.
841  */
842 struct pldm_downstream_device_parameters_entry {
843 	uint16_t downstream_device_index;
844 	uint32_t active_comp_comparison_stamp;
845 	uint8_t active_comp_ver_str_type;
846 	uint8_t active_comp_ver_str_len;
847 	/* Append 1 bytes for null termination so that it can be used as a
848 	 * Null-terminated string.
849 	 */
850 	char active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN + 1];
851 	uint32_t pending_comp_comparison_stamp;
852 	uint8_t pending_comp_ver_str_type;
853 	uint8_t pending_comp_ver_str_len;
854 	/* Append 1 bytes for null termination so that it can be used as a
855 	 * Null-terminated string.
856 	 */
857 	char pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN + 1];
858 	bitfield16_t comp_activation_methods;
859 	bitfield32_t capabilities_during_update;
860 	const void *active_comp_ver_str;
861 	const void *pending_comp_ver_str;
862 };
863 
864 /** @struct pldm_request_update_req
865  *
866  *  Structure representing fixed part of Request Update request, as wire format.
867  */
868 struct pldm_request_update_req {
869 	uint32_t max_transfer_size;
870 	uint16_t num_of_comp;
871 	uint8_t max_outstanding_transfer_req;
872 	uint16_t pkg_data_len;
873 	uint8_t comp_image_set_ver_str_type;
874 	uint8_t comp_image_set_ver_str_len;
875 } __attribute__((packed));
876 
877 /** @struct pldm_request_update_req_full
878  *
879  *  Structure representing fixed part of Request Update request, including
880  *  version string. This is unpacked (contrast to struct pldm_request_update_req).
881  */
882 struct pldm_request_update_req_full {
883 	uint32_t max_transfer_size;
884 	uint16_t num_of_comp;
885 	uint8_t max_outstanding_transfer_req;
886 	uint16_t pkg_data_len;
887 
888 	struct pldm_firmware_string image_set_ver;
889 };
890 
891 /** @struct pldm_request_update_resp
892  *
893  *  Structure representing Request Update response
894  */
895 struct pldm_request_update_resp {
896 	uint8_t completion_code;
897 	uint16_t fd_meta_data_len;
898 	uint8_t fd_will_send_pkg_data;
899 } __attribute__((packed));
900 
901 /** @struct pldm_request_downstream_dev_update_req
902  *
903  *  Structure representing Request Downstream Device Update request
904  */
905 struct pldm_request_downstream_device_update_req {
906 	uint32_t maximum_downstream_device_transfer_size;
907 	uint8_t maximum_outstanding_transfer_requests;
908 	uint16_t downstream_device_package_data_length;
909 };
910 #define PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES 7
911 
912 /** @struct pldm_request_downstream_dev_update_resp
913  *
914  *  Structure representing Request Downstream Device Update response
915  */
916 struct pldm_request_downstream_device_update_resp {
917 	uint8_t completion_code;
918 	uint16_t downstream_device_meta_data_length;
919 	uint8_t downstream_device_will_send_get_package_data;
920 	uint16_t get_package_data_maximum_transfer_size;
921 };
922 #define PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES 6
923 
924 /** @struct pldm_pass_component_table_req
925  *
926  *  Structure representing PassComponentTable request, wire format.
927  *  Version string data is not included.
928  *  Prefer pldm_pass_component_table_req_full for new uses.
929  */
930 struct pldm_pass_component_table_req {
931 	uint8_t transfer_flag;
932 	uint16_t comp_classification;
933 	uint16_t comp_identifier;
934 	uint8_t comp_classification_index;
935 	uint32_t comp_comparison_stamp;
936 	uint8_t comp_ver_str_type;
937 	uint8_t comp_ver_str_len;
938 } __attribute__((packed));
939 
940 /** @struct pldm_pass_component_table_req_full
941  *
942  *  Structure representing PassComponentTable request, including
943  *  version string storage.
944  */
945 struct pldm_pass_component_table_req_full {
946 	uint8_t transfer_flag;
947 	uint16_t comp_classification;
948 	uint16_t comp_identifier;
949 	uint8_t comp_classification_index;
950 	uint32_t comp_comparison_stamp;
951 	struct pldm_firmware_string version;
952 };
953 
954 /** @struct pldm_pass_component_table_resp
955  *
956  *  Structure representing PassComponentTable response
957  */
958 struct pldm_pass_component_table_resp {
959 	uint8_t completion_code;
960 	uint8_t comp_resp;
961 	uint8_t comp_resp_code;
962 } __attribute__((packed));
963 
964 /** @struct pldm_update_component_req
965  *
966  *  Structure representing UpdateComponent request, wire format.
967  *  Version string data is not included.
968  *  Prefer pldm_update_component_req_full for new uses.
969  */
970 struct pldm_update_component_req {
971 	uint16_t comp_classification;
972 	uint16_t comp_identifier;
973 	uint8_t comp_classification_index;
974 	uint32_t comp_comparison_stamp;
975 	uint32_t comp_image_size;
976 	bitfield32_t update_option_flags;
977 	uint8_t comp_ver_str_type;
978 	uint8_t comp_ver_str_len;
979 } __attribute__((packed));
980 
981 /** @struct pldm_update_component_req_full
982  *
983  *  Structure representing UpdateComponent request, including
984  *  version string storage.
985  */
986 struct pldm_update_component_req_full {
987 	uint16_t comp_classification;
988 	uint16_t comp_identifier;
989 	uint8_t comp_classification_index;
990 
991 	uint32_t comp_comparison_stamp;
992 	struct pldm_firmware_string version;
993 
994 	uint32_t comp_image_size;
995 	bitfield32_t update_option_flags;
996 };
997 
998 /** @struct pldm_update_component_resp
999  *
1000  *  Structure representing UpdateComponent response
1001  */
1002 struct pldm_update_component_resp {
1003 	uint8_t completion_code;
1004 	uint8_t comp_compatibility_resp;
1005 	uint8_t comp_compatibility_resp_code;
1006 	bitfield32_t update_option_flags_enabled;
1007 	uint16_t time_before_req_fw_data;
1008 } __attribute__((packed));
1009 
1010 /** @struct pldm_request_firmware_data_req
1011  *
1012  *  Structure representing RequestFirmwareData request.
1013  */
1014 struct pldm_request_firmware_data_req {
1015 	uint32_t offset;
1016 	uint32_t length;
1017 } __attribute__((packed));
1018 
1019 /** @struct pldm_apply_complete_req
1020  *
1021  *  Structure representing ApplyComplete request.
1022  */
1023 struct pldm_apply_complete_req {
1024 	uint8_t apply_result;
1025 	bitfield16_t comp_activation_methods_modification;
1026 } __attribute__((packed));
1027 
1028 /** @struct pldm_activate_firmware_req
1029  *
1030  *  Structure representing ActivateFirmware request
1031  */
1032 struct pldm_activate_firmware_req {
1033 	bool8_t self_contained_activation_req;
1034 } __attribute__((packed));
1035 
1036 /** @struct activate_firmware_resp
1037  *
1038  *  Structure representing Activate Firmware response
1039  */
1040 struct pldm_activate_firmware_resp {
1041 	uint8_t completion_code;
1042 	uint16_t estimated_time_activation;
1043 } __attribute__((packed));
1044 
1045 /** @struct pldm_get_status_resp
1046  *
1047  *  Structure representing GetStatus response.
1048  */
1049 struct pldm_get_status_resp {
1050 	uint8_t completion_code;
1051 	uint8_t current_state;
1052 	uint8_t previous_state;
1053 	uint8_t aux_state;
1054 	uint8_t aux_state_status;
1055 	uint8_t progress_percent;
1056 	uint8_t reason_code;
1057 	bitfield32_t update_option_flags_enabled;
1058 } __attribute__((packed));
1059 
1060 /** @struct pldm_cancel_update_resp
1061  *
1062  *  Structure representing CancelUpdate response.
1063  */
1064 struct pldm_cancel_update_resp {
1065 	uint8_t completion_code;
1066 	bool8_t non_functioning_component_indication;
1067 	uint64_t non_functioning_component_bitmap;
1068 } __attribute__((packed));
1069 
1070 /** @brief Decode the PLDM package header information
1071  *
1072  *  @param[in] data - pointer to package header information
1073  *  @param[in] length - available length in the firmware update package
1074  *  @param[out] package_header_info - pointer to fixed part of PLDM package
1075  *                                    header information
1076  *  @param[out] package_version_str - pointer to package version string
1077  *
1078  *  @return pldm_completion_codes
1079  */
1080 int decode_pldm_package_header_info(
1081 	const uint8_t *data, size_t length,
1082 	struct pldm_package_header_information *package_header_info,
1083 	struct variable_field *package_version_str);
1084 
1085 /** @brief Decode individual firmware device ID record
1086  *
1087  *  @param[in] data - pointer to firmware device ID record
1088  *  @param[in] length - available length in the firmware update package
1089  *  @param[in] component_bitmap_bit_length - ComponentBitmapBitLengthfield
1090  *                                           parsed from the package header info
1091  *  @param[out] fw_device_id_record - pointer to fixed part of firmware device
1092  *                                    id record
1093  *  @param[out] applicable_components - pointer to ApplicableComponents
1094  *  @param[out] comp_image_set_version_str - pointer to
1095  *                                           ComponentImageSetVersionString
1096  *  @param[out] record_descriptors - pointer to RecordDescriptors
1097  *  @param[out] fw_device_pkg_data - pointer to FirmwareDevicePackageData
1098  *
1099  *  @return pldm_completion_codes
1100  */
1101 int decode_firmware_device_id_record(
1102 	const uint8_t *data, size_t length,
1103 	uint16_t component_bitmap_bit_length,
1104 	struct pldm_firmware_device_id_record *fw_device_id_record,
1105 	struct variable_field *applicable_components,
1106 	struct variable_field *comp_image_set_version_str,
1107 	struct variable_field *record_descriptors,
1108 	struct variable_field *fw_device_pkg_data);
1109 
1110 /** @brief Decode the record descriptor entries in the firmware update package
1111  *         and the Descriptors in the QueryDeviceIDentifiers command
1112  *
1113  *  @param[in] data - pointer to descriptor entry
1114  *  @param[in] length - remaining length of the descriptor data
1115  *  @param[out] descriptor_type - pointer to descriptor type
1116  *  @param[out] descriptor_data - pointer to descriptor data
1117  *
1118  *  @return pldm_completion_codes
1119  */
1120 int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
1121 					uint16_t *descriptor_type,
1122 					struct variable_field *descriptor_data);
1123 
1124 /** @brief Decode the vendor defined descriptor value
1125  *
1126  *  @param[in] data - pointer to vendor defined descriptor value
1127  *  @param[in] length - length of the vendor defined descriptor value
1128  *  @param[out] descriptor_title_str_type - pointer to vendor defined descriptor
1129  *                                          title string type
1130  *  @param[out] descriptor_title_str - pointer to vendor defined descriptor
1131  *                                     title string
1132  *  @param[out] descriptor_data - pointer to vendor defined descriptor data
1133  *
1134  *  @return pldm_completion_codes
1135  */
1136 int decode_vendor_defined_descriptor_value(
1137 	const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
1138 	struct variable_field *descriptor_title_str,
1139 	struct variable_field *descriptor_data);
1140 
1141 /** @brief Decode individual component image information
1142  *
1143  *  @param[in] data - pointer to component image information
1144  *  @param[in] length - available length in the firmware update package
1145  *  @param[out] pldm_comp_image_info - pointer to fixed part of component image
1146  *                                     information
1147  *  @param[out] comp_version_str - pointer to component version string
1148  *
1149  *  @return pldm_completion_codes
1150  */
1151 int decode_pldm_comp_image_info(
1152 	const uint8_t *data, size_t length,
1153 	struct pldm_component_image_information *pldm_comp_image_info,
1154 	struct variable_field *comp_version_str);
1155 
1156 /** @brief Create a PLDM request message for QueryDeviceIdentifiers
1157  *
1158  *  @param[in] instance_id - Message's instance id
1159  *  @param[in] payload_length - Length of the request message payload
1160  *  @param[in,out] msg - Message will be written to this
1161  *
1162  *  @return pldm_completion_codes
1163  *
1164  *  @note  Caller is responsible for memory alloc and dealloc of param
1165  *         'msg.payload'
1166  */
1167 int encode_query_device_identifiers_req(uint8_t instance_id,
1168 					size_t payload_length,
1169 					struct pldm_msg *msg);
1170 
1171 /** @brief Create a PLDM response message for QueryDeviceIdentifiers
1172  *
1173  *  @param[in] instance_id - Message's instance id
1174  *  @param[in] descriptor_count - Number of descriptors
1175  *  @param[in] descriptor - Array of descriptors
1176  *  @param[in,out] msg - Message will be written to this
1177  *  @param[in,out] payload_length - Size of the response message payload, updated
1178  *				    with used length.
1179  *
1180  *  @return 0 on success, a negative errno value on failure.
1181  *
1182  *  @note  Caller is responsible for memory alloc and dealloc of param
1183  *         'msg.payload'
1184  */
1185 int encode_query_device_identifiers_resp(
1186 	uint8_t instance_id, uint8_t descriptor_count,
1187 	const struct pldm_descriptor *descriptors, struct pldm_msg *msg,
1188 	size_t *payload_length);
1189 
1190 /** @brief Decode QueryDeviceIdentifiers response message
1191  *
1192  *  @param[in] msg - Response message
1193  *  @param[in] payload_length - Length of response message payload
1194  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
1195  *  @param[out] device_identifiers_len - Pointer to device identifiers length
1196  *  @param[out] descriptor_count - Pointer to descriptor count
1197  *  @param[out] descriptor_data - Pointer to descriptor data
1198  *
1199  *  @return pldm_completion_codes
1200  */
1201 int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
1202 					 size_t payload_length,
1203 					 uint8_t *completion_code,
1204 					 uint32_t *device_identifiers_len,
1205 					 uint8_t *descriptor_count,
1206 					 uint8_t **descriptor_data);
1207 
1208 /** @brief Create a PLDM request message for GetFirmwareParameters
1209  *
1210  *  @param[in] instance_id - Message's instance id
1211  *  @param[in] payload_length - Length of the request message payload
1212  *  @param[in,out] msg - Message will be written to this
1213  *
1214  *  @return pldm_completion_codes
1215  *
1216  *  @note  Caller is responsible for memory alloc and dealloc of param
1217  *         'msg.payload'
1218  */
1219 int encode_get_firmware_parameters_req(uint8_t instance_id,
1220 				       size_t payload_length,
1221 				       struct pldm_msg *msg);
1222 
1223 /** @brief Decode GetFirmwareParameters response
1224  *
1225  *  @param[in] msg - Response message
1226  *  @param[in] payload_length - Length of response message payload
1227  *  @param[out] resp_data - Pointer to get firmware parameters response
1228  *  @param[out] active_comp_image_set_ver_str - Pointer to active component
1229  *                                              image set version string
1230  *  @param[out] pending_comp_image_set_ver_str - Pointer to pending component
1231  *                                               image set version string
1232  *  @param[out] comp_parameter_table - Pointer to component parameter table
1233  *
1234  *  @return pldm_completion_codes
1235  */
1236 int decode_get_firmware_parameters_resp(
1237 	const struct pldm_msg *msg, size_t payload_length,
1238 	struct pldm_get_firmware_parameters_resp *resp_data,
1239 	struct variable_field *active_comp_image_set_ver_str,
1240 	struct variable_field *pending_comp_image_set_ver_str,
1241 	struct variable_field *comp_parameter_table);
1242 
1243 /** @brief Decode component entries in the component parameter table which is
1244  *         part of the response of GetFirmwareParameters command
1245  *
1246  *  @param[in] data - Component entry
1247  *  @param[in] length - Length of component entry
1248  *  @param[out] component_data - Pointer to component parameter table
1249  *  @param[out] active_comp_ver_str - Pointer to active component version string
1250  *  @param[out] pending_comp_ver_str - Pointer to pending component version
1251  *                                     string
1252  *
1253  *  @return pldm_completion_codes
1254  */
1255 int decode_get_firmware_parameters_resp_comp_entry(
1256 	const uint8_t *data, size_t length,
1257 	struct pldm_component_parameter_entry *component_data,
1258 	struct variable_field *active_comp_ver_str,
1259 	struct variable_field *pending_comp_ver_str);
1260 
1261 /** @brief Encode a GetFirmwareParameters response
1262  *
1263  *  @param[in] instance_id - Message's instance id
1264  *  @param[in] resp_data - Parameter data
1265  *  @param[in,out] msg - Message will be written to this
1266  *  @param[in,out] payload_length - Size of the response message payload, updated
1267  *				    with used length.
1268  *
1269  *  @return 0 on success, a negative errno value on failure.
1270  */
1271 int encode_get_firmware_parameters_resp(
1272 	uint8_t instance_id,
1273 	const struct pldm_get_firmware_parameters_resp_full *resp_data,
1274 	struct pldm_msg *msg, size_t *payload_length);
1275 
1276 /** @brief Encode a ComponentParameterTable entry
1277  *
1278  *  @param[in] comp - Component entry
1279  *  @param[in,out] payload - Message will be written to this
1280  *  @param[in,out] payload_length - Size of payload, updated
1281  *				    with used length.
1282  *
1283  *  @return 0 on success, a negative errno value on failure.
1284  */
1285 int encode_get_firmware_parameters_resp_comp_entry(
1286 	const struct pldm_component_parameter_entry_full *comp,
1287 	uint8_t *payload, size_t *payload_length);
1288 
1289 /** @brief Create a PLDM request message for QueryDownstreamDevices
1290  *
1291  *  @param[in] instance_id - Message's instance id
1292  *  @param[out] msg - Message will be written to this
1293  *
1294  *  @return 0 on success, otherwise -EINVAL if the input parameters' memory
1295  *          are not allocated, -EOVERFLOW if the payload length is not enough
1296  *          to encode the message, -EBADMSG if the message is not valid.
1297  *
1298  *  @note  Caller is responsible for memory alloc and dealloc of param
1299  *         'msg.payload'
1300  */
1301 int encode_query_downstream_devices_req(uint8_t instance_id,
1302 					struct pldm_msg *msg);
1303 
1304 /**
1305  * @brief Decodes the response message for Querying Downstream Devices.
1306  *
1307  * @param[in] msg The PLDM message to decode.
1308  * @param[in] payload_length The length of the message payload.
1309  * @param[out] resp_data Pointer to the structure to store the decoded response data.
1310  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1311  *         are not allocated, -EOVERFLOW if the payload length is not enough
1312  *         to decode the message, -EBADMSG if the message is not valid.
1313  *
1314  * @note  Caller is responsible for memory alloc and dealloc of param
1315  *         'msg.payload'
1316  */
1317 int decode_query_downstream_devices_resp(
1318 	const struct pldm_msg *msg, size_t payload_length,
1319 	struct pldm_query_downstream_devices_resp *resp_data);
1320 
1321 /**
1322  * @brief Encodes a request message for Query Downstream Identifiers.
1323  *
1324  * @param[in] instance_id The instance ID of the PLDM entity.
1325  * @param[in] data_transfer_handle The handle for the data transfer.
1326  * @param[in] transfer_operation_flag The flag indicating the transfer operation.
1327  * @param[out] msg Pointer to the PLDM message structure to store the encoded message.
1328  * @param[in] payload_length The length of the payload.
1329  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1330  *         are not allocated, -EOVERFLOW if the payload length is not enough
1331  *         to encode the message, -EBADMSG if the message is not valid.
1332  *
1333  * @note Caller is responsible for memory alloc and dealloc of param
1334  *        'msg.payload'
1335  */
1336 int encode_query_downstream_identifiers_req(
1337 	uint8_t instance_id,
1338 	const struct pldm_query_downstream_identifiers_req *params_req,
1339 	struct pldm_msg *msg, size_t payload_length);
1340 
1341 /**
1342  * @brief Decodes the response message for Querying Downstream Identifiers.
1343  * @param[in] msg The PLDM message to decode.
1344  * @param[in] payload_length The length of the message payload.
1345  * @param[out] resp_data Pointer to the decoded response data.
1346  * @param[out] iter Pointer to the downstream device iterator structure.
1347  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1348  *         are not allocated, -EOVERFLOW if the payload length is not enough
1349  *         to decode the message, -EBADMSG if the message is not valid.
1350  *
1351  * @note Caller is responsible for memory alloc and dealloc of pointer params
1352  */
1353 int decode_query_downstream_identifiers_resp(
1354 	const struct pldm_msg *msg, size_t payload_length,
1355 	struct pldm_query_downstream_identifiers_resp *resp_data,
1356 	struct pldm_downstream_device_iter *iter);
1357 
1358 /**
1359  * @brief Encodes request message for Get Downstream Firmware Parameters.
1360  *
1361  * @param[in] instance_id - The instance ID of the PLDM entity.
1362  * @param[in] data_transfer_handle - The handle for the data transfer.
1363  * @param[in] transfer_operation_flag - The flag indicating the transfer operation.
1364  * @param[in,out] msg - A pointer to the PLDM message structure to store the encoded message.
1365  * @param[in] payload_length - The length of the payload.
1366  *
1367  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1368  *         are not allocated, -EOVERFLOW if the payload length is not enough
1369  *         to encode the message, -EBADMSG if the message is not valid.
1370  *
1371  * @note Caller is responsible for memory alloc and dealloc of param
1372  *        'msg.payload'
1373  */
1374 int encode_get_downstream_firmware_parameters_req(
1375 	uint8_t instance_id,
1376 	const struct pldm_get_downstream_firmware_parameters_req *params_req,
1377 	struct pldm_msg *msg, size_t payload_length);
1378 
1379 struct pldm_downstream_device_parameters_iter {
1380 	struct variable_field field;
1381 	size_t entries;
1382 };
1383 
1384 /**
1385  * @brief Decode response message for Get Downstream Firmware Parameters
1386  *
1387  * @param[in] msg - The PLDM message to decode
1388  * @param[in] payload_length - The length of the message payload
1389  * @param[out] resp_data - Pointer to the structure to store the decoded response data
1390  * @param[out] downstream_device_param_table - Pointer to the variable field structure
1391  *                                           to store the decoded downstream device
1392  *                                           parameter table
1393  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1394  *         are not allocated, -EOVERFLOW if the payload length is not enough
1395  *         to decode the message, -EBADMSG if the message is not valid.
1396  *
1397  * @note Caller is responsible for memory alloc and dealloc of param
1398  *        'resp_data' and 'downstream_device_param_table'
1399  */
1400 int decode_get_downstream_firmware_parameters_resp(
1401 	const struct pldm_msg *msg, size_t payload_length,
1402 	struct pldm_get_downstream_firmware_parameters_resp *resp_data,
1403 	struct pldm_downstream_device_parameters_iter *iter);
1404 
1405 /**
1406  * @brief Decode the next downstream device parameter table entry
1407  *
1408  * @param[in,out] data - A variable field covering the table entries in the
1409  *                       response message data. @p data is updated to point to
1410  *                       the remaining entries once the current entry has been
1411  *                       decoded.
1412 
1413  * @param[out] entry - The struct object into which the current table entry will
1414  *                     be decoded
1415 
1416  * @param[out] versions - A variable field covering the active and
1417  *                        pending component version strings in the
1418  *                        response message data. The component version
1419  *                        strings can be decoded into @p entry using
1420  *                        decode_downstream_device_parameter_table_entry_versions()
1421  *
1422  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1423  *         are not allocated, -EOVERFLOW if the payload length is not enough
1424  *         to decode the entry.
1425  *
1426  * @note Caller is responsible for memory alloc and dealloc of param
1427  * 	  'entry', 'active_comp_ver_str' and 'pending_comp_ver_str'
1428  */
1429 int decode_pldm_downstream_device_parameters_entry_from_iter(
1430 	struct pldm_downstream_device_parameters_iter *iter,
1431 	struct pldm_downstream_device_parameters_entry *entry);
1432 
1433 LIBPLDM_ITERATOR
pldm_downstream_device_parameters_iter_end(const struct pldm_downstream_device_parameters_iter * iter)1434 bool pldm_downstream_device_parameters_iter_end(
1435 	const struct pldm_downstream_device_parameters_iter *iter)
1436 {
1437 	return !iter->entries;
1438 }
1439 
1440 LIBPLDM_ITERATOR
pldm_downstream_device_parameters_iter_next(struct pldm_downstream_device_parameters_iter * iter)1441 bool pldm_downstream_device_parameters_iter_next(
1442 	struct pldm_downstream_device_parameters_iter *iter)
1443 {
1444 	if (!iter->entries) {
1445 		return false;
1446 	}
1447 
1448 	iter->entries--;
1449 	return true;
1450 }
1451 
1452 /** @brief Iterator downstream device parameter entries in Get Downstream
1453  *         Firmware Parameters response
1454  *
1455  * @param params The @ref "struct pldm_downstream_device_parameters_iter" lvalue
1456  *               used as the out-value from the corresponding call to @ref
1457  *               decode_get_downstream_firmware_parameters_resp
1458  * @param entry The @ref "struct pldm_downstream_device_parameters_entry" lvalue
1459  *              into which the next parameter table entry should be decoded
1460  * @param rc An lvalue of type int into which the return code from the decoding
1461  *           will be placed
1462  *
1463  * Example use of the macro is as follows:
1464  *
1465  * @code
1466  * struct pldm_get_downstream_firmware_parameters_resp resp;
1467  * struct pldm_downstream_device_parameters_iter params;
1468  * struct pldm_downstream_device_parameters_entry entry;
1469  * int rc;
1470  *
1471  * rc = decode_get_downstream_firmware_parameters_resp(..., &resp, &params);
1472  * if (rc) {
1473  *     // Handle any error from decoding the fixed-portion of response
1474  * }
1475  *
1476  * foreach_pldm_downstream_device_parameters_entry(params, entry, rc) {
1477  *     // Do something with the decoded entry
1478  * }
1479  *
1480  * if (rc) {
1481  *     // Handle any decoding error while iterating the variable-length set of
1482  *     //parameter entries
1483  * }
1484  * @endcode
1485  */
1486 #define foreach_pldm_downstream_device_parameters_entry(params, entry, rc)       \
1487 	for ((rc) = 0;                                                           \
1488 	     (!pldm_downstream_device_parameters_iter_end(&(params)) &&          \
1489 	      !((rc) = decode_pldm_downstream_device_parameters_entry_from_iter( \
1490 			&(params), &(entry))));                                  \
1491 	     pldm_downstream_device_parameters_iter_next(&(params)))
1492 
1493 /** @brief Create PLDM request message for RequestUpdate
1494  *
1495  *  @param[in] instance_id - Message's instance id
1496  *  @param[in] max_transfer_size - Maximum size of the variable payload allowed
1497  *                                 to be requested via RequestFirmwareData
1498  *                                 command
1499  *  @param[in] num_of_comp - Total number of components that will be passed to
1500  *                           the FD during the update
1501  *  @param[in] max_outstanding_transfer_req - Total number of outstanding
1502  * 					      RequestFirmwareData
1503  * commands that can be sent by the FD
1504  *  @param[in] pkg_data_len - Value of the FirmwareDevicePackageDataLength field
1505  *                            present in firmware package header
1506  *  @param[in] comp_image_set_ver_str_type - StringType of
1507  *                                           ComponentImageSetVersionString
1508  *  @param[in] comp_image_set_ver_str_len - The length of the
1509  *                                          ComponentImageSetVersionString
1510  *  @param[in] comp_img_set_ver_str - Component Image Set version information
1511  *  @param[in,out] msg - Message will be written to this
1512  *  @param[in] payload_length - Length of request message payload
1513  *
1514  *  @return pldm_completion_codes
1515  *
1516  *  @note Caller is responsible for memory alloc and dealloc of param
1517  *        'msg.payload'
1518  */
1519 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1520 			      uint16_t num_of_comp,
1521 			      uint8_t max_outstanding_transfer_req,
1522 			      uint16_t pkg_data_len,
1523 			      uint8_t comp_image_set_ver_str_type,
1524 			      uint8_t comp_image_set_ver_str_len,
1525 			      const struct variable_field *comp_img_set_ver_str,
1526 			      struct pldm_msg *msg, size_t payload_length);
1527 
1528 /** @brief Decode PLDM request message for RequestUpdate
1529  *
1530  *  @param[in] msg - Message
1531  *  @param[in] payload_length - Length of request message payload
1532  *  @param[out] req - RequestUpdate request parameters
1533  *
1534  *  @return 0 on success, a negative errno value on failure.
1535  *
1536  *  @note Caller is responsible for memory alloc and dealloc of param
1537  *        'msg.payload'
1538  */
1539 int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length,
1540 			      struct pldm_request_update_req_full *req);
1541 
1542 /** @brief Decode a RequestUpdate response message
1543  *
1544  *  @param[in] msg - Response message
1545  *  @param[in] payload_length - Length of response message payload
1546  *  @param[out] completion_code - Pointer to hold the completion code
1547  *  @param[out] fd_meta_data_len - Pointer to hold the length of FD metadata
1548  *  @param[out] fd_will_send_pkg_data - Pointer to hold information whether FD
1549  *                                      will send GetPackageData command
1550  *  @return pldm_completion_codes
1551  */
1552 int decode_request_update_resp(const struct pldm_msg *msg,
1553 			       size_t payload_length, uint8_t *completion_code,
1554 			       uint16_t *fd_meta_data_len,
1555 			       uint8_t *fd_will_send_pkg_data);
1556 
1557 /** @brief Create PLDM response message for RequestUpdate
1558  *
1559  *  @param[in] instance_id - Message's instance id
1560  *  @param[in] resp_data - Response data
1561  *  @param[out] msg - Message will be written to this
1562  *  @param[inout] payload_length - Length of response message payload
1563  *
1564  *  @return 0 on success, a negative errno value on failure.
1565  *
1566  *  @note  Caller is responsible for memory alloc and dealloc of param
1567  *		   'msg.payload'
1568  */
1569 int encode_request_update_resp(uint8_t instance_id,
1570 			       const struct pldm_request_update_resp *resp_data,
1571 			       struct pldm_msg *msg, size_t *payload_length);
1572 
1573 /** @brief Create PLDM request message for RequestDownstreamDeviceUpdate
1574  *
1575  *  @param[in] instance_id - Message's instance id
1576  *  @param[in] req_data - Request data.
1577  *  @param[in,out] msg - Message will be written to this
1578  *  @param[in,out] payload_length - Length of response message payload
1579  *
1580  *  @return 0 on success,
1581  *		-EINVAL if any argument is invalid,
1582  *		-ENOMSG if the message type is incorrect,
1583  *		-EOVERFLOW if the payload length is invalid
1584  *
1585  *  @note Caller is responsible for memory alloc and dealloc of param
1586  *        'msg.payload'
1587  */
1588 int encode_request_downstream_device_update_req(
1589 	uint8_t instance_id,
1590 	const struct pldm_request_downstream_device_update_req *req_data,
1591 	struct pldm_msg *msg, size_t *payload_length);
1592 
1593 /** @brief Decode PLDM request message for RequestDownstreamDeviceUpdate
1594  *
1595  *  @param[in] msg - Message
1596  *  @param[in] payload_length - Length of request message payload
1597  *  @param[out] req_data - RequestDownstreamDeviceUpdate request parameters
1598  *
1599  *  @return 0 on success,
1600  *		-EINVAL if any argument is invalid,
1601  *		-ENOMSG if the message type is incorrect,
1602  *		-EOVERFLOW if the payload length is invalid,
1603  *		-EBADMSG if the message buffer was not fully consumed
1604  *
1605  *  @note Caller is responsible for memory alloc and dealloc of param
1606  *        'msg.payload'
1607  */
1608 int decode_request_downstream_device_update_req(
1609 	const struct pldm_msg *msg, size_t payload_length,
1610 	struct pldm_request_downstream_device_update_req *req_data);
1611 
1612 /** @brief Create PLDM response message for RequestDownstreamDeviceUpdate
1613  *
1614  *  @param[in] instance_id - Message's instance id
1615  *  @param[in] resp_data - Response data
1616  *  @param[out] msg - Message will be written to this
1617  *  @param[inout] payload_length - Length of response message payload
1618  *
1619  *  @return 0 on success,
1620  *		-EINVAL if any argument is invalid,
1621  *		-ENOMSG if the message type is incorrect,
1622  *		-EOVERFLOW if the payload length is invalid
1623  *
1624  *  @note  Caller is responsible for memory alloc and dealloc of param
1625  *		   'msg.payload'
1626  */
1627 int encode_request_downstream_device_update_resp(
1628 	uint8_t instance_id,
1629 	const struct pldm_request_downstream_device_update_resp *resp_data,
1630 	struct pldm_msg *msg, size_t *payload_length);
1631 
1632 /** @brief Decode a RequestDownstreamDeviceUpdate response message
1633  *
1634  *  @param[in] msg - Response message
1635  *  @param[in] payload_length - Length of response message payload
1636  *  @param[out] resp_data - RequestDownstreamDeviceUpdate respond parameters
1637  *
1638  *  @return 0 on success,
1639  *		-EINVAL if any argument is invalid,
1640  *		-ENOMSG if the message type is incorrect,
1641  *		-EOVERFLOW if the payload length is invalid,
1642  *		-EBADMSG if the message buffer was not fully consumed
1643  */
1644 int decode_request_downstream_device_update_resp(
1645 	const struct pldm_msg *msg, size_t payload_length,
1646 	struct pldm_request_downstream_device_update_resp *resp_data);
1647 
1648 /** @brief Create PLDM request message for PassComponentTable
1649  *
1650  *  @param[in] instance_id - Message's instance id
1651  *  @param[in] transfer_flag - TransferFlag
1652  *  @param[in] comp_classification - ComponentClassification
1653  *  @param[in] comp_identifier - ComponentIdentifier
1654  *  @param[in] comp_classification_index - ComponentClassificationIndex
1655  *  @param[in] comp_comparison_stamp - ComponentComparisonStamp
1656  *  @param[in] comp_ver_str_type - ComponentVersionStringType
1657  *  @param[in] comp_ver_str_len - ComponentVersionStringLength
1658  *  @param[in] comp_ver_str - ComponentVersionString
1659  *  @param[in,out] msg - Message will be written to this
1660  *  @param[in] payload_length - Length of request message payload
1661  *                              information
1662  *
1663  *  @return pldm_completion_codes
1664  *
1665  *  @note  Caller is responsible for memory alloc and dealloc of param
1666  *         'msg.payload'
1667  */
1668 int encode_pass_component_table_req(
1669 	uint8_t instance_id, uint8_t transfer_flag,
1670 	uint16_t comp_classification, uint16_t comp_identifier,
1671 	uint8_t comp_classification_index, uint32_t comp_comparison_stamp,
1672 	uint8_t comp_ver_str_type, uint8_t comp_ver_str_len,
1673 	const struct variable_field *comp_ver_str, struct pldm_msg *msg,
1674 	size_t payload_length);
1675 
1676 /** @brief Decode a PassComponentTable request
1677  *
1678  *  @param[in] msg - PLDM Message
1679  *  @param[in] payload_length
1680  *  @param[out] pcomp - Pass Component Table Request
1681  *
1682  *  @return 0 on success, a negative errno value on failure.
1683  */
1684 int decode_pass_component_table_req(
1685 	const struct pldm_msg *msg, size_t payload_length,
1686 	struct pldm_pass_component_table_req_full *pcomp);
1687 
1688 /** @brief Decode PassComponentTable response message
1689  *
1690  *  @param[in] msg - Response message
1691  *  @param[in] payload_length - Length of response message payload
1692  *  @param[out] completion_code - Pointer to hold completion code
1693  *  @param[out] comp_resp - Pointer to hold component response
1694  *  @param[out] comp_resp_code - Pointer to hold component response code
1695  *
1696  *  @return pldm_completion_codes
1697  */
1698 int decode_pass_component_table_resp(const struct pldm_msg *msg,
1699 				     size_t payload_length,
1700 				     uint8_t *completion_code,
1701 				     uint8_t *comp_resp,
1702 				     uint8_t *comp_resp_code);
1703 
1704 /** @brief Encode PassComponentTable response
1705  *
1706  *  @param[in] instance_id - PLDM Instance ID matching the request
1707  *  @param[in] resp_data - response data
1708  *  @param[out] msg - Response message
1709  *  @param[inout] payload_length - Length of msg payload buffer,
1710  *				   will be updated with the written
1711  * 				   length on success.
1712  *
1713  *  @return 0 on success, a negative errno value on failure.
1714  */
1715 int encode_pass_component_table_resp(
1716 	uint8_t instance_id,
1717 	const struct pldm_pass_component_table_resp *resp_data,
1718 	struct pldm_msg *msg, size_t *payload_length);
1719 
1720 /** @brief Create PLDM request message for UpdateComponent
1721  *
1722  *  @param[in] instance_id - Message's instance id
1723  *  @param[in] comp_classification - ComponentClassification
1724  *  @param[in] comp_identifier - ComponentIdentifier
1725  *  @param[in] comp_classification_index - ComponentClassificationIndex
1726  *  @param[in] comp_comparison_stamp - ComponentComparisonStamp
1727  *  @param[in] comp_image_size - ComponentImageSize
1728  *  @param[in] update_option_flags - UpdateOptionFlags
1729  *  @param[in] comp_ver_str_type - ComponentVersionStringType
1730  *  @param[in] comp_ver_str_len - ComponentVersionStringLength
1731  *  @param[in] comp_ver_str - ComponentVersionString
1732  *  @param[in,out] msg - Message will be written to this
1733  *  @param[in] payload_length - Length of request message payload
1734  *                              information
1735  *
1736  *  @return pldm_completion_codes
1737  *
1738  *  @note  Caller is responsible for memory alloc and dealloc of param
1739  *         'msg.payload'
1740  */
1741 int encode_update_component_req(
1742 	uint8_t instance_id, uint16_t comp_classification,
1743 	uint16_t comp_identifier, uint8_t comp_classification_index,
1744 	uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1745 	bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1746 	uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1747 	struct pldm_msg *msg, size_t payload_length);
1748 
1749 /** @brief Decode UpdateComponent request message
1750  *
1751  *  @param[in] msg - Request message
1752  *  @param[in] payload_length - Length of request message payload
1753  *  @param[out] up - UpdateComponent request parameters
1754  *
1755  *  @return 0 on success, a negative errno value on failure.
1756  */
1757 int decode_update_component_req(const struct pldm_msg *msg,
1758 				size_t payload_length,
1759 				struct pldm_update_component_req_full *up);
1760 
1761 /** @brief Decode UpdateComponent response message
1762  *
1763  *  @param[in] msg - Response message
1764  *  @param[in] payload_length - Length of response message payload
1765  *  @param[out] completion_code - Pointer to hold completion code
1766  *  @param[out] comp_compatibility_resp - Pointer to hold component
1767  *                                        compatibility response
1768  *  @param[out] comp_compatibility_resp_code - Pointer to hold component
1769  *                                             compatibility response code
1770  *  @param[out] update_option_flags_enabled - Pointer to hold
1771  *                                            UpdateOptionsFlagEnabled
1772  *  @param[out] time_before_req_fw_data - Pointer to hold the estimated time
1773  *                                        before sending RequestFirmwareData
1774  *
1775  *  @return pldm_completion_codes
1776  */
1777 int decode_update_component_resp(const struct pldm_msg *msg,
1778 				 size_t payload_length,
1779 				 uint8_t *completion_code,
1780 				 uint8_t *comp_compatibility_resp,
1781 				 uint8_t *comp_compatibility_resp_code,
1782 				 bitfield32_t *update_option_flags_enabled,
1783 				 uint16_t *time_before_req_fw_data);
1784 
1785 /** @brief Encode UpdateComponent response
1786  *
1787  *  @param[in] instance_id - PLDM Instance ID matching the request
1788  *  @param[in] resp_data - Response data
1789  *  @param[out] msg - Response message
1790  *  @param[inout] payload_length - Length of msg payload buffer,
1791  *				   will be updated with the written
1792  * 				   length on success.
1793  *
1794  *  @return 0 on success, a negative errno value on failure.
1795  */
1796 int encode_update_component_resp(
1797 	uint8_t instance_id, const struct pldm_update_component_resp *resp_data,
1798 	struct pldm_msg *msg, size_t *payload_length);
1799 
1800 /** @brief Decode RequestFirmwareData request message
1801  *
1802  *	@param[in] msg - Request message
1803  *	@param[in] payload_length - Length of request message payload
1804  *	@param[out] offset - Pointer to hold offset
1805  *	@param[out] length - Pointer to hold the size of the component image
1806  *                       segment requested by the FD/FDP
1807  *
1808  *	@return pldm_completion_codes
1809  */
1810 int decode_request_firmware_data_req(const struct pldm_msg *msg,
1811 				     size_t payload_length, uint32_t *offset,
1812 				     uint32_t *length);
1813 
1814 /** @brief Encode RequestFirmwareData request
1815  *
1816  *  @param[in] instance_id - PLDM Instance ID
1817  *  @param[in] req_params - Request parameters
1818  *  @param[in] length - firmware data length to request
1819  *  @param[out] msg - Response message
1820  *  @param[inout] payload_length - Length of msg payload buffer,
1821  *				   will be updated with the written
1822  * 				   length on success.
1823  *
1824  *  @return 0 on success, a negative errno value on failure.
1825  */
1826 int encode_request_firmware_data_req(
1827 	uint8_t instance_id,
1828 	const struct pldm_request_firmware_data_req *req_params,
1829 	struct pldm_msg *msg, size_t *payload_length);
1830 
1831 /** @brief Create PLDM response message for RequestFirmwareData
1832  *
1833  *  The ComponentImagePortion is not encoded in the PLDM response message
1834  *  by encode_request_firmware_data_resp to avoid an additional copy. Populating
1835  *  ComponentImagePortion in the PLDM response message is handled by the user
1836  *  of this API. The payload_length validation considers only the
1837  *  CompletionCode.
1838  *
1839  *	@param[in] instance_id - Message's instance id
1840  *	@param[in] completion_code - CompletionCode
1841  *	@param[in,out] msg - Message will be written to this
1842  *  @param[in] payload_length - Length of response message payload
1843  *
1844  *	@return pldm_completion_codes
1845  *
1846  *	@note  Caller is responsible for memory alloc and dealloc of param
1847  *		   'msg.payload'
1848  */
1849 int encode_request_firmware_data_resp(uint8_t instance_id,
1850 				      uint8_t completion_code,
1851 				      struct pldm_msg *msg,
1852 				      size_t payload_length);
1853 
1854 /** @brief Decode TransferComplete request message
1855  *
1856  *  @param[in] msg - Request message
1857  *  @param[in] payload_length - Length of request message payload
1858  *  @param[out] transfer_result - Pointer to hold TransferResult
1859  *
1860  *  @return pldm_completion_codes
1861  */
1862 int decode_transfer_complete_req(const struct pldm_msg *msg,
1863 				 size_t payload_length,
1864 				 uint8_t *transfer_result);
1865 
1866 /** @brief Encode TransferComplete request
1867  *
1868  *  @param[in] instance_id - PLDM Instance ID
1869  *  @param[in] transfer_result
1870  *  @param[out] msg - Response message
1871  *  @param[inout] payload_length - Length of msg payload buffer,
1872  *				   will be updated with the written
1873  * 				   length on success.
1874  *
1875  *  @return 0 on success, a negative errno value on failure.
1876  */
1877 int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
1878 				 struct pldm_msg *msg, size_t *payload_length);
1879 
1880 /** @brief Create PLDM response message for TransferComplete
1881  *
1882  *  @param[in] instance_id - Message's instance id
1883  *  @param[in] completion_code - CompletionCode
1884  *  @param[in,out] msg - Message will be written to this
1885  *  @param[in] payload_length - Length of response message payload
1886  *
1887  *  @return pldm_completion_codes
1888  *
1889  *  @note  Caller is responsible for memory alloc and dealloc of param
1890  *         'msg.payload'
1891  */
1892 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1893 				  struct pldm_msg *msg, size_t payload_length);
1894 
1895 /** @brief Decode VerifyComplete request message
1896  *
1897  *  @param[in] msg - Request message
1898  *  @param[in] payload_length - Length of request message payload
1899  *  @param[in] verify_result - Pointer to hold VerifyResult
1900  *
1901  *  @return pldm_completion_codes
1902  */
1903 int decode_verify_complete_req(const struct pldm_msg *msg,
1904 			       size_t payload_length, uint8_t *verify_result);
1905 
1906 /** @brief Encode VerifyComplete request
1907  *
1908  *  @param[in] instance_id - PLDM Instance ID
1909  *  @param[in] verify_result
1910  *  @param[out] msg - Response message
1911  *  @param[inout] payload_length - Length of msg payload buffer,
1912  *				   will be updated with the written
1913  * 				   length on success.
1914  *
1915  *  @return 0 on success, a negative errno value on failure.
1916  */
1917 int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
1918 			       struct pldm_msg *msg, size_t *payload_length);
1919 
1920 /** @brief Create PLDM response message for VerifyComplete
1921  *
1922  *  @param[in] instance_id - Message's instance id
1923  *  @param[in] completion_code - CompletionCode
1924  *  @param[in,out] msg - Message will be written to this
1925  *  @param[in] payload_length - Length of response message payload
1926  *
1927  *  @return pldm_completion_codes
1928  *
1929  *  @note  Caller is responsible for memory alloc and dealloc of param
1930  *         'msg.payload'
1931  */
1932 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1933 				struct pldm_msg *msg, size_t payload_length);
1934 
1935 /** @brief Decode ApplyComplete request message
1936  *
1937  *  @param[in] msg - Request message
1938  *  @param[in] payload_length - Length of request message payload
1939  *  @param[in] apply_result - Pointer to hold ApplyResult
1940  *  @param[in] comp_activation_methods_modification - Pointer to hold the
1941  *                                        ComponentActivationMethodsModification
1942  *
1943  *  @return pldm_completion_codes
1944  */
1945 int decode_apply_complete_req(
1946 	const struct pldm_msg *msg, size_t payload_length,
1947 	uint8_t *apply_result,
1948 	bitfield16_t *comp_activation_methods_modification);
1949 
1950 /** @brief Encode ApplyComplete request
1951  *
1952  *  @param[in] instance_id - PLDM Instance ID
1953  *  @param[in] req_data - Request data
1954  *  @param[out] msg - Request message
1955  *  @param[inout] payload_length - Length of msg payload buffer,
1956  *				   will be updated with the written
1957  * 				   length on success.
1958  *
1959  *  @return 0 on success, a negative errno value on failure.
1960  */
1961 int encode_apply_complete_req(uint8_t instance_id,
1962 			      const struct pldm_apply_complete_req *req_data,
1963 			      struct pldm_msg *msg, size_t *payload_length);
1964 
1965 /** @brief Create PLDM response message for ApplyComplete
1966  *
1967  *  @param[in] instance_id - Message's instance id
1968  *  @param[in] completion_code - CompletionCode
1969  *  @param[in,out] msg - Message will be written to this
1970  *  @param[in] payload_length - Length of response message payload
1971  *
1972  *  @return pldm_completion_codes
1973  *
1974  *  @note Caller is responsible for memory alloc and dealloc of param
1975  *        'msg.payload'
1976  */
1977 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1978 			       struct pldm_msg *msg, size_t payload_length);
1979 
1980 /** @brief Create PLDM request message for ActivateFirmware
1981  *
1982  *  @param[in] instance_id - Message's instance id
1983  *  @param[in] self_contained_activation_req SelfContainedActivationRequest
1984  *  @param[in,out] msg - Message will be written to this
1985  *  @param[in] payload_length - Length of request message payload
1986  *
1987  *  @return pldm_completion_codes
1988  *
1989  *  @note  Caller is responsible for memory alloc and dealloc of param
1990  *         'msg.payload'
1991  */
1992 int encode_activate_firmware_req(uint8_t instance_id,
1993 				 bool8_t self_contained_activation_req,
1994 				 struct pldm_msg *msg, size_t payload_length);
1995 
1996 /** @brief Decode ActivateFirmware request
1997  *
1998  *  @param[in] msg - Request message
1999  *  @param[in] payload_length - Length of request message payload
2000  *  @param[out] self_contained
2001  *
2002  *  @return 0 on success, a negative errno value on failure.
2003  */
2004 int decode_activate_firmware_req(const struct pldm_msg *msg,
2005 				 size_t payload_length, bool *self_contained);
2006 
2007 /** @brief Decode ActivateFirmware response message
2008  *
2009  *  @param[in] msg - Response message
2010  *  @param[in] payload_length - Length of response message payload
2011  *  @param[out] completion_code - Pointer to hold CompletionCode
2012  *  @param[out] estimated_time_activation - Pointer to hold
2013  *                                       EstimatedTimeForSelfContainedActivation
2014  *
2015  *  @return pldm_completion_codes
2016  */
2017 int decode_activate_firmware_resp(const struct pldm_msg *msg,
2018 				  size_t payload_length,
2019 				  uint8_t *completion_code,
2020 				  uint16_t *estimated_time_activation);
2021 
2022 /** @brief Encode ActivateFirmware response
2023  *
2024  *  @param[in] instance_id - PLDM Instance ID matching the request
2025  *  @param[in] resp_data - Response data
2026  *  @param[out] msg - Response message
2027  *  @param[inout] payload_length - Length of msg payload buffer,
2028  *				   will be updated with the written
2029  * 				   length on success.
2030  *
2031  *  @return 0 on success, a negative errno value on failure.
2032  */
2033 int encode_activate_firmware_resp(
2034 	uint8_t instance_id,
2035 	const struct pldm_activate_firmware_resp *resp_data,
2036 	struct pldm_msg *msg, size_t *payload_length);
2037 
2038 /** @brief Create PLDM request message for GetStatus
2039  *
2040  *  @param[in] instance_id - Message's instance id
2041  *  @param[in,out] msg - Message will be written to this
2042  *  @param[in] payload_length - Length of request message payload
2043  *
2044  *  @return pldm_completion_codes
2045  *
2046  *  @note Caller is responsible for memory alloc and dealloc of param
2047  *        'msg.payload'
2048  */
2049 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
2050 			  size_t payload_length);
2051 
2052 /** @brief Decode GetStatus response message
2053  *
2054  *  @param[in] msg - Response message
2055  *  @param[in] payload_length - Length of response message payload
2056  *  @param[out] completion_code - Pointer to completion code
2057  *  @param[out] current_state - Pointer to current state machine state
2058  *  @param[out] previous_state - Pointer to previous different state machine
2059  *                               state
2060  *  @param[out] aux_state - Pointer to current operation state of FD/FDP
2061  *  @param[out] aux_state_status - Pointer to aux state status
2062  *  @param[out] progress_percent - Pointer to progress percentage
2063  *  @param[out] reason_code - Pointer to reason for entering current state
2064  *  @param[out] update_option_flags_enabled - Pointer to update option flags
2065  *                                            enabled
2066  *
2067  *  @return pldm_completion_codes
2068  */
2069 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
2070 			   uint8_t *completion_code, uint8_t *current_state,
2071 			   uint8_t *previous_state, uint8_t *aux_state,
2072 			   uint8_t *aux_state_status, uint8_t *progress_percent,
2073 			   uint8_t *reason_code,
2074 			   bitfield32_t *update_option_flags_enabled);
2075 
2076 /** @brief Encode GetStatus response
2077  *
2078  *  @param[in] instance_id - PLDM Instance ID matching the request
2079  *  @param[in] status - GetStatus response. completion_code must be PLDM_SUCCESS.
2080  *  @param[out] msg - Response message
2081  *  @param[inout] payload_length - Length of msg payload buffer,
2082  *				   will be updated with the written
2083  * 				   length on success.
2084  *
2085  *  @return 0 on success, a negative errno value on failure.
2086  */
2087 int encode_get_status_resp(uint8_t instance_id,
2088 			   const struct pldm_get_status_resp *status,
2089 			   struct pldm_msg *msg, size_t *payload_length);
2090 
2091 /** @brief Create PLDM request message for CancelUpdateComponent
2092  *
2093  *  @param[in] instance_id - Message's instance id
2094  *  @param[in,out] msg - Message will be written to this
2095  *  @param[in] payload_length - Length of request message payload
2096  *
2097  *  @return pldm_completion_codes
2098  *
2099  *  @note  Caller is responsible for memory alloc and dealloc of param
2100  *         'msg.payload'
2101  */
2102 int encode_cancel_update_component_req(uint8_t instance_id,
2103 				       struct pldm_msg *msg,
2104 				       size_t payload_length);
2105 
2106 /** @brief Decode CancelUpdateComponent response message
2107  *
2108  *  @param[in] msg - Response message
2109  *  @param[in] payload_length - Length of response message payload
2110  *  @param[out] completion_code - Pointer to the completion code
2111  *
2112  *  @return pldm_completion_codes
2113  */
2114 int decode_cancel_update_component_resp(const struct pldm_msg *msg,
2115 					size_t payload_length,
2116 					uint8_t *completion_code);
2117 
2118 /** @brief Create PLDM request message for CancelUpdate
2119  *
2120  *	@param[in] instance_id - Message's instance id
2121  *	@param[in,out] msg - Message will be written to this
2122  *  @param[in] payload_length - Length of request message payload
2123  *
2124  *	@return pldm_completion_codes
2125  *
2126  *	@note  Caller is responsible for memory alloc and dealloc of param
2127  *         'msg.payload'
2128  */
2129 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
2130 			     size_t payload_length);
2131 
2132 /** @brief Decode CancelUpdate response message
2133  *
2134  *	@param[in] msg - Response message
2135  *  @param[in] payload_length - Length of response message payload
2136  *	@param[out] completion_code - Pointer to completion code
2137  *	@param[out] non_functioning_component_indication - Pointer to non
2138 						       functioning
2139  *                                                     component indication
2140  *	@param[out] non_functioning_component_bitmap - Pointer to non
2141  functioning
2142  *                                                 component bitmap
2143  *
2144  *	@return pldm_completion_codes
2145  */
2146 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
2147 			      uint8_t *completion_code,
2148 			      bool8_t *non_functioning_component_indication,
2149 			      bitfield64_t *non_functioning_component_bitmap);
2150 
2151 /** @brief Encode CancelUpdate response
2152  *
2153  *  @param[in] instance_id - PLDM Instance ID matching the request
2154  *  @param[in] resp_data - Response data,
2155  *  @param[out] msg - Response message
2156  *  @param[inout] payload_length - Length of msg payload buffer,
2157  *				   will be updated with the written
2158  * 				   length on success.
2159  *
2160  *  @return 0 on success, a negative errno value on failure.
2161  */
2162 int encode_cancel_update_resp(uint8_t instance_id,
2163 			      const struct pldm_cancel_update_resp *resp_data,
2164 			      struct pldm_msg *msg, size_t *payload_length);
2165 
2166 /** @brief Firmware update v1.0 package header identifier */
2167 #define PLDM_PACKAGE_HEADER_IDENTIFIER_V1_0                                    \
2168 	{ 0xF0, 0x18, 0x87, 0x8C, 0xCB, 0x7D, 0x49, 0x43,                      \
2169 	  0x98, 0x00, 0xA0, 0x2F, 0x05, 0x9A, 0xCA, 0x02 }
2170 
2171 /** @brief Firmware update v1.0 package header format revision */
2172 #define PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H 0x01
2173 
2174 /** @brief Firmware update v1.1 package header identifier */
2175 #define PLDM_PACKAGE_HEADER_IDENTIFIER_V1_1                                    \
2176 	{                                                                      \
2177 		0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18,                \
2178 		0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5a,                \
2179 	}
2180 
2181 /** @brief Firmware update v1.1 package header format revision */
2182 #define PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR02H 0x02
2183 
2184 /** @brief Consumer-side version pinning for package format parsing
2185  *
2186  * Parsing a firmware update package requires the package to be of a revision
2187  * defined in the specification, for libpldm to support parsing a package
2188  * formatted at the specified revision, and for the consumer to support calling
2189  * libpldm's package-parsing APIs in the manner required for the package format.
2190  *
2191  * pldm_package_format_pin communicates to libpldm the maximum package format
2192  * revision supported by the consumer.
2193  *
2194  * The definition of the pldm_package_format_pin object in the consumer
2195  * application should not be open-coded. Instead, users should call on of the
2196  * following macros:
2197  *
2198  * - @ref DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR01H
2199  * - @ref DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H
2200  *
2201  * The package pinning operates by providing versioning over multiple structs
2202  * required to perform the package parsing. See [Conventions for extensible
2203  * system calls][lwn-extensible-syscalls] for discussion of related concepts.
2204  * Like the syscall structs described there, the structs captured here by the
2205  * pinning concept must only ever be modified by addition of new members, never
2206  * alteration of existing members.
2207  *
2208  * [lwn-extensible-syscalls]: https://lwn.net/Articles/830666/
2209  */
2210 struct pldm_package_format_pin {
2211 	struct {
2212 		/**
2213 		 * A value that communicates information about object sizes to the implementation.
2214 		 *
2215 		 * For magic version 0, the sum must be calculated using @ref LIBPLDM_SIZEAT for
2216 		 * the final relevant member of each relevant struct for the format revision
2217 		 * represented by the pin.
2218 		 */
2219 		const uint32_t magic;
2220 
2221 		/**
2222 		 * Versioning for the derivation of the magic value
2223 		 *
2224 		 * A version value of 0 defines the magic number to be the sum of the relevant
2225 		 * struct sizes for the members required at the format revision specified by
2226 		 * the pin.
2227 		 */
2228 		const uint8_t version;
2229 	} meta;
2230 	struct {
2231 		/** The maximum supported package format UUID */
2232 		const pldm_uuid identifier;
2233 
2234 		/** The maximum supported header format revision */
2235 		const uint8_t revision;
2236 	} format;
2237 };
2238 
2239 /**
2240  * @brief Header information as parsed from the provided package
2241  *
2242  * See Table 3, DSP0267 v1.3.0.
2243  *
2244  * The provided package data must out-live the header struct.
2245  */
2246 struct pldm__package_header_information {
2247 	pldm_uuid package_header_identifier;
2248 	uint8_t package_header_format_revision;
2249 	uint8_t package_release_date_time[PLDM_TIMESTAMP104_SIZE];
2250 	uint16_t component_bitmap_bit_length;
2251 	uint8_t package_version_string_type;
2252 
2253 	/** A field pointing to the package version string in the provided package data */
2254 	struct variable_field package_version_string;
2255 
2256 	/* TODO: some metadata for the parsing process is stored here, reconsider */
2257 	struct variable_field areas;
2258 	struct variable_field package;
2259 };
2260 /* TODO: Deprecate the other struct pldm_package_header_information, remove, drop typedef */
2261 typedef struct pldm__package_header_information
2262 	pldm_package_header_information_pad;
2263 
2264 /* TODO: Consider providing an API to access valid bits */
2265 struct pldm_package_component_bitmap {
2266 	struct variable_field bitmap;
2267 };
2268 
2269 /**
2270  * @brief A firmware device ID record from the firmware update package
2271  *
2272  * See Table 4, DSP0267 v1.3.0.
2273  *
2274  * The provided package data must out-live the @ref "struct
2275  * pldm_package_firmware_device_id_record" instance.
2276  */
2277 struct pldm_package_firmware_device_id_record {
2278 	uint8_t descriptor_count;
2279 	bitfield32_t device_update_option_flags;
2280 	uint8_t component_image_set_version_string_type;
2281 
2282 	/**
2283 	 * A field pointing to the component image set version string in the provided
2284 	 * package data.
2285 	 */
2286 	struct variable_field component_image_set_version_string;
2287 
2288 	/**
2289 	 * A field pointing to the to a bitmap of length @ref
2290 	 * component_bitmap_bit_length in the provided package data..
2291 	 */
2292 	struct pldm_package_component_bitmap applicable_components;
2293 
2294 	/**
2295 	 * A field pointing to record descriptors for the
2296 	 * firmware device. Iterate over the entries using @ref
2297 	 * foreach_pldm_package_firmware_device_id_record_descriptor
2298 	 *
2299 	 * See Table 7, DSP0267 v1.3.0
2300 	 */
2301 	struct variable_field record_descriptors;
2302 	struct variable_field firmware_device_package_data;
2303 };
2304 
2305 /**
2306  * @brief A downstream device ID record from the firmware update package
2307  *
2308  * See Table 5, DSP0267 v1.3.0.
2309  *
2310  * The provided package data must out-live the @ref "struct
2311  * pldm_package_downstream_device_id_record" instance.
2312  */
2313 struct pldm_package_downstream_device_id_record {
2314 	uint8_t descriptor_count;
2315 	bitfield32_t update_option_flags;
2316 	uint8_t self_contained_activation_min_version_string_type;
2317 
2318 	/**
2319 	 * A field pointing to the self-contained activation minimum version string in
2320 	 * the provided package data.
2321 	 */
2322 	struct variable_field self_contained_activation_min_version_string;
2323 	uint32_t self_contained_activation_min_version_comparison_stamp;
2324 
2325 	/**
2326 	 * A field pointing to a bitmap of length @ref component_bitmap_bit_length in
2327 	 * the provided package data.
2328 	 */
2329 	struct pldm_package_component_bitmap applicable_components;
2330 
2331 	/**
2332 	 * A field pointing to record descriptors for the
2333 	 * downstream device. Iterate over the entries using @ref
2334 	 * foreach_pldm_package_downstream_device_id_record_descriptor
2335 	 *
2336 	 * See Table 7, DSP0267 v1.3.0
2337 	 */
2338 	struct variable_field record_descriptors;
2339 
2340 	/**
2341 	 * A field that may point to package data to be proxied by the firmware device.
2342 	 * If present, points into the provided package data.
2343 	 */
2344 	struct variable_field package_data;
2345 };
2346 
2347 /**
2348  * @brief Component image information from the firmware update package.
2349  *
2350  * See Table 6, DSP0267 v1.3.0
2351  *
2352  * The provided package data must out-live the @ref "struct
2353  * pldm_package_component_image_information" instance.
2354  */
2355 struct pldm_package_component_image_information {
2356 	uint16_t component_classification;
2357 	uint16_t component_identifier;
2358 	uint32_t component_comparison_stamp;
2359 	bitfield16_t component_options;
2360 	bitfield16_t requested_component_activation_method;
2361 
2362 	/**
2363 	 * A field that points to the component image for a device in the provided
2364 	 * package data.
2365 	 */
2366 	struct variable_field component_image;
2367 	uint8_t component_version_string_type;
2368 
2369 	/**
2370 	 * A field that points to the component version string for the image in the
2371 	 * provided package data.
2372 	 */
2373 	struct variable_field component_version_string;
2374 };
2375 
2376 struct pldm_package_firmware_device_id_record_iter {
2377 	struct variable_field field;
2378 	size_t entries;
2379 };
2380 
2381 struct pldm_package_downstream_device_id_record_iter {
2382 	struct variable_field field;
2383 	size_t entries;
2384 };
2385 
2386 struct pldm_package_component_image_information_iter {
2387 	struct variable_field field;
2388 	size_t entries;
2389 };
2390 
2391 /**
2392  * @brief State tracking for firmware update package iteration
2393  *
2394  * Declare an instance on the stack to be initialised by @ref
2395  * decode_pldm_firmware_update_package
2396  *
2397  * The state is consumed by the following macros:
2398  *
2399  * - @ref foreach_pldm_package_firmware_device_id_record
2400  * - @ref foreach_pldm_package_firmware_device_id_record_descriptor
2401  * - @ref foreach_pldm_package_downstream_device_id_record
2402  * - @ref foreach_pldm_package_downstream_device_id_record_descriptor
2403  * - @ref foreach_pldm_package_component_image_information
2404  */
2405 struct pldm_package_iter {
2406 	const pldm_package_header_information_pad *hdr;
2407 
2408 	/* Modified in the course of iteration */
2409 	struct pldm_package_firmware_device_id_record_iter fds;
2410 	struct pldm_package_downstream_device_id_record_iter dds;
2411 	struct pldm_package_component_image_information_iter infos;
2412 };
2413 
2414 /**
2415  * @brief Initialize the firmware update package iterator.
2416  *
2417  * @param[in] data The buffer containing the complete firmware update package
2418  * @param[in] length The length of the buffer pointed at by @p data
2419  * @param[in] pin The maximum supported package format revision of the caller
2420  * @param[out] hdr The parsed package header structure
2421  * @param[out] iter State-tracking for parsing subsequent package records and components
2422  *
2423  * Must be called to ensure version requirements for parsing are met by all
2424  * components, and to initialise @p iter prior to any subsequent extraction of
2425  * package records and components.
2426  *
2427  * @note @p data is stored in @iter for later reference, and therefore must
2428  *       out-live @p iter
2429  * @note @p hdr is stored in @iter for later reference, and therefore must
2430  *       out-live @p iter
2431  *
2432  * @return 0 on success. Otherwise, a negative errno value:
2433  * - -EBADMSG if the package fails to meet minimum required length for a valid
2434  *   package
2435  * - -EINVAL if provided parameter values are invalid
2436  * - -ENOTSUP on unrecognised or unsupported versions for the format pin or
2437  *   provided package
2438  * - -EOVERFLOW if the variable length structures extend beyond the package
2439  *   data buffer
2440  * - -EPROTO if parsed values violate the package format specification
2441  * - -EUCLEAN if the package fails embedded integrity checks
2442  */
2443 int decode_pldm_firmware_update_package(
2444 	const void *data, size_t length,
2445 	const struct pldm_package_format_pin *pin,
2446 	pldm_package_header_information_pad *hdr,
2447 	struct pldm_package_iter *iter);
2448 
2449 LIBPLDM_ITERATOR
pldm_package_firmware_device_id_record_iter_end(const struct pldm_package_firmware_device_id_record_iter * iter)2450 bool pldm_package_firmware_device_id_record_iter_end(
2451 	const struct pldm_package_firmware_device_id_record_iter *iter)
2452 {
2453 	return iter->entries == 0;
2454 }
2455 
2456 LIBPLDM_ITERATOR
pldm_package_firmware_device_id_record_iter_next(struct pldm_package_firmware_device_id_record_iter * iter)2457 bool pldm_package_firmware_device_id_record_iter_next(
2458 	struct pldm_package_firmware_device_id_record_iter *iter)
2459 {
2460 	if (!iter->entries) {
2461 		return false;
2462 	}
2463 	iter->entries--;
2464 	return true;
2465 }
2466 
2467 int pldm_package_firmware_device_id_record_iter_init(
2468 	const pldm_package_header_information_pad *hdr,
2469 	struct pldm_package_firmware_device_id_record_iter *iter);
2470 
2471 int decode_pldm_package_firmware_device_id_record_from_iter(
2472 	const pldm_package_header_information_pad *hdr,
2473 	struct pldm_package_firmware_device_id_record_iter *iter,
2474 	struct pldm_package_firmware_device_id_record *rec);
2475 
2476 /**
2477  * @brief Iterate over a package's firmware device ID records
2478  *
2479  * @param iter[in,out] The lvalue for the instance of @ref "struct pldm_package_iter"
2480  *             initialised by @ref decode_pldm_firmware_update_package
2481  * @param rec[out] An lvalue of type @ref "struct pldm_package_firmware_device_id_record"
2482  * @param rc[out] An lvalue of type int that holds the status result of parsing the
2483  *                firmware device ID record
2484  *
2485  * @p rc is set to 0 on successful decode. Otherwise, on error, @p rc is set to:
2486  * - -EINVAL if parameters values are invalid
2487  * - -EOVERFLOW if the package layout exceeds the bounds of the package buffer
2488  * - -EPROTO if package metadata doesn't conform to specification constraints
2489  *
2490  * Example use of the macro is as follows:
2491  *
2492  * @code
2493  * DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(pin);
2494  *
2495  * struct pldm_package_firmware_device_id_record fdrec;
2496  * pldm_package_header_information_pad hdr;
2497  * struct pldm_package_iter iter;
2498  * int rc;
2499  *
2500  * rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr,
2501  * 					 &iter);
2502  * if (rc < 0) {
2503  * 	   // Handle header parsing failure
2504  * }
2505  * foreach_pldm_package_firmware_device_id_record(iter, fdrec, rc) {
2506  * 	   // Do something with fdrec
2507  * }
2508  * if (rc) {
2509  * 	   // Handle parsing failure for fdrec
2510  * }
2511  * @endcode
2512  */
2513 #define foreach_pldm_package_firmware_device_id_record(iter, rec, rc)          \
2514 	for ((rc) = pldm_package_firmware_device_id_record_iter_init(          \
2515 		     (iter).hdr, &(iter).fds);                                 \
2516 	     !(rc) &&                                                          \
2517 	     !pldm_package_firmware_device_id_record_iter_end(&(iter).fds) &&  \
2518 	     !((rc) = decode_pldm_package_firmware_device_id_record_from_iter( \
2519 		       (iter).hdr, &(iter).fds, &(rec)));                      \
2520 	     pldm_package_firmware_device_id_record_iter_next(&(iter).fds))
2521 
2522 LIBPLDM_ITERATOR
2523 struct pldm_descriptor_iter
pldm_package_firmware_device_id_record_descriptor_iter_init(struct pldm_package_firmware_device_id_record_iter * iter,struct pldm_package_firmware_device_id_record * rec)2524 pldm_package_firmware_device_id_record_descriptor_iter_init(
2525 	struct pldm_package_firmware_device_id_record_iter *iter,
2526 	struct pldm_package_firmware_device_id_record *rec)
2527 {
2528 	(void)iter;
2529 	return (struct pldm_descriptor_iter){ &rec->record_descriptors,
2530 					      rec->descriptor_count };
2531 }
2532 
2533 /**
2534  * @brief Iterate over the descriptors in a package's firmware device ID record
2535  *
2536  * @param iter[in,out] The lvalue for the instance of @ref "struct pldm_package_iter"
2537  *             initialised by @ref decode_pldm_firmware_update_package
2538  * @param rec[in] An lvalue of type @ref "struct pldm_package_firmware_device_id_record"
2539  * @param desc[out] An lvalue of type @ref "struct pldm_descriptor" that holds
2540  *                  the parsed descriptor
2541  * @param rc[out] An lvalue of type int that holds the status result of parsing the
2542  *                firmware device ID record
2543  *
2544  * @p rc is set to 0 on successful decode. Otherwise, on error, @p rc is set to:
2545  * - -EINVAL if parameters values are invalid
2546  * - -EOVERFLOW if the package layout exceeds the bounds of the package buffer
2547  * - -EPROTO if package metadata doesn't conform to specification constraints
2548  *
2549  * Example use of the macro is as follows:
2550  *
2551  * @code
2552  * DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(pin);
2553  *
2554  * struct pldm_package_firmware_device_id_record fdrec;
2555  * pldm_package_header_information_pad hdr;
2556  * struct pldm_package_iter iter;
2557  * int rc;
2558  *
2559  * rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr,
2560  * 					 &iter);
2561  * if (rc < 0) { ... }
2562  *
2563  * foreach_pldm_package_firmware_device_id_record(iter, fdrec, rc) {
2564  *     struct pldm_descriptor desc;
2565  *
2566  * 	   ...
2567  *
2568  *     foreach_pldm_package_firmware_device_id_record_descriptor(
2569  *             iter, fdrec, desc, rc) {
2570  *         // Do something with desc
2571  *     }
2572  *     if (rc) {
2573  *         // Handle failure to parse desc
2574  *     }
2575  * }
2576  * if (rc) { ... }
2577  * @endcode
2578  */
2579 #define foreach_pldm_package_firmware_device_id_record_descriptor(iter, rec,      \
2580 								  desc, rc)       \
2581 	for (struct pldm_descriptor_iter desc##_iter =                            \
2582 		     ((rc) = 0,                                                   \
2583 		     pldm_package_firmware_device_id_record_descriptor_iter_init( \
2584 			      &(iter).fds, &(rec)));                              \
2585 	     (!pldm_descriptor_iter_end(&(desc##_iter))) &&                       \
2586 	     !((rc) = decode_pldm_descriptor_from_iter(&(desc##_iter),            \
2587 						       &(desc)));                 \
2588 	     pldm_descriptor_iter_next(&(desc##_iter)))
2589 
2590 LIBPLDM_ITERATOR
pldm_package_downstream_device_id_record_iter_end(const struct pldm_package_downstream_device_id_record_iter * iter)2591 bool pldm_package_downstream_device_id_record_iter_end(
2592 	const struct pldm_package_downstream_device_id_record_iter *iter)
2593 {
2594 	return iter->entries == 0;
2595 }
2596 
2597 LIBPLDM_ITERATOR
pldm_package_downstream_device_id_record_iter_next(struct pldm_package_downstream_device_id_record_iter * iter)2598 bool pldm_package_downstream_device_id_record_iter_next(
2599 	struct pldm_package_downstream_device_id_record_iter *iter)
2600 {
2601 	if (!iter->entries) {
2602 		return false;
2603 	}
2604 	iter->entries--;
2605 	return true;
2606 }
2607 
2608 int pldm_package_downstream_device_id_record_iter_init(
2609 	const pldm_package_header_information_pad *hdr,
2610 	struct pldm_package_firmware_device_id_record_iter *fds,
2611 	struct pldm_package_downstream_device_id_record_iter *dds);
2612 
2613 int decode_pldm_package_downstream_device_id_record_from_iter(
2614 	const pldm_package_header_information_pad *hdr,
2615 	struct pldm_package_downstream_device_id_record_iter *iter,
2616 	struct pldm_package_downstream_device_id_record *rec);
2617 
2618 /**
2619  * @brief Iterate over a package's downstream device ID records
2620  *
2621  * @param iter[in,out] The lvalue for the instance of @ref "struct pldm_package_iter"
2622  *             initialised by @ref decode_pldm_firmware_update_package
2623  * @param rec[out] An lvalue of type @ref "struct pldm_package_downstream_device_id_record"
2624  * @param rc[out] An lvalue of type int that holds the status result of parsing the
2625  *                firmware device ID record
2626  *
2627  * @p rc is set to 0 on successful decode. Otherwise, on error, @p rc is set to:
2628  * - -EINVAL if parameters values are invalid
2629  * - -EOVERFLOW if the package layout exceeds the bounds of the package buffer
2630  * - -EPROTO if package metadata doesn't conform to specification constraints
2631  *
2632  * Example use of the macro is as follows:
2633  *
2634  * @code
2635  * DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(pin);
2636  *
2637  * struct pldm_package_downstream_device_id_record ddrec;
2638  * struct pldm_package_firmware_device_id_record fdrec;
2639  * pldm_package_header_information_pad hdr;
2640  * struct pldm_package_iter iter;
2641  * int rc;
2642  *
2643  * rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr,
2644  * 					 &iter);
2645  * if (rc < 0) { ... }
2646  *
2647  * foreach_pldm_package_firmware_device_id_record(iter, fdrec, rc) {
2648  *     struct pldm_descriptor desc;
2649  * 	   ...
2650  *     foreach_pldm_package_firmware_device_id_record_descriptor(
2651  *             iter, fdrec, desc, rc) {
2652  *         ...
2653  *     }
2654  *     if (rc) { ... }
2655  * }
2656  * if (rc) { ... }
2657  *
2658  * foreach_pldm_package_downstream_device_id_record(iter, ddrec, rc) {
2659  * 	   // Do something with ddrec
2660  * }
2661  * if (rc) {
2662  * 	   // Handle parsing failure for ddrec
2663  * }
2664  * @endcode
2665  */
2666 #define foreach_pldm_package_downstream_device_id_record(iter, rec, rc)          \
2667 	for ((rc) = pldm_package_downstream_device_id_record_iter_init(          \
2668 		     (iter).hdr, &(iter).fds, &(iter).dds);                      \
2669 	     !(rc) &&                                                            \
2670 	     !pldm_package_downstream_device_id_record_iter_end(                 \
2671 		     &(iter).dds) &&                                             \
2672 	     !((rc) = decode_pldm_package_downstream_device_id_record_from_iter( \
2673 		       (iter).hdr, &(iter).dds, &(rec)));                        \
2674 	     pldm_package_downstream_device_id_record_iter_next(&(iter).dds))
2675 
2676 LIBPLDM_ITERATOR
2677 struct pldm_descriptor_iter
pldm_package_downstream_device_id_record_descriptor_iter_init(struct pldm_package_downstream_device_id_record_iter * iter,struct pldm_package_downstream_device_id_record * rec)2678 pldm_package_downstream_device_id_record_descriptor_iter_init(
2679 	struct pldm_package_downstream_device_id_record_iter *iter,
2680 	struct pldm_package_downstream_device_id_record *rec)
2681 {
2682 	(void)iter;
2683 	return (struct pldm_descriptor_iter){ &rec->record_descriptors,
2684 					      rec->descriptor_count };
2685 }
2686 
2687 /**
2688  * @brief Iterate over the descriptors in a package's downstream device ID record
2689  *
2690  * @param iter[in,out] The lvalue for the instance of @ref "struct pldm_package_iter"
2691  *             initialised by @ref decode_pldm_firmware_update_package
2692  * @param rec[in] An lvalue of type @ref "struct pldm_package_downstream_device_id_record"
2693  * @param desc[out] An lvalue of type @ref "struct pldm_descriptor" that holds
2694  *                  the parsed descriptor
2695  * @param rc[out] An lvalue of type int that holds the status result of parsing the
2696  *                downstream device ID record
2697  *
2698  * @p rc is set to 0 on successful decode. Otherwise, on error, @p rc is set to:
2699  * - -EINVAL if parameters values are invalid
2700  * - -EOVERFLOW if the package layout exceeds the bounds of the package buffer
2701  * - -EPROTO if package metadata doesn't conform to specification constraints
2702  *
2703  * Example use of the macro is as follows:
2704  *
2705  * @code
2706  * DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(pin);
2707  *
2708  * struct pldm_package_downstream_device_id_record ddrec;
2709  * struct pldm_package_firmware_device_id_record fdrec;
2710  * pldm_package_header_information_pad hdr;
2711  * struct pldm_package_iter iter;
2712  * int rc;
2713  *
2714  * rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr,
2715  * 					 &iter);
2716  * if (rc < 0) { ... }
2717  *
2718  * foreach_pldm_package_firmware_device_id_record(iter, fdrec, rc) {
2719  *     struct pldm_descriptor desc;
2720  * 	   ...
2721  *     foreach_pldm_package_firmware_device_id_record_descriptor(
2722  *             iter, fdrec, desc, rc) {
2723  *         ...
2724  *     }
2725  *     if (rc) { ... }
2726  * }
2727  * if (rc) { ... }
2728  *
2729  * foreach_pldm_package_downstream_device_id_record(iter, ddrec, rc) {
2730  *     struct pldm_descriptor desc;
2731  * 	   ...
2732  *     foreach_pldm_package_downstream_device_id_record_descriptor(
2733  *             iter, ddrec, desc, rc)
2734  *     {
2735  *         // Do something with desc
2736  *     }
2737  *     if (rc) {
2738  *         // Handle parsing failure for desc
2739  *     }
2740  * }
2741  * if (rc) { ... }
2742  * @endcode
2743  */
2744 #define foreach_pldm_package_downstream_device_id_record_descriptor(iter, rec,      \
2745 								    desc, rc)       \
2746 	for (struct pldm_descriptor_iter desc##_iter =                              \
2747 		     ((rc) = 0,                                                     \
2748 		     pldm_package_downstream_device_id_record_descriptor_iter_init( \
2749 			      &(iter).dds, &(rec)));                                \
2750 	     (!pldm_descriptor_iter_end(&(desc##_iter))) &&                         \
2751 	     !((rc) = decode_pldm_descriptor_from_iter(&(desc##_iter),              \
2752 						       &(desc)));                   \
2753 	     pldm_descriptor_iter_next(&(desc##_iter)))
2754 
2755 LIBPLDM_ITERATOR
pldm_package_component_image_information_iter_end(const struct pldm_package_component_image_information_iter * iter)2756 bool pldm_package_component_image_information_iter_end(
2757 	const struct pldm_package_component_image_information_iter *iter)
2758 {
2759 	return (iter->entries == 0);
2760 }
2761 
2762 LIBPLDM_ITERATOR
pldm_package_component_image_information_iter_next(struct pldm_package_component_image_information_iter * iter)2763 bool pldm_package_component_image_information_iter_next(
2764 	struct pldm_package_component_image_information_iter *iter)
2765 {
2766 	if (!iter->entries) {
2767 		return false;
2768 	}
2769 	iter->entries--;
2770 	return true;
2771 }
2772 
2773 int pldm_package_component_image_information_iter_init(
2774 	const pldm_package_header_information_pad *hdr,
2775 	struct pldm_package_downstream_device_id_record_iter *dds,
2776 	struct pldm_package_component_image_information_iter *infos);
2777 
2778 int decode_pldm_package_component_image_information_from_iter(
2779 	const pldm_package_header_information_pad *hdr,
2780 	struct pldm_package_component_image_information_iter *iter,
2781 	struct pldm_package_component_image_information *info);
2782 
2783 /**
2784  * @brief Iterate over the component image information contained in the package
2785  *
2786  * @param iter[in,out] The lvalue for the instance of @ref "struct pldm_package_iter"
2787  *             initialised by @ref decode_pldm_firmware_update_package
2788  * @param rec[in] An lvalue of type @ref "struct pldm_package_downstream_device_id_record"
2789  * @param desc[out] An lvalue of type @ref "struct pldm_descriptor" that holds
2790  *                  the parsed descriptor
2791  * @param rc[out] An lvalue of type int that holds the status result of parsing the
2792  *                downstream device ID record
2793  *
2794  * @p rc is set to 0 on successful decode. Otherwise, on error, @p rc is set to:
2795  * - -EINVAL if parameters values are invalid
2796  * - -EOVERFLOW if the package layout exceeds the bounds of the package buffer
2797  * - -EPROTO if package metadata doesn't conform to specification constraints
2798  *
2799  * Example use of the macro is as follows:
2800  *
2801  * @code
2802  * DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(pin);
2803  *
2804  * struct pldm_package_downstream_device_id_record ddrec;
2805  * struct pldm_package_component_image_information info;
2806  * struct pldm_package_firmware_device_id_record fdrec;
2807  * pldm_package_header_information_pad hdr;
2808  * struct pldm_package_iter iter;
2809  * int rc;
2810  *
2811  * rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr,
2812  * 					 &iter);
2813  * if (rc < 0) { ... }
2814  *
2815  * foreach_pldm_package_firmware_device_id_record(iter, fdrec, rc) {
2816  *     struct pldm_descriptor desc;
2817  * 	   ...
2818  *     foreach_pldm_package_firmware_device_id_record_descriptor(
2819  *             iter, fdrec, desc, rc) {
2820  *         ...
2821  *     }
2822  *     if (rc) { ... }
2823  * }
2824  * if (rc) { ... }
2825  *
2826  * foreach_pldm_package_downstream_device_id_record(iter, ddrec, rc) {
2827  *     struct pldm_descriptor desc;
2828  * 	   ...
2829  *     foreach_pldm_package_downstream_device_id_record_descriptor(
2830  *             iter, ddrec, desc, rc) {
2831  *         ...
2832  *     }
2833  *     if (rc) { ... }
2834  * }
2835  * if (rc) { ... }
2836  *
2837  * foreach_pldm_package_component_image_information(iter, info, rc) {
2838  *     // Do something with info
2839  * }
2840  * if (rc) {
2841  * 	   // Handle parsing failure for info
2842  * }
2843  * @endcode
2844  */
2845 #define foreach_pldm_package_component_image_information(iter, info, rc)         \
2846 	for ((rc) = pldm_package_component_image_information_iter_init(          \
2847 		     (iter).hdr, &(iter).dds, &(iter).infos);                    \
2848 	     !(rc) &&                                                            \
2849 	     !pldm_package_component_image_information_iter_end(                 \
2850 		     &(iter).infos) &&                                           \
2851 	     !((rc) = decode_pldm_package_component_image_information_from_iter( \
2852 		       (iter).hdr, &(iter).infos, &(info)));                     \
2853 	     pldm_package_component_image_information_iter_next(                 \
2854 		     &(iter).infos))
2855 
2856 /**
2857  * Declare consumer support for at most revision 1 of the firmware update
2858  * package header
2859  *
2860  * @param name The name for the pin object
2861  *
2862  * The pin object must be provided to @ref decode_pldm_firmware_update_package
2863  */
2864 #define DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR01H(name)                             \
2865 	struct pldm_package_format_pin name = { \
2866 		.meta = { \
2867 			.magic = ( \
2868 				LIBPLDM_SIZEAT(struct pldm__package_header_information, package) + \
2869 				LIBPLDM_SIZEAT(struct pldm_package_firmware_device_id_record, firmware_device_package_data) + \
2870 				LIBPLDM_SIZEAT(struct pldm_descriptor, descriptor_data) + \
2871 				LIBPLDM_SIZEAT(struct pldm_package_component_image_information, component_version_string) + \
2872 				LIBPLDM_SIZEAT(struct pldm_package_iter, infos) \
2873 			), \
2874 			.version = 0u, \
2875 		}, \
2876 		.format = { \
2877 			.identifier = PLDM_PACKAGE_HEADER_IDENTIFIER_V1_0, \
2878 			.revision = PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H, \
2879 		} \
2880 	}
2881 
2882 /**
2883  * Declare consumer support for at most revision 2 of the firmware update
2884  * package header
2885  *
2886  * @param name The name for the pin object
2887  *
2888  * The pin object must be provided to @ref decode_pldm_firmware_update_package
2889  */
2890 #define DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(name)                             \
2891 	struct pldm_package_format_pin name = { \
2892 		.meta = { \
2893 			.magic = ( \
2894 				LIBPLDM_SIZEAT(struct pldm__package_header_information, package) + \
2895 				LIBPLDM_SIZEAT(struct pldm_package_firmware_device_id_record, firmware_device_package_data) + \
2896 				LIBPLDM_SIZEAT(struct pldm_descriptor, descriptor_data) + \
2897 				LIBPLDM_SIZEAT(struct pldm_package_downstream_device_id_record, package_data) + \
2898 				LIBPLDM_SIZEAT(struct pldm_package_component_image_information, component_version_string) + \
2899 				LIBPLDM_SIZEAT(struct pldm_package_iter, infos) \
2900 			), \
2901 			.version = 0u, \
2902 		}, \
2903 		.format = { \
2904 			.identifier = PLDM_PACKAGE_HEADER_IDENTIFIER_V1_1, \
2905 			.revision = PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR02H, \
2906 		} \
2907 	}
2908 
2909 #ifdef __cplusplus
2910 }
2911 #endif
2912 
2913 #endif // End of FW_UPDATE_H
2914