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 uint32_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_erased_val(const struct flash_area * fap)441 uint8_t flash_area_erased_val(const struct flash_area *fap)
442 {
443     int ret = 0;
444 
445     if (fap->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
446     {
447         ret = CY_BOOT_INTERNAL_FLASH_ERASE_VALUE;
448     }
449 #ifdef CY_BOOT_USE_EXTERNAL_FLASH
450     else if ((fap->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
451     {
452         ret = CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE;
453     }
454 #endif
455     else
456     {
457         assert(false) ;
458     }
459 
460     return ret ;
461 }
462 
flash_area_read_is_empty(const struct flash_area * fa,uint32_t off,void * dst,uint32_t len)463 int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
464         void *dst, uint32_t len)
465 {
466     uint8_t *mem_dest;
467     int rc;
468 
469     mem_dest = (uint8_t *)dst;
470     rc = flash_area_read(fa, off, dst, len);
471     if (rc) {
472         return -1;
473     }
474 
475     for (uint8_t i = 0; i < len; i++) {
476         if (mem_dest[i] != flash_area_erased_val(fa)) {
477             return 0;
478         }
479     }
480     return 1;
481 }
482 
483 #ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
flash_area_get_sectors(int idx,uint32_t * cnt,struct flash_sector * ret)484 int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret)
485 {
486     int rc = 0;
487     uint32_t i = 0;
488     struct flash_area *fa = NULL;
489 
490     while(NULL != boot_area_descs[i])
491     {
492         if(idx == boot_area_descs[i]->fa_id)
493         {
494             fa = boot_area_descs[i];
495             break;
496         }
497         i++;
498     }
499 
500     if(NULL != boot_area_descs[i])
501     {
502         size_t sector_size = 0;
503 
504         if(fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
505         {
506             sector_size = CY_FLASH_SIZEOF_ROW;
507         }
508 #ifdef CY_BOOT_USE_EXTERNAL_FLASH
509         else if((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
510         {
511             /* implement for SMIF */
512             /* lets assume they are equal */
513             sector_size = CY_FLASH_SIZEOF_ROW;
514         }
515 #endif
516         else
517         {
518             rc = -1;
519         }
520 
521         if(0 == rc)
522         {
523             uint32_t addr = 0;
524             size_t sectors_n = 0;
525 
526             sectors_n = (fa->fa_size + (sector_size - 1)) / sector_size;
527             assert(sectors_n <= *cnt);
528 
529             addr = fa->fa_off;
530             for(i = 0; i < sectors_n; i++)
531             {
532                 ret[i].fs_size = sector_size ;
533                 ret[i].fs_off = addr ;
534                 addr += sector_size ;
535             }
536 
537             *cnt = sectors_n;
538         }
539     }
540     else
541     {
542         rc = -1;
543     }
544 
545     return rc;
546 }
547 #endif
548