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