xref: /openbmc/libpldm/include/libpldm/firmware_fd.h (revision cc6f6434b70fc0ffc272db7ee156ff709bb160ee)
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