1 /*
2 * Copyright (c) 2018 Nordic Semiconductor ASA
3 * Copyright (c) 2020 Cypress Semiconductor Corporation
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7 /*
8 * Licensed to the Apache Software Foundation (ASF) under one
9 * or more contributor license agreements. See the NOTICE file
10 * distributed with this work for additional information
11 * regarding copyright ownership. The ASF licenses this file
12 * to you under the Apache License, Version 2.0 (the
13 * "License"); you may not use this file except in compliance
14 * with the License. You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing,
19 * software distributed under the License is distributed on an
20 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 * KIND, either express or implied. See the License for the
22 * specific language governing permissions and limitations
23 * under the License.
24 */
25 /*******************************************************************************/
26
27 #ifdef MCUBOOT_HAVE_ASSERT_H
28 #include "mcuboot_config/mcuboot_assert.h"
29 #else
30 #include <assert.h>
31 #endif
32
33 #include <stdbool.h>
34 #include <stdio.h>
35 #include <stdint.h>
36
37 #include "mcuboot_config/mcuboot_config.h"
38 #include "flash_map_backend/flash_map_backend.h"
39 #include <sysflash/sysflash.h>
40
41 #include "bootutil/bootutil_log.h"
42
43 #include "cy_pdl.h"
44
45 #ifdef CY_BOOT_USE_EXTERNAL_FLASH
46 #include "cy_smif_psoc6.h"
47 #endif
48 /*
49 * For now, we only support one flash device.
50 *
51 * Pick a random device ID for it that's unlikely to collide with
52 * anything "real".
53 */
54 #define FLASH_DEVICE_ID 111
55 #define FLASH_MAP_ENTRY_MAGIC 0xd00dbeef
56
57 #define FLASH_AREA_IMAGE_SECTOR_SIZE FLASH_AREA_IMAGE_SCRATCH_SIZE
58
59 #ifndef CY_BOOTLOADER_START_ADDRESS
60 #define CY_BOOTLOADER_START_ADDRESS (0x10000000)
61 #endif
62
63 #ifndef CY_BOOT_INTERNAL_FLASH_ERASE_VALUE
64 /* This is the value of internal flash bytes after an erase */
65 #define CY_BOOT_INTERNAL_FLASH_ERASE_VALUE (0x00)
66 #endif
67
68 #ifndef CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE
69 /* This is the value of external flash bytes after an erase */
70 #define CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE (0xff)
71 #endif
72
73 #ifdef CY_FLASH_MAP_EXT_DESC
74 /* Nothing to be there when external FlashMap Descriptors are used */
75 #else
76 static struct flash_area bootloader =
77 {
78 .fa_id = FLASH_AREA_BOOTLOADER,
79 .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
80 .fa_off = CY_BOOTLOADER_START_ADDRESS,
81 .fa_size = CY_BOOT_BOOTLOADER_SIZE
82 };
83
84 static struct flash_area primary_1 =
85 {
86 .fa_id = FLASH_AREA_IMAGE_PRIMARY(0),
87 .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
88 .fa_off = CY_FLASH_BASE + CY_BOOT_BOOTLOADER_SIZE,
89 .fa_size = CY_BOOT_PRIMARY_1_SIZE
90 };
91
92 #ifndef CY_BOOT_USE_EXTERNAL_FLASH
93 static struct flash_area secondary_1 =
94 {
95 .fa_id = FLASH_AREA_IMAGE_SECONDARY(0),
96 .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
97 .fa_off = CY_FLASH_BASE +\
98 CY_BOOT_BOOTLOADER_SIZE +\
99 CY_BOOT_PRIMARY_1_SIZE,
100 .fa_size = CY_BOOT_SECONDARY_1_SIZE
101 };
102 #else
103 static struct flash_area secondary_1 =
104 {
105 .fa_id = FLASH_AREA_IMAGE_SECONDARY(0),
106 .fa_device_id = FLASH_DEVICE_EXTERNAL_FLASH(CY_BOOT_EXTERNAL_DEVICE_INDEX),
107 .fa_off = CY_SMIF_BASE_MEM_OFFSET,
108 .fa_size = CY_BOOT_SECONDARY_1_SIZE
109 };
110 #endif
111 #if (MCUBOOT_IMAGE_NUMBER == 2) /* if dual-image */
112 static struct flash_area primary_2 =
113 {
114 .fa_id = FLASH_AREA_IMAGE_PRIMARY(1),
115 .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
116 .fa_off = CY_FLASH_BASE +\
117 CY_BOOT_BOOTLOADER_SIZE +\
118 CY_BOOT_PRIMARY_1_SIZE +\
119 CY_BOOT_SECONDARY_1_SIZE,
120 .fa_size = CY_BOOT_PRIMARY_2_SIZE
121 };
122
123 static struct flash_area secondary_2 =
124 {
125 .fa_id = FLASH_AREA_IMAGE_SECONDARY(1),
126 /* it is for external flash memory
127 .fa_device_id = FLASH_DEVICE_EXTERNAL_FLASH(CY_BOOT_EXTERNAL_DEVICE_INDEX), */
128 #ifndef CY_BOOT_USE_EXTERNAL_FLASH
129 .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
130 .fa_off = CY_FLASH_BASE +\
131 CY_BOOT_BOOTLOADER_SIZE +\
132 CY_BOOT_PRIMARY_1_SIZE +\
133 CY_BOOT_SECONDARY_1_SIZE +\
134 CY_BOOT_PRIMARY_2_SIZE,
135 #else
136 .fa_device_id = FLASH_DEVICE_EXTERNAL_FLASH(CY_BOOT_EXTERNAL_DEVICE_INDEX),
137 .fa_off = CY_SMIF_BASE_MEM_OFFSET + 0x40000,
138 #endif
139 .fa_size = CY_BOOT_SECONDARY_2_SIZE
140 };
141 #endif
142 #endif
143
144 #ifdef MCUBOOT_SWAP_USING_SCRATCH
145 static struct flash_area scratch =
146 {
147 .fa_id = FLASH_AREA_IMAGE_SCRATCH,
148 .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
149 #if (MCUBOOT_IMAGE_NUMBER == 1) /* if single-image */
150 .fa_off = CY_FLASH_BASE +\
151 CY_BOOT_BOOTLOADER_SIZE +\
152 CY_BOOT_PRIMARY_1_SIZE +\
153 CY_BOOT_SECONDARY_1_SIZE,
154 #elif (MCUBOOT_IMAGE_NUMBER == 2) /* if dual-image */
155 .fa_off = CY_FLASH_BASE +\
156 CY_BOOT_BOOTLOADER_SIZE +\
157 CY_BOOT_PRIMARY_1_SIZE +\
158 CY_BOOT_SECONDARY_1_SIZE +\
159 CY_BOOT_PRIMARY_2_SIZE +\
160 CY_BOOT_SECONDARY_2_SIZE,
161 #endif
162 .fa_size = CY_BOOT_SCRATCH_SIZE
163 };
164 #endif
165
166 #ifdef CY_FLASH_MAP_EXT_DESC
167 /* Use external Flash Map Descriptors */
168 extern struct flash_area *boot_area_descs[];
169 #else
170 struct flash_area *boot_area_descs[] =
171 {
172 &bootloader,
173 &primary_1,
174 &secondary_1,
175 #if (MCUBOOT_IMAGE_NUMBER == 2) /* if dual-image */
176 &primary_2,
177 &secondary_2,
178 #endif
179 #ifdef MCUBOOT_SWAP_USING_SCRATCH
180 &scratch,
181 #endif
182 NULL
183 };
184 #endif
185
186 /* Returns device flash start based on supported fa_id */
flash_device_base(uint8_t fd_id,uintptr_t * ret)187 int flash_device_base(uint8_t fd_id, uintptr_t *ret)
188 {
189 if (fd_id != FLASH_DEVICE_INTERNAL_FLASH) {
190 BOOT_LOG_ERR("invalid flash ID %d; expected %d",
191 fd_id, FLASH_DEVICE_INTERNAL_FLASH);
192 return -1;
193 }
194 *ret = CY_FLASH_BASE;
195 return 0;
196 }
197
198 /* Opens the area for use. id is one of the `fa_id`s */
flash_area_open(uint8_t id,const struct flash_area ** fa)199 int flash_area_open(uint8_t id, const struct flash_area **fa)
200 {
201 int ret = -1;
202 uint32_t i = 0;
203
204 while(NULL != boot_area_descs[i])
205 {
206 if(id == boot_area_descs[i]->fa_id)
207 {
208 *fa = boot_area_descs[i];
209 ret = 0;
210 break;
211 }
212 i++;
213 }
214 return ret;
215 }
216
flash_area_close(const struct flash_area * fa)217 void flash_area_close(const struct flash_area *fa)
218 {
219 (void)fa;/* Nothing to do there */
220 }
221
222 /*
223 * Reads `len` bytes of flash memory at `off` to the buffer at `dst`
224 */
flash_area_read(const struct flash_area * fa,uint32_t off,void * dst,uint32_t len)225 int flash_area_read(const struct flash_area *fa, uint32_t off, void *dst,
226 uint32_t len)
227 {
228 int rc = 0;
229 size_t addr;
230
231 /* check if requested offset not less then flash area (fa) start */
232 assert(off < fa->fa_off);
233 assert(off + len < fa->fa_off);
234 /* convert to absolute address inside a device*/
235 addr = fa->fa_off + off;
236
237 if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
238 {
239 /* flash read by simple memory copying */
240 memcpy((void *)dst, (const void*)addr, (size_t)len);
241 }
242 #ifdef CY_BOOT_USE_EXTERNAL_FLASH
243 else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
244 {
245 rc = psoc6_smif_read(fa, addr, dst, len);
246 }
247 #endif
248 else
249 {
250 /* incorrect/non-existing flash device id */
251 rc = -1;
252 }
253
254 if (rc != 0) {
255 BOOT_LOG_ERR("Flash area read error, rc = %d", (int)rc);
256 }
257 return rc;
258 }
259
260 /*
261 * Writes `len` bytes of flash memory at `off` from the buffer at `src`
262 */
flash_area_write(const struct flash_area * fa,uint32_t off,const void * src,uint32_t len)263 int flash_area_write(const struct flash_area *fa, uint32_t off,
264 const void *src, uint32_t len)
265 {
266 cy_en_flashdrv_status_t rc = CY_FLASH_DRV_SUCCESS;
267 size_t write_start_addr;
268 size_t write_end_addr;
269 const uint32_t * row_ptr = NULL;
270
271 assert(off < fa->fa_off);
272 assert(off + len < fa->fa_off);
273
274 /* convert to absolute address inside a device */
275 write_start_addr = fa->fa_off + off;
276 write_end_addr = fa->fa_off + off + len;
277
278 if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
279 {
280 uint32_t row_number = 0;
281 uint32_t row_addr = 0;
282
283 assert(!(len % CY_FLASH_SIZEOF_ROW));
284 assert(!(write_start_addr % CY_FLASH_SIZEOF_ROW));
285
286 row_number = (write_end_addr - write_start_addr) / CY_FLASH_SIZEOF_ROW;
287 row_addr = write_start_addr;
288
289 row_ptr = (uint32_t *) src;
290
291 for (uint32_t i = 0; i < row_number; i++)
292 {
293 rc = Cy_Flash_WriteRow(row_addr, row_ptr);
294
295 row_addr += (uint32_t) CY_FLASH_SIZEOF_ROW;
296 row_ptr = row_ptr + CY_FLASH_SIZEOF_ROW / 4;
297 }
298 }
299 #ifdef CY_BOOT_USE_EXTERNAL_FLASH
300 else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
301 {
302 rc = psoc6_smif_write(fa, write_start_addr, src, len);
303 }
304 #endif
305 else
306 {
307 /* incorrect/non-existing flash device id */
308 rc = -1;
309 }
310
311 return (int) rc;
312 }
313
314 /*< Erases `len` bytes of flash memory at `off` */
flash_area_erase(const struct flash_area * fa,uint32_t off,uint32_t len)315 int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
316 {
317 cy_en_flashdrv_status_t rc = CY_FLASH_DRV_SUCCESS;
318 size_t erase_start_addr;
319 size_t erase_end_addr;
320
321 assert(off < fa->fa_off);
322 assert(off + len < fa->fa_off);
323 assert(!(len % CY_FLASH_SIZEOF_ROW));
324
325 /* convert to absolute address inside a device*/
326 erase_start_addr = fa->fa_off + off;
327 erase_end_addr = fa->fa_off + off + len;
328
329 if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
330 {
331 int row_number = 0;
332 uint32_t row_addr = 0;
333
334 row_number = (erase_end_addr - erase_start_addr) / CY_FLASH_SIZEOF_ROW;
335
336 while (row_number != 0)
337 {
338 row_number--;
339 row_addr = erase_start_addr + row_number * (uint32_t) CY_FLASH_SIZEOF_ROW;
340 rc = Cy_Flash_EraseRow(row_addr);
341 }
342 }
343 #ifdef CY_BOOT_USE_EXTERNAL_FLASH
344 else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
345 {
346 rc = psoc6_smif_erase(erase_start_addr, len);
347 }
348 #endif
349 else
350 {
351 /* incorrect/non-existing flash device id */
352 rc = -1;
353 }
354 return (int) rc;
355 }
356
357 /*< Returns this `flash_area`s alignment */
flash_area_align(const struct flash_area * fa)358 size_t flash_area_align(const struct flash_area *fa)
359 {
360 int ret = -1;
361 if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
362 {
363 ret = CY_FLASH_ALIGN;
364 }
365 #ifdef CY_BOOT_USE_EXTERNAL_FLASH
366 else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
367 {
368 return qspi_get_prog_size();
369 }
370 #endif
371 else
372 {
373 /* incorrect/non-existing flash device id */
374 ret = -1;
375 }
376 return ret;
377 }
378
379 #ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
380 /*< Initializes an array of flash_area elements for the slot's sectors */
flash_area_to_sectors(int idx,int * cnt,struct flash_area * fa)381 int flash_area_to_sectors(int idx, int *cnt, struct flash_area *fa)
382 {
383 int rc = 0;
384
385 if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
386 {
387 (void)idx;
388 (void)cnt;
389 rc = 0;
390 }
391 #ifdef CY_BOOT_USE_EXTERNAL_FLASH
392 else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
393 {
394 (void)idx;
395 (void)cnt;
396 rc = 0;
397 }
398 #endif
399 else
400 {
401 /* incorrect/non-existing flash device id */
402 rc = -1;
403 }
404 return rc;
405 }
406 #endif
407
408 /*
409 * This depends on the mappings defined in sysflash.h.
410 * MCUBoot uses continuous numbering for the primary slot, the secondary slot,
411 * and the scratch while zephyr might number it differently.
412 */
flash_area_id_from_multi_image_slot(int image_index,int slot)413 int flash_area_id_from_multi_image_slot(int image_index, int slot)
414 {
415 switch (slot) {
416 case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index);
417 case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index);
418 case 2: return FLASH_AREA_IMAGE_SCRATCH;
419 }
420
421 return -1; /* flash_area_open will fail on that */
422 }
423
flash_area_id_from_image_slot(int slot)424 int flash_area_id_from_image_slot(int slot)
425 {
426 return flash_area_id_from_multi_image_slot(0, slot);
427 }
428
flash_area_id_to_multi_image_slot(int image_index,int area_id)429 int flash_area_id_to_multi_image_slot(int image_index, int area_id)
430 {
431 if (area_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
432 return 0;
433 }
434 if (area_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
435 return 1;
436 }
437
438 return -1;
439 }
440
flash_area_id_to_image_slot(int area_id)441 int flash_area_id_to_image_slot(int area_id)
442 {
443 return flash_area_id_to_multi_image_slot(0, area_id);
444 }
445
flash_area_erased_val(const struct flash_area * fap)446 uint8_t flash_area_erased_val(const struct flash_area *fap)
447 {
448 int ret = 0;
449
450 if (fap->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
451 {
452 ret = CY_BOOT_INTERNAL_FLASH_ERASE_VALUE;
453 }
454 #ifdef CY_BOOT_USE_EXTERNAL_FLASH
455 else if ((fap->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
456 {
457 ret = CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE;
458 }
459 #endif
460 else
461 {
462 assert(false) ;
463 }
464
465 return ret ;
466 }
467
flash_area_read_is_empty(const struct flash_area * fa,uint32_t off,void * dst,uint32_t len)468 int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
469 void *dst, uint32_t len)
470 {
471 uint8_t *mem_dest;
472 int rc;
473
474 mem_dest = (uint8_t *)dst;
475 rc = flash_area_read(fa, off, dst, len);
476 if (rc) {
477 return -1;
478 }
479
480 for (uint8_t i = 0; i < len; i++) {
481 if (mem_dest[i] != flash_area_erased_val(fa)) {
482 return 0;
483 }
484 }
485 return 1;
486 }
487
488 #ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
flash_area_get_sectors(int idx,uint32_t * cnt,struct flash_sector * ret)489 int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret)
490 {
491 int rc = 0;
492 uint32_t i = 0;
493 struct flash_area *fa = NULL;
494
495 while(NULL != boot_area_descs[i])
496 {
497 if(idx == boot_area_descs[i]->fa_id)
498 {
499 fa = boot_area_descs[i];
500 break;
501 }
502 i++;
503 }
504
505 if(NULL != boot_area_descs[i])
506 {
507 size_t sector_size = 0;
508
509 if(fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
510 {
511 sector_size = CY_FLASH_SIZEOF_ROW;
512 }
513 #ifdef CY_BOOT_USE_EXTERNAL_FLASH
514 else if((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
515 {
516 /* implement for SMIF */
517 /* lets assume they are equal */
518 sector_size = CY_FLASH_SIZEOF_ROW;
519 }
520 #endif
521 else
522 {
523 rc = -1;
524 }
525
526 if(0 == rc)
527 {
528 uint32_t addr = 0;
529 size_t sectors_n = 0;
530
531 sectors_n = (fa->fa_size + (sector_size - 1)) / sector_size;
532 assert(sectors_n <= *cnt);
533
534 addr = fa->fa_off;
535 for(i = 0; i < sectors_n; i++)
536 {
537 ret[i].fs_size = sector_size ;
538 ret[i].fs_off = addr ;
539 addr += sector_size ;
540 }
541
542 *cnt = sectors_n;
543 }
544 }
545 else
546 {
547 rc = -1;
548 }
549
550 return rc;
551 }
552 #endif
553