Line data Source code
1 0 : /*
2 : * Copyright (c) 2018-2021 mcumgr authors
3 : * Copyright (c) 2022-2024 Nordic Semiconductor ASA
4 : *
5 : * SPDX-License-Identifier: Apache-2.0
6 : */
7 :
8 : #ifndef H_IMG_MGMT_
9 : #define H_IMG_MGMT_
10 :
11 : #include <inttypes.h>
12 : #include <bootutil/image.h>
13 : #include <zcbor_common.h>
14 :
15 : #ifdef CONFIG_MCUMGR_GRP_IMG_VERBOSE_ERR
16 : #include <zephyr/mgmt/mcumgr/mgmt/mgmt.h>
17 : #include <zephyr/mgmt/mcumgr/smp/smp.h>
18 : #endif
19 :
20 : /**
21 : * @brief MCUmgr Image Management API
22 : * @defgroup mcumgr_img_mgmt Image Management
23 : * @ingroup mcumgr_mgmt_api
24 : * @{
25 : */
26 :
27 : #ifdef __cplusplus
28 : extern "C" {
29 : #endif
30 :
31 0 : #define IMG_MGMT_DATA_SHA_LEN 32 /* SHA256 */
32 :
33 : /**
34 : * @name Image state flags
35 : * @{
36 : */
37 : /** Image is set for next swap */
38 1 : #define IMG_MGMT_STATE_F_PENDING 0x01
39 : /** Image has been confirmed. */
40 1 : #define IMG_MGMT_STATE_F_CONFIRMED 0x02
41 : /** Image is currently active. */
42 1 : #define IMG_MGMT_STATE_F_ACTIVE 0x04
43 : /** Image is to stay in primary slot after the next boot. */
44 1 : #define IMG_MGMT_STATE_F_PERMANENT 0x08
45 : /** @} */
46 :
47 : /* 255.255.65535.4294967295\0 */
48 0 : #define IMG_MGMT_VER_MAX_STR_LEN (sizeof("255.255.65535.4294967295"))
49 :
50 : /**
51 : * @name Swap Types for image management state machine
52 : * @{
53 : */
54 1 : #define IMG_MGMT_SWAP_TYPE_NONE 0 /**< No swap */
55 1 : #define IMG_MGMT_SWAP_TYPE_TEST 1 /**< Test swap */
56 1 : #define IMG_MGMT_SWAP_TYPE_PERM 2 /**< Permanent swap */
57 1 : #define IMG_MGMT_SWAP_TYPE_REVERT 3 /**< Revert swap */
58 1 : #define IMG_MGMT_SWAP_TYPE_UNKNOWN 255 /**< Unknown swap */
59 : /** @} */
60 :
61 : /**
62 : * @name Command IDs for image management group.
63 : * @{
64 : */
65 1 : #define IMG_MGMT_ID_STATE 0 /**< State of images */
66 1 : #define IMG_MGMT_ID_UPLOAD 1 /**< Image upload */
67 1 : #define IMG_MGMT_ID_FILE 2 /**< File */
68 1 : #define IMG_MGMT_ID_CORELIST 3 /**< Corelist */
69 1 : #define IMG_MGMT_ID_CORELOAD 4 /**< Coreload */
70 1 : #define IMG_MGMT_ID_ERASE 5 /**< Image erase */
71 1 : #define IMG_MGMT_ID_SLOT_INFO 6 /**< Slot info */
72 : /** @} */
73 :
74 : /**
75 : * Command result codes for image management group.
76 : */
77 1 : enum img_mgmt_err_code_t {
78 : /** No error, this is implied if there is no ret value in the response */
79 : IMG_MGMT_ERR_OK = 0,
80 :
81 : /** Unknown error occurred. */
82 : IMG_MGMT_ERR_UNKNOWN,
83 :
84 : /** Failed to query flash area configuration. */
85 : IMG_MGMT_ERR_FLASH_CONFIG_QUERY_FAIL,
86 :
87 : /** There is no image in the slot. */
88 : IMG_MGMT_ERR_NO_IMAGE,
89 :
90 : /** The image in the slot has no TLVs (tag, length, value). */
91 : IMG_MGMT_ERR_NO_TLVS,
92 :
93 : /** The image in the slot has an invalid TLV type and/or length. */
94 : IMG_MGMT_ERR_INVALID_TLV,
95 :
96 : /** The image in the slot has multiple hash TLVs, which is invalid. */
97 : IMG_MGMT_ERR_TLV_MULTIPLE_HASHES_FOUND,
98 :
99 : /** The image in the slot has an invalid TLV size. */
100 : IMG_MGMT_ERR_TLV_INVALID_SIZE,
101 :
102 : /** The image in the slot does not have a hash TLV, which is required. */
103 : IMG_MGMT_ERR_HASH_NOT_FOUND,
104 :
105 : /** There is no free slot to place the image. */
106 : IMG_MGMT_ERR_NO_FREE_SLOT,
107 :
108 : /** Flash area opening failed. */
109 : IMG_MGMT_ERR_FLASH_OPEN_FAILED,
110 :
111 : /** Flash area reading failed. */
112 : IMG_MGMT_ERR_FLASH_READ_FAILED,
113 :
114 : /** Flash area writing failed. */
115 : IMG_MGMT_ERR_FLASH_WRITE_FAILED,
116 :
117 : /** Flash area erase failed. */
118 : IMG_MGMT_ERR_FLASH_ERASE_FAILED,
119 :
120 : /** The provided slot is not valid. */
121 : IMG_MGMT_ERR_INVALID_SLOT,
122 :
123 : /** Insufficient heap memory (malloc failed). */
124 : IMG_MGMT_ERR_NO_FREE_MEMORY,
125 :
126 : /** The flash context is already set. */
127 : IMG_MGMT_ERR_FLASH_CONTEXT_ALREADY_SET,
128 :
129 : /** The flash context is not set. */
130 : IMG_MGMT_ERR_FLASH_CONTEXT_NOT_SET,
131 :
132 : /** The device for the flash area is NULL. */
133 : IMG_MGMT_ERR_FLASH_AREA_DEVICE_NULL,
134 :
135 : /** The offset for a page number is invalid. */
136 : IMG_MGMT_ERR_INVALID_PAGE_OFFSET,
137 :
138 : /** The offset parameter was not provided and is required. */
139 : IMG_MGMT_ERR_INVALID_OFFSET,
140 :
141 : /** The length parameter was not provided and is required. */
142 : IMG_MGMT_ERR_INVALID_LENGTH,
143 :
144 : /** The image length is smaller than the size of an image header. */
145 : IMG_MGMT_ERR_INVALID_IMAGE_HEADER,
146 :
147 : /** The image header magic value does not match the expected value. */
148 : IMG_MGMT_ERR_INVALID_IMAGE_HEADER_MAGIC,
149 :
150 : /** The hash parameter provided is not valid. */
151 : IMG_MGMT_ERR_INVALID_HASH,
152 :
153 : /** The image load address does not match the address of the flash area. */
154 : IMG_MGMT_ERR_INVALID_FLASH_ADDRESS,
155 :
156 : /** Failed to get version of currently running application. */
157 : IMG_MGMT_ERR_VERSION_GET_FAILED,
158 :
159 : /** The currently running application is newer than the version being uploaded. */
160 : IMG_MGMT_ERR_CURRENT_VERSION_IS_NEWER,
161 :
162 : /** There is already an image operating pending. */
163 : IMG_MGMT_ERR_IMAGE_ALREADY_PENDING,
164 :
165 : /** The image vector table is invalid. */
166 : IMG_MGMT_ERR_INVALID_IMAGE_VECTOR_TABLE,
167 :
168 : /** The image it too large to fit. */
169 : IMG_MGMT_ERR_INVALID_IMAGE_TOO_LARGE,
170 :
171 : /** The amount of data sent is larger than the provided image size. */
172 : IMG_MGMT_ERR_INVALID_IMAGE_DATA_OVERRUN,
173 :
174 : /** Confirmation of image has been denied */
175 : IMG_MGMT_ERR_IMAGE_CONFIRMATION_DENIED,
176 :
177 : /** Setting test to active slot is not allowed */
178 : IMG_MGMT_ERR_IMAGE_SETTING_TEST_TO_ACTIVE_DENIED,
179 :
180 : /** Current active slot for image cannot be determined */
181 : IMG_MGMT_ERR_ACTIVE_SLOT_NOT_KNOWN,
182 : };
183 :
184 : /**
185 : * IMG_MGMT_ID_UPLOAD statuses.
186 : */
187 0 : enum img_mgmt_id_upload_t {
188 : IMG_MGMT_ID_UPLOAD_STATUS_START = 0,
189 : IMG_MGMT_ID_UPLOAD_STATUS_ONGOING,
190 : IMG_MGMT_ID_UPLOAD_STATUS_COMPLETE,
191 : };
192 :
193 0 : extern int boot_current_slot;
194 0 : extern struct img_mgmt_state g_img_mgmt_state;
195 :
196 : /** Represents an individual upload request. */
197 1 : struct img_mgmt_upload_req {
198 0 : uint32_t image; /* 0 by default */
199 0 : size_t off; /* SIZE_MAX if unspecified */
200 0 : size_t size; /* SIZE_MAX if unspecified */
201 0 : struct zcbor_string img_data;
202 0 : struct zcbor_string data_sha;
203 0 : bool upgrade; /* Only allow greater version numbers. */
204 : };
205 :
206 : /** Global state for upload in progress. */
207 1 : struct img_mgmt_state {
208 : /** Flash area being written; -1 if no upload in progress. */
209 1 : int area_id;
210 : /** Flash offset of next chunk. */
211 1 : size_t off;
212 : /** Total size of image data. */
213 1 : size_t size;
214 : /** Hash of image data; used for resumption of a partial upload. */
215 1 : uint8_t data_sha_len;
216 0 : uint8_t data_sha[IMG_MGMT_DATA_SHA_LEN];
217 : };
218 :
219 : /** Describes what to do during processing of an upload request. */
220 1 : struct img_mgmt_upload_action {
221 : /** The total size of the image. */
222 1 : unsigned long long size;
223 : /** The number of image bytes to write to flash. */
224 1 : int write_bytes;
225 : /** The flash area to write to. */
226 1 : int area_id;
227 : /** Whether to process the request; false if offset is wrong. */
228 1 : bool proceed;
229 : /** Whether to erase the destination flash area. */
230 1 : bool erase;
231 : #ifdef CONFIG_MCUMGR_GRP_IMG_VERBOSE_ERR
232 : /** "rsn" string to be sent as explanation for "rc" code */
233 : const char *rc_rsn;
234 : #endif
235 : };
236 :
237 : /*
238 : * @brief Read info of an image at the specified slot number
239 : *
240 : * @param image_slot image slot number
241 : * @param ver output buffer for image version
242 : * @param hash output buffer for image hash
243 : * @param flags output buffer for image flags
244 : *
245 : * @return 0 on success, non-zero on failure.
246 : */
247 0 : int img_mgmt_read_info(int image_slot, struct image_version *ver, uint8_t *hash, uint32_t *flags);
248 :
249 : /**
250 : * @brief Get the image version of the currently running application.
251 : *
252 : * @param ver output buffer for an image version information object.
253 : *
254 : * @return 0 on success, non-zero on failure.
255 : */
256 1 : int img_mgmt_my_version(struct image_version *ver);
257 :
258 : /**
259 : * @brief Format version string from struct image_version
260 : *
261 : * @param ver pointer to image_version object
262 : * @param dst output buffer for image version string
263 : *
264 : * @return Non-negative on success, negative value on error.
265 : */
266 1 : int img_mgmt_ver_str(const struct image_version *ver, char *dst);
267 :
268 : /**
269 : * @brief Get active, running application slot number for an image
270 : *
271 : * @param image image number to get active slot for.
272 : *
273 : * @return Non-negative slot number
274 : */
275 1 : int img_mgmt_active_slot(int image);
276 :
277 : /**
278 : * @brief Get active image number
279 : *
280 : * Gets 0 based number for running application.
281 : *
282 : * @return Non-negative image number.
283 : */
284 1 : int img_mgmt_active_image(void);
285 :
286 : /**
287 : * @brief Check if the image slot is in use.
288 : *
289 : * The check is based on MCUboot flags, not image contents. This means that
290 : * slot with image in it, but no bootable flags set, is considered empty.
291 : * Active slot is always in use.
292 : *
293 : * @param slot slot number
294 : *
295 : * @return 0 if slot is not used, non-0 otherwise.
296 : */
297 1 : int img_mgmt_slot_in_use(int slot);
298 :
299 : /**
300 : * @brief Check if any slot is in MCUboot pending state.
301 : *
302 : * Function returns 1 if slot 0 or slot 1 is in MCUboot pending state,
303 : * which means that it has been either marked for test or confirmed.
304 : *
305 : * @return 1 if there's pending DFU otherwise 0.
306 : */
307 1 : int img_mgmt_state_any_pending(void);
308 :
309 : /**
310 : * @brief Returns state flags set to slot.
311 : *
312 : * Flags are translated from MCUboot image state flags.
313 : * Returned value is zero if no flags are set or a combination of:
314 : * IMG_MGMT_STATE_F_PENDING
315 : * IMG_MGMT_STATE_F_CONFIRMED
316 : * IMG_MGMT_STATE_F_ACTIVE
317 : * IMG_MGMT_STATE_F_PERMANENT
318 : *
319 : * @param query_slot slot number
320 : *
321 : * @return return the state flags.
322 : *
323 : */
324 1 : uint8_t img_mgmt_state_flags(int query_slot);
325 :
326 : /**
327 : * @brief Sets the pending flag for the specified image slot.
328 : *
329 : * Sets specified image slot to be used as active slot during next boot,
330 : * either for test or permanently. Non-permanent image will be reverted
331 : * unless image confirms itself during next boot.
332 : *
333 : * @param slot slot number
334 : * @param permanent permanent or test only
335 : *
336 : * @return 0 on success, non-zero on failure
337 : */
338 1 : int img_mgmt_state_set_pending(int slot, int permanent);
339 :
340 : /**
341 : * @brief Confirms the current image state.
342 : *
343 : * Prevents a fallback from occurring on the next reboot if the active image
344 : * is currently being tested.
345 : *
346 : * @return 0 on success, non-zero on failure
347 : */
348 1 : int img_mgmt_state_confirm(void);
349 :
350 : /**
351 : * Compares two image version numbers in a semver-compatible way.
352 : *
353 : * @param a The first version to compare
354 : * @param b The second version to compare
355 : *
356 : * @return -1 if a < b
357 : * @return 0 if a = b
358 : * @return 1 if a > b
359 : */
360 1 : int img_mgmt_vercmp(const struct image_version *a, const struct image_version *b);
361 :
362 : #if defined(CONFIG_MCUMGR_GRP_IMG_MUTEX)
363 : /*
364 : * @brief Will reset the image management state back to default (no ongoing upload),
365 : * requires that CONFIG_MCUMGR_GRP_IMG_MUTEX be enabled to allow for mutex
366 : * locking of the image management state object.
367 : */
368 : void img_mgmt_reset_upload(void);
369 : #endif
370 :
371 : #ifdef CONFIG_MCUMGR_GRP_IMG_VERBOSE_ERR
372 : #define IMG_MGMT_UPLOAD_ACTION_SET_RC_RSN(action, rsn) ((action)->rc_rsn = (rsn))
373 : #define IMG_MGMT_UPLOAD_ACTION_RC_RSN(action) ((action)->rc_rsn)
374 : int img_mgmt_error_rsp(struct smp_streamer *ctxt, int rc, const char *rsn);
375 : extern const char *img_mgmt_err_str_app_reject;
376 : extern const char *img_mgmt_err_str_hdr_malformed;
377 : extern const char *img_mgmt_err_str_magic_mismatch;
378 : extern const char *img_mgmt_err_str_no_slot;
379 : extern const char *img_mgmt_err_str_flash_open_failed;
380 : extern const char *img_mgmt_err_str_flash_erase_failed;
381 : extern const char *img_mgmt_err_str_flash_write_failed;
382 : extern const char *img_mgmt_err_str_downgrade;
383 : extern const char *img_mgmt_err_str_image_bad_flash_addr;
384 : extern const char *img_mgmt_err_str_image_too_large;
385 : extern const char *img_mgmt_err_str_data_overrun;
386 : #else
387 0 : #define IMG_MGMT_UPLOAD_ACTION_SET_RC_RSN(action, rsn)
388 0 : #define IMG_MGMT_UPLOAD_ACTION_RC_RSN(action) NULL
389 : #endif
390 :
391 : /**
392 : * @}
393 : */
394 :
395 : #ifdef __cplusplus
396 : }
397 : #endif
398 :
399 : #endif /* H_IMG_MGMT_ */
|