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 <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 #define IMG_MGMT_DATA_SHA_LEN 32 /* SHA256 */ 29 30 /** 31 * Image state flags 32 */ 33 #define IMG_MGMT_STATE_F_PENDING 0x01 34 #define IMG_MGMT_STATE_F_CONFIRMED 0x02 35 #define IMG_MGMT_STATE_F_ACTIVE 0x04 36 #define IMG_MGMT_STATE_F_PERMANENT 0x08 37 38 /* 255.255.65535.4294967295\0 */ 39 #define IMG_MGMT_VER_MAX_STR_LEN (sizeof("255.255.65535.4294967295")) 40 41 /** 42 * Swap Types for image management state machine 43 */ 44 #define IMG_MGMT_SWAP_TYPE_NONE 0 45 #define IMG_MGMT_SWAP_TYPE_TEST 1 46 #define IMG_MGMT_SWAP_TYPE_PERM 2 47 #define IMG_MGMT_SWAP_TYPE_REVERT 3 48 #define IMG_MGMT_SWAP_TYPE_UNKNOWN 255 49 50 /** 51 * Command IDs for image management group. 52 */ 53 #define IMG_MGMT_ID_STATE 0 54 #define IMG_MGMT_ID_UPLOAD 1 55 #define IMG_MGMT_ID_FILE 2 56 #define IMG_MGMT_ID_CORELIST 3 57 #define IMG_MGMT_ID_CORELOAD 4 58 #define IMG_MGMT_ID_ERASE 5 59 #define IMG_MGMT_ID_SLOT_INFO 6 60 61 /** 62 * Command result codes for image management group. 63 */ 64 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 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 extern int boot_current_slot; 181 extern struct img_mgmt_state g_img_mgmt_state; 182 183 /** Represents an individual upload request. */ 184 struct img_mgmt_upload_req { 185 uint32_t image; /* 0 by default */ 186 size_t off; /* SIZE_MAX if unspecified */ 187 size_t size; /* SIZE_MAX if unspecified */ 188 struct zcbor_string img_data; 189 struct zcbor_string data_sha; 190 bool upgrade; /* Only allow greater version numbers. */ 191 }; 192 193 /** Global state for upload in progress. */ 194 struct img_mgmt_state { 195 /** Flash area being written; -1 if no upload in progress. */ 196 int area_id; 197 /** Flash offset of next chunk. */ 198 size_t off; 199 /** Total size of image data. */ 200 size_t size; 201 /** Hash of image data; used for resumption of a partial upload. */ 202 uint8_t data_sha_len; 203 uint8_t data_sha[IMG_MGMT_DATA_SHA_LEN]; 204 }; 205 206 /** Describes what to do during processing of an upload request. */ 207 struct img_mgmt_upload_action { 208 /** The total size of the image. */ 209 unsigned long long size; 210 /** The number of image bytes to write to flash. */ 211 int write_bytes; 212 /** The flash area to write to. */ 213 int area_id; 214 /** Whether to process the request; false if offset is wrong. */ 215 bool proceed; 216 /** Whether to erase the destination flash area. */ 217 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 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 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 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 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 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 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 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 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 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 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 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 #define IMG_MGMT_UPLOAD_ACTION_SET_RC_RSN(action, rsn) 375 #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_ */ 387