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