1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ 2 #pragma once 3 4 #ifdef __cplusplus 5 extern "C" { 6 #endif 7 8 #include <stdint.h> 9 #include <stdbool.h> 10 11 #include <libpldm/pldm.h> 12 #include <libpldm/base.h> 13 #include <libpldm/utils.h> 14 #include <libpldm/control.h> 15 #include <libpldm/firmware_update.h> 16 17 /** @struct pldm_firmware_component_standalone 18 * 19 * A PLDM Firmware Update Component representation, for use 20 * with pldm_fd_ops callbacks. 21 */ 22 struct pldm_firmware_component_standalone { 23 uint16_t comp_classification; 24 uint16_t comp_identifier; 25 uint8_t comp_classification_index; 26 27 struct pldm_firmware_version active_ver; 28 struct pldm_firmware_version pending_ver; 29 30 bitfield16_t comp_activation_methods; 31 bitfield32_t capabilities_during_update; 32 }; 33 34 /** @struct pldm_firmware_update_component 35 * 36 * An entry for Pass Component Table or Update Component 37 */ 38 struct pldm_firmware_update_component { 39 uint16_t comp_classification; 40 uint16_t comp_identifier; 41 uint8_t comp_classification_index; 42 uint32_t comp_comparison_stamp; 43 struct pldm_firmware_string version; 44 45 /* Not set for PassComponentTable */ 46 uint32_t comp_image_size; 47 /* Not set for PassComponentTable */ 48 bitfield32_t update_option_flags; 49 }; 50 51 /** @struct pldm_fd_ops 52 * 53 * Device-specific callbacks provided by an application, 54 * to define the device update behaviour. 55 * 56 * These will be called by the FD responder when pldm_fd_handle_msg() 57 * or pldm_fd_progress() are called by the application. 58 * 59 * Note that return values vary between functions. Some return a PLDM 60 * completion code or status code which will be sent to the UA, others 61 * return a negative errno on failure. 62 */ 63 struct pldm_fd_ops { 64 /** @brief Provide PLDM descriptors 65 * 66 * @param[in] ctx - callback context 67 * @param[out] ret_descriptors_count - count of descriptors returned 68 * @param[out] ret_descriptors - array of descriptors. 69 * 70 * @return 0 on success, a negative errno value on failure. 71 * (specific errno value is ignored) 72 */ 73 int (*device_identifiers)( 74 void *ctx, uint8_t *ret_descriptors_count, 75 const struct pldm_descriptor **ret_descriptors); 76 77 /** @brief Provide PLDM component table from the application 78 * 79 * @param[in] ctx - callback context 80 * @param[out] ret_entry_count - length of returned ret_entries 81 * @param[out] ret_entries - an array of component pointers 82 * 83 * @return 0 on success, a negative errno value on failure. 84 * (specific errno value is ignored) 85 * 86 * It will be called several times in an update flow. 87 */ 88 int (*components)( 89 void *ctx, uint16_t *ret_entry_count, 90 const struct pldm_firmware_component_standalone ***ret_entries); 91 92 /** @brief Return imageset version from the application 93 * 94 * @param[in] ctx - callback context 95 * @param[out] ret_active - ActiveComponentVersion string 96 * @param[out] ret_active - PendingComponentVersion string 97 * 98 * @return 0 on success, a negative errno value on failure. 99 * (specific errno value is ignored) 100 * 101 * This is used by the FD responder for GetFirmwareParameters. 102 */ 103 int (*imageset_versions)(void *ctx, 104 struct pldm_firmware_string *ret_active, 105 struct pldm_firmware_string *ret_pending); 106 107 /** @brief Called on PassComponentTable or UpdateComponent 108 * 109 * @param[in] ctx - callback context 110 * @param[in] update - will be set for UpdateComponent, and indicates that 111 * an update flow is starting, with the same comp used 112 * for subsequent firmware_data, verify, apply callbacks. 113 * @param[in] comp - the component being used. The FD implementation 114 * will only pass comp that has already been 115 * validated against the pldm_fd_ops.components callback. 116 * 117 * @return PLDM_CRC_COMP_CAN_BE_UPDATED if the component can be updated. 118 */ 119 enum pldm_component_response_codes (*update_component)( 120 void *ctx, bool update, 121 const struct pldm_firmware_update_component *comp); 122 123 /** @brief Provide the transfer size to use 124 * 125 * @param[in] ctx - callback context 126 * @param[in] ua_max_transfer_size - size requested by the UA. 127 * 128 * @return The transfer size to use. This will be clamped to 129 * 32 <= size <= ua_max_transfer_size. 130 * The final data chunk may be shorter. 131 */ 132 uint32_t (*transfer_size)(void *ctx, uint32_t ua_max_transfer_size); 133 134 /* @brief Provides firmware update data from the UA 135 * 136 * @param[in] ctx - callback context 137 * @param[in] offset - offset of the data 138 * @param[in] data - firmware data buffer 139 * @param[in] len - length of data 140 * @param[in] comp - the relevant component 141 * 142 * @return TransferComplete code - either 143 * enum pldm_firmware_update_common_error_codes or 144 * enum pldm_firmware_update_transfer_result_values. 145 * 146 * PLDM_FWUP_TRANSFER_SUCCESS will accept the data chunk, other codes will 147 * abort the transfer, returning that code as TransferComplete 148 */ 149 uint8_t (*firmware_data)( 150 void *ctx, uint32_t offset, const uint8_t *data, uint32_t len, 151 const struct pldm_firmware_update_component *comp); 152 153 /* @brief Requests the application verify the update 154 * 155 * @param[in] ctx - callback context 156 * @param[in] comp - the relevant component 157 * @param[out] ret_pending - set when verify will run asynchronously 158 * @param[out] ret_progress_percent - can optionally be set 159 * during asynchronous verify, 160 * or leave defaulted (101). 161 * 162 * @return VerifyComplete code - either 163 * enum pldm_firmware_update_common_error_codes or 164 * enum pldm_firmware_update_verify_result_values. 165 * 166 * verify() will only be called once all firmware_data (up to the UA-specified 167 * comp_image_size) has been provided. Implementations should check that length 168 * as part of verification, if not already checked. 169 * 170 * If the verify is going to complete asynchronously, implementations set 171 * *ret_pending=true and return PLDM_FWUP_VERIFY_SUCCESS. The FD will then 172 * call verify() again when pldm_fd_progress() is called. 173 */ 174 uint8_t (*verify)(void *ctx, 175 const struct pldm_firmware_update_component *comp, 176 bool *ret_pending, uint8_t *ret_progress_percent); 177 178 /* @brief Requests the application apply the update 179 * 180 * @param[in] ctx - callback context 181 * @param[in] comp - the relevant component 182 * @param[out] ret_pending - set when apply will run asynchronously 183 * @param[out] ret_progress_percent - can optionally be set 184 * during asynchronous apply, 185 * or leave defaulted (101). 186 * 187 * @return ApplyComplete code - either 188 * enum pldm_firmware_update_common_error_codes or 189 * enum pldm_firmware_update_apply_result_values. 190 * 191 * If the apply is going to complete asynchronously, implementations set 192 * *ret_pending=true and return PLDM_FWUP_APPLY_SUCCESS. The FD will then 193 * call apply() again when pldm_fd_progress() is called. 194 */ 195 uint8_t (*apply)(void *ctx, 196 const struct pldm_firmware_update_component *comp, 197 bool *ret_pending, uint8_t *ret_progress_percent); 198 199 /* @brief Activates new firmware 200 * 201 * @param[in] ctx - callback context 202 * @param[in] self_contained - Self Contained Activation is requested 203 * @param[out] ret_estimated_time - a time in seconds to perform 204 * self activation, or may be left as 0. 205 * 206 * @return PLDM completion code 207 * 208 * The device implementation is responsible for checking that 209 * expected components have been updated, returning 210 * PLDM_FWUP_INCOMPLETE_UPDATE if not. 211 */ 212 uint8_t (*activate)(void *ctx, bool self_contained, 213 uint16_t *ret_estimated_time); 214 215 /* @brief Cancel Update Component 216 * 217 * @param[in] ctx - callback context 218 * @param[in] comp - the relevant component 219 * 220 * Called when a component update is cancelled prior to being applied. 221 * This function is called for both Cancel Update Component 222 * and Cancel Update (when a component is currently in progress). */ 223 void (*cancel_update_component)( 224 void *ctx, const struct pldm_firmware_update_component *comp); 225 226 /* @brief Returns a monotonic timestamp 227 * 228 * @param[in] ctx - callback context 229 * 230 * @return timestamp in milliseconds, from an arbitrary origin. 231 Must not go backwards. 232 */ 233 uint64_t (*now)(void *ctx); 234 }; 235 236 /* Static storage can be allocated with 237 * PLDM_SIZEOF_PLDM_FD macro */ 238 #define PLDM_ALIGNOF_PLDM_FD 8 239 struct pldm_fd; 240 241 /** @brief Allocate and initialise a FD responder 242 * 243 * @param[in] ops - Application provided callbacks which define the device 244 * update behaviour 245 * @param[in] ops_ctx - opaque context pointer that will be passed as ctx 246 * to ops callbacks 247 * @param[in] control - an optional struct pldm_control. If provided 248 * the FD responder will set PLDM FW update type 249 * and commands for the control. 250 * 251 * @return a malloced struct pldm_fd, owned by the caller. It should be released 252 * with free(). Returns NULL on failure. 253 * 254 * This will call pldm_fd_setup() on the allocated pldm_fd. 255 */ 256 struct pldm_fd *pldm_fd_new(const struct pldm_fd_ops *ops, void *ops_ctx, 257 struct pldm_control *control); 258 259 /** @brief Initialise a FD responder struct 260 * 261 * @param[in] fd - A pointer to a struct pldm_fd. Applications can allocate this 262 * in static storage of size PLDM_SIZEOF_PLDM_FD if required. 263 * @param[in] pldm_fd_size - applications should pass PLDM_SIZEOF_PLDM_FD, to check 264 * for consistency with the fd pointer. 265 * @param[in] ops - Application provided callbacks which define the device 266 * update behaviour 267 * @param[in] ops_ctx - opaque context pointer that will be passed as ctx 268 * to ops callbacks 269 * @param[in] control - an optional struct pldm_control. If provided 270 * the FD responder will set PLDM FW update type 271 * and commands for the control. 272 * 273 * @return 0 on success, a negative errno value on failure. 274 */ 275 int pldm_fd_setup(struct pldm_fd *fd, size_t pldm_fd_size, 276 const struct pldm_fd_ops *ops, void *ops_ctx, 277 struct pldm_control *control); 278 279 /** @brief Handle a PLDM Firmware Update message 280 * 281 * @param[in] fd 282 * @param[in] remote_address - the source address of the message. 283 * @param[in] in_msg - PLDM incoming message payload 284 * @param[in] in_len - length of in_msg buffer 285 * @param[out] out_msg - PLDM outgoing message payload buffer 286 * @param[inout] out_len - length of available out_msg buffer, will be updated 287 * with the length written to out_msg. 288 * 289 * @return 0 on success, a negative errno value on failure. 290 * 291 * Will return a message to send if out_len > 0 292 * and returning 0. 293 */ 294 int pldm_fd_handle_msg(struct pldm_fd *fd, pldm_tid_t remote_address, 295 const void *in_msg, size_t in_len, void *out_msg, 296 size_t *out_len); 297 298 /** @brief Handle periodic progress events 299 * 300 * @param[in] fd 301 * @param[out] out_msg - PLDM outgoing message payload buffer 302 * @param[inout] out_len - length of available out_msg buffer, will be updated 303 * with the length written to out_msg. 304 * @param[out] remote_address - destination address for the message to send. 305 * This is the address used to initiate the update, 306 * from a previous pldm_fd_handle_msg call. 307 * 308 * @return 0 on success, a negative errno value on failure. 309 * 310 * Will return a message to send to remote_address if out_len > 0 311 * and returning 0. 312 * 313 * This could be called periodically by the application to send retries 314 * during an update flow. A 1 second interval is recommended. 315 */ 316 int pldm_fd_progress(struct pldm_fd *fd, void *out_msg, size_t *out_len, 317 pldm_tid_t *remote_address); 318 319 /** @brief Set update mode idle timeout 320 * 321 * @param[in] fd 322 * @param[in] time - Amount of time before the FD shall exit from update mode 323 * if no command is received, in milliseconds. FD_T1. 324 * Should be 60000-120000 (60-120 sec), initial default is 325 * 120000. 326 * 327 * @return 0 on success, a negative errno value on failure. 328 */ 329 int pldm_fd_set_update_idle_timeout(struct pldm_fd *fd, uint32_t time); 330 331 /** @brief Set request retry time 332 * 333 * @param[in] fd 334 * @param[in] time - Time for retries of Request Firmware Data, 335 * Verify, Apply commands, in miliseconds. FD_T2. 336 * Should be 1000-5000, initial default is 1000. 337 * 338 * Will return a message to send to remote_address if out_len > 0 339 * and returning 0. 340 * 341 * This could be called periodically by the application to send retries 342 * during an update flow. A 1 second interval is recommended. 343 * 344 * @return 0 on success, a negative errno value on failure. 345 */ 346 int pldm_fd_set_request_retry_time(struct pldm_fd *fd, uint32_t time); 347 348 #ifdef __cplusplus 349 } 350 #endif 351