blob: b47651741bee3f36866d0a1e0f59a44309c690f2 [file] [log] [blame]
Tamas Banf70ef8c2017-12-19 15:35:09 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
Tamas Ban581034a2017-12-19 19:54:37 +000020#include <errno.h>
21#include <stdbool.h>
Tamas Banf70ef8c2017-12-19 15:35:09 +000022
23#include "target.h"
Tamas Banc3828852018-02-01 12:24:16 +000024#include "bl2_util.h"
25#include "Driver_Flash.h"
Tamas Banf70ef8c2017-12-19 15:35:09 +000026
27#include <flash_map/flash_map.h>
Tamas Banf70ef8c2017-12-19 15:35:09 +000028
29#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
30#include "bootutil/bootutil_log.h"
31
Tamas Banc3828852018-02-01 12:24:16 +000032/* Flash device name must be specified by target */
33extern ARM_DRIVER_FLASH FLASH_DEV_NAME;
Tamas Banf70ef8c2017-12-19 15:35:09 +000034
35/*
36 * For now, we only support one flash device.
37 *
38 * Pick a random device ID for it that's unlikely to collide with
39 * anything "real".
40 */
41#define FLASH_DEVICE_ID 100
Tamas Ban581034a2017-12-19 19:54:37 +000042#define FLASH_DEVICE_BASE FLASH_BASE_ADDRESS
Tamas Banf70ef8c2017-12-19 15:35:09 +000043
44#define FLASH_MAP_ENTRY_MAGIC 0xd00dbeef
45
46struct flash_map_entry {
47 const uint32_t magic;
48 const struct flash_area area;
49 unsigned int ref_count;
50};
51
52/*
53 * The flash area describes essentially the partition table of the
54 * flash. In this case, it starts with FLASH_AREA_IMAGE_0.
55 */
56static struct flash_map_entry part_map[] = {
57 {
58 .magic = FLASH_MAP_ENTRY_MAGIC,
59 .area = {
60 .fa_id = FLASH_AREA_IMAGE_0,
61 .fa_device_id = FLASH_DEVICE_ID,
62 .fa_off = FLASH_AREA_IMAGE_0_OFFSET,
63 .fa_size = FLASH_AREA_IMAGE_0_SIZE,
64 },
65 },
66 {
67 .magic = FLASH_MAP_ENTRY_MAGIC,
68 .area = {
69 .fa_id = FLASH_AREA_IMAGE_1,
70 .fa_device_id = FLASH_DEVICE_ID,
71 .fa_off = FLASH_AREA_IMAGE_1_OFFSET,
72 .fa_size = FLASH_AREA_IMAGE_1_SIZE,
73 },
74 },
75 {
76 .magic = FLASH_MAP_ENTRY_MAGIC,
77 .area = {
78 .fa_id = FLASH_AREA_IMAGE_SCRATCH,
79 .fa_device_id = FLASH_DEVICE_ID,
80 .fa_off = FLASH_AREA_IMAGE_SCRATCH_OFFSET,
81 .fa_size = FLASH_AREA_IMAGE_SCRATCH_SIZE,
82 },
83 }
84};
85
86int flash_device_base(uint8_t fd_id, uintptr_t *ret)
87{
88 if (fd_id != FLASH_DEVICE_ID) {
89 BOOT_LOG_ERR("invalid flash ID %d; expected %d",
90 fd_id, FLASH_DEVICE_ID);
91 return -EINVAL;
92 }
93 *ret = FLASH_DEVICE_BASE;
94 return 0;
95}
96
97/*
98 * `open` a flash area. The `area` in this case is not the individual
99 * sectors, but describes the particular flash area in question.
100 */
101int flash_area_open(uint8_t id, const struct flash_area **area)
102{
103 int i;
104
105 BOOT_LOG_DBG("area %d", id);
106
107 for (i = 0; i < ARRAY_SIZE(part_map); i++) {
108 if (id == part_map[i].area.fa_id) {
109 break;
110 }
111 }
112 if (i == ARRAY_SIZE(part_map)) {
113 return -1;
114 }
115
116 *area = &part_map[i].area;
117 part_map[i].ref_count++;
118 return 0;
119}
120
121/*
122 * Nothing to do on close.
123 */
124void flash_area_close(const struct flash_area *area)
125{
126 struct flash_map_entry *entry;
127
128 if (!area) {
129 return;
130 }
131
132 entry = CONTAINER_OF(area, struct flash_map_entry, area);
133 if (entry->magic != FLASH_MAP_ENTRY_MAGIC) {
134 BOOT_LOG_ERR("invalid area %p (id %u)", area, area->fa_id);
135 return;
136 }
137 if (entry->ref_count == 0) {
138 BOOT_LOG_ERR("area %u use count underflow", area->fa_id);
139 return;
140 }
141 entry->ref_count--;
142}
143
Tamas Ban581034a2017-12-19 19:54:37 +0000144void flash_area_warn_on_open(void)
Tamas Banf70ef8c2017-12-19 15:35:09 +0000145{
146 int i;
Tamas Ban581034a2017-12-19 19:54:37 +0000147 struct flash_map_entry *entry;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000148
149 for (i = 0; i < ARRAY_SIZE(part_map); i++) {
Tamas Ban581034a2017-12-19 19:54:37 +0000150 entry = &part_map[i];
Tamas Banf70ef8c2017-12-19 15:35:09 +0000151 if (entry->ref_count) {
152 BOOT_LOG_WRN("area %u has %u users",
153 entry->area.fa_id, entry->ref_count);
154 }
155 }
156}
157
158int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
159 uint32_t len)
160{
Tamas Banc3828852018-02-01 12:24:16 +0000161 BOOT_LOG_DBG("read area=%d, off=%#x, len=%#x", area->fa_id, off, len);
162 return FLASH_DEV_NAME.ReadData(area->fa_off + off, dst, len);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000163}
164
Tamas Ban581034a2017-12-19 19:54:37 +0000165int flash_area_write(const struct flash_area *area, uint32_t off,
166 const void *src, uint32_t len)
Tamas Banf70ef8c2017-12-19 15:35:09 +0000167{
Tamas Banc3828852018-02-01 12:24:16 +0000168 BOOT_LOG_DBG("write area=%d, off=%#x, len=%#x", area->fa_id, off, len);
169 return FLASH_DEV_NAME.ProgramData(area->fa_off + off, src, len);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000170}
171
172int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
173{
Tamas Banc3828852018-02-01 12:24:16 +0000174 ARM_FLASH_INFO *flash_info;
175 uint32_t deleted_len = 0;
176 int32_t rc = 0;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000177
Tamas Banc3828852018-02-01 12:24:16 +0000178 BOOT_LOG_DBG("erase area=%d, off=%#x, len=%#x", area->fa_id, off, len);
179 flash_info = FLASH_DEV_NAME.GetInfo();
180
181 if (flash_info->sector_info == NULL) {
182 /* Uniform sector layout */
183 while (deleted_len < len) {
184 rc = FLASH_DEV_NAME.EraseSector(area->fa_off + off);
185 if (rc != 0) {
186 break;
187 }
188 deleted_len += flash_info->sector_size;
189 off += flash_info->sector_size;
190 }
191 } else {
192 /* Inhomogeneous sector layout, explicitly defined
193 * Currently not supported.
194 */
195 }
196
Tamas Banf70ef8c2017-12-19 15:35:09 +0000197 return rc;
198}
199
200uint8_t flash_area_align(const struct flash_area *area)
201{
Tamas Banc3828852018-02-01 12:24:16 +0000202 ARM_FLASH_INFO *flash_info;
203
204 flash_info = FLASH_DEV_NAME.GetInfo();
205 return flash_info->program_unit;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000206}
207
208/*
209 * This depends on the mappings defined in sysflash.h, and assumes
210 * that slot 0, slot 1, and the scratch area area contiguous.
211 */
212int flash_area_id_from_image_slot(int slot)
213{
214 return slot + FLASH_AREA_IMAGE_0;
215}
216
Tamas Ban581034a2017-12-19 19:54:37 +0000217static int validate_idx(int idx, uint32_t *off, uint32_t *len)
Tamas Banf70ef8c2017-12-19 15:35:09 +0000218{
219 /*
220 * This simple layout has uniform slots, so just fill in the
221 * right one.
222 */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000223
224 switch (idx) {
225 case FLASH_AREA_IMAGE_0:
226 *off = FLASH_AREA_IMAGE_0_OFFSET;
227 *len = FLASH_AREA_IMAGE_0_SIZE;
228 break;
229 case FLASH_AREA_IMAGE_1:
230 *off = FLASH_AREA_IMAGE_1_OFFSET;
231 *len = FLASH_AREA_IMAGE_1_SIZE;
232 break;
233 case FLASH_AREA_IMAGE_SCRATCH:
234 *off = FLASH_AREA_IMAGE_SCRATCH_OFFSET;
235 *len = FLASH_AREA_IMAGE_SCRATCH_SIZE;
236 break;
237 default:
238 BOOT_LOG_ERR("unknown flash area %d", idx);
239 return -1;
240 }
241
Tamas Ban581034a2017-12-19 19:54:37 +0000242 BOOT_LOG_DBG("area %d: offset=0x%x, length=0x%x, sector size=0x%x",
243 idx, *off, *len, FLASH_AREA_IMAGE_SECTOR_SIZE);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000244 return 0;
245}
246
Tamas Banf70ef8c2017-12-19 15:35:09 +0000247int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
248{
Tamas Ban581034a2017-12-19 19:54:37 +0000249 uint32_t off;
250 uint32_t len;
251 uint32_t max_cnt = *cnt;
252 uint32_t rem_len;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000253
Tamas Ban581034a2017-12-19 19:54:37 +0000254 if (validate_idx(idx, &off, &len)) {
255 return -1;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000256 }
257
Tamas Ban581034a2017-12-19 19:54:37 +0000258 if (*cnt < 1) {
259 return -1;
260 }
Tamas Banf70ef8c2017-12-19 15:35:09 +0000261
Tamas Ban581034a2017-12-19 19:54:37 +0000262 rem_len = len;
263 *cnt = 0;
264 while (rem_len > 0 && *cnt < max_cnt) {
265 if (rem_len < FLASH_AREA_IMAGE_SECTOR_SIZE) {
266 BOOT_LOG_ERR("area %d size 0x%x not divisible by sector size 0x%x",
267 idx, len, FLASH_AREA_IMAGE_SECTOR_SIZE);
268 return -1;
269 }
270
271 ret[*cnt].fa_id = idx;
272 ret[*cnt].fa_device_id = 0;
273 ret[*cnt].pad16 = 0;
274 ret[*cnt].fa_off = off + (FLASH_AREA_IMAGE_SECTOR_SIZE * (*cnt));
275 ret[*cnt].fa_size = FLASH_AREA_IMAGE_SECTOR_SIZE;
276 *cnt = *cnt + 1;
277 rem_len -= FLASH_AREA_IMAGE_SECTOR_SIZE;
278 }
279
Tamas Banc3828852018-02-01 12:24:16 +0000280 if (*cnt > max_cnt) {
Tamas Ban581034a2017-12-19 19:54:37 +0000281 BOOT_LOG_ERR("flash area %d sector count overflow", idx);
282 return -1;
283 }
284
285 return 0;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000286}
287
Tamas Ban581034a2017-12-19 19:54:37 +0000288/*
289 * Lookup the sector map for a given flash area. This should fill in
290 * `ret` with all of the sectors in the area. `*cnt` will be set to
291 * the storage at `ret` and should be set to the final number of
292 * sectors in this area.
293 */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000294int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret)
295{
Tamas Ban581034a2017-12-19 19:54:37 +0000296 uint32_t off;
297 uint32_t len;
298 uint32_t max_cnt = *cnt;
299 uint32_t rem_len;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000300
Tamas Ban581034a2017-12-19 19:54:37 +0000301 if (validate_idx(idx, &off, &len)) {
302 return -1;
303 }
304
305 if (*cnt < 1) {
306 return -1;
307 }
308
309 rem_len = len;
310 *cnt = 0;
311 while (rem_len > 0 && *cnt < max_cnt) {
312 if (rem_len < FLASH_AREA_IMAGE_SECTOR_SIZE) {
313 BOOT_LOG_ERR("area %d size 0x%x not divisible by sector size 0x%x",
314 idx, len, FLASH_AREA_IMAGE_SECTOR_SIZE);
315 return -1;
316 }
317
318 ret[*cnt].fs_off = FLASH_AREA_IMAGE_SECTOR_SIZE * (*cnt);
319 ret[*cnt].fs_size = FLASH_AREA_IMAGE_SECTOR_SIZE;
320 *cnt = *cnt + 1;
321 rem_len -= FLASH_AREA_IMAGE_SECTOR_SIZE;
322 }
323
Tamas Banc3828852018-02-01 12:24:16 +0000324 if (*cnt > max_cnt) {
Tamas Ban581034a2017-12-19 19:54:37 +0000325 BOOT_LOG_ERR("flash area %d sector count overflow", idx);
326 return -1;
327 }
328
329 return 0;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000330}