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