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