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