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