1 /*
2 * Copyright (c) 2018 Nordic Semiconductor ASA
3 * Copyright (c) 2015 Runtime Inc
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/kernel.h>
9 #include <zephyr/devicetree.h>
10 #include <zephyr/drivers/flash.h>
11
12 #include "target.h"
13
14 #include <flash_map_backend/flash_map_backend.h>
15 #include <sysflash/sysflash.h>
16
17 #include "bootutil/boot_hooks.h"
18 #include "bootutil/bootutil_log.h"
19 #include "bootutil/bootutil_public.h"
20
21 BOOT_LOG_MODULE_DECLARE(mcuboot);
22
23 #if (!defined(CONFIG_XTENSA) && DT_HAS_CHOSEN(zephyr_flash_controller))
24 #define FLASH_DEVICE_ID SOC_FLASH_0_ID
25 #define FLASH_DEVICE_BASE CONFIG_FLASH_BASE_ADDRESS
26 #define FLASH_DEVICE_NODE DT_CHOSEN(zephyr_flash_controller)
27
28 #elif (defined(CONFIG_XTENSA) && DT_NODE_EXISTS(DT_INST(0, jedec_spi_nor)))
29 #define FLASH_DEVICE_ID SPI_FLASH_0_ID
30 #define FLASH_DEVICE_BASE 0
31 #define FLASH_DEVICE_NODE DT_INST(0, jedec_spi_nor)
32
33 #elif defined(CONFIG_SOC_FAMILY_ESPRESSIF_ESP32)
34
35 #define FLASH_DEVICE_ID SPI_FLASH_0_ID
36 #define FLASH_DEVICE_BASE 0
37 #define FLASH_DEVICE_NODE DT_CHOSEN(zephyr_flash_controller)
38
39 #else
40 #error "FLASH_DEVICE_ID could not be determined"
41 #endif
42
43 static const struct device *flash_dev = DEVICE_DT_GET(FLASH_DEVICE_NODE);
44
flash_device_base(uint8_t fd_id,uintptr_t * ret)45 int flash_device_base(uint8_t fd_id, uintptr_t *ret)
46 {
47 if (fd_id != FLASH_DEVICE_ID) {
48 BOOT_LOG_ERR("invalid flash ID %d; expected %d",
49 fd_id, FLASH_DEVICE_ID);
50 return -EINVAL;
51 }
52 *ret = FLASH_DEVICE_BASE;
53 return 0;
54 }
55
56 /*
57 * This depends on the mappings defined in sysflash.h.
58 * MCUBoot uses continuous numbering for the primary slot, the secondary slot,
59 * and the scratch while zephyr might number it differently.
60 */
flash_area_id_from_multi_image_slot(int image_index,int slot)61 int flash_area_id_from_multi_image_slot(int image_index, int slot)
62 {
63 int rc, id;
64
65 rc = BOOT_HOOK_FLASH_AREA_CALL(flash_area_id_from_multi_image_slot_hook,
66 BOOT_HOOK_REGULAR, image_index, slot, &id);
67 if (rc != BOOT_HOOK_REGULAR) {
68 return id;
69 }
70
71 switch (slot) {
72 case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index);
73 #if !defined(CONFIG_SINGLE_APPLICATION_SLOT)
74 case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index);
75 #endif
76 }
77
78 return -EINVAL; /* flash_area_open will fail on that */
79 }
80
flash_area_id_from_image_slot(int slot)81 int flash_area_id_from_image_slot(int slot)
82 {
83 return flash_area_id_from_multi_image_slot(0, slot);
84 }
85
flash_area_id_to_multi_image_slot(int image_index,int area_id)86 int flash_area_id_to_multi_image_slot(int image_index, int area_id)
87 {
88 if (area_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
89 return 0;
90 }
91 #if !defined(CONFIG_SINGLE_APPLICATION_SLOT)
92 if (area_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
93 return 1;
94 }
95 #endif
96
97 BOOT_LOG_ERR("invalid flash area ID");
98 return -1;
99 }
100
101 #if defined(CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD)
flash_area_id_from_direct_image(int image_id)102 int flash_area_id_from_direct_image(int image_id)
103 {
104 switch (image_id) {
105 case 0:
106 case 1:
107 return FIXED_PARTITION_ID(slot0_partition);
108 #if FIXED_PARTITION_EXISTS(slot1_partition)
109 case 2:
110 return FIXED_PARTITION_ID(slot1_partition);
111 #endif
112 #if FIXED_PARTITION_EXISTS(slot2_partition)
113 case 3:
114 return FIXED_PARTITION_ID(slot2_partition);
115 #endif
116 #if FIXED_PARTITION_EXISTS(slot3_partition)
117 case 4:
118 return FIXED_PARTITION_ID(slot3_partition);
119 #endif
120 #if FIXED_PARTITION_EXISTS(slot4_partition)
121 case 5:
122 return FIXED_PARTITION_ID(slot4_partition);
123 #endif
124 #if FIXED_PARTITION_EXISTS(slot5_partition)
125 case 6:
126 return FIXED_PARTITION_ID(slot5_partition);
127 #endif
128 }
129 return -EINVAL;
130 }
131 #endif
132
flash_area_sector_from_off(off_t off,struct flash_sector * sector)133 int flash_area_sector_from_off(off_t off, struct flash_sector *sector)
134 {
135 int rc;
136 struct flash_pages_info page;
137
138 rc = flash_get_page_info_by_offs(flash_dev, off, &page);
139 if (rc) {
140 return rc;
141 }
142
143 sector->fs_off = page.start_offset;
144 sector->fs_size = page.size;
145
146 return rc;
147 }
148
flash_area_get_device_id(const struct flash_area * fa)149 uint8_t flash_area_get_device_id(const struct flash_area *fa)
150 {
151 uint8_t device_id;
152 int rc;
153
154 rc = BOOT_HOOK_FLASH_AREA_CALL(flash_area_get_device_id_hook,
155 BOOT_HOOK_REGULAR, fa, &device_id);
156 if (rc != BOOT_HOOK_REGULAR) {
157 return device_id;
158 }
159
160 #if defined(CONFIG_ARM)
161 return fa->fa_id;
162 #else
163 (void)fa;
164 return FLASH_DEVICE_ID;
165 #endif
166 }
167
168 #define ERASED_VAL 0xff
flash_area_erased_val(const struct flash_area * fap)169 __weak uint8_t flash_area_erased_val(const struct flash_area *fap)
170 {
171 (void)fap;
172 return ERASED_VAL;
173 }
174
flash_area_get_sector(const struct flash_area * fap,off_t off,struct flash_sector * fsp)175 int flash_area_get_sector(const struct flash_area *fap, off_t off,
176 struct flash_sector *fsp)
177 {
178 struct flash_pages_info fpi;
179 int rc;
180
181 if (off >= fap->fa_size) {
182 return -ERANGE;
183 }
184
185 rc = flash_get_page_info_by_offs(fap->fa_dev, fap->fa_off + off,
186 &fpi);
187
188 if (rc == 0) {
189 fsp->fs_off = fpi.start_offset - fap->fa_off;
190 fsp->fs_size = fpi.size;
191 }
192
193 return rc;
194 }
195