blob: a80a85994976c5cfba8aa7210c82d3646381f9d0 [file] [log] [blame]
Shubham Kulkarni052561d2021-07-20 11:42:44 +05301/*
2 * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#include <string.h>
8#include <stdlib.h>
9
10#include "mcuboot_config/mcuboot_logging.h"
11#include "flash_map_backend/flash_map_backend.h"
12#include "sysflash/sysflash.h"
13#include "bootutil/bootutil.h"
14
Shubham Kulkarnicd869652021-07-20 11:44:08 +053015#include "esp_err.h"
16#include "bootloader_flash.h"
17#include "bootloader_flash_priv.h"
18
Shubham Kulkarni052561d2021-07-20 11:42:44 +053019#define ARRAY_SIZE(arr) sizeof(arr)/sizeof(arr[0])
20
21#define BOOTLOADER_START_ADDRESS 0x1000
22#define BOOTLOADER_SIZE CONFIG_ESP_BOOTLOADER_SIZE
23#define APPLICATION_PRIMARY_START_ADDRESS CONFIG_ESP_APPLICATION_PRIMARY_START_ADDRESS
24#define APPLICATION_SECONDARY_START_ADDRESS CONFIG_ESP_APPLICATION_SECONDARY_START_ADDRESS
25#define APPLICATION_SIZE CONFIG_ESP_APPLICATION_SIZE
26#define SCRATCH_OFFSET CONFIG_ESP_SCRATCH_OFFSET
27#define SCRATCH_SIZE CONFIG_ESP_SCRATCH_SIZE
28
Shubham Kulkarni052561d2021-07-20 11:42:44 +053029extern int ets_printf(const char *fmt, ...);
30
31static const struct flash_area bootloader = {
32 .fa_id = FLASH_AREA_BOOTLOADER,
33 .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
34 .fa_off = BOOTLOADER_START_ADDRESS,
35 .fa_size = BOOTLOADER_SIZE,
36};
37
38static const struct flash_area primary_img0 = {
39 .fa_id = FLASH_AREA_IMAGE_PRIMARY(0),
40 .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
41 .fa_off = APPLICATION_PRIMARY_START_ADDRESS,
42 .fa_size = APPLICATION_SIZE,
43};
44
45static const struct flash_area secondary_img0 = {
46 .fa_id = FLASH_AREA_IMAGE_SECONDARY(0),
47 .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
48 .fa_off = APPLICATION_SECONDARY_START_ADDRESS,
49 .fa_size = APPLICATION_SIZE,
50};
51
52static const struct flash_area scratch_img0 = {
53 .fa_id = FLASH_AREA_IMAGE_SCRATCH,
54 .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
55 .fa_off = SCRATCH_OFFSET,
56 .fa_size = SCRATCH_SIZE,
57};
58
59static const struct flash_area *s_flash_areas[] = {
60 &bootloader,
61 &primary_img0,
62 &secondary_img0,
63 &scratch_img0,
64};
65
66static const struct flash_area *prv_lookup_flash_area(uint8_t id) {
67 for (size_t i = 0; i < ARRAY_SIZE(s_flash_areas); i++) {
68 const struct flash_area *area = s_flash_areas[i];
69 if (id == area->fa_id) {
70 return area;
71 }
72 }
73 return NULL;
74}
75
76int flash_area_open(uint8_t id, const struct flash_area **area_outp)
77{
78 MCUBOOT_LOG_DBG("%s: ID=%d", __func__, (int)id);
79 const struct flash_area *area = prv_lookup_flash_area(id);
80 *area_outp = area;
81 return area != NULL ? 0 : -1;
82}
83
84void flash_area_close(const struct flash_area *area)
85{
86
87}
88
89int flash_area_read(const struct flash_area *fa, uint32_t off, void *dst,
90 uint32_t len)
91{
Shubham Kulkarnicd869652021-07-20 11:44:08 +053092 uint32_t internal_data = 0, read_len = 0;
93 void *read_ptr;
Shubham Kulkarni052561d2021-07-20 11:42:44 +053094 if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) {
95 return -1;
96 }
97
98 const uint32_t end_offset = off + len;
Shubham Kulkarnicd869652021-07-20 11:44:08 +053099
Shubham Kulkarni052561d2021-07-20 11:42:44 +0530100 if (end_offset > fa->fa_size) {
101 MCUBOOT_LOG_ERR("%s: Out of Bounds (0x%x vs 0x%x)", __func__, end_offset, fa->fa_size);
102 return -1;
103 }
Shubham Kulkarnicd869652021-07-20 11:44:08 +0530104 read_len = (len < 4) ? sizeof(uint32_t) : len;
105 read_ptr = (len < 4) ? (void *)&internal_data : dst;
106 if (bootloader_flash_read(fa->fa_off + off, read_ptr, read_len, true) != ESP_OK) {
107 MCUBOOT_LOG_ERR("%s: Flash read failed", __func__);
108 return -1;
109 }
110 if (len < 4) {
111 memcpy(dst, read_ptr, len);
112 }
Shubham Kulkarni052561d2021-07-20 11:42:44 +0530113 return 0;
114}
115
116int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src,
117 uint32_t len)
118{
Shubham Kulkarnicd869652021-07-20 11:44:08 +0530119 uint32_t write_len = len, write_data = 0;
120 void *write_ptr = (void *)src;
Shubham Kulkarni052561d2021-07-20 11:42:44 +0530121 if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) {
122 return -1;
123 }
124
125 const uint32_t end_offset = off + len;
Shubham Kulkarnicd869652021-07-20 11:44:08 +0530126
Shubham Kulkarni052561d2021-07-20 11:42:44 +0530127 if (end_offset > fa->fa_size) {
128 MCUBOOT_LOG_ERR("%s: Out of Bounds (0x%x vs 0x%x)", __func__, end_offset, fa->fa_size);
129 return -1;
130 }
131
Shubham Kulkarnicd869652021-07-20 11:44:08 +0530132 const uint32_t start_addr = fa->fa_off + off;
133 MCUBOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len);
134 if (len < 4) {
135 flash_area_read(fa, start_addr, &write_data, sizeof(uint32_t));
136 memcpy(&write_data, src, len);
137 write_ptr = (void *)&write_data;
138 write_len = sizeof(uint32_t);
139 }
Shubham Kulkarni052561d2021-07-20 11:42:44 +0530140
Shubham Kulkarnicd869652021-07-20 11:44:08 +0530141 if (bootloader_flash_write(start_addr, write_ptr, write_len, false) != ESP_OK) {
142 MCUBOOT_LOG_ERR("%s: Flash write failed", __func__);
143 return -1;
144 }
Shubham Kulkarni052561d2021-07-20 11:42:44 +0530145#if VALIDATE_PROGRAM_OP
146 if (memcmp((void *)addr, src, len) != 0) {
147 MCUBOOT_LOG_ERR("%s: Program Failed", __func__);
148 assert(0);
149 }
150#endif
151
152 return 0;
153}
154
155int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
156{
157 if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) {
158 return -1;
159 }
160
161 if ((len % FLASH_SECTOR_SIZE) != 0 || (off % FLASH_SECTOR_SIZE) != 0) {
162 MCUBOOT_LOG_ERR("%s: Not aligned on sector Offset: 0x%x Length: 0x%x", __func__,
163 (int)off, (int)len);
164 return -1;
165 }
166
167 const uint32_t start_addr = fa->fa_off + off;
168 MCUBOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len);
169
Shubham Kulkarnicd869652021-07-20 11:44:08 +0530170 if (bootloader_flash_erase_range(start_addr, len) != ESP_OK) {
171 MCUBOOT_LOG_ERR("%s: Flash erase failed", __func__);
172 return -1;
173 }
Shubham Kulkarni052561d2021-07-20 11:42:44 +0530174#if VALIDATE_PROGRAM_OP
175 for (size_t i = 0; i < len; i++) {
176 uint8_t *val = (void *)(start_addr + i);
177 if (*val != 0xff) {
178 MCUBOOT_LOG_ERR("%s: Erase at 0x%x Failed", __func__, (int)val);
179 assert(0);
180 }
181 }
182#endif
183
184 return 0;
185}
186
187size_t flash_area_align(const struct flash_area *area)
188{
189 return 4;
190}
191
192uint8_t flash_area_erased_val(const struct flash_area *area)
193{
194 return 0xff;
195}
196
197int flash_area_get_sectors(int fa_id, uint32_t *count,
198 struct flash_sector *sectors)
199{
200 const struct flash_area *fa = prv_lookup_flash_area(fa_id);
201 if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) {
202 return -1;
203 }
204
205 const size_t sector_size = FLASH_SECTOR_SIZE;
206 uint32_t total_count = 0;
207 for (size_t off = 0; off < fa->fa_size; off += sector_size) {
208 // Note: Offset here is relative to flash area, not device
209 sectors[total_count].fs_off = off;
210 sectors[total_count].fs_size = sector_size;
211 total_count++;
212 }
213
214 *count = total_count;
215 return 0;
216}
217
218int flash_area_id_from_multi_image_slot(int image_index, int slot)
219{
220 MCUBOOT_LOG_DBG("%s", __func__);
221 switch (slot) {
222 case 0:
223 return FLASH_AREA_IMAGE_PRIMARY(image_index);
224 case 1:
225 return FLASH_AREA_IMAGE_SECONDARY(image_index);
226 }
227
228 MCUBOOT_LOG_ERR("Unexpected Request: image_index=%d, slot=%d", image_index, slot);
229 return -1; /* flash_area_open will fail on that */
230}
231
232int flash_area_id_from_image_slot(int slot)
233{
Almir Okatod5320292021-06-18 02:00:40 -0300234 return flash_area_id_from_multi_image_slot(0, slot);
Shubham Kulkarni052561d2021-07-20 11:42:44 +0530235}
236
237int flash_area_to_sectors(int idx, int *cnt, struct flash_area *fa)
238{
Almir Okatod5320292021-06-18 02:00:40 -0300239 return -1;
Shubham Kulkarni052561d2021-07-20 11:42:44 +0530240}
241
242void mcuboot_assert_handler(const char *file, int line, const char *func)
243{
244 ets_printf("assertion failed: file \"%s\", line %d, func: %s\n", file, line, func);
245 abort();
246}