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