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