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) 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_swap_state { 149 uint8_t magic; /* One of the BOOT_MAGIC_[...] values. */ 150 uint8_t swap_type; /* One of the BOOT_SWAP_TYPE_[...] values. */ 151 uint8_t copy_done; /* One of the BOOT_FLAG_[...] values. */ 152 uint8_t image_ok; /* One of the BOOT_FLAG_[...] values. */ 153 uint8_t image_num; /* Boot status belongs to this image */ 154 }; 155 156 /** 157 * @brief Determines the action, if any, that mcuboot will take on a image pair. 158 * 159 * @param image_index Image pair index. 160 * 161 * @return a BOOT_SWAP_TYPE_[...] constant on success, negative errno code on 162 * fail. 163 */ 164 int boot_swap_type_multi(int image_index); 165 166 /** 167 * @brief Determines the action, if any, that mcuboot will take. 168 * 169 * Works the same as a boot_swap_type_multi(0) call; 170 * 171 * @return a BOOT_SWAP_TYPE_[...] constant on success, negative errno code on 172 * fail. 173 */ 174 int boot_swap_type(void); 175 176 /** 177 * Marks the image with the given index in the secondary slot as pending. On the 178 * next reboot, the system will perform a one-time boot of the the secondary 179 * slot image. 180 * 181 * @param image_index Image pair index. 182 * 183 * @param permanent Whether the image should be used permanently or 184 * only tested once: 185 * 0=run image once, then confirm or revert. 186 * 1=run image forever. 187 * 188 * @return 0 on success; nonzero on failure. 189 */ 190 int boot_set_pending_multi(int image_index, int permanent); 191 192 /** 193 * Marks the image with index 0 in the secondary slot as pending. On the next 194 * reboot, the system will perform a one-time boot of the the secondary slot 195 * image. Note that this API is kept for compatibility. The 196 * boot_set_pending_multi() API is recommended. 197 * 198 * @param permanent Whether the image should be used permanently or 199 * only tested once: 200 * 0=run image once, then confirm or revert. 201 * 1=run image forever. 202 * 203 * @return 0 on success; nonzero on failure. 204 */ 205 int boot_set_pending(int permanent); 206 207 /** 208 * Marks the image with the given index in the primary slot as confirmed. The 209 * system will continue booting into the image in the primary slot until told to 210 * boot from a different slot. 211 * 212 * @param image_index Image pair index. 213 * 214 * @return 0 on success; nonzero on failure. 215 */ 216 int boot_set_confirmed_multi(int image_index); 217 218 /** 219 * Marks the image with index 0 in the primary slot as confirmed. The system 220 * will continue booting into the image in the primary slot until told to boot 221 * from a different slot. Note that this API is kept for compatibility. The 222 * boot_set_confirmed_multi() API is recommended. 223 * 224 * @return 0 on success; nonzero on failure. 225 */ 226 int boot_set_confirmed(void); 227 228 /** 229 * @brief Get offset of the swap info field in the image trailer. 230 * 231 * @param fap Flash are for which offset is determined. 232 * 233 * @retval offset of the swap info field. 234 */ 235 uint32_t boot_swap_info_off(const struct flash_area *fap); 236 237 /** 238 * @brief Get value of image-ok flag of the image. 239 * 240 * If called from chin-loaded image the image-ok flag value can be used to check 241 * whether application itself is already confirmed. 242 * 243 * @param fap Flash area of the image. 244 * @param image_ok[out] image-ok value. 245 * 246 * @return 0 on success; nonzero on failure. 247 */ 248 int boot_read_image_ok(const struct flash_area *fap, uint8_t *image_ok); 249 250 /** 251 * @brief Read the image swap state 252 * 253 * @param flash_area_id id of flash partition from which state will be read; 254 * @param state pointer to structure for storing swap state. 255 * 256 * @return 0 on success; non-zero error code on failure; 257 */ 258 int 259 boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state); 260 261 /** 262 * @brief Read the image swap state 263 * 264 * @param fa pointer to flash_area object; 265 * @param state pointer to structure for storing swap state. 266 * 267 * @return 0 on success; non-zero error code on failure. 268 */ 269 int 270 boot_read_swap_state(const struct flash_area *fa, 271 struct boot_swap_state *state); 272 273 /** 274 * @brief Set next image application slot by flash area pointer 275 * 276 * @param fa pointer to flash_area representing image to set for next boot; 277 * @param active should be true if @fa points to currently running image 278 * slot, false otherwise; 279 * @param confirm confirms image; when @p active is true, this is considered 280 * true, regardless of passed value. 281 * 282 * It is users responsibility to identify whether @p fa provided as parameter 283 * is currently running/active image and provide proper value to @p active. 284 * Failing to do so may render device non-upgradeable. 285 * 286 * Note that in multi-image setup running/active application is the one 287 * that is currently being executed by any MCU core, from the pair of 288 * slots dedicated to that MCU core. As confirming application currently 289 * running on a given slot should be, preferably, done after functional 290 * tests prove application to function correctly, it may not be a good idea 291 * to cross-confirm running images. 292 * An application should only confirm slots designated to MCU core it is 293 * running on. 294 * 295 * @return 0 on success; non-zero error code on failure. 296 */ 297 int 298 boot_set_next(const struct flash_area *fa, bool active, bool confirm); 299 300 /** 301 * Attempts to load image header from flash; verifies flash header fields. 302 * 303 * @param[in] fa_p flash area pointer 304 * @param[out] hdr buffer for image header 305 * 306 * @return 0 on success, error code otherwise 307 */ 308 int 309 boot_image_load_header(const struct flash_area *fa_p, 310 struct image_header *hdr); 311 312 #ifdef __cplusplus 313 } 314 #endif 315 316 #endif 317