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