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