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