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