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