1 /*
2 * Copyright (c) 2024 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/gpio.h>
8 #include <zephyr/kernel.h>
9
10 #include "bootutil/bootutil.h"
11 #include "bootutil/bootutil_public.h"
12 #include "bootutil/fault_injection_hardening.h"
13
14 #define BOOT_TMPBUF_SZ 256
15
16 static struct image_header _hdr;
17 static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
18
19 static uint8_t known_ids[] = {
20 FIXED_PARTITION_ID(slot0_partition),
21 FIXED_PARTITION_ID(slot1_partition),
22 };
23
24 static int current_id;
25
26 #define SW1_NODE DT_ALIAS(sw1)
27 #if DT_NODE_HAS_STATUS(SW1_NODE, okay)
28 static struct gpio_dt_spec sw1_spec = GPIO_DT_SPEC_GET(SW1_NODE, gpios);
29 #endif
30
boot_go_hook(struct boot_rsp * rsp)31 fih_ret boot_go_hook(struct boot_rsp *rsp)
32 {
33 int rc;
34 #ifdef MCUBOOT_RAM_LOAD
35 struct boot_loader_state *state;
36 #endif
37 FIH_DECLARE(fih_rc, FIH_FAILURE);
38 const struct flash_area *_fa_p;
39
40 current_id = 0;
41
42 #if DT_NODE_HAS_STATUS(SW1_NODE, okay)
43 if (gpio_pin_configure_dt(&sw1_spec, GPIO_INPUT) == 0) {
44 if (gpio_pin_get_dt(&sw1_spec) == 1) {
45 current_id = ARRAY_SIZE(known_ids) - 1;
46 printk("%s pressed, forcing boot from partition %u\n",
47 sw1_spec.port->name, known_ids[current_id]);
48 } else {
49 printk("%s not pressed, looping partitions to boot\n",
50 sw1_spec.port->name);
51 }
52 }
53 #else
54 printk("SW1 not defined, looping partitions to boot\n");
55 #endif
56
57 for ( ; current_id < ARRAY_SIZE(known_ids); current_id++) {
58 printk("Trying to boot from fixed partition %u\n",
59 known_ids[current_id]);
60
61 rc = flash_area_open(known_ids[current_id], &_fa_p);
62 if (rc != 0) {
63 continue;
64 }
65
66 rc = boot_image_load_header(_fa_p, &_hdr);
67 if (rc != 0) {
68 flash_area_close(_fa_p);
69 continue;
70 }
71
72 #ifdef MCUBOOT_RAM_LOAD
73 state = boot_get_loader_state();
74
75 rc = boot_load_image_from_flash_to_sram(state, &_hdr);
76 if (rc != 0) {
77 flash_area_close(_fa_p);
78 continue;
79 }
80 #endif
81
82 FIH_CALL(bootutil_img_validate, fih_rc, NULL, &_hdr, _fa_p, tmpbuf,
83 BOOT_TMPBUF_SZ, NULL, 0, NULL);
84 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
85 flash_area_close(_fa_p);
86 #ifdef MCUBOOT_RAM_LOAD
87 boot_remove_image_from_sram(state);
88 #endif
89 continue;
90 }
91
92 rsp->br_flash_dev_id = flash_area_get_device_id(_fa_p);
93 rsp->br_image_off = flash_area_get_off(_fa_p);
94 rsp->br_hdr = &_hdr;
95
96 flash_area_close(_fa_p);
97 break;
98 }
99
100 FIH_RET(fih_rc);
101 }
102
flash_area_id_from_multi_image_slot_hook(int image_index,int slot,int * area_id)103 int flash_area_id_from_multi_image_slot_hook(int image_index, int slot,
104 int *area_id)
105 {
106 *area_id = known_ids[current_id];
107
108 return 0;
109 }
110
flash_area_get_device_id_hook(const struct flash_area * fa,uint8_t * dev_id)111 int flash_area_get_device_id_hook(const struct flash_area *fa, uint8_t *dev_id)
112 {
113 return BOOT_HOOK_REGULAR;
114 }
115