1 /*
2  * Copyright (c) 2018-2021 mcumgr authors
3  * Copyright (c) 2022-2023 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #ifndef H_IMG_MGMT_PRIV_
9 #define H_IMG_MGMT_PRIV_
10 
11 #include <stdbool.h>
12 #include <inttypes.h>
13 
14 #include <zephyr/mgmt/mcumgr/smp/smp.h>
15 #include <zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt.h>
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 /**
22  * @brief Ensures the spare slot (slot 1) is fully erased.
23  *
24  * @param slot		A slot to erase.
25  *
26  * @return 0 on success, MGMT_ERR_[...] code on failure.
27  */
28 int img_mgmt_erase_slot(int slot);
29 
30 /**
31  * @brief Marks the image in the specified slot as pending. On the next reboot,
32  * the system will perform a boot of the specified image.
33  *
34  * @param slot		The slot to mark as pending.  In the typical use case, this is 1.
35  * @param permanent	Whether the image should be used permanently or only tested once:
36  *				0=run image once, then confirm or revert.
37  *				1=run image forever.
38  *
39  * @return 0 on success, MGMT_ERR_[...] code on failure.
40  */
41 int img_mgmt_write_pending(int slot, bool permanent);
42 
43 /**
44  * @brief Marks the image in slot 0 as confirmed. The system will continue
45  * booting into the image in slot 0 until told to boot from a different slot.
46  *
47  * @return 0 on success, MGMT_ERR_[...] code on failure.
48  */
49 int img_mgmt_write_confirmed(void);
50 
51 /**
52  * @brief Reads the specified chunk of data from an image slot.
53  *
54  * @param slot		The index of the slot to read from.
55  * @param offset	The offset within the slot to read from.
56  * @param dst		On success, the read data gets written here.
57  * @param num_bytes	The number of bytes to read.
58  *
59  * @return 0 on success, MGMT_ERR_[...] code on failure.
60  */
61 int img_mgmt_read(int slot, unsigned int offset, void *dst, unsigned int num_bytes);
62 
63 /**
64  * @brief Writes the specified chunk of image data to slot 1.
65  *
66  * @param offset	The offset within slot 1 to write to.
67  * @param data		The image data to write.
68  * @param num_bytes	The number of bytes to write.
69  * @param last		Whether this chunk is the end of the image:
70  *				false=additional image chunks are forthcoming.
71  *				true=last image chunk; flush unwritten data to disk.
72  *
73  * @return 0 on success, MGMT_ERR_[...] code on failure.
74  */
75 int img_mgmt_write_image_data(unsigned int offset, const void *data, unsigned int num_bytes,
76 			      bool last);
77 
78 /**
79  * @brief Indicates the type of swap operation that will occur on the next
80  * reboot, if any, between provided slot and it's pair.
81  * Querying any slots of the same pair will give the same result.
82  *
83  * @param slot                  An slot number;
84  *
85  * @return                      An IMG_MGMT_SWAP_TYPE_[...] code.
86  */
87 int img_mgmt_swap_type(int slot);
88 
89 /**
90  * @brief Returns image that the given slot belongs to.
91  *
92  * @param slot			A slot number.
93  *
94  * @return 0 based image number.
95  */
img_mgmt_slot_to_image(int slot)96 static inline int img_mgmt_slot_to_image(int slot)
97 {
98 	__ASSERT(slot >= 0 && slot < (CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER << 1),
99 		 "Impossible slot number");
100 
101 	return (slot >> 1);
102 }
103 
104 /**
105  * @brief Get slot number of alternate (inactive) image pair
106  *
107  * @param slot			A slot number.
108  *
109  * @return Number of other slot in pair
110  */
img_mgmt_get_opposite_slot(int slot)111 static inline int img_mgmt_get_opposite_slot(int slot)
112 {
113 	__ASSERT(slot >= 0 && slot < (CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER << 1),
114 		 "Impossible slot number");
115 
116 	return (slot ^ 1);
117 }
118 
119 enum img_mgmt_next_boot_type {
120 	/** The normal boot to active or non-active slot */
121 	NEXT_BOOT_TYPE_NORMAL	=	0,
122 	/** The test/non-permanent boot to non-active slot */
123 	NEXT_BOOT_TYPE_TEST	=	1,
124 	/** Next boot will be revert to already confirmed slot; this
125 	 * type of next boot means that active slot is not confirmed
126 	 * yet as it has been marked for test in previous boot.
127 	 */
128 	NEXT_BOOT_TYPE_REVERT	=	2
129 };
130 
131 /**
132  * @brief Get next boot slot number for a given image.
133  *
134  * @param image			An image number.
135  * @param type			Type of next boot
136  *
137  * @return Number of slot, from pair of slots assigned to image, that will
138  * boot on next reset. User needs to compare this slot against active slot
139  * to check whether application image will change for the next boot.
140  * @return -1 in case when next boot slot can not be established.
141  */
142 int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type);
143 
144 /**
145  * Collects information about the specified image slot.
146  *
147  * @return Flags of the specified image slot
148  */
149 uint8_t img_mgmt_state_flags(int query_slot);
150 
151 /**
152  * Erases image data at given offset
153  *
154  * @param offset	The offset within slot 1 to erase at.
155  * @param num_bytes	The number of bytes to erase.
156  *
157  * @return 0 on success, MGMT_ERR_[...] code on failure.
158  */
159 int img_mgmt_erase_image_data(unsigned int off, unsigned int num_bytes);
160 
161 /**
162  * Erases a flash sector as image upload crosses a sector boundary.
163  * Erasing the entire flash size at one time can take significant time,
164  *   causing a bluetooth disconnect or significant battery sag.
165  * Instead we will erase immediately prior to crossing a sector.
166  * We could check for empty to increase efficiency, but instead we always erase
167  *   for consistency and simplicity.
168  *
169  * @param off		Offset that is about to be written
170  * @param len		Number of bytes to be written
171  *
172  * @return 0 if success ERROR_CODE if could not erase sector
173  */
174 int img_mgmt_erase_if_needed(uint32_t off, uint32_t len);
175 
176 /**
177  * Verifies an upload request and indicates the actions that should be taken
178  * during processing of the request.  This is a "read only" function in the
179  * sense that it doesn't write anything to flash and doesn't modify any global
180  * variables.
181  *
182  * @param req		The upload request to inspect.
183  * @param action	On success, gets populated with information about how to
184  *                      process the request.
185  *
186  * @return 0 if processing should occur;
187  *           A MGMT_ERR code if an error response should be sent instead.
188  */
189 int img_mgmt_upload_inspect(const struct img_mgmt_upload_req *req,
190 			    struct img_mgmt_upload_action *action);
191 
192 /**
193  * @brief	Takes the image management lock (if enabled) to prevent other
194  *		threads interfering with an ongoing operation.
195  */
196 void img_mgmt_take_lock(void);
197 
198 /**
199  * @brief	Releases the held image management lock (if enabled) to allow
200  *		other threads to use image management operations.
201  */
202 void img_mgmt_release_lock(void);
203 
204 #define ERASED_VAL_32(x) (((x) << 24) | ((x) << 16) | ((x) << 8) | (x))
205 int img_mgmt_erased_val(int slot, uint8_t *erased_val);
206 
207 int img_mgmt_find_by_hash(uint8_t *find, struct image_version *ver);
208 int img_mgmt_find_by_ver(struct image_version *find, uint8_t *hash);
209 int img_mgmt_state_read(struct smp_streamer *ctxt);
210 int img_mgmt_state_write(struct smp_streamer *njb);
211 int img_mgmt_flash_area_id(int slot);
212 
213 #ifdef __cplusplus
214 }
215 #endif
216 
217 #endif
218