1 /* 2 * SPDX-License-Identifier: Apache-2.0 3 * 4 * Copyright (c) 2017-2019 Linaro LTD 5 * Copyright (c) 2016-2019 JUUL Labs 6 * Copyright (c) 2019-2021 Arm Limited 7 * Copyright (c) 2020-2021 Nordic Semiconductor ASA 8 * 9 * Original license: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one 12 * or more contributor license agreements. See the NOTICE file 13 * distributed with this work for additional information 14 * regarding copyright ownership. The ASF licenses this file 15 * to you under the Apache License, Version 2.0 (the 16 * "License"); you may not use this file except in compliance 17 * with the License. You may obtain a copy of the License at 18 * 19 * http://www.apache.org/licenses/LICENSE-2.0 20 * 21 * Unless required by applicable law or agreed to in writing, 22 * software distributed under the License is distributed on an 23 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 24 * KIND, either express or implied. See the License for the 25 * specific language governing permissions and limitations 26 * under the License. 27 */ 28 29 /** 30 * @file 31 * @brief Public MCUBoot interface API 32 * 33 * This file contains API which can be combined with the application in order 34 * to interact with the MCUBoot bootloader. This API are shared code-base betwen 35 * MCUBoot and the application which controls DFU process. 36 */ 37 38 #ifndef H_BOOTUTIL_PUBLIC 39 #define H_BOOTUTIL_PUBLIC 40 41 #include <inttypes.h> 42 #include <stdbool.h> 43 #include <string.h> 44 #include <flash_map_backend/flash_map_backend.h> 45 #include <mcuboot_config/mcuboot_config.h> 46 #include <bootutil/image.h> 47 48 #ifdef __cplusplus 49 extern "C" { 50 #endif 51 52 #ifndef ALIGN_UP 53 #define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) 54 #endif 55 56 #ifndef ALIGN_DOWN 57 #define ALIGN_DOWN(num, align) ((num) & ~((align) - 1)) 58 #endif 59 60 /** Attempt to boot the contents of the primary slot. */ 61 #define BOOT_SWAP_TYPE_NONE 1 62 63 /** 64 * Swap to the secondary slot. 65 * Absent a confirm command, revert back on next boot. 66 */ 67 #define BOOT_SWAP_TYPE_TEST 2 68 69 /** 70 * Swap to the secondary slot, 71 * and permanently switch to booting its contents. 72 */ 73 #define BOOT_SWAP_TYPE_PERM 3 74 75 /** Swap back to alternate slot. A confirm changes this state to NONE. */ 76 #define BOOT_SWAP_TYPE_REVERT 4 77 78 /** Swap failed because image to be run is not valid */ 79 #define BOOT_SWAP_TYPE_FAIL 5 80 81 /** Swapping encountered an unrecoverable error */ 82 #define BOOT_SWAP_TYPE_PANIC 0xff 83 84 #define BOOT_MAGIC_SZ 16 85 86 #ifdef MCUBOOT_BOOT_MAX_ALIGN 87 88 #if defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_OFFSET) 89 _Static_assert(MCUBOOT_BOOT_MAX_ALIGN >= 8 && MCUBOOT_BOOT_MAX_ALIGN <= 32, 90 "Unsupported value for MCUBOOT_BOOT_MAX_ALIGN for SWAP upgrade modes"); 91 #endif 92 93 #define BOOT_MAX_ALIGN MCUBOOT_BOOT_MAX_ALIGN 94 #define BOOT_MAGIC_ALIGN_SIZE ALIGN_UP(BOOT_MAGIC_SZ, BOOT_MAX_ALIGN) 95 #else 96 #define BOOT_MAX_ALIGN 8 97 #define BOOT_MAGIC_ALIGN_SIZE BOOT_MAGIC_SZ 98 #endif 99 100 #define BOOT_MAGIC_GOOD 1 101 #define BOOT_MAGIC_BAD 2 102 #define BOOT_MAGIC_UNSET 3 103 #define BOOT_MAGIC_ANY 4 /* NOTE: control only, not dependent on sector */ 104 #define BOOT_MAGIC_NOTGOOD 5 /* NOTE: control only, not dependent on sector */ 105 106 /* 107 * NOTE: leave BOOT_FLAG_SET equal to one, this is written to flash! 108 */ 109 #define BOOT_FLAG_SET 1 110 #define BOOT_FLAG_BAD 2 111 #define BOOT_FLAG_UNSET 3 112 #define BOOT_FLAG_ANY 4 /* NOTE: control only, not dependent on sector */ 113 114 #define BOOT_EFLASH 1 115 #define BOOT_EFILE 2 116 #define BOOT_EBADIMAGE 3 117 #define BOOT_EBADVECT 4 118 #define BOOT_EBADSTATUS 5 119 #define BOOT_ENOMEM 6 120 #define BOOT_EBADARGS 7 121 #define BOOT_EBADVERSION 8 122 #define BOOT_EFLASH_SEC 9 123 124 #define BOOT_HOOK_REGULAR 1 125 /* 126 * Extract the swap type and image number from image trailers's swap_info 127 * filed. 128 */ 129 #define BOOT_GET_SWAP_TYPE(swap_info) ((swap_info) & 0x0F) 130 #define BOOT_GET_IMAGE_NUM(swap_info) ((swap_info) >> 4) 131 132 /* Construct the swap_info field from swap type and image number */ 133 #define BOOT_SET_SWAP_INFO(swap_info, image, type) { \ 134 assert((image) < 0xF); \ 135 assert((type) < 0xF); \ 136 (swap_info) = (image) << 4 \ 137 | (type); \ 138 } 139 #ifdef MCUBOOT_HAVE_ASSERT_H 140 #include "mcuboot_config/mcuboot_assert.h" 141 #else 142 #include <assert.h> 143 #ifndef ASSERT 144 #define ASSERT assert 145 #endif 146 #endif 147 148 struct boot_loader_state; 149 150 struct boot_swap_state { 151 uint8_t magic; /* One of the BOOT_MAGIC_[...] values. */ 152 uint8_t swap_type; /* One of the BOOT_SWAP_TYPE_[...] values. */ 153 uint8_t copy_done; /* One of the BOOT_FLAG_[...] values. */ 154 uint8_t image_ok; /* One of the BOOT_FLAG_[...] values. */ 155 uint8_t image_num; /* Boot status belongs to this image */ 156 }; 157 158 /** 159 * @brief Determines the action, if any, that mcuboot will take on a image pair. 160 * 161 * @param image_index Image pair index. 162 * 163 * @return a BOOT_SWAP_TYPE_[...] constant on success, negative errno code on 164 * fail. 165 */ 166 int boot_swap_type_multi(int image_index); 167 168 /** 169 * @brief Determines the action, if any, that mcuboot will take. 170 * 171 * Works the same as a boot_swap_type_multi(0) call; 172 * 173 * @return a BOOT_SWAP_TYPE_[...] constant on success, negative errno code on 174 * fail. 175 */ 176 int boot_swap_type(void); 177 178 /** 179 * Marks the image with the given index in the secondary slot as pending. On the 180 * next reboot, the system will perform a one-time boot of the the secondary 181 * slot image. 182 * 183 * @param image_index Image pair index. 184 * 185 * @param permanent Whether the image should be used permanently or 186 * only tested once: 187 * 0=run image once, then confirm or revert. 188 * 1=run image forever. 189 * 190 * @return 0 on success; nonzero on failure. 191 */ 192 int boot_set_pending_multi(int image_index, int permanent); 193 194 /** 195 * Marks the image with index 0 in the secondary slot as pending. On the next 196 * reboot, the system will perform a one-time boot of the the secondary slot 197 * image. Note that this API is kept for compatibility. The 198 * boot_set_pending_multi() API is recommended. 199 * 200 * @param permanent Whether the image should be used permanently or 201 * only tested once: 202 * 0=run image once, then confirm or revert. 203 * 1=run image forever. 204 * 205 * @return 0 on success; nonzero on failure. 206 */ 207 int boot_set_pending(int permanent); 208 209 /** 210 * Marks the image with the given index in the primary slot as confirmed. The 211 * system will continue booting into the image in the primary slot until told to 212 * boot from a different slot. 213 * 214 * @param image_index Image pair index. 215 * 216 * @return 0 on success; nonzero on failure. 217 */ 218 int boot_set_confirmed_multi(int image_index); 219 220 /** 221 * Marks the image with index 0 in the primary slot as confirmed. The system 222 * will continue booting into the image in the primary slot until told to boot 223 * from a different slot. Note that this API is kept for compatibility. The 224 * boot_set_confirmed_multi() API is recommended. 225 * 226 * @return 0 on success; nonzero on failure. 227 */ 228 int boot_set_confirmed(void); 229 230 /** 231 * @brief Get offset of the swap info field in the image trailer. 232 * 233 * @param fap Flash are for which offset is determined. 234 * 235 * @retval offset of the swap info field. 236 */ 237 uint32_t boot_swap_info_off(const struct flash_area *fap); 238 239 /** 240 * @brief Get value of image-ok flag of the image. 241 * 242 * If called from chin-loaded image the image-ok flag value can be used to check 243 * whether application itself is already confirmed. 244 * 245 * @param fap Flash area of the image. 246 * @param image_ok[out] image-ok value. 247 * 248 * @return 0 on success; nonzero on failure. 249 */ 250 int boot_read_image_ok(const struct flash_area *fap, uint8_t *image_ok); 251 252 /** 253 * @brief Read the image swap state 254 * 255 * @param flash_area_id id of flash partition from which state will be read; 256 * @param state pointer to structure for storing swap state. 257 * 258 * @return 0 on success; non-zero error code on failure; 259 */ 260 int 261 boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state); 262 263 /** 264 * @brief Read the image swap state 265 * 266 * @param fa pointer to flash_area object; 267 * @param state pointer to structure for storing swap state. 268 * 269 * @return 0 on success; non-zero error code on failure. 270 */ 271 int 272 boot_read_swap_state(const struct flash_area *fa, 273 struct boot_swap_state *state); 274 275 /** 276 * @brief Set next image application slot by flash area pointer 277 * 278 * @param fa pointer to flash_area representing image to set for next boot; 279 * @param active should be true if @fa points to currently running image 280 * slot, false otherwise; 281 * @param confirm confirms image; when @p active is true, this is considered 282 * true, regardless of passed value. 283 * 284 * It is users responsibility to identify whether @p fa provided as parameter 285 * is currently running/active image and provide proper value to @p active. 286 * Failing to do so may render device non-upgradeable. 287 * 288 * Note that in multi-image setup running/active application is the one 289 * that is currently being executed by any MCU core, from the pair of 290 * slots dedicated to that MCU core. As confirming application currently 291 * running on a given slot should be, preferably, done after functional 292 * tests prove application to function correctly, it may not be a good idea 293 * to cross-confirm running images. 294 * An application should only confirm slots designated to MCU core it is 295 * running on. 296 * 297 * @return 0 on success; non-zero error code on failure. 298 */ 299 int 300 boot_set_next(const struct flash_area *fa, bool active, bool confirm); 301 302 /** 303 * Attempts to load image header from flash; verifies flash header fields. 304 * 305 * @param[in] fa_p flash area pointer 306 * @param[out] hdr buffer for image header 307 * 308 * @return 0 on success, error code otherwise 309 */ 310 int 311 boot_image_load_header(const struct flash_area *fa_p, 312 struct image_header *hdr); 313 314 #ifdef MCUBOOT_RAM_LOAD 315 /** 316 * Loads image with given header to RAM. 317 * 318 * Destination on RAM and size is described on image header. 319 * 320 * @param[in] state boot loader state 321 * @param[in] hdr image header 322 * 323 * @return 0 on success, error code otherwise 324 */ 325 int boot_load_image_from_flash_to_sram(struct boot_loader_state *state, 326 struct image_header *hdr); 327 328 /** 329 * Removes an image from SRAM, by overwriting it with zeros. 330 * 331 * @param state Boot loader status information. 332 * 333 * @return 0 on success; nonzero on failure. 334 */ 335 int boot_remove_image_from_sram(struct boot_loader_state *state); 336 337 /** 338 * Removes an image from flash by erasing the corresponding flash area 339 * 340 * @param state Boot loader status information. 341 * @param slot The flash slot of the image to be erased. 342 * 343 * @return 0 on success; nonzero on failure. 344 */ 345 int boot_remove_image_from_flash(struct boot_loader_state *state, 346 uint32_t slot); 347 #endif 348 349 #ifdef __cplusplus 350 } 351 #endif 352 353 #endif 354