xref: /openbmc/libpldm/include/libpldm/firmware_update.h (revision 844eff4d13280d9086de7a8962307ed6807e5f66)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #ifndef FW_UPDATE_H
3 #define FW_UPDATE_H
4 
5 #ifdef __cplusplus
6 extern "C" {
7 #endif
8 
9 #include "compiler.h"
10 
11 #include <libpldm/api.h>
12 #include <libpldm/base.h>
13 #include <libpldm/pldm_types.h>
14 
15 #include <assert.h>
16 #include <stdbool.h>
17 #include <stddef.h>
18 #include <stdint.h>
19 
20 #define PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE		 8
21 #define PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP 0xffffffff
22 #define PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES		 0
23 
24 /** @brief Length of QueryDownstreamDevices response defined in DSP0267_1.1.0
25  *  Table 15 - QueryDownstreamDevices command format.
26  *
27  *  1 byte for completion code
28  *  1 byte for downstream device update supported
29  *  2 bytes for number of downstream devices
30  *  2 bytes for max number of downstream devices
31  *  4 bytes for capabilities
32  */
33 #define PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES 10
34 
35 /** @brief Length of QueryDownstreamIdentifiers request defined in DSP0267_1.1.0
36  * 	Table 16 - QueryDownstreamIdentifiers command format.
37  *
38  *  4 bytes for data transfer handle
39  *  1 byte for transfer operation flag
40 */
41 #define PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES 5
42 
43 /** @brief Minimum length of QueryDownstreamIdentifiers response from DSP0267_1.1.0
44  *  if the complement code is success.
45  *
46  *  1 byte for completion code
47  *  4 bytes for next data transfer handle
48  *  1 byte for transfer flag
49  *  4 bytes for downstream devices length
50  *  2 bytes for number of downstream devices
51  */
52 #define PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN 12
53 
54 /** @brief Minimum length of device descriptor, 2 bytes for descriptor type,
55  *         2 bytes for descriptor length and at least 1 byte of descriptor data
56  */
57 #define PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN 5
58 
59 /** @brief Length of GetDownstreamFirmwareParameters request defined in DSP0267_1.1.0
60  *
61  * 4 bytes for Data Transfer Handle
62  * 1 byte for Transfer Operation Flag
63  */
64 #define PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES 5
65 
66 /** @brief Minimum length of GetDownstreamFirmwareParameters response from
67  * DSP0267_1.1.0 if the completion code is success.
68  *
69  * 1 byte for completion code
70  * 4 bytes for next data transfer handle
71  * 1 byte for transfer flag
72  * 4 bytes for FDP capabilities during update
73  * 2 bytes for downstream device count
74  */
75 #define PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN 12
76 
77 /** @brief Minimum length of DownstreamDeviceParameterTable entry from
78  * DSP0267_1.1.0 table 21 - DownstreamDeviceParameterTable
79  *
80  * 2 bytes for Downstream Device Index
81  * 4 bytes for Active Component Comparison Stamp
82  * 1 byte for Active Component Version String Type
83  * 1 byte for Active Component Version String Length
84  * 8 bytes for Active Component Release Date
85  * 4 bytes for Pending Component Comparison Stamp
86  * 1 byte for Pending Component Version String Type
87  * 1 byte for Pending Component Version String Length
88  * 8 bytes for Pending Component Release Date
89  * 2 bytes for Component Activation Methods
90  * 4 bytes for Capabilities During Update
91  */
92 #define PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN 36
93 
94 #define PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES 0
95 #define PLDM_FWUP_BASELINE_TRANSFER_SIZE       32
96 #define PLDM_FWUP_MIN_OUTSTANDING_REQ	       1
97 #define PLDM_GET_STATUS_REQ_BYTES	       0
98 /* Maximum progress percentage value*/
99 #define PLDM_FWUP_MAX_PROGRESS_PERCENT	       0x65
100 #define PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES 0
101 #define PLDM_CANCEL_UPDATE_REQ_BYTES	       0
102 
103 /** @brief PLDM component release data size in bytes defined in DSP0267_1.1.0
104  * Table 14 - ComponentParameterTable and Table 21 - ComponentParameterTable
105  *
106  * The size can be used in `ASCII[8] - ActiveComponentReleaseDate` and
107  * `ASCII[8] - PendingComponentReleaseDate` fields in the tables above.
108  */
109 #define PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN 8
110 
111 /** @brief PLDM Firmware update commands
112  */
113 enum pldm_firmware_update_commands {
114 	PLDM_QUERY_DEVICE_IDENTIFIERS = 0x01,
115 	PLDM_GET_FIRMWARE_PARAMETERS = 0x02,
116 	PLDM_QUERY_DOWNSTREAM_DEVICES = 0x03,
117 	PLDM_QUERY_DOWNSTREAM_IDENTIFIERS = 0x04,
118 	PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS = 0x05,
119 	PLDM_REQUEST_UPDATE = 0x10,
120 	PLDM_GET_PACKAGE_DATA = 0x11,
121 	PLDM_GET_DEVICE_META_DATA = 0x12,
122 	PLDM_PASS_COMPONENT_TABLE = 0x13,
123 	PLDM_UPDATE_COMPONENT = 0x14,
124 	PLDM_REQUEST_FIRMWARE_DATA = 0x15,
125 	PLDM_TRANSFER_COMPLETE = 0x16,
126 	PLDM_VERIFY_COMPLETE = 0x17,
127 	PLDM_APPLY_COMPLETE = 0x18,
128 	PLDM_GET_META_DATA = 0x19,
129 	PLDM_ACTIVATE_FIRMWARE = 0x1a,
130 	PLDM_GET_STATUS = 0x1b,
131 	PLDM_CANCEL_UPDATE_COMPONENT = 0x1c,
132 	PLDM_CANCEL_UPDATE = 0x1d,
133 	PLDM_ACTIVATE_PENDING_COMPONENT_IMAGE_SET = 0x1e,
134 	PLDM_ACTIVATE_PENDING_COMPONENT_IMAGE = 0x1f,
135 	PLDM_REQUEST_DOWNSTREAM_DEVICE_UPDATE = 0x20,
136 	PLDM_GET_COMPONENT_OPAQUE_DATA = 0x21,
137 	PLDM_UPTATE_SECURITY_REVISION = 0x22,
138 	PLDM_UPDATE_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 /** @struct pldm_update_security_revision_req
1087  *
1088  *  Structure representing UpdateSecurityRevision request.
1089  */
1090 struct pldm_fwup_update_security_revision_req {
1091 	uint16_t component_classification;
1092 	uint16_t component_identifier;
1093 	uint8_t component_classification_index;
1094 };
1095 
1096 #define PLDM_FWUP_UPDATE_SECURITY_REVISION_REQ_BYTES 5
1097 
1098 /** @brief Decode the PLDM package header information
1099  *
1100  *  @param[in] data - pointer to package header information
1101  *  @param[in] length - available length in the firmware update package
1102  *  @param[out] package_header_info - pointer to fixed part of PLDM package
1103  *                                    header information
1104  *  @param[out] package_version_str - pointer to package version string
1105  *
1106  *  @return pldm_completion_codes
1107  */
1108 int decode_pldm_package_header_info(
1109 	const uint8_t *data, size_t length,
1110 	struct pldm_package_header_information *package_header_info,
1111 	struct variable_field *package_version_str);
1112 
1113 /** @brief Decode individual firmware device ID record
1114  *
1115  *  @param[in] data - pointer to firmware device ID record
1116  *  @param[in] length - available length in the firmware update package
1117  *  @param[in] component_bitmap_bit_length - ComponentBitmapBitLengthfield
1118  *                                           parsed from the package header info
1119  *  @param[out] fw_device_id_record - pointer to fixed part of firmware device
1120  *                                    id record
1121  *  @param[out] applicable_components - pointer to ApplicableComponents
1122  *  @param[out] comp_image_set_version_str - pointer to
1123  *                                           ComponentImageSetVersionString
1124  *  @param[out] record_descriptors - pointer to RecordDescriptors
1125  *  @param[out] fw_device_pkg_data - pointer to FirmwareDevicePackageData
1126  *
1127  *  @return pldm_completion_codes
1128  */
1129 int decode_firmware_device_id_record(
1130 	const uint8_t *data, size_t length,
1131 	uint16_t component_bitmap_bit_length,
1132 	struct pldm_firmware_device_id_record *fw_device_id_record,
1133 	struct variable_field *applicable_components,
1134 	struct variable_field *comp_image_set_version_str,
1135 	struct variable_field *record_descriptors,
1136 	struct variable_field *fw_device_pkg_data);
1137 
1138 /** @brief Decode the record descriptor entries in the firmware update package
1139  *         and the Descriptors in the QueryDeviceIDentifiers command
1140  *
1141  *  @param[in] data - pointer to descriptor entry
1142  *  @param[in] length - remaining length of the descriptor data
1143  *  @param[out] descriptor_type - pointer to descriptor type
1144  *  @param[out] descriptor_data - pointer to descriptor data
1145  *
1146  *  @return pldm_completion_codes
1147  */
1148 int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
1149 					uint16_t *descriptor_type,
1150 					struct variable_field *descriptor_data);
1151 
1152 /** @brief Decode the vendor defined descriptor value
1153  *
1154  *  @param[in] data - pointer to vendor defined descriptor value
1155  *  @param[in] length - length of the vendor defined descriptor value
1156  *  @param[out] descriptor_title_str_type - pointer to vendor defined descriptor
1157  *                                          title string type
1158  *  @param[out] descriptor_title_str - pointer to vendor defined descriptor
1159  *                                     title string
1160  *  @param[out] descriptor_data - pointer to vendor defined descriptor data
1161  *
1162  *  @return pldm_completion_codes
1163  */
1164 int decode_vendor_defined_descriptor_value(
1165 	const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
1166 	struct variable_field *descriptor_title_str,
1167 	struct variable_field *descriptor_data);
1168 
1169 /** @brief Decode individual component image information
1170  *
1171  *  @param[in] data - pointer to component image information
1172  *  @param[in] length - available length in the firmware update package
1173  *  @param[out] pldm_comp_image_info - pointer to fixed part of component image
1174  *                                     information
1175  *  @param[out] comp_version_str - pointer to component version string
1176  *
1177  *  @return pldm_completion_codes
1178  */
1179 int decode_pldm_comp_image_info(
1180 	const uint8_t *data, size_t length,
1181 	struct pldm_component_image_information *pldm_comp_image_info,
1182 	struct variable_field *comp_version_str);
1183 
1184 /** @brief Create a PLDM request message for QueryDeviceIdentifiers
1185  *
1186  *  @param[in] instance_id - Message's instance id
1187  *  @param[in] payload_length - Length of the request message payload
1188  *  @param[in,out] msg - Message will be written to this
1189  *
1190  *  @return pldm_completion_codes
1191  *
1192  *  @note  Caller is responsible for memory alloc and dealloc of param
1193  *         'msg.payload'
1194  */
1195 int encode_query_device_identifiers_req(uint8_t instance_id,
1196 					size_t payload_length,
1197 					struct pldm_msg *msg);
1198 
1199 /** @brief Create a PLDM response message for QueryDeviceIdentifiers
1200  *
1201  *  @param[in] instance_id - Message's instance id
1202  *  @param[in] descriptor_count - Number of descriptors
1203  *  @param[in] descriptor - Array of descriptors
1204  *  @param[in,out] msg - Message will be written to this
1205  *  @param[in,out] payload_length - Size of the response message payload, updated
1206  *				    with used length.
1207  *
1208  *  @return 0 on success, a negative errno value on failure.
1209  *
1210  *  @note  Caller is responsible for memory alloc and dealloc of param
1211  *         'msg.payload'
1212  */
1213 int encode_query_device_identifiers_resp(
1214 	uint8_t instance_id, uint8_t descriptor_count,
1215 	const struct pldm_descriptor *descriptors, struct pldm_msg *msg,
1216 	size_t *payload_length);
1217 
1218 /** @brief Decode QueryDeviceIdentifiers response message
1219  *
1220  *  @param[in] msg - Response message
1221  *  @param[in] payload_length - Length of response message payload
1222  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
1223  *  @param[out] device_identifiers_len - Pointer to device identifiers length
1224  *  @param[out] descriptor_count - Pointer to descriptor count
1225  *  @param[out] descriptor_data - Pointer to descriptor data
1226  *
1227  *  @return pldm_completion_codes
1228  */
1229 int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
1230 					 size_t payload_length,
1231 					 uint8_t *completion_code,
1232 					 uint32_t *device_identifiers_len,
1233 					 uint8_t *descriptor_count,
1234 					 uint8_t **descriptor_data);
1235 
1236 /** @brief Create a PLDM request message for GetFirmwareParameters
1237  *
1238  *  @param[in] instance_id - Message's instance id
1239  *  @param[in] payload_length - Length of the request message payload
1240  *  @param[in,out] msg - Message will be written to this
1241  *
1242  *  @return pldm_completion_codes
1243  *
1244  *  @note  Caller is responsible for memory alloc and dealloc of param
1245  *         'msg.payload'
1246  */
1247 int encode_get_firmware_parameters_req(uint8_t instance_id,
1248 				       size_t payload_length,
1249 				       struct pldm_msg *msg);
1250 
1251 /** @brief Decode GetFirmwareParameters response
1252  *
1253  *  @param[in] msg - Response message
1254  *  @param[in] payload_length - Length of response message payload
1255  *  @param[out] resp_data - Pointer to get firmware parameters response
1256  *  @param[out] active_comp_image_set_ver_str - Pointer to active component
1257  *                                              image set version string
1258  *  @param[out] pending_comp_image_set_ver_str - Pointer to pending component
1259  *                                               image set version string
1260  *  @param[out] comp_parameter_table - Pointer to component parameter table
1261  *
1262  *  @return pldm_completion_codes
1263  */
1264 int decode_get_firmware_parameters_resp(
1265 	const struct pldm_msg *msg, size_t payload_length,
1266 	struct pldm_get_firmware_parameters_resp *resp_data,
1267 	struct variable_field *active_comp_image_set_ver_str,
1268 	struct variable_field *pending_comp_image_set_ver_str,
1269 	struct variable_field *comp_parameter_table);
1270 
1271 /** @brief Decode component entries in the component parameter table which is
1272  *         part of the response of GetFirmwareParameters command
1273  *
1274  *  @param[in] data - Component entry
1275  *  @param[in] length - Length of component entry
1276  *  @param[out] component_data - Pointer to component parameter table
1277  *  @param[out] active_comp_ver_str - Pointer to active component version string
1278  *  @param[out] pending_comp_ver_str - Pointer to pending component version
1279  *                                     string
1280  *
1281  *  @return pldm_completion_codes
1282  */
1283 int decode_get_firmware_parameters_resp_comp_entry(
1284 	const uint8_t *data, size_t length,
1285 	struct pldm_component_parameter_entry *component_data,
1286 	struct variable_field *active_comp_ver_str,
1287 	struct variable_field *pending_comp_ver_str);
1288 
1289 /** @brief Encode a GetFirmwareParameters response
1290  *
1291  *  @param[in] instance_id - Message's instance id
1292  *  @param[in] resp_data - Parameter data
1293  *  @param[in,out] msg - Message will be written to this
1294  *  @param[in,out] payload_length - Size of the response message payload, updated
1295  *				    with used length.
1296  *
1297  *  @return 0 on success, a negative errno value on failure.
1298  */
1299 int encode_get_firmware_parameters_resp(
1300 	uint8_t instance_id,
1301 	const struct pldm_get_firmware_parameters_resp_full *resp_data,
1302 	struct pldm_msg *msg, size_t *payload_length);
1303 
1304 /** @brief Encode a ComponentParameterTable entry
1305  *
1306  *  @param[in] comp - Component entry
1307  *  @param[in,out] payload - Message will be written to this
1308  *  @param[in,out] payload_length - Size of payload, updated
1309  *				    with used length.
1310  *
1311  *  @return 0 on success, a negative errno value on failure.
1312  */
1313 int encode_get_firmware_parameters_resp_comp_entry(
1314 	const struct pldm_component_parameter_entry_full *comp,
1315 	uint8_t *payload, size_t *payload_length);
1316 
1317 /** @brief Create a PLDM request message for QueryDownstreamDevices
1318  *
1319  *  @param[in] instance_id - Message's instance id
1320  *  @param[out] msg - Message will be written to this
1321  *
1322  *  @return 0 on success, otherwise -EINVAL if the input parameters' memory
1323  *          are not allocated, -EOVERFLOW if the payload length is not enough
1324  *          to encode the message, -EBADMSG if the message is not valid.
1325  *
1326  *  @note  Caller is responsible for memory alloc and dealloc of param
1327  *         'msg.payload'
1328  */
1329 int encode_query_downstream_devices_req(uint8_t instance_id,
1330 					struct pldm_msg *msg);
1331 
1332 /**
1333  * @brief Decodes the response message for Querying Downstream Devices.
1334  *
1335  * @param[in] msg The PLDM message to decode.
1336  * @param[in] payload_length The length of the message payload.
1337  * @param[out] resp_data Pointer to the structure to store the decoded response data.
1338  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1339  *         are not allocated, -EOVERFLOW if the payload length is not enough
1340  *         to decode the message, -EBADMSG if the message is not valid.
1341  *
1342  * @note  Caller is responsible for memory alloc and dealloc of param
1343  *         'msg.payload'
1344  */
1345 int decode_query_downstream_devices_resp(
1346 	const struct pldm_msg *msg, size_t payload_length,
1347 	struct pldm_query_downstream_devices_resp *resp_data);
1348 
1349 /**
1350  * @brief Encodes a request message for Query Downstream Identifiers.
1351  *
1352  * @param[in] instance_id The instance ID of the PLDM entity.
1353  * @param[in] data_transfer_handle The handle for the data transfer.
1354  * @param[in] transfer_operation_flag The flag indicating the transfer operation.
1355  * @param[out] msg Pointer to the PLDM message structure to store the encoded message.
1356  * @param[in] payload_length The length of the payload.
1357  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1358  *         are not allocated, -EOVERFLOW if the payload length is not enough
1359  *         to encode the message, -EBADMSG if the message is not valid.
1360  *
1361  * @note Caller is responsible for memory alloc and dealloc of param
1362  *        'msg.payload'
1363  */
1364 int encode_query_downstream_identifiers_req(
1365 	uint8_t instance_id,
1366 	const struct pldm_query_downstream_identifiers_req *params_req,
1367 	struct pldm_msg *msg, size_t payload_length);
1368 
1369 /**
1370  * @brief Decodes the response message for Querying Downstream Identifiers.
1371  * @param[in] msg The PLDM message to decode.
1372  * @param[in] payload_length The length of the message payload.
1373  * @param[out] resp_data Pointer to the decoded response data.
1374  * @param[out] iter Pointer to the downstream device iterator structure.
1375  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1376  *         are not allocated, -EOVERFLOW if the payload length is not enough
1377  *         to decode the message, -EBADMSG if the message is not valid.
1378  *
1379  * @note Caller is responsible for memory alloc and dealloc of pointer params
1380  */
1381 int decode_query_downstream_identifiers_resp(
1382 	const struct pldm_msg *msg, size_t payload_length,
1383 	struct pldm_query_downstream_identifiers_resp *resp_data,
1384 	struct pldm_downstream_device_iter *iter);
1385 
1386 /**
1387  * @brief Encodes request message for Get Downstream Firmware Parameters.
1388  *
1389  * @param[in] instance_id - The instance ID of the PLDM entity.
1390  * @param[in] data_transfer_handle - The handle for the data transfer.
1391  * @param[in] transfer_operation_flag - The flag indicating the transfer operation.
1392  * @param[in,out] msg - A pointer to the PLDM message structure to store the encoded message.
1393  * @param[in] payload_length - The length of the payload.
1394  *
1395  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1396  *         are not allocated, -EOVERFLOW if the payload length is not enough
1397  *         to encode the message, -EBADMSG if the message is not valid.
1398  *
1399  * @note Caller is responsible for memory alloc and dealloc of param
1400  *        'msg.payload'
1401  */
1402 int encode_get_downstream_firmware_parameters_req(
1403 	uint8_t instance_id,
1404 	const struct pldm_get_downstream_firmware_parameters_req *params_req,
1405 	struct pldm_msg *msg, size_t payload_length);
1406 
1407 struct pldm_downstream_device_parameters_iter {
1408 	struct variable_field field;
1409 	size_t entries;
1410 };
1411 
1412 /**
1413  * @brief Decode response message for Get Downstream Firmware Parameters
1414  *
1415  * @param[in] msg - The PLDM message to decode
1416  * @param[in] payload_length - The length of the message payload
1417  * @param[out] resp_data - Pointer to the structure to store the decoded response data
1418  * @param[out] downstream_device_param_table - Pointer to the variable field structure
1419  *                                           to store the decoded downstream device
1420  *                                           parameter table
1421  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1422  *         are not allocated, -EOVERFLOW if the payload length is not enough
1423  *         to decode the message, -EBADMSG if the message is not valid.
1424  *
1425  * @note Caller is responsible for memory alloc and dealloc of param
1426  *        'resp_data' and 'downstream_device_param_table'
1427  */
1428 int decode_get_downstream_firmware_parameters_resp(
1429 	const struct pldm_msg *msg, size_t payload_length,
1430 	struct pldm_get_downstream_firmware_parameters_resp *resp_data,
1431 	struct pldm_downstream_device_parameters_iter *iter);
1432 
1433 /**
1434  * @brief Decode the next downstream device parameter table entry
1435  *
1436  * @param[in,out] data - A variable field covering the table entries in the
1437  *                       response message data. @p data is updated to point to
1438  *                       the remaining entries once the current entry has been
1439  *                       decoded.
1440 
1441  * @param[out] entry - The struct object into which the current table entry will
1442  *                     be decoded
1443 
1444  * @param[out] versions - A variable field covering the active and
1445  *                        pending component version strings in the
1446  *                        response message data. The component version
1447  *                        strings can be decoded into @p entry using
1448  *                        decode_downstream_device_parameter_table_entry_versions()
1449  *
1450  * @return 0 on success, otherwise -EINVAL if the input parameters' memory
1451  *         are not allocated, -EOVERFLOW if the payload length is not enough
1452  *         to decode the entry.
1453  *
1454  * @note Caller is responsible for memory alloc and dealloc of param
1455  * 	  'entry', 'active_comp_ver_str' and 'pending_comp_ver_str'
1456  */
1457 int decode_pldm_downstream_device_parameters_entry_from_iter(
1458 	struct pldm_downstream_device_parameters_iter *iter,
1459 	struct pldm_downstream_device_parameters_entry *entry);
1460 
1461 LIBPLDM_ITERATOR
pldm_downstream_device_parameters_iter_end(const struct pldm_downstream_device_parameters_iter * iter)1462 bool pldm_downstream_device_parameters_iter_end(
1463 	const struct pldm_downstream_device_parameters_iter *iter)
1464 {
1465 	return !iter->entries;
1466 }
1467 
1468 LIBPLDM_ITERATOR
pldm_downstream_device_parameters_iter_next(struct pldm_downstream_device_parameters_iter * iter)1469 bool pldm_downstream_device_parameters_iter_next(
1470 	struct pldm_downstream_device_parameters_iter *iter)
1471 {
1472 	if (!iter->entries) {
1473 		return false;
1474 	}
1475 
1476 	iter->entries--;
1477 	return true;
1478 }
1479 
1480 /** @brief Iterator downstream device parameter entries in Get Downstream
1481  *         Firmware Parameters response
1482  *
1483  * @param params The @ref "struct pldm_downstream_device_parameters_iter" lvalue
1484  *               used as the out-value from the corresponding call to @ref
1485  *               decode_get_downstream_firmware_parameters_resp
1486  * @param entry The @ref "struct pldm_downstream_device_parameters_entry" lvalue
1487  *              into which the next parameter table entry should be decoded
1488  * @param rc An lvalue of type int into which the return code from the decoding
1489  *           will be placed
1490  *
1491  * Example use of the macro is as follows:
1492  *
1493  * @code
1494  * struct pldm_get_downstream_firmware_parameters_resp resp;
1495  * struct pldm_downstream_device_parameters_iter params;
1496  * struct pldm_downstream_device_parameters_entry entry;
1497  * int rc;
1498  *
1499  * rc = decode_get_downstream_firmware_parameters_resp(..., &resp, &params);
1500  * if (rc) {
1501  *     // Handle any error from decoding the fixed-portion of response
1502  * }
1503  *
1504  * foreach_pldm_downstream_device_parameters_entry(params, entry, rc) {
1505  *     // Do something with the decoded entry
1506  * }
1507  *
1508  * if (rc) {
1509  *     // Handle any decoding error while iterating the variable-length set of
1510  *     //parameter entries
1511  * }
1512  * @endcode
1513  */
1514 #define foreach_pldm_downstream_device_parameters_entry(params, entry, rc)       \
1515 	for ((rc) = 0;                                                           \
1516 	     (!pldm_downstream_device_parameters_iter_end(&(params)) &&          \
1517 	      !((rc) = decode_pldm_downstream_device_parameters_entry_from_iter( \
1518 			&(params), &(entry))));                                  \
1519 	     pldm_downstream_device_parameters_iter_next(&(params)))
1520 
1521 /** @brief Create PLDM request message for RequestUpdate
1522  *
1523  *  @param[in] instance_id - Message's instance id
1524  *  @param[in] max_transfer_size - Maximum size of the variable payload allowed
1525  *                                 to be requested via RequestFirmwareData
1526  *                                 command
1527  *  @param[in] num_of_comp - Total number of components that will be passed to
1528  *                           the FD during the update
1529  *  @param[in] max_outstanding_transfer_req - Total number of outstanding
1530  * 					      RequestFirmwareData
1531  * commands that can be sent by the FD
1532  *  @param[in] pkg_data_len - Value of the FirmwareDevicePackageDataLength field
1533  *                            present in firmware package header
1534  *  @param[in] comp_image_set_ver_str_type - StringType of
1535  *                                           ComponentImageSetVersionString
1536  *  @param[in] comp_image_set_ver_str_len - The length of the
1537  *                                          ComponentImageSetVersionString
1538  *  @param[in] comp_img_set_ver_str - Component Image Set version information
1539  *  @param[in,out] msg - Message will be written to this
1540  *  @param[in] payload_length - Length of request message payload
1541  *
1542  *  @return pldm_completion_codes
1543  *
1544  *  @note Caller is responsible for memory alloc and dealloc of param
1545  *        'msg.payload'
1546  */
1547 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1548 			      uint16_t num_of_comp,
1549 			      uint8_t max_outstanding_transfer_req,
1550 			      uint16_t pkg_data_len,
1551 			      uint8_t comp_image_set_ver_str_type,
1552 			      uint8_t comp_image_set_ver_str_len,
1553 			      const struct variable_field *comp_img_set_ver_str,
1554 			      struct pldm_msg *msg, size_t payload_length);
1555 
1556 /** @brief Decode PLDM request message for RequestUpdate
1557  *
1558  *  @param[in] msg - Message
1559  *  @param[in] payload_length - Length of request message payload
1560  *  @param[out] req - RequestUpdate request parameters
1561  *
1562  *  @return 0 on success, a negative errno value on failure.
1563  *
1564  *  @note Caller is responsible for memory alloc and dealloc of param
1565  *        'msg.payload'
1566  */
1567 int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length,
1568 			      struct pldm_request_update_req_full *req);
1569 
1570 /** @brief Decode a RequestUpdate response message
1571  *
1572  *  @param[in] msg - Response message
1573  *  @param[in] payload_length - Length of response message payload
1574  *  @param[out] completion_code - Pointer to hold the completion code
1575  *  @param[out] fd_meta_data_len - Pointer to hold the length of FD metadata
1576  *  @param[out] fd_will_send_pkg_data - Pointer to hold information whether FD
1577  *                                      will send GetPackageData command
1578  *  @return pldm_completion_codes
1579  */
1580 int decode_request_update_resp(const struct pldm_msg *msg,
1581 			       size_t payload_length, uint8_t *completion_code,
1582 			       uint16_t *fd_meta_data_len,
1583 			       uint8_t *fd_will_send_pkg_data);
1584 
1585 /** @brief Create PLDM response message for RequestUpdate
1586  *
1587  *  @param[in] instance_id - Message's instance id
1588  *  @param[in] resp_data - Response data
1589  *  @param[out] msg - Message will be written to this
1590  *  @param[inout] payload_length - Length of response message payload
1591  *
1592  *  @return 0 on success, a negative errno value on failure.
1593  *
1594  *  @note  Caller is responsible for memory alloc and dealloc of param
1595  *		   'msg.payload'
1596  */
1597 int encode_request_update_resp(uint8_t instance_id,
1598 			       const struct pldm_request_update_resp *resp_data,
1599 			       struct pldm_msg *msg, size_t *payload_length);
1600 
1601 /** @brief Create PLDM request message for RequestDownstreamDeviceUpdate
1602  *
1603  *  @param[in] instance_id - Message's instance id
1604  *  @param[in] req_data - Request data.
1605  *  @param[in,out] msg - Message will be written to this
1606  *  @param[in,out] payload_length - Length of response message payload
1607  *
1608  *  @return 0 on success,
1609  *		-EINVAL if any argument is invalid,
1610  *		-ENOMSG if the message type is incorrect,
1611  *		-EOVERFLOW if the payload length is invalid
1612  *
1613  *  @note Caller is responsible for memory alloc and dealloc of param
1614  *        'msg.payload'
1615  */
1616 int encode_request_downstream_device_update_req(
1617 	uint8_t instance_id,
1618 	const struct pldm_request_downstream_device_update_req *req_data,
1619 	struct pldm_msg *msg, size_t *payload_length);
1620 
1621 /** @brief Decode PLDM request message for RequestDownstreamDeviceUpdate
1622  *
1623  *  @param[in] msg - Message
1624  *  @param[in] payload_length - Length of request message payload
1625  *  @param[out] req_data - RequestDownstreamDeviceUpdate request parameters
1626  *
1627  *  @return 0 on success,
1628  *		-EINVAL if any argument is invalid,
1629  *		-ENOMSG if the message type is incorrect,
1630  *		-EOVERFLOW if the payload length is invalid,
1631  *		-EBADMSG if the message buffer was not fully consumed
1632  *
1633  *  @note Caller is responsible for memory alloc and dealloc of param
1634  *        'msg.payload'
1635  */
1636 int decode_request_downstream_device_update_req(
1637 	const struct pldm_msg *msg, size_t payload_length,
1638 	struct pldm_request_downstream_device_update_req *req_data);
1639 
1640 /** @brief Create PLDM response message for RequestDownstreamDeviceUpdate
1641  *
1642  *  @param[in] instance_id - Message's instance id
1643  *  @param[in] resp_data - Response data
1644  *  @param[out] msg - Message will be written to this
1645  *  @param[inout] payload_length - Length of response message payload
1646  *
1647  *  @return 0 on success,
1648  *		-EINVAL if any argument is invalid,
1649  *		-ENOMSG if the message type is incorrect,
1650  *		-EOVERFLOW if the payload length is invalid
1651  *
1652  *  @note  Caller is responsible for memory alloc and dealloc of param
1653  *		   'msg.payload'
1654  */
1655 int encode_request_downstream_device_update_resp(
1656 	uint8_t instance_id,
1657 	const struct pldm_request_downstream_device_update_resp *resp_data,
1658 	struct pldm_msg *msg, size_t *payload_length);
1659 
1660 /** @brief Decode a RequestDownstreamDeviceUpdate response message
1661  *
1662  *  @param[in] msg - Response message
1663  *  @param[in] payload_length - Length of response message payload
1664  *  @param[out] resp_data - RequestDownstreamDeviceUpdate respond parameters
1665  *
1666  *  @return 0 on success,
1667  *		-EINVAL if any argument is invalid,
1668  *		-ENOMSG if the message type is incorrect,
1669  *		-EOVERFLOW if the payload length is invalid,
1670  *		-EBADMSG if the message buffer was not fully consumed
1671  */
1672 int decode_request_downstream_device_update_resp(
1673 	const struct pldm_msg *msg, size_t payload_length,
1674 	struct pldm_request_downstream_device_update_resp *resp_data);
1675 
1676 /** @brief Create PLDM request message for PassComponentTable
1677  *
1678  *  @param[in] instance_id - Message's instance id
1679  *  @param[in] transfer_flag - TransferFlag
1680  *  @param[in] comp_classification - ComponentClassification
1681  *  @param[in] comp_identifier - ComponentIdentifier
1682  *  @param[in] comp_classification_index - ComponentClassificationIndex
1683  *  @param[in] comp_comparison_stamp - ComponentComparisonStamp
1684  *  @param[in] comp_ver_str_type - ComponentVersionStringType
1685  *  @param[in] comp_ver_str_len - ComponentVersionStringLength
1686  *  @param[in] comp_ver_str - ComponentVersionString
1687  *  @param[in,out] msg - Message will be written to this
1688  *  @param[in] payload_length - Length of request message payload
1689  *                              information
1690  *
1691  *  @return pldm_completion_codes
1692  *
1693  *  @note  Caller is responsible for memory alloc and dealloc of param
1694  *         'msg.payload'
1695  */
1696 int encode_pass_component_table_req(
1697 	uint8_t instance_id, uint8_t transfer_flag,
1698 	uint16_t comp_classification, uint16_t comp_identifier,
1699 	uint8_t comp_classification_index, uint32_t comp_comparison_stamp,
1700 	uint8_t comp_ver_str_type, uint8_t comp_ver_str_len,
1701 	const struct variable_field *comp_ver_str, struct pldm_msg *msg,
1702 	size_t payload_length);
1703 
1704 /** @brief Decode a PassComponentTable request
1705  *
1706  *  @param[in] msg - PLDM Message
1707  *  @param[in] payload_length
1708  *  @param[out] pcomp - Pass Component Table Request
1709  *
1710  *  @return 0 on success, a negative errno value on failure.
1711  */
1712 int decode_pass_component_table_req(
1713 	const struct pldm_msg *msg, size_t payload_length,
1714 	struct pldm_pass_component_table_req_full *pcomp);
1715 
1716 /** @brief Decode PassComponentTable response message
1717  *
1718  *  @param[in] msg - Response message
1719  *  @param[in] payload_length - Length of response message payload
1720  *  @param[out] completion_code - Pointer to hold completion code
1721  *  @param[out] comp_resp - Pointer to hold component response
1722  *  @param[out] comp_resp_code - Pointer to hold component response code
1723  *
1724  *  @return pldm_completion_codes
1725  */
1726 int decode_pass_component_table_resp(const struct pldm_msg *msg,
1727 				     size_t payload_length,
1728 				     uint8_t *completion_code,
1729 				     uint8_t *comp_resp,
1730 				     uint8_t *comp_resp_code);
1731 
1732 /** @brief Encode PassComponentTable response
1733  *
1734  *  @param[in] instance_id - PLDM Instance ID matching the request
1735  *  @param[in] resp_data - response data
1736  *  @param[out] msg - Response message
1737  *  @param[inout] payload_length - Length of msg payload buffer,
1738  *				   will be updated with the written
1739  * 				   length on success.
1740  *
1741  *  @return 0 on success, a negative errno value on failure.
1742  */
1743 int encode_pass_component_table_resp(
1744 	uint8_t instance_id,
1745 	const struct pldm_pass_component_table_resp *resp_data,
1746 	struct pldm_msg *msg, size_t *payload_length);
1747 
1748 /** @brief Create PLDM request message for UpdateComponent
1749  *
1750  *  @param[in] instance_id - Message's instance id
1751  *  @param[in] comp_classification - ComponentClassification
1752  *  @param[in] comp_identifier - ComponentIdentifier
1753  *  @param[in] comp_classification_index - ComponentClassificationIndex
1754  *  @param[in] comp_comparison_stamp - ComponentComparisonStamp
1755  *  @param[in] comp_image_size - ComponentImageSize
1756  *  @param[in] update_option_flags - UpdateOptionFlags
1757  *  @param[in] comp_ver_str_type - ComponentVersionStringType
1758  *  @param[in] comp_ver_str_len - ComponentVersionStringLength
1759  *  @param[in] comp_ver_str - ComponentVersionString
1760  *  @param[in,out] msg - Message will be written to this
1761  *  @param[in] payload_length - Length of request message payload
1762  *                              information
1763  *
1764  *  @return pldm_completion_codes
1765  *
1766  *  @note  Caller is responsible for memory alloc and dealloc of param
1767  *         'msg.payload'
1768  */
1769 int encode_update_component_req(
1770 	uint8_t instance_id, uint16_t comp_classification,
1771 	uint16_t comp_identifier, uint8_t comp_classification_index,
1772 	uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1773 	bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1774 	uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1775 	struct pldm_msg *msg, size_t payload_length);
1776 
1777 /** @brief Decode UpdateComponent request message
1778  *
1779  *  @param[in] msg - Request message
1780  *  @param[in] payload_length - Length of request message payload
1781  *  @param[out] up - UpdateComponent request parameters
1782  *
1783  *  @return 0 on success, a negative errno value on failure.
1784  */
1785 int decode_update_component_req(const struct pldm_msg *msg,
1786 				size_t payload_length,
1787 				struct pldm_update_component_req_full *up);
1788 
1789 /** @brief Decode UpdateComponent response message
1790  *
1791  *  @param[in] msg - Response message
1792  *  @param[in] payload_length - Length of response message payload
1793  *  @param[out] completion_code - Pointer to hold completion code
1794  *  @param[out] comp_compatibility_resp - Pointer to hold component
1795  *                                        compatibility response
1796  *  @param[out] comp_compatibility_resp_code - Pointer to hold component
1797  *                                             compatibility response code
1798  *  @param[out] update_option_flags_enabled - Pointer to hold
1799  *                                            UpdateOptionsFlagEnabled
1800  *  @param[out] time_before_req_fw_data - Pointer to hold the estimated time
1801  *                                        before sending RequestFirmwareData
1802  *
1803  *  @return pldm_completion_codes
1804  */
1805 int decode_update_component_resp(const struct pldm_msg *msg,
1806 				 size_t payload_length,
1807 				 uint8_t *completion_code,
1808 				 uint8_t *comp_compatibility_resp,
1809 				 uint8_t *comp_compatibility_resp_code,
1810 				 bitfield32_t *update_option_flags_enabled,
1811 				 uint16_t *time_before_req_fw_data);
1812 
1813 /** @brief Encode UpdateComponent response
1814  *
1815  *  @param[in] instance_id - PLDM Instance ID matching the request
1816  *  @param[in] resp_data - Response data
1817  *  @param[out] msg - Response message
1818  *  @param[inout] payload_length - Length of msg payload buffer,
1819  *				   will be updated with the written
1820  * 				   length on success.
1821  *
1822  *  @return 0 on success, a negative errno value on failure.
1823  */
1824 int encode_update_component_resp(
1825 	uint8_t instance_id, const struct pldm_update_component_resp *resp_data,
1826 	struct pldm_msg *msg, size_t *payload_length);
1827 
1828 /** @brief Decode RequestFirmwareData request message
1829  *
1830  *	@param[in] msg - Request message
1831  *	@param[in] payload_length - Length of request message payload
1832  *	@param[out] offset - Pointer to hold offset
1833  *	@param[out] length - Pointer to hold the size of the component image
1834  *                       segment requested by the FD/FDP
1835  *
1836  *	@return pldm_completion_codes
1837  */
1838 int decode_request_firmware_data_req(const struct pldm_msg *msg,
1839 				     size_t payload_length, uint32_t *offset,
1840 				     uint32_t *length);
1841 
1842 /** @brief Encode RequestFirmwareData request
1843  *
1844  *  @param[in] instance_id - PLDM Instance ID
1845  *  @param[in] req_params - Request parameters
1846  *  @param[in] length - firmware data length to request
1847  *  @param[out] msg - Response message
1848  *  @param[inout] payload_length - Length of msg payload buffer,
1849  *				   will be updated with the written
1850  * 				   length on success.
1851  *
1852  *  @return 0 on success, a negative errno value on failure.
1853  */
1854 int encode_request_firmware_data_req(
1855 	uint8_t instance_id,
1856 	const struct pldm_request_firmware_data_req *req_params,
1857 	struct pldm_msg *msg, size_t *payload_length);
1858 
1859 /** @brief Create PLDM response message for RequestFirmwareData
1860  *
1861  *  The ComponentImagePortion is not encoded in the PLDM response message
1862  *  by encode_request_firmware_data_resp to avoid an additional copy. Populating
1863  *  ComponentImagePortion in the PLDM response message is handled by the user
1864  *  of this API. The payload_length validation considers only the
1865  *  CompletionCode.
1866  *
1867  *	@param[in] instance_id - Message's instance id
1868  *	@param[in] completion_code - CompletionCode
1869  *	@param[in,out] msg - Message will be written to this
1870  *  @param[in] payload_length - Length of response message payload
1871  *
1872  *	@return pldm_completion_codes
1873  *
1874  *	@note  Caller is responsible for memory alloc and dealloc of param
1875  *		   'msg.payload'
1876  */
1877 int encode_request_firmware_data_resp(uint8_t instance_id,
1878 				      uint8_t completion_code,
1879 				      struct pldm_msg *msg,
1880 				      size_t payload_length);
1881 
1882 /** @brief Decode TransferComplete request message
1883  *
1884  *  @param[in] msg - Request message
1885  *  @param[in] payload_length - Length of request message payload
1886  *  @param[out] transfer_result - Pointer to hold TransferResult
1887  *
1888  *  @return pldm_completion_codes
1889  */
1890 int decode_transfer_complete_req(const struct pldm_msg *msg,
1891 				 size_t payload_length,
1892 				 uint8_t *transfer_result);
1893 
1894 /** @brief Encode TransferComplete request
1895  *
1896  *  @param[in] instance_id - PLDM Instance ID
1897  *  @param[in] transfer_result
1898  *  @param[out] msg - Response message
1899  *  @param[inout] payload_length - Length of msg payload buffer,
1900  *				   will be updated with the written
1901  * 				   length on success.
1902  *
1903  *  @return 0 on success, a negative errno value on failure.
1904  */
1905 int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
1906 				 struct pldm_msg *msg, size_t *payload_length);
1907 
1908 /** @brief Create PLDM response message for TransferComplete
1909  *
1910  *  @param[in] instance_id - Message's instance id
1911  *  @param[in] completion_code - CompletionCode
1912  *  @param[in,out] msg - Message will be written to this
1913  *  @param[in] payload_length - Length of response message payload
1914  *
1915  *  @return pldm_completion_codes
1916  *
1917  *  @note  Caller is responsible for memory alloc and dealloc of param
1918  *         'msg.payload'
1919  */
1920 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1921 				  struct pldm_msg *msg, size_t payload_length);
1922 
1923 /** @brief Decode VerifyComplete request message
1924  *
1925  *  @param[in] msg - Request message
1926  *  @param[in] payload_length - Length of request message payload
1927  *  @param[in] verify_result - Pointer to hold VerifyResult
1928  *
1929  *  @return pldm_completion_codes
1930  */
1931 int decode_verify_complete_req(const struct pldm_msg *msg,
1932 			       size_t payload_length, uint8_t *verify_result);
1933 
1934 /** @brief Encode VerifyComplete request
1935  *
1936  *  @param[in] instance_id - PLDM Instance ID
1937  *  @param[in] verify_result
1938  *  @param[out] msg - Response message
1939  *  @param[inout] payload_length - Length of msg payload buffer,
1940  *				   will be updated with the written
1941  * 				   length on success.
1942  *
1943  *  @return 0 on success, a negative errno value on failure.
1944  */
1945 int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
1946 			       struct pldm_msg *msg, size_t *payload_length);
1947 
1948 /** @brief Create PLDM response message for VerifyComplete
1949  *
1950  *  @param[in] instance_id - Message's instance id
1951  *  @param[in] completion_code - CompletionCode
1952  *  @param[in,out] msg - Message will be written to this
1953  *  @param[in] payload_length - Length of response message payload
1954  *
1955  *  @return pldm_completion_codes
1956  *
1957  *  @note  Caller is responsible for memory alloc and dealloc of param
1958  *         'msg.payload'
1959  */
1960 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1961 				struct pldm_msg *msg, size_t payload_length);
1962 
1963 /** @brief Decode ApplyComplete request message
1964  *
1965  *  @param[in] msg - Request message
1966  *  @param[in] payload_length - Length of request message payload
1967  *  @param[in] apply_result - Pointer to hold ApplyResult
1968  *  @param[in] comp_activation_methods_modification - Pointer to hold the
1969  *                                        ComponentActivationMethodsModification
1970  *
1971  *  @return pldm_completion_codes
1972  */
1973 int decode_apply_complete_req(
1974 	const struct pldm_msg *msg, size_t payload_length,
1975 	uint8_t *apply_result,
1976 	bitfield16_t *comp_activation_methods_modification);
1977 
1978 /** @brief Encode ApplyComplete request
1979  *
1980  *  @param[in] instance_id - PLDM Instance ID
1981  *  @param[in] req_data - Request data
1982  *  @param[out] msg - Request message
1983  *  @param[inout] payload_length - Length of msg payload buffer,
1984  *				   will be updated with the written
1985  * 				   length on success.
1986  *
1987  *  @return 0 on success, a negative errno value on failure.
1988  */
1989 int encode_apply_complete_req(uint8_t instance_id,
1990 			      const struct pldm_apply_complete_req *req_data,
1991 			      struct pldm_msg *msg, size_t *payload_length);
1992 
1993 /** @brief Create PLDM response message for ApplyComplete
1994  *
1995  *  @param[in] instance_id - Message's instance id
1996  *  @param[in] completion_code - CompletionCode
1997  *  @param[in,out] msg - Message will be written to this
1998  *  @param[in] payload_length - Length of response message payload
1999  *
2000  *  @return pldm_completion_codes
2001  *
2002  *  @note Caller is responsible for memory alloc and dealloc of param
2003  *        'msg.payload'
2004  */
2005 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
2006 			       struct pldm_msg *msg, size_t payload_length);
2007 
2008 /** @brief Create PLDM request message for ActivateFirmware
2009  *
2010  *  @param[in] instance_id - Message's instance id
2011  *  @param[in] self_contained_activation_req SelfContainedActivationRequest
2012  *  @param[in,out] msg - Message will be written to this
2013  *  @param[in] payload_length - Length of request message payload
2014  *
2015  *  @return pldm_completion_codes
2016  *
2017  *  @note  Caller is responsible for memory alloc and dealloc of param
2018  *         'msg.payload'
2019  */
2020 int encode_activate_firmware_req(uint8_t instance_id,
2021 				 bool8_t self_contained_activation_req,
2022 				 struct pldm_msg *msg, size_t payload_length);
2023 
2024 /** @brief Decode ActivateFirmware request
2025  *
2026  *  @param[in] msg - Request message
2027  *  @param[in] payload_length - Length of request message payload
2028  *  @param[out] self_contained
2029  *
2030  *  @return 0 on success, a negative errno value on failure.
2031  */
2032 int decode_activate_firmware_req(const struct pldm_msg *msg,
2033 				 size_t payload_length, bool *self_contained);
2034 
2035 /** @brief Decode ActivateFirmware response message
2036  *
2037  *  @param[in] msg - Response message
2038  *  @param[in] payload_length - Length of response message payload
2039  *  @param[out] completion_code - Pointer to hold CompletionCode
2040  *  @param[out] estimated_time_activation - Pointer to hold
2041  *                                       EstimatedTimeForSelfContainedActivation
2042  *
2043  *  @return pldm_completion_codes
2044  */
2045 int decode_activate_firmware_resp(const struct pldm_msg *msg,
2046 				  size_t payload_length,
2047 				  uint8_t *completion_code,
2048 				  uint16_t *estimated_time_activation);
2049 
2050 /** @brief Encode ActivateFirmware response
2051  *
2052  *  @param[in] instance_id - PLDM Instance ID matching the request
2053  *  @param[in] resp_data - Response data
2054  *  @param[out] msg - Response message
2055  *  @param[inout] payload_length - Length of msg payload buffer,
2056  *				   will be updated with the written
2057  * 				   length on success.
2058  *
2059  *  @return 0 on success, a negative errno value on failure.
2060  */
2061 int encode_activate_firmware_resp(
2062 	uint8_t instance_id,
2063 	const struct pldm_activate_firmware_resp *resp_data,
2064 	struct pldm_msg *msg, size_t *payload_length);
2065 
2066 /** @brief Create PLDM request message for GetStatus
2067  *
2068  *  @param[in] instance_id - Message's instance id
2069  *  @param[in,out] msg - Message will be written to this
2070  *  @param[in] payload_length - Length of request message payload
2071  *
2072  *  @return pldm_completion_codes
2073  *
2074  *  @note Caller is responsible for memory alloc and dealloc of param
2075  *        'msg.payload'
2076  */
2077 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
2078 			  size_t payload_length);
2079 
2080 /** @brief Decode GetStatus response message
2081  *
2082  *  @param[in] msg - Response message
2083  *  @param[in] payload_length - Length of response message payload
2084  *  @param[out] completion_code - Pointer to completion code
2085  *  @param[out] current_state - Pointer to current state machine state
2086  *  @param[out] previous_state - Pointer to previous different state machine
2087  *                               state
2088  *  @param[out] aux_state - Pointer to current operation state of FD/FDP
2089  *  @param[out] aux_state_status - Pointer to aux state status
2090  *  @param[out] progress_percent - Pointer to progress percentage
2091  *  @param[out] reason_code - Pointer to reason for entering current state
2092  *  @param[out] update_option_flags_enabled - Pointer to update option flags
2093  *                                            enabled
2094  *
2095  *  @return pldm_completion_codes
2096  */
2097 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
2098 			   uint8_t *completion_code, uint8_t *current_state,
2099 			   uint8_t *previous_state, uint8_t *aux_state,
2100 			   uint8_t *aux_state_status, uint8_t *progress_percent,
2101 			   uint8_t *reason_code,
2102 			   bitfield32_t *update_option_flags_enabled);
2103 
2104 /** @brief Encode GetStatus response
2105  *
2106  *  @param[in] instance_id - PLDM Instance ID matching the request
2107  *  @param[in] status - GetStatus response. completion_code must be PLDM_SUCCESS.
2108  *  @param[out] msg - Response message
2109  *  @param[inout] payload_length - Length of msg payload buffer,
2110  *				   will be updated with the written
2111  * 				   length on success.
2112  *
2113  *  @return 0 on success, a negative errno value on failure.
2114  */
2115 int encode_get_status_resp(uint8_t instance_id,
2116 			   const struct pldm_get_status_resp *status,
2117 			   struct pldm_msg *msg, size_t *payload_length);
2118 
2119 /** @brief Create PLDM request message for CancelUpdateComponent
2120  *
2121  *  @param[in] instance_id - Message's instance id
2122  *  @param[in,out] msg - Message will be written to this
2123  *  @param[in] payload_length - Length of request message payload
2124  *
2125  *  @return pldm_completion_codes
2126  *
2127  *  @note  Caller is responsible for memory alloc and dealloc of param
2128  *         'msg.payload'
2129  */
2130 int encode_cancel_update_component_req(uint8_t instance_id,
2131 				       struct pldm_msg *msg,
2132 				       size_t payload_length);
2133 
2134 /** @brief Decode CancelUpdateComponent response message
2135  *
2136  *  @param[in] msg - Response message
2137  *  @param[in] payload_length - Length of response message payload
2138  *  @param[out] completion_code - Pointer to the completion code
2139  *
2140  *  @return pldm_completion_codes
2141  */
2142 int decode_cancel_update_component_resp(const struct pldm_msg *msg,
2143 					size_t payload_length,
2144 					uint8_t *completion_code);
2145 
2146 /** @brief Create PLDM request message for CancelUpdate
2147  *
2148  *	@param[in] instance_id - Message's instance id
2149  *	@param[in,out] msg - Message will be written to this
2150  *  @param[in] payload_length - Length of request message payload
2151  *
2152  *	@return pldm_completion_codes
2153  *
2154  *	@note  Caller is responsible for memory alloc and dealloc of param
2155  *         'msg.payload'
2156  */
2157 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
2158 			     size_t payload_length);
2159 
2160 /** @brief Decode CancelUpdate response message
2161  *
2162  *	@param[in] msg - Response message
2163  *  @param[in] payload_length - Length of response message payload
2164  *	@param[out] completion_code - Pointer to completion code
2165  *	@param[out] non_functioning_component_indication - Pointer to non
2166 						       functioning
2167  *                                                     component indication
2168  *	@param[out] non_functioning_component_bitmap - Pointer to non
2169  functioning
2170  *                                                 component bitmap
2171  *
2172  *	@return pldm_completion_codes
2173  */
2174 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
2175 			      uint8_t *completion_code,
2176 			      bool8_t *non_functioning_component_indication,
2177 			      bitfield64_t *non_functioning_component_bitmap);
2178 
2179 /** @brief Encode CancelUpdate response
2180  *
2181  *  @param[in] instance_id - PLDM Instance ID matching the request
2182  *  @param[in] resp_data - Response data,
2183  *  @param[out] msg - Response message
2184  *  @param[inout] payload_length - Length of msg payload buffer,
2185  *				   will be updated with the written
2186  * 				   length on success.
2187  *
2188  *  @return 0 on success, a negative errno value on failure.
2189  */
2190 int encode_cancel_update_resp(uint8_t instance_id,
2191 			      const struct pldm_cancel_update_resp *resp_data,
2192 			      struct pldm_msg *msg, size_t *payload_length);
2193 
2194 /** @brief Create PLDM request message for UpdateSecurityRevision
2195  *
2196  *  @param[in] instance_id - Message's instance id
2197  *  @param[in] req - Pointer to the request data
2198  *  @param[out] msg - Message will be written to this
2199  *  @param[inout] payload_length - Length of msg payload buffer,
2200  *				   will be updated with the written
2201  * 				   length on success.
2202  *
2203  *  @return 0 on success, a negative errno value on failure.
2204  */
2205 int encode_pldm_fwup_update_security_revision_req(
2206 	const uint8_t instance_id,
2207 	const struct pldm_fwup_update_security_revision_req *req,
2208 	struct pldm_msg *msg, size_t *payload_length);
2209 
2210 /** @brief Decode UpdateSecurityRevision response message
2211  *
2212  *  @param[in] msg - Response message
2213  *  @param[in] payload_length - Length of response message payload
2214  *  @param[out] completion_code - Pointer to the completion code
2215  *
2216  *  @return 0 on success, a negative errno value on failure.
2217  */
2218 int decode_pldm_fwup_update_security_revision_resp(const struct pldm_msg *msg,
2219 						   size_t payload_length,
2220 						   uint8_t *completion_code);
2221 
2222 /** @brief Firmware update v1.0 package header identifier */
2223 #define PLDM_PACKAGE_HEADER_IDENTIFIER_V1_0                                    \
2224 	{ 0xF0, 0x18, 0x87, 0x8C, 0xCB, 0x7D, 0x49, 0x43,                      \
2225 	  0x98, 0x00, 0xA0, 0x2F, 0x05, 0x9A, 0xCA, 0x02 }
2226 
2227 /** @brief Firmware update v1.0 package header format revision */
2228 #define PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H 0x01
2229 
2230 /** @brief Firmware update v1.1 package header identifier */
2231 #define PLDM_PACKAGE_HEADER_IDENTIFIER_V1_1                                    \
2232 	{                                                                      \
2233 		0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18,                \
2234 		0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5a,                \
2235 	}
2236 
2237 /** @brief Firmware update v1.1 package header format revision */
2238 #define PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR02H 0x02
2239 
2240 /** @brief Firmware update v1.2 package header identifier */
2241 #define PLDM_PACKAGE_HEADER_IDENTIFIER_V1_2                                    \
2242 	{                                                                      \
2243 		0x31, 0x19, 0xce, 0x2f, 0xe8, 0x0a, 0x4a, 0x99,                \
2244 		0xaf, 0x6d, 0x46, 0xf8, 0xb1, 0x21, 0xf6, 0xbf,                \
2245 	}
2246 
2247 /** @brief Firmware update v1.2 package header format revision */
2248 #define PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR03H 0x03
2249 
2250 /** @brief Firmware update v1.3 package header identifier */
2251 #define PLDM_PACKAGE_HEADER_IDENTIFIER_V1_3                                    \
2252 	{                                                                      \
2253 		0x7b, 0x29, 0x1c, 0x99, 0x6d, 0xb6, 0x42, 0x08,                \
2254 		0x80, 0x1b, 0x02, 0x02, 0x6e, 0x46, 0x3c, 0x78,                \
2255 	}
2256 
2257 /** @brief Firmware update v1.3 package header format revision */
2258 #define PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H 0x04
2259 
2260 /** @brief Consumer-side version pinning for package format parsing
2261  *
2262  * Parsing a firmware update package requires the package to be of a revision
2263  * defined in the specification, for libpldm to support parsing a package
2264  * formatted at the specified revision, and for the consumer to support calling
2265  * libpldm's package-parsing APIs in the manner required for the package format.
2266  *
2267  * pldm_package_format_pin communicates to libpldm the maximum package format
2268  * revision supported by the consumer.
2269  *
2270  * The definition of the pldm_package_format_pin object in the consumer
2271  * application should not be open-coded. Instead, users should call on of the
2272  * following macros:
2273  *
2274  * - @ref DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR01H
2275  * - @ref DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H
2276  * - @ref DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR03H
2277  * - @ref DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR04H
2278  *
2279  * The package pinning operates by providing versioning over multiple structs
2280  * required to perform the package parsing. See [Conventions for extensible
2281  * system calls][lwn-extensible-syscalls] for discussion of related concepts.
2282  * Like the syscall structs described there, the structs captured here by the
2283  * pinning concept must only ever be modified by addition of new members, never
2284  * alteration of existing members.
2285  *
2286  * [lwn-extensible-syscalls]: https://lwn.net/Articles/830666/
2287  */
2288 struct pldm_package_format_pin {
2289 	struct {
2290 		/**
2291 		 * A value that communicates information about object sizes to the implementation.
2292 		 *
2293 		 * For magic version 0, the sum must be calculated using @ref LIBPLDM_SIZEAT for
2294 		 * the final relevant member of each relevant struct for the format revision
2295 		 * represented by the pin.
2296 		 */
2297 		const uint32_t magic;
2298 
2299 		/**
2300 		 * Versioning for the derivation of the magic value
2301 		 *
2302 		 * A version value of 0 defines the magic number to be the sum of the relevant
2303 		 * struct sizes for the members required at the format revision specified by
2304 		 * the pin.
2305 		 */
2306 		const uint8_t version;
2307 	} meta;
2308 	struct {
2309 		/** The maximum supported package format UUID */
2310 		const pldm_uuid identifier;
2311 
2312 		/** The maximum supported header format revision */
2313 		const uint8_t revision;
2314 	} format;
2315 };
2316 
2317 enum pldm_package_parse {
2318 	PLDM_PACKAGE_PARSE_INIT = 0,
2319 	PLDM_PACKAGE_PARSE_COMPLETE = 1,
2320 	PLDM_PACKAGE_PARSE_HEADER = 2,
2321 	PLDM_PACKAGE_PARSE_FIRMWARE_DEVICES = 3,
2322 	PLDM_PACKAGE_PARSE_DOWNSTREAM_DEVICES = 4,
2323 	PLDM_PACKAGE_PARSE_COMPONENT_IMAGE_INFORMATION = 5,
2324 };
2325 
2326 struct pldm_package_iter {
2327 	struct variable_field field;
2328 	size_t entries;
2329 };
2330 
2331 /**
2332  * @brief Header information as parsed from the provided package
2333  *
2334  * See Table 3, DSP0267 v1.3.0.
2335  *
2336  * The provided package data must out-live the header struct.
2337  */
2338 // NOLINTNEXTLINE(bugprone-reserved-identifier, cert-dcl37-c, cert-dcl51-cpp)
2339 struct pldm__package_header_information {
2340 	pldm_uuid package_header_identifier;
2341 	uint8_t package_header_format_revision;
2342 	uint8_t package_release_date_time[PLDM_TIMESTAMP104_SIZE];
2343 	uint16_t component_bitmap_bit_length;
2344 	uint8_t package_version_string_type;
2345 
2346 	/** A field pointing to the package version string in the provided package data */
2347 	struct variable_field package_version_string;
2348 };
2349 /* TODO: Deprecate the other struct pldm_package_header_information, remove, drop typedef */
2350 // NOLINTNEXTLINE(bugprone-reserved-identifier, cert-dcl37-c, cert-dcl51-cpp)
2351 typedef struct pldm__package_header_information
2352 	pldm_package_header_information_pad;
2353 
2354 /* TODO: Consider providing an API to access valid bits */
2355 struct pldm_package_component_bitmap {
2356 	struct variable_field bitmap;
2357 };
2358 
2359 /**
2360  * @brief A firmware device ID record from the firmware update package
2361  *
2362  * See Table 4, DSP0267 v1.3.0.
2363  *
2364  * The provided package data must out-live the @ref "struct
2365  * pldm_package_firmware_device_id_record" instance.
2366  */
2367 struct pldm_package_firmware_device_id_record {
2368 	uint8_t descriptor_count;
2369 	bitfield32_t device_update_option_flags;
2370 	uint8_t component_image_set_version_string_type;
2371 
2372 	/**
2373 	 * A field pointing to the component image set version string in the provided
2374 	 * package data.
2375 	 */
2376 	struct variable_field component_image_set_version_string;
2377 
2378 	/**
2379 	 * A field pointing to the to a bitmap of length @ref
2380 	 * component_bitmap_bit_length in the provided package data..
2381 	 */
2382 	struct pldm_package_component_bitmap applicable_components;
2383 
2384 	/**
2385 	 * A field pointing to record descriptors for the
2386 	 * firmware device. Iterate over the entries using @ref
2387 	 * foreach_pldm_package_firmware_device_id_record_descriptor
2388 	 *
2389 	 * See Table 7, DSP0267 v1.3.0
2390 	 */
2391 	struct variable_field record_descriptors;
2392 	struct variable_field firmware_device_package_data;
2393 
2394 	/**
2395 	 * An optional field that can contain a Reference Manifest for the firmware
2396 	 * update package. If present, this field points to the Reference Manifest
2397 	 * data, which describes the firmware update provided by this package. The
2398 	 * UA (Update Agent) may use this data as a reference for the firmware
2399 	 * version.
2400 	 *
2401 	 * Note that this data shall not be transferred to the firmware device (FD).
2402 	 * The format of the data is either a Standard Body or Vendor-Defined Header,
2403 	 * followed by the Reference Manifest data.
2404 	 *
2405 	 * See Table 7, DSP0267 v1.3.0
2406 	 */
2407 	struct variable_field reference_manifest_data;
2408 };
2409 
2410 /**
2411  * @brief A downstream device ID record from the firmware update package
2412  *
2413  * See Table 5, DSP0267 v1.3.0.
2414  *
2415  * The provided package data must out-live the @ref "struct
2416  * pldm_package_downstream_device_id_record" instance.
2417  */
2418 struct pldm_package_downstream_device_id_record {
2419 	uint8_t descriptor_count;
2420 	bitfield32_t update_option_flags;
2421 	uint8_t self_contained_activation_min_version_string_type;
2422 
2423 	/**
2424 	 * A field pointing to the self-contained activation minimum version string in
2425 	 * the provided package data.
2426 	 */
2427 	struct variable_field self_contained_activation_min_version_string;
2428 	uint32_t self_contained_activation_min_version_comparison_stamp;
2429 
2430 	/**
2431 	 * A field pointing to a bitmap of length @ref component_bitmap_bit_length in
2432 	 * the provided package data.
2433 	 */
2434 	struct pldm_package_component_bitmap applicable_components;
2435 
2436 	/**
2437 	 * A field pointing to record descriptors for the
2438 	 * downstream device. Iterate over the entries using @ref
2439 	 * foreach_pldm_package_downstream_device_id_record_descriptor
2440 	 *
2441 	 * See Table 7, DSP0267 v1.3.0
2442 	 */
2443 	struct variable_field record_descriptors;
2444 
2445 	/**
2446 	 * A field that may point to package data to be proxied by the firmware device.
2447 	 * If present, points into the provided package data.
2448 	 */
2449 	struct variable_field package_data;
2450 
2451 	/**
2452 	* A field pointing to a Reference Manifest for the downstream device.
2453 	* If present, this field points to the Reference Manifest data, which describes
2454 	*
2455 	* See Table 7, DSP0267 v1.3.0
2456 	*/
2457 	struct variable_field reference_manifest_data;
2458 };
2459 
2460 /**
2461  * @brief Component image information from the firmware update package.
2462  *
2463  * See Table 6, DSP0267 v1.3.0
2464  *
2465  * The provided package data must out-live the @ref "struct
2466  * pldm_package_component_image_information" instance.
2467  */
2468 struct pldm_package_component_image_information {
2469 	uint16_t component_classification;
2470 	uint16_t component_identifier;
2471 	uint32_t component_comparison_stamp;
2472 	bitfield16_t component_options;
2473 	bitfield16_t requested_component_activation_method;
2474 
2475 	/**
2476 	 * A field that points to the component image for a device in the provided
2477 	 * package data.
2478 	 */
2479 	struct variable_field component_image;
2480 	uint8_t component_version_string_type;
2481 
2482 	/**
2483 	 * A field that points to the component version string for the image in the
2484 	 * provided package data.
2485 	 */
2486 	struct variable_field component_version_string;
2487 
2488 	/**
2489 	 * A field that points to the component opaque data in the
2490 	 * provided package data.
2491 	 */
2492 	struct variable_field component_opaque_data;
2493 };
2494 
2495 /**
2496  * @brief State tracking for firmware update package iteration
2497  *
2498  * Declare an instance on the stack to be initialised by @ref
2499  * decode_pldm_firmware_update_package
2500  *
2501  * The state is consumed by the following macros:
2502  *
2503  * - @ref foreach_pldm_package_firmware_device_id_record
2504  * - @ref foreach_pldm_package_firmware_device_id_record_descriptor
2505  * - @ref foreach_pldm_package_downstream_device_id_record
2506  * - @ref foreach_pldm_package_downstream_device_id_record_descriptor
2507  * - @ref foreach_pldm_package_component_image_information
2508  */
2509 struct pldm_package {
2510 	const struct pldm_package_format_pin *pin;
2511 	const pldm_package_header_information_pad *hdr;
2512 	enum pldm_package_parse state;
2513 	uint32_t flags;
2514 	struct variable_field package;
2515 	struct variable_field areas;
2516 	struct pldm_package_iter iter;
2517 };
2518 
2519 /**
2520  * @brief Initialize the firmware update package iterator.
2521  *
2522  * @param[in] data The buffer containing the complete firmware update package
2523  * @param[in] length The length of the buffer pointed at by @p data
2524  * @param[in] pin The maximum supported package format revision of the caller
2525  * @param[out] hdr The parsed package header structure
2526  * @param[out] pkg State-tracking for parsing subsequent package records and components
2527  * @param[in] flags Affects the parsing behaviour of the library
2528  *
2529  * @pre @p pkg must be zero-initialised.
2530  *
2531  * Must be called to ensure version requirements for parsing are met by all
2532  * components, and to initialise @p pkg prior to any subsequent extraction of
2533  * package records and components.
2534  *
2535  * @note @p flags must be zero
2536  * @note @p data is stored in @iter for later reference, and therefore must
2537  *       out-live @p iter
2538  * @note @p hdr is stored in @iter for later reference, and therefore must
2539  *       out-live @p iter
2540  *
2541  * @return 0 on success. Otherwise, a negative errno value:
2542  * - -EBADMSG if the package fails to meet minimum required length for a valid
2543  *   package
2544  * - -EINVAL if provided parameter values are invalid
2545  * - -ENOTSUP on unrecognised or unsupported versions for the format pin or
2546  *   provided package
2547  * - -EOVERFLOW if the variable length structures extend beyond the package
2548  *   data buffer
2549  * - -EPROTO if parsed values violate the package format specification
2550  * - -EUCLEAN if the package fails embedded integrity checks
2551  */
2552 int decode_pldm_firmware_update_package(
2553 	const void *data, size_t length,
2554 	const struct pldm_package_format_pin *pin,
2555 	pldm_package_header_information_pad *hdr, struct pldm_package *pkg,
2556 	uint32_t flags);
2557 
2558 LIBPLDM_ITERATOR
pldm_package_firmware_device_id_record_iter_end(const struct pldm_package * pkg)2559 bool pldm_package_firmware_device_id_record_iter_end(
2560 	const struct pldm_package *pkg)
2561 {
2562 	assert(pkg->state == PLDM_PACKAGE_PARSE_FIRMWARE_DEVICES);
2563 	return pkg->iter.entries == 0;
2564 }
2565 
2566 LIBPLDM_ITERATOR
pldm_package_firmware_device_id_record_iter_next(struct pldm_package * pkg)2567 bool pldm_package_firmware_device_id_record_iter_next(struct pldm_package *pkg)
2568 {
2569 	assert(pkg->state == PLDM_PACKAGE_PARSE_FIRMWARE_DEVICES);
2570 	if (!pkg->iter.entries) {
2571 		return false;
2572 	}
2573 
2574 	pkg->iter.entries--;
2575 	return true;
2576 }
2577 
2578 int pldm_package_firmware_device_id_record_iter_init(struct pldm_package *pkg);
2579 
2580 int decode_pldm_package_firmware_device_id_record_from_iter(
2581 	struct pldm_package *pkg,
2582 	struct pldm_package_firmware_device_id_record *rec);
2583 
2584 /**
2585  * @brief Iterate over a package's firmware device ID records
2586  *
2587  * @param pkg[in,out] The lvalue for the instance of @ref "struct pldm_package"
2588  *             initialised by @ref decode_pldm_firmware_update_package
2589  * @param rec[out] An lvalue of type @ref "struct pldm_package_firmware_device_id_record"
2590  * @param rc[out] An lvalue of type int that holds the status result of parsing the
2591  *                firmware device ID record
2592  *
2593  * @p rc is set to 0 on successful decode. Otherwise, on error, @p rc is set to:
2594  * - -EINVAL if parameters values are invalid
2595  * - -EOVERFLOW if the package layout exceeds the bounds of the package buffer
2596  * - -EPROTO if package metadata doesn't conform to specification constraints
2597  *
2598  * Example use of the macro is as follows:
2599  *
2600  * @code
2601  * DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(pin);
2602  *
2603  * struct pldm_package_firmware_device_id_record fdrec;
2604  * pldm_package_header_information_pad hdr;
2605  * struct pldm_package pkg;
2606  * int rc;
2607  *
2608  * rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr,
2609  * 					 &pkg);
2610  * if (rc < 0) {
2611  * 	   // Handle header parsing failure
2612  * }
2613  * foreach_pldm_package_firmware_device_id_record(pkg, fdrec, rc) {
2614  * 	   // Do something with fdrec
2615  * }
2616  * if (rc) {
2617  * 	   // Handle parsing failure for fdrec
2618  * }
2619  * @endcode
2620  */
2621 #define foreach_pldm_package_firmware_device_id_record(pkg, rec, rc)           \
2622 	for ((rc) = pldm_package_firmware_device_id_record_iter_init(&(pkg));  \
2623 	     !(rc) &&                                                          \
2624 	     !pldm_package_firmware_device_id_record_iter_end(&(pkg)) &&       \
2625 	     !((rc) = decode_pldm_package_firmware_device_id_record_from_iter( \
2626 		       &(pkg), &(rec)));                                       \
2627 	     pldm_package_firmware_device_id_record_iter_next(&(pkg)))
2628 
2629 LIBPLDM_ITERATOR
2630 struct pldm_descriptor_iter
pldm_package_firmware_device_id_record_descriptor_iter_init(struct pldm_package * pkg,struct pldm_package_firmware_device_id_record * rec)2631 pldm_package_firmware_device_id_record_descriptor_iter_init(
2632 	struct pldm_package *pkg,
2633 	struct pldm_package_firmware_device_id_record *rec)
2634 {
2635 	(void)pkg;
2636 	assert(pkg->state == PLDM_PACKAGE_PARSE_FIRMWARE_DEVICES);
2637 	return (struct pldm_descriptor_iter){ &rec->record_descriptors,
2638 					      rec->descriptor_count };
2639 }
2640 
2641 /**
2642  * @brief Iterate over the descriptors in a package's firmware device ID record
2643  *
2644  * @param pkg[in,out] The lvalue for the instance of @ref "struct pldm_package"
2645  *             initialised by @ref decode_pldm_firmware_update_package
2646  * @param rec[in] An lvalue of type @ref "struct pldm_package_firmware_device_id_record"
2647  * @param desc[out] An lvalue of type @ref "struct pldm_descriptor" that holds
2648  *                  the parsed descriptor
2649  * @param rc[out] An lvalue of type int that holds the status result of parsing the
2650  *                firmware device ID record
2651  *
2652  * @p rc is set to 0 on successful decode. Otherwise, on error, @p rc is set to:
2653  * - -EINVAL if parameters values are invalid
2654  * - -EOVERFLOW if the package layout exceeds the bounds of the package buffer
2655  * - -EPROTO if package metadata doesn't conform to specification constraints
2656  *
2657  * Example use of the macro is as follows:
2658  *
2659  * @code
2660  * DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(pin);
2661  *
2662  * struct pldm_package_firmware_device_id_record fdrec;
2663  * pldm_package_header_information_pad hdr;
2664  * struct pldm_package pkg;
2665  * int rc;
2666  *
2667  * rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr,
2668  * 					 &pkg);
2669  * if (rc < 0) { ... }
2670  *
2671  * foreach_pldm_package_firmware_device_id_record(pkg, fdrec, rc) {
2672  *     struct pldm_descriptor desc;
2673  *
2674  * 	   ...
2675  *
2676  *     foreach_pldm_package_firmware_device_id_record_descriptor(
2677  *             pkg, fdrec, desc, rc) {
2678  *         // Do something with desc
2679  *     }
2680  *     if (rc) {
2681  *         // Handle failure to parse desc
2682  *     }
2683  * }
2684  * if (rc) { ... }
2685  * @endcode
2686  */
2687 #define foreach_pldm_package_firmware_device_id_record_descriptor(pkg, rec,       \
2688 								  desc, rc)       \
2689 	for (struct pldm_descriptor_iter desc##_iter =                            \
2690 		     ((rc) = 0,                                                   \
2691 		     pldm_package_firmware_device_id_record_descriptor_iter_init( \
2692 			      &(pkg), &(rec)));                                   \
2693 	     (!pldm_descriptor_iter_end(&(desc##_iter))) &&                       \
2694 	     !((rc) = decode_pldm_descriptor_from_iter(&(desc##_iter),            \
2695 						       &(desc)));                 \
2696 	     pldm_descriptor_iter_next(&(desc##_iter)))
2697 
2698 LIBPLDM_ITERATOR
pldm_package_downstream_device_id_record_iter_end(const struct pldm_package * pkg)2699 bool pldm_package_downstream_device_id_record_iter_end(
2700 	const struct pldm_package *pkg)
2701 {
2702 	assert(pkg->state == PLDM_PACKAGE_PARSE_DOWNSTREAM_DEVICES);
2703 	return pkg->iter.entries == 0;
2704 }
2705 
2706 LIBPLDM_ITERATOR
pldm_package_downstream_device_id_record_iter_next(struct pldm_package * pkg)2707 bool pldm_package_downstream_device_id_record_iter_next(struct pldm_package *pkg)
2708 {
2709 	assert(pkg->state == PLDM_PACKAGE_PARSE_DOWNSTREAM_DEVICES);
2710 	if (!pkg->iter.entries) {
2711 		return false;
2712 	}
2713 	pkg->iter.entries--;
2714 	return true;
2715 }
2716 
2717 int pldm_package_downstream_device_id_record_iter_init(struct pldm_package *pkg);
2718 
2719 int decode_pldm_package_downstream_device_id_record_from_iter(
2720 	struct pldm_package *pkg,
2721 	struct pldm_package_downstream_device_id_record *rec);
2722 
2723 /**
2724  * @brief Iterate over a package's downstream device ID records
2725  *
2726  * @param pkg[in,out] The lvalue for the instance of @ref "struct pldm_package"
2727  *             initialised by @ref decode_pldm_firmware_update_package
2728  * @param rec[out] An lvalue of type @ref "struct pldm_package_downstream_device_id_record"
2729  * @param rc[out] An lvalue of type int that holds the status result of parsing the
2730  *                firmware device ID record
2731  *
2732  * @p rc is set to 0 on successful decode. Otherwise, on error, @p rc is set to:
2733  * - -EINVAL if parameters values are invalid
2734  * - -EOVERFLOW if the package layout exceeds the bounds of the package buffer
2735  * - -EPROTO if package metadata doesn't conform to specification constraints
2736  *
2737  * Example use of the macro is as follows:
2738  *
2739  * @code
2740  * DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(pin);
2741  *
2742  * struct pldm_package_downstream_device_id_record ddrec;
2743  * struct pldm_package_firmware_device_id_record fdrec;
2744  * pldm_package_header_information_pad hdr;
2745  * struct pldm_package pkg;
2746  * int rc;
2747  *
2748  * rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr,
2749  * 					 &pkg);
2750  * if (rc < 0) { ... }
2751  *
2752  * foreach_pldm_package_firmware_device_id_record(pkg, fdrec, rc) {
2753  *     struct pldm_descriptor desc;
2754  * 	   ...
2755  *     foreach_pldm_package_firmware_device_id_record_descriptor(
2756  *             pkg, fdrec, desc, rc) {
2757  *         ...
2758  *     }
2759  *     if (rc) { ... }
2760  * }
2761  * if (rc) { ... }
2762  *
2763  * foreach_pldm_package_downstream_device_id_record(pkg, ddrec, rc) {
2764  * 	   // Do something with ddrec
2765  * }
2766  * if (rc) {
2767  * 	   // Handle parsing failure for ddrec
2768  * }
2769  * @endcode
2770  */
2771 #define foreach_pldm_package_downstream_device_id_record(pkg, rec, rc)           \
2772 	for ((rc) = pldm_package_downstream_device_id_record_iter_init(          \
2773 		     &(pkg));                                                    \
2774 	     !(rc) &&                                                            \
2775 	     !pldm_package_downstream_device_id_record_iter_end(&(pkg)) &&       \
2776 	     !((rc) = decode_pldm_package_downstream_device_id_record_from_iter( \
2777 		       &(pkg), &(rec)));                                         \
2778 	     pldm_package_downstream_device_id_record_iter_next(&(pkg)))
2779 
2780 LIBPLDM_ITERATOR
2781 struct pldm_descriptor_iter
pldm_package_downstream_device_id_record_descriptor_iter_init(struct pldm_package * pkg,struct pldm_package_downstream_device_id_record * rec)2782 pldm_package_downstream_device_id_record_descriptor_iter_init(
2783 	struct pldm_package *pkg,
2784 	struct pldm_package_downstream_device_id_record *rec)
2785 {
2786 	(void)pkg;
2787 	return (struct pldm_descriptor_iter){ &rec->record_descriptors,
2788 					      rec->descriptor_count };
2789 }
2790 
2791 /**
2792  * @brief Iterate over the descriptors in a package's downstream device ID record
2793  *
2794  * @param pkg[in,out] The lvalue for the instance of @ref "struct pldm_package"
2795  *             initialised by @ref decode_pldm_firmware_update_package
2796  * @param rec[in] An lvalue of type @ref "struct pldm_package_downstream_device_id_record"
2797  * @param desc[out] An lvalue of type @ref "struct pldm_descriptor" that holds
2798  *                  the parsed descriptor
2799  * @param rc[out] An lvalue of type int that holds the status result of parsing the
2800  *                downstream device ID record
2801  *
2802  * @p rc is set to 0 on successful decode. Otherwise, on error, @p rc is set to:
2803  * - -EINVAL if parameters values are invalid
2804  * - -EOVERFLOW if the package layout exceeds the bounds of the package buffer
2805  * - -EPROTO if package metadata doesn't conform to specification constraints
2806  *
2807  * Example use of the macro is as follows:
2808  *
2809  * @code
2810  * DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(pin);
2811  *
2812  * struct pldm_package_downstream_device_id_record ddrec;
2813  * struct pldm_package_firmware_device_id_record fdrec;
2814  * pldm_package_header_information_pad hdr;
2815  * struct pldm_package pkg;
2816  * int rc;
2817  *
2818  * rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr,
2819  * 					 &pkg);
2820  * if (rc < 0) { ... }
2821  *
2822  * foreach_pldm_package_firmware_device_id_record(pkg, fdrec, rc) {
2823  *     struct pldm_descriptor desc;
2824  * 	   ...
2825  *     foreach_pldm_package_firmware_device_id_record_descriptor(
2826  *             pkg, fdrec, desc, rc) {
2827  *         ...
2828  *     }
2829  *     if (rc) { ... }
2830  * }
2831  * if (rc) { ... }
2832  *
2833  * foreach_pldm_package_downstream_device_id_record(pkg, ddrec, rc) {
2834  *     struct pldm_descriptor desc;
2835  * 	   ...
2836  *     foreach_pldm_package_downstream_device_id_record_descriptor(
2837  *             pkg, ddrec, desc, rc)
2838  *     {
2839  *         // Do something with desc
2840  *     }
2841  *     if (rc) {
2842  *         // Handle parsing failure for desc
2843  *     }
2844  * }
2845  * if (rc) { ... }
2846  * @endcode
2847  */
2848 #define foreach_pldm_package_downstream_device_id_record_descriptor(pkg, rec,       \
2849 								    desc, rc)       \
2850 	for (struct pldm_descriptor_iter desc##_iter =                              \
2851 		     ((rc) = 0,                                                     \
2852 		     pldm_package_downstream_device_id_record_descriptor_iter_init( \
2853 			      &(pkg), &(rec)));                                     \
2854 	     (!pldm_descriptor_iter_end(&(desc##_iter))) &&                         \
2855 	     !((rc) = decode_pldm_descriptor_from_iter(&(desc##_iter),              \
2856 						       &(desc)));                   \
2857 	     pldm_descriptor_iter_next(&(desc##_iter)))
2858 
2859 LIBPLDM_ITERATOR
pldm_package_component_image_information_iter_end(const struct pldm_package * pkg)2860 bool pldm_package_component_image_information_iter_end(
2861 	const struct pldm_package *pkg)
2862 {
2863 	assert((pkg->state == PLDM_PACKAGE_PARSE_COMPLETE &&
2864 		pkg->iter.entries == 0) ||
2865 	       pkg->state == PLDM_PACKAGE_PARSE_COMPONENT_IMAGE_INFORMATION);
2866 	return pkg->state == PLDM_PACKAGE_PARSE_COMPLETE;
2867 }
2868 
2869 LIBPLDM_ITERATOR
pldm_package_component_image_information_iter_next(struct pldm_package * pkg)2870 bool pldm_package_component_image_information_iter_next(struct pldm_package *pkg)
2871 {
2872 	if (pkg->state == PLDM_PACKAGE_PARSE_COMPLETE) {
2873 		return false;
2874 	}
2875 
2876 	assert(pkg->state == PLDM_PACKAGE_PARSE_COMPONENT_IMAGE_INFORMATION);
2877 	pkg->iter.entries--;
2878 	if (!pkg->iter.entries) {
2879 		/*
2880 		 * Perform the final transition to complete now as there should be no further
2881 		 * interaction with the package parsing APIs
2882 		 */
2883 		pkg->state = PLDM_PACKAGE_PARSE_COMPLETE;
2884 		return false;
2885 	}
2886 	return true;
2887 }
2888 
2889 int pldm_package_component_image_information_iter_init(struct pldm_package *pkg);
2890 
2891 int decode_pldm_package_component_image_information_from_iter(
2892 	struct pldm_package *pkg,
2893 	struct pldm_package_component_image_information *info);
2894 
2895 /**
2896  * @brief Iterate over the component image information contained in the package
2897  *
2898  * @param pkg[in,out] The lvalue for the instance of @ref "struct pldm_package"
2899  *             initialised by @ref decode_pldm_firmware_update_package
2900  * @param rec[in] An lvalue of type @ref "struct pldm_package_downstream_device_id_record"
2901  * @param desc[out] An lvalue of type @ref "struct pldm_descriptor" that holds
2902  *                  the parsed descriptor
2903  * @param rc[out] An lvalue of type int that holds the status result of parsing the
2904  *                downstream device ID record
2905  *
2906  * @p rc is set to 0 on successful decode. Otherwise, on error, @p rc is set to:
2907  * - -EINVAL if parameters values are invalid
2908  * - -EOVERFLOW if the package layout exceeds the bounds of the package buffer
2909  * - -EPROTO if package metadata doesn't conform to specification constraints
2910  *
2911  * Example use of the macro is as follows:
2912  *
2913  * @code
2914  * DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(pin);
2915  *
2916  * struct pldm_package_downstream_device_id_record ddrec;
2917  * struct pldm_package_component_image_information info;
2918  * struct pldm_package_firmware_device_id_record fdrec;
2919  * pldm_package_header_information_pad hdr;
2920  * struct pldm_package pkg;
2921  * int rc;
2922  *
2923  * rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr,
2924  * 					 &pkg);
2925  * if (rc < 0) { ... }
2926  *
2927  * foreach_pldm_package_firmware_device_id_record(pkg, fdrec, rc) {
2928  *     struct pldm_descriptor desc;
2929  * 	   ...
2930  *     foreach_pldm_package_firmware_device_id_record_descriptor(
2931  *             pkg, fdrec, desc, rc) {
2932  *         ...
2933  *     }
2934  *     if (rc) { ... }
2935  * }
2936  * if (rc) { ... }
2937  *
2938  * foreach_pldm_package_downstream_device_id_record(pkg, ddrec, rc) {
2939  *     struct pldm_descriptor desc;
2940  * 	   ...
2941  *     foreach_pldm_package_downstream_device_id_record_descriptor(
2942  *             pkg, ddrec, desc, rc) {
2943  *         ...
2944  *     }
2945  *     if (rc) { ... }
2946  * }
2947  * if (rc) { ... }
2948  *
2949  * foreach_pldm_package_component_image_information(pkg, info, rc) {
2950  *     // Do something with info
2951  * }
2952  * if (rc) {
2953  * 	   // Handle parsing failure for info
2954  * }
2955  * @endcode
2956  */
2957 #define foreach_pldm_package_component_image_information(pkg, info, rc)          \
2958 	for ((rc) = pldm_package_component_image_information_iter_init(          \
2959 		     &(pkg));                                                    \
2960 	     !(rc) &&                                                            \
2961 	     !pldm_package_component_image_information_iter_end(&(pkg)) &&       \
2962 	     !((rc) = decode_pldm_package_component_image_information_from_iter( \
2963 		       &(pkg), &(info)));                                        \
2964 	     pldm_package_component_image_information_iter_next(&(pkg)))
2965 
2966 /**
2967  * Declare consumer support for at most revision 1 of the firmware update
2968  * package header
2969  *
2970  * @param name The name for the pin object
2971  *
2972  * The pin object must be provided to @ref decode_pldm_firmware_update_package
2973  */
2974 #define DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR01H(name)                             \
2975 	struct pldm_package_format_pin name = { \
2976 		.meta = { \
2977 			.magic = ( \
2978 				LIBPLDM_SIZEAT(struct pldm_package, iter) + \
2979 				LIBPLDM_SIZEAT(struct pldm__package_header_information, package_version_string) + \
2980 				LIBPLDM_SIZEAT(struct pldm_package_firmware_device_id_record, firmware_device_package_data) + \
2981 				LIBPLDM_SIZEAT(struct pldm_descriptor, descriptor_data) + \
2982 				LIBPLDM_SIZEAT(struct pldm_package_component_image_information, component_version_string) \
2983 			), \
2984 			.version = 0u, \
2985 		}, \
2986 		.format = { \
2987 			.identifier = PLDM_PACKAGE_HEADER_IDENTIFIER_V1_0, \
2988 			.revision = PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H, \
2989 		} \
2990 	}
2991 
2992 /**
2993  * Declare consumer support for at most revision 2 of the firmware update
2994  * package header
2995  *
2996  * @param name The name for the pin object
2997  *
2998  * The pin object must be provided to @ref decode_pldm_firmware_update_package
2999  */
3000 #define DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(name)                             \
3001 	struct pldm_package_format_pin name = { \
3002 		.meta = { \
3003 			.magic = ( \
3004 				LIBPLDM_SIZEAT(struct pldm_package, iter) + \
3005 				LIBPLDM_SIZEAT(struct pldm__package_header_information, package_version_string) + \
3006 				LIBPLDM_SIZEAT(struct pldm_package_firmware_device_id_record, firmware_device_package_data) + \
3007 				LIBPLDM_SIZEAT(struct pldm_descriptor, descriptor_data) + \
3008 				LIBPLDM_SIZEAT(struct pldm_package_downstream_device_id_record, package_data) + \
3009 				LIBPLDM_SIZEAT(struct pldm_package_component_image_information, component_version_string) \
3010 			), \
3011 			.version = 0u, \
3012 		}, \
3013 		.format = { \
3014 			.identifier = PLDM_PACKAGE_HEADER_IDENTIFIER_V1_1, \
3015 			.revision = PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR02H, \
3016 		} \
3017 	}
3018 
3019 /**
3020  * Declare consumer support for at most revision 3 of the firmware update
3021  * package header
3022  *
3023  * @param name The name for the pin object
3024  *
3025  * The pin object must be provided to @ref decode_pldm_firmware_update_package
3026  */
3027 #define DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR03H(name)                             \
3028 	struct pldm_package_format_pin name = { \
3029 		.meta = { \
3030 			.magic = ( \
3031 				LIBPLDM_SIZEAT(struct pldm_package, iter) + \
3032 				LIBPLDM_SIZEAT(struct pldm__package_header_information, package_version_string) + \
3033 				LIBPLDM_SIZEAT(struct pldm_package_firmware_device_id_record, firmware_device_package_data) + \
3034 				LIBPLDM_SIZEAT(struct pldm_descriptor, descriptor_data) + \
3035 				LIBPLDM_SIZEAT(struct pldm_package_downstream_device_id_record, package_data) + \
3036 				LIBPLDM_SIZEAT(struct pldm_package_component_image_information, component_opaque_data) \
3037 			), \
3038 			.version = 0u, \
3039 		}, \
3040 		.format = { \
3041 			.identifier = PLDM_PACKAGE_HEADER_IDENTIFIER_V1_2, \
3042 			.revision = PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR03H, \
3043 		} \
3044 	}
3045 
3046 /**
3047  * Declare consumer support for at most revision 4 of the firmware update
3048  * package header
3049  *
3050  * @param name The name for the pin object
3051  *
3052  * The pin object must be provided to @ref decode_pldm_firmware_update_package
3053  */
3054 #define DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR04H(name)                             \
3055 	struct pldm_package_format_pin name = { \
3056 		.meta = { \
3057 			.magic = ( \
3058 				LIBPLDM_SIZEAT(struct pldm_package, iter) + \
3059 				LIBPLDM_SIZEAT(struct pldm__package_header_information, package_version_string) + \
3060 				LIBPLDM_SIZEAT(struct pldm_package_firmware_device_id_record, reference_manifest_data) + \
3061 				LIBPLDM_SIZEAT(struct pldm_descriptor, descriptor_data) + \
3062 				LIBPLDM_SIZEAT(struct pldm_package_downstream_device_id_record, reference_manifest_data) + \
3063 				LIBPLDM_SIZEAT(struct pldm_package_component_image_information, component_opaque_data) \
3064 			), \
3065 			.version = 0u, \
3066 		}, \
3067 		.format = { \
3068 			.identifier = PLDM_PACKAGE_HEADER_IDENTIFIER_V1_3, \
3069 			.revision = PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H, \
3070 		} \
3071 	}
3072 
3073 #ifdef __cplusplus
3074 }
3075 #endif
3076 
3077 #endif // End of FW_UPDATE_H
3078