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