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