1 /*
2  * Copyright (c) 2012-2014 Wind River Systems, Inc.
3  * Copyright (c) 2020 Arm Limited
4  * Copyright (c) 2021-2023 Nordic Semiconductor ASA
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <assert.h>
20 #include <zephyr/kernel.h>
21 #include <zephyr/devicetree.h>
22 #include <zephyr/drivers/gpio.h>
23 #include <zephyr/sys/__assert.h>
24 #include <zephyr/drivers/flash.h>
25 #include <zephyr/drivers/timer/system_timer.h>
26 #include <zephyr/usb/usb_device.h>
27 #include <soc.h>
28 #include <zephyr/linker/linker-defs.h>
29 
30 #if defined(CONFIG_BOOT_DISABLE_CACHES)
31 #include <zephyr/cache.h>
32 #endif
33 
34 #if defined(CONFIG_ARM)
35 #include <cmsis_core.h>
36 #endif
37 
38 #include "io/io.h"
39 #include "target.h"
40 
41 #include "bootutil/bootutil_log.h"
42 #include "bootutil/image.h"
43 #include "bootutil/bootutil.h"
44 #include "bootutil/boot_hooks.h"
45 #include "bootutil/fault_injection_hardening.h"
46 #include "bootutil/mcuboot_status.h"
47 #include "flash_map_backend/flash_map_backend.h"
48 
49 /* Check if Espressif target is supported */
50 #ifdef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32
51 
52 #include <bootloader_init.h>
53 #include <esp_image_loader.h>
54 
55 #define IMAGE_INDEX_0   0
56 #define IMAGE_INDEX_1   1
57 
58 #define PRIMARY_SLOT    0
59 #define SECONDARY_SLOT  1
60 
61 #define IMAGE0_PRIMARY_START_ADDRESS \
62           DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_0), reg, 0)
63 #define IMAGE0_PRIMARY_SIZE \
64           DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_0), reg, 1)
65 
66 #define IMAGE1_PRIMARY_START_ADDRESS \
67           DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_1), reg, 0)
68 #define IMAGE1_PRIMARY_SIZE \
69           DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_1), reg, 1)
70 
71 #endif /* CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */
72 
73 #ifdef CONFIG_MCUBOOT_SERIAL
74 #include "boot_serial/boot_serial.h"
75 #include "serial_adapter/serial_adapter.h"
76 
77 const struct boot_uart_funcs boot_funcs = {
78     .read = console_read,
79     .write = console_write
80 };
81 #endif
82 
83 #if defined(CONFIG_BOOT_USB_DFU_WAIT) || defined(CONFIG_BOOT_USB_DFU_GPIO)
84 #include <zephyr/usb/class/usb_dfu.h>
85 #endif
86 
87 #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE
88 #include <arm_cleanup.h>
89 #endif
90 
91 /* CONFIG_LOG_MINIMAL is the legacy Kconfig property,
92  * replaced by CONFIG_LOG_MODE_MINIMAL.
93  */
94 #if (defined(CONFIG_LOG_MODE_MINIMAL) || defined(CONFIG_LOG_MINIMAL))
95 #define ZEPHYR_LOG_MODE_MINIMAL 1
96 #endif
97 
98 /* CONFIG_LOG_IMMEDIATE is the legacy Kconfig property,
99  * replaced by CONFIG_LOG_MODE_IMMEDIATE.
100  */
101 #if (defined(CONFIG_LOG_MODE_IMMEDIATE) || defined(CONFIG_LOG_IMMEDIATE))
102 #define ZEPHYR_LOG_MODE_IMMEDIATE 1
103 #endif
104 
105 #if defined(CONFIG_LOG) && !defined(ZEPHYR_LOG_MODE_IMMEDIATE) && \
106     !defined(ZEPHYR_LOG_MODE_MINIMAL)
107 #ifdef CONFIG_LOG_PROCESS_THREAD
108 #warning "The log internal thread for log processing can't transfer the log"\
109          "well for MCUBoot."
110 #else
111 #include <zephyr/logging/log_ctrl.h>
112 
113 #define BOOT_LOG_PROCESSING_INTERVAL K_MSEC(30) /* [ms] */
114 
115 /* log are processing in custom routine */
116 K_THREAD_STACK_DEFINE(boot_log_stack, CONFIG_MCUBOOT_LOG_THREAD_STACK_SIZE);
117 struct k_thread boot_log_thread;
118 volatile bool boot_log_stop = false;
119 K_SEM_DEFINE(boot_log_sem, 1, 1);
120 
121 /* log processing need to be initalized by the application */
122 #define ZEPHYR_BOOT_LOG_START() zephyr_boot_log_start()
123 #define ZEPHYR_BOOT_LOG_STOP() zephyr_boot_log_stop()
124 #endif /* CONFIG_LOG_PROCESS_THREAD */
125 #else
126 /* synchronous log mode doesn't need to be initalized by the application */
127 #define ZEPHYR_BOOT_LOG_START() do { } while (false)
128 #define ZEPHYR_BOOT_LOG_STOP() do { } while (false)
129 #endif /* defined(CONFIG_LOG) && !defined(ZEPHYR_LOG_MODE_IMMEDIATE) && \
130         * !defined(ZEPHYR_LOG_MODE_MINIMAL)
131 	*/
132 
133 BOOT_LOG_MODULE_REGISTER(mcuboot);
134 
135 void os_heap_init(void);
136 
137 #if defined(CONFIG_ARM)
138 
139 #ifdef CONFIG_SW_VECTOR_RELAY
140 extern void *_vector_table_pointer;
141 #endif
142 
143 struct arm_vector_table {
144     uint32_t msp;
145     uint32_t reset;
146 };
147 
do_boot(struct boot_rsp * rsp)148 static void do_boot(struct boot_rsp *rsp)
149 {
150     struct arm_vector_table *vt;
151 
152     /* The beginning of the image is the ARM vector table, containing
153      * the initial stack pointer address and the reset vector
154      * consecutively. Manually set the stack pointer and jump into the
155      * reset vector
156      */
157 #ifdef CONFIG_BOOT_RAM_LOAD
158     /* Get ram address for image */
159     vt = (struct arm_vector_table *)(rsp->br_hdr->ih_load_addr + rsp->br_hdr->ih_hdr_size);
160 #else
161     int rc;
162     const struct flash_area *fap;
163     static uint32_t dst[2];
164 
165     /* Jump to flash image */
166     rc = flash_area_open(rsp->br_flash_dev_id, &fap);
167     assert(rc == 0);
168 
169     rc = flash_area_read(fap, rsp->br_hdr->ih_hdr_size, dst, sizeof(dst));
170     assert(rc == 0);
171 #ifndef CONFIG_ASSERT
172     /* Enter a lock up as asserts are disabled */
173     if (rc != 0) {
174         while (1);
175     }
176 #endif
177 
178     flash_area_close(fap);
179 
180     vt = (struct arm_vector_table *)dst;
181 #endif
182 
183     if (IS_ENABLED(CONFIG_SYSTEM_TIMER_HAS_DISABLE_SUPPORT)) {
184         sys_clock_disable();
185     }
186 
187 #ifdef CONFIG_USB_DEVICE_STACK
188     /* Disable the USB to prevent it from firing interrupts */
189     usb_disable();
190 #endif
191 #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE
192     cleanup_arm_nvic(); /* cleanup NVIC registers */
193 
194 #if defined(CONFIG_BOOT_DISABLE_CACHES)
195     /* Flush and disable instruction/data caches before chain-loading the application */
196     (void)sys_cache_instr_flush_all();
197     (void)sys_cache_data_flush_all();
198     sys_cache_instr_disable();
199     sys_cache_data_disable();
200 #endif
201 
202 #if CONFIG_CPU_HAS_ARM_MPU || CONFIG_CPU_HAS_NXP_MPU
203     z_arm_clear_arm_mpu_config();
204 #endif
205 
206 #if defined(CONFIG_BUILTIN_STACK_GUARD) && \
207     defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM)
208     /* Reset limit registers to avoid inflicting stack overflow on image
209      * being booted.
210      */
211     __set_PSPLIM(0);
212     __set_MSPLIM(0);
213 #endif
214 
215 #else
216     irq_lock();
217 #endif /* CONFIG_MCUBOOT_CLEANUP_ARM_CORE */
218 
219 #ifdef CONFIG_BOOT_INTR_VEC_RELOC
220 #if defined(CONFIG_SW_VECTOR_RELAY)
221     _vector_table_pointer = vt;
222 #ifdef CONFIG_CPU_CORTEX_M_HAS_VTOR
223     SCB->VTOR = (uint32_t)__vector_relay_table;
224 #endif
225 #elif defined(CONFIG_CPU_CORTEX_M_HAS_VTOR)
226     SCB->VTOR = (uint32_t)vt;
227 #endif /* CONFIG_SW_VECTOR_RELAY */
228 #else /* CONFIG_BOOT_INTR_VEC_RELOC */
229 #if defined(CONFIG_CPU_CORTEX_M_HAS_VTOR) && defined(CONFIG_SW_VECTOR_RELAY)
230     _vector_table_pointer = _vector_start;
231     SCB->VTOR = (uint32_t)__vector_relay_table;
232 #endif
233 #endif /* CONFIG_BOOT_INTR_VEC_RELOC */
234 
235     __set_MSP(vt->msp);
236 #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE
237     __set_CONTROL(0x00); /* application will configures core on its own */
238     __ISB();
239 #endif
240 #if CONFIG_MCUBOOT_CLEANUP_RAM
241     __asm__ volatile (
242         /* vt->reset -> r0 */
243         "   mov     r0, %0\n"
244         /* base to write -> r1 */
245         "   mov     r1, %1\n"
246         /* size to write -> r2 */
247         "   mov     r2, %2\n"
248         /* value to write -> r3 */
249         "   mov     r3, %3\n"
250         "clear:\n"
251         "   str     r3, [r1]\n"
252         "   add     r1, r1, #4\n"
253         "   sub     r2, r2, #4\n"
254         "   cbz     r2, out\n"
255         "   b       clear\n"
256         "out:\n"
257         "   dsb\n"
258         /* jump to reset vector of an app */
259         "   bx      r0\n"
260         :
261         : "r" (vt->reset), "i" (CONFIG_SRAM_BASE_ADDRESS),
262           "i" (CONFIG_SRAM_SIZE * 1024), "i" (0)
263         : "r0", "r1", "r2", "r3", "memory"
264     );
265 #else
266     ((void (*)(void))vt->reset)();
267 #endif
268 }
269 
270 #elif defined(CONFIG_XTENSA) || defined(CONFIG_RISCV)
271 
272 #ifndef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32
273 
274 #define SRAM_BASE_ADDRESS	0xBE030000
275 
copy_img_to_SRAM(int slot,unsigned int hdr_offset)276 static void copy_img_to_SRAM(int slot, unsigned int hdr_offset)
277 {
278     const struct flash_area *fap;
279     int area_id;
280     int rc;
281     unsigned char *dst = (unsigned char *)(SRAM_BASE_ADDRESS + hdr_offset);
282 
283     BOOT_LOG_INF("Copying image to SRAM");
284 
285     area_id = flash_area_id_from_image_slot(slot);
286     rc = flash_area_open(area_id, &fap);
287     if (rc != 0) {
288         BOOT_LOG_ERR("flash_area_open failed with %d\n", rc);
289         goto done;
290     }
291 
292     rc = flash_area_read(fap, hdr_offset, dst, fap->fa_size - hdr_offset);
293     if (rc != 0) {
294         BOOT_LOG_ERR("flash_area_read failed with %d\n", rc);
295         goto done;
296     }
297 
298 done:
299     flash_area_close(fap);
300 }
301 #endif /* !CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */
302 
303 /* Entry point (.ResetVector) is at the very beginning of the image.
304  * Simply copy the image to a suitable location and jump there.
305  */
do_boot(struct boot_rsp * rsp)306 static void do_boot(struct boot_rsp *rsp)
307 {
308 #ifndef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32
309     void *start;
310 #endif /* CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */
311 
312     BOOT_LOG_INF("br_image_off = 0x%x\n", rsp->br_image_off);
313     BOOT_LOG_INF("ih_hdr_size = 0x%x\n", rsp->br_hdr->ih_hdr_size);
314 
315 #ifdef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32
316     int slot = (rsp->br_image_off == IMAGE0_PRIMARY_START_ADDRESS) ?
317                 PRIMARY_SLOT : SECONDARY_SLOT;
318     /* Load memory segments and start from entry point */
319     start_cpu0_image(IMAGE_INDEX_0, slot, rsp->br_hdr->ih_hdr_size);
320 #else
321     /* Copy from the flash to HP SRAM */
322     copy_img_to_SRAM(0, rsp->br_hdr->ih_hdr_size);
323 
324     /* Jump to entry point */
325     start = (void *)(SRAM_BASE_ADDRESS + rsp->br_hdr->ih_hdr_size);
326     ((void (*)(void))start)();
327 #endif /* CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */
328 }
329 
330 #else
331 /* Default: Assume entry point is at the very beginning of the image. Simply
332  * lock interrupts and jump there. This is the right thing to do for X86 and
333  * possibly other platforms.
334  */
do_boot(struct boot_rsp * rsp)335 static void do_boot(struct boot_rsp *rsp)
336 {
337     void *start;
338 
339 #if defined(MCUBOOT_RAM_LOAD)
340     start = (void *)(rsp->br_hdr->ih_load_addr + rsp->br_hdr->ih_hdr_size);
341 #else
342     uintptr_t flash_base;
343     int rc;
344 
345     rc = flash_device_base(rsp->br_flash_dev_id, &flash_base);
346     assert(rc == 0);
347 
348     start = (void *)(flash_base + rsp->br_image_off +
349                      rsp->br_hdr->ih_hdr_size);
350 #endif
351 
352     /* Lock interrupts and dive into the entry point */
353     irq_lock();
354     ((void (*)(void))start)();
355 }
356 #endif
357 
358 #if defined(CONFIG_LOG) && !defined(ZEPHYR_LOG_MODE_IMMEDIATE) && \
359     !defined(CONFIG_LOG_PROCESS_THREAD) && !defined(ZEPHYR_LOG_MODE_MINIMAL)
360 /* The log internal thread for log processing can't transfer log well as has too
361  * low priority.
362  * Dedicated thread for log processing below uses highest application
363  * priority. This allows to transmit all logs without adding k_sleep/k_yield
364  * anywhere else int the code.
365  */
366 
367 /* most simple log processing theread */
boot_log_thread_func(void * dummy1,void * dummy2,void * dummy3)368 void boot_log_thread_func(void *dummy1, void *dummy2, void *dummy3)
369 {
370     (void)dummy1;
371     (void)dummy2;
372     (void)dummy3;
373 
374     log_init();
375 
376     while (1) {
377 #if defined(CONFIG_LOG1) || defined(CONFIG_LOG2)
378         /* support Zephyr legacy logging implementation before commit c5f2cde */
379         if (log_process(false) == false) {
380 #else
381         if (log_process() == false) {
382 #endif
383             if (boot_log_stop) {
384                 break;
385             }
386             k_sleep(BOOT_LOG_PROCESSING_INTERVAL);
387         }
388     }
389 
390     k_sem_give(&boot_log_sem);
391 }
392 
393 void zephyr_boot_log_start(void)
394 {
395     /* start logging thread */
396     k_thread_create(&boot_log_thread, boot_log_stack,
397                     K_THREAD_STACK_SIZEOF(boot_log_stack),
398                     boot_log_thread_func, NULL, NULL, NULL,
399                     K_HIGHEST_APPLICATION_THREAD_PRIO, 0,
400                     BOOT_LOG_PROCESSING_INTERVAL);
401 
402     k_thread_name_set(&boot_log_thread, "logging");
403 }
404 
405 void zephyr_boot_log_stop(void)
406 {
407     boot_log_stop = true;
408 
409     /* wait until log procesing thread expired
410      * This can be reworked using a thread_join() API once a such will be
411      * available in zephyr.
412      * see https://github.com/zephyrproject-rtos/zephyr/issues/21500
413      */
414     (void)k_sem_take(&boot_log_sem, K_FOREVER);
415 }
416 #endif /* defined(CONFIG_LOG) && !defined(ZEPHYR_LOG_MODE_IMMEDIATE) && \
417         * !defined(CONFIG_LOG_PROCESS_THREAD) && !defined(ZEPHYR_LOG_MODE_MINIMAL)
418         */
419 
420 #if defined(CONFIG_BOOT_SERIAL_ENTRANCE_GPIO) || defined(CONFIG_BOOT_SERIAL_PIN_RESET) \
421     || defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_SERIAL_NO_APPLICATION)
422 static void boot_serial_enter()
423 {
424     int rc;
425 
426 #ifdef CONFIG_MCUBOOT_INDICATION_LED
427     io_led_set(1);
428 #endif
429 
430     mcuboot_status_change(MCUBOOT_STATUS_SERIAL_DFU_ENTERED);
431 
432     BOOT_LOG_INF("Enter the serial recovery mode");
433     rc = boot_console_init();
434     __ASSERT(rc == 0, "Error initializing boot console.\n");
435     boot_serial_start(&boot_funcs);
436     __ASSERT(0, "Bootloader serial process was terminated unexpectedly.\n");
437 }
438 #endif
439 
440 int main(void)
441 {
442     struct boot_rsp rsp;
443     int rc;
444     FIH_DECLARE(fih_rc, FIH_FAILURE);
445 
446     MCUBOOT_WATCHDOG_SETUP();
447     MCUBOOT_WATCHDOG_FEED();
448 
449 #if !defined(MCUBOOT_DIRECT_XIP)
450     BOOT_LOG_INF("Starting bootloader");
451 #else
452     BOOT_LOG_INF("Starting Direct-XIP bootloader");
453 #endif
454 
455 #ifdef CONFIG_MCUBOOT_INDICATION_LED
456     /* LED init */
457     io_led_init();
458 #endif
459 
460     os_heap_init();
461 
462     ZEPHYR_BOOT_LOG_START();
463 
464     (void)rc;
465 
466     mcuboot_status_change(MCUBOOT_STATUS_STARTUP);
467 
468 #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO
469     if (io_detect_pin() &&
470             !io_boot_skip_serial_recovery()) {
471         boot_serial_enter();
472     }
473 #endif
474 
475 #ifdef CONFIG_BOOT_SERIAL_PIN_RESET
476     if (io_detect_pin_reset()) {
477         boot_serial_enter();
478     }
479 #endif
480 
481 #if defined(CONFIG_BOOT_USB_DFU_GPIO)
482     if (io_detect_pin()) {
483 #ifdef CONFIG_MCUBOOT_INDICATION_LED
484         io_led_set(1);
485 #endif
486 
487         mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_ENTERED);
488 
489         rc = usb_enable(NULL);
490         if (rc) {
491             BOOT_LOG_ERR("Cannot enable USB");
492         } else {
493             BOOT_LOG_INF("Waiting for USB DFU");
494             wait_for_usb_dfu(K_FOREVER);
495             BOOT_LOG_INF("USB DFU wait time elapsed");
496         }
497     }
498 #elif defined(CONFIG_BOOT_USB_DFU_WAIT)
499     rc = usb_enable(NULL);
500     if (rc) {
501         BOOT_LOG_ERR("Cannot enable USB");
502     } else {
503         BOOT_LOG_INF("Waiting for USB DFU");
504 
505         mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_WAITING);
506 
507         wait_for_usb_dfu(K_MSEC(CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS));
508         BOOT_LOG_INF("USB DFU wait time elapsed");
509 
510         mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_TIMED_OUT);
511     }
512 #endif
513 
514 #ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU
515     /* Initialize the boot console, so we can already fill up our buffers while
516      * waiting for the boot image check to finish. This image check, can take
517      * some time, so it's better to reuse thistime to already receive the
518      * initial mcumgr command(s) into our buffers
519      */
520     rc = boot_console_init();
521     int timeout_in_ms = CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT;
522     uint32_t start = k_uptime_get_32();
523 
524 #ifdef CONFIG_MCUBOOT_INDICATION_LED
525     io_led_set(1);
526 #endif
527 #endif
528 
529     BOOT_HOOK_GO_CALL_FIH(boot_go_hook, FIH_BOOT_HOOK_REGULAR, fih_rc, &rsp);
530     if (FIH_EQ(fih_rc, FIH_BOOT_HOOK_REGULAR)) {
531         FIH_CALL(boot_go, fih_rc, &rsp);
532     }
533 
534 #ifdef CONFIG_BOOT_SERIAL_BOOT_MODE
535     if (io_detect_boot_mode()) {
536         /* Boot mode to stay in bootloader, clear status and enter serial
537          * recovery mode
538          */
539         boot_serial_enter();
540     }
541 #endif
542 
543 #ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU
544     timeout_in_ms -= (k_uptime_get_32() - start);
545     if( timeout_in_ms <= 0 ) {
546         /* at least one check if time was expired */
547         timeout_in_ms = 1;
548     }
549     boot_serial_check_start(&boot_funcs,timeout_in_ms);
550 
551 #ifdef CONFIG_MCUBOOT_INDICATION_LED
552     io_led_set(0);
553 #endif
554 #endif
555 
556     if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
557         BOOT_LOG_ERR("Unable to find bootable image");
558 
559         mcuboot_status_change(MCUBOOT_STATUS_NO_BOOTABLE_IMAGE_FOUND);
560 
561 #ifdef CONFIG_BOOT_SERIAL_NO_APPLICATION
562         /* No bootable image and configuration set to remain in serial
563          * recovery mode
564          */
565         boot_serial_enter();
566 #elif defined(CONFIG_BOOT_USB_DFU_NO_APPLICATION)
567         rc = usb_enable(NULL);
568         if (rc && rc != -EALREADY) {
569             BOOT_LOG_ERR("Cannot enable USB");
570         } else {
571             BOOT_LOG_INF("Waiting for USB DFU");
572             wait_for_usb_dfu(K_FOREVER);
573         }
574 #endif
575 
576         FIH_PANIC;
577     }
578 
579 #ifdef CONFIG_BOOT_RAM_LOAD
580     BOOT_LOG_INF("Bootloader chainload address offset: 0x%x",
581                  rsp.br_hdr->ih_load_addr);
582 #else
583     BOOT_LOG_INF("Bootloader chainload address offset: 0x%x",
584                  rsp.br_image_off);
585 #endif
586 
587     BOOT_LOG_INF("Image version: v%d.%d.%d", rsp.br_hdr->ih_ver.iv_major,
588                                                     rsp.br_hdr->ih_ver.iv_minor,
589                                                     rsp.br_hdr->ih_ver.iv_revision);
590 
591 #if defined(MCUBOOT_DIRECT_XIP)
592     BOOT_LOG_INF("Jumping to the image slot");
593 #else
594     BOOT_LOG_INF("Jumping to the first image slot");
595 #endif
596 
597     mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND);
598 
599     ZEPHYR_BOOT_LOG_STOP();
600     do_boot(&rsp);
601 
602     mcuboot_status_change(MCUBOOT_STATUS_BOOT_FAILED);
603 
604     BOOT_LOG_ERR("Never should get here");
605     while (1)
606         ;
607 }
608