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