1 /****************************************************************************
2  * boot/nuttx/src/flash_map_backend/flash_map_backend.c
3  *
4  * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * 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, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  ****************************************************************************/
19 
20 /****************************************************************************
21  * Included Files
22  ****************************************************************************/
23 
24 #include <nuttx/config.h>
25 
26 #include <assert.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <stdint.h>
30 #include <string.h>
31 #include <sys/ioctl.h>
32 #include <unistd.h>
33 
34 #include <nuttx/fs/fs.h>
35 #include <nuttx/mtd/mtd.h>
36 
37 #include <bootutil/bootutil_log.h>
38 
39 #include "flash_map_backend/flash_map_backend.h"
40 #include "os/os_malloc.h"
41 #include "sysflash/sysflash.h"
42 
43 /****************************************************************************
44  * Pre-processor Definitions
45  ****************************************************************************/
46 
47 #define ARRAYSIZE(x)                (sizeof((x)) / sizeof((x)[0]))
48 
49 /****************************************************************************
50  * Private Types
51  ****************************************************************************/
52 
53 struct flash_device_s
54 {
55   /* Reference to the flash area configuration parameters */
56 
57   struct flash_area *fa_cfg;
58 
59   /* Geometry characteristics of the underlying MTD device */
60 
61   struct mtd_geometry_s mtdgeo;
62 
63   /* Partition information */
64 
65   struct partition_info_s partinfo;
66 
67   int      fd;          /* File descriptor for an open flash area */
68   uint32_t refs;        /* Reference counter */
69   uint8_t  erase_state; /* Byte value of the flash erased state */
70 };
71 
72 /****************************************************************************
73  * Private Data
74  ****************************************************************************/
75 
76 static struct flash_area g_primary_img0 =
77 {
78   .fa_id = FLASH_AREA_IMAGE_PRIMARY(0),
79   .fa_device_id = 0,
80   .fa_off = 0,
81   .fa_size = 0,
82   .fa_mtd_path = CONFIG_MCUBOOT_PRIMARY_SLOT_PATH
83 };
84 
85 static struct flash_device_s g_primary_priv =
86 {
87   .fa_cfg = &g_primary_img0,
88   .mtdgeo =
89             {
90               0
91             },
92   .partinfo =
93               {
94                 0
95               },
96   .fd = -1,
97   .refs = 0,
98   .erase_state = CONFIG_MCUBOOT_DEFAULT_FLASH_ERASE_STATE
99 };
100 
101 static struct flash_area g_secondary_img0 =
102 {
103   .fa_id = FLASH_AREA_IMAGE_SECONDARY(0),
104   .fa_device_id = 0,
105   .fa_off = 0,
106   .fa_size = 0,
107   .fa_mtd_path = CONFIG_MCUBOOT_SECONDARY_SLOT_PATH
108 };
109 
110 static struct flash_device_s g_secondary_priv =
111 {
112   .fa_cfg = &g_secondary_img0,
113   .mtdgeo =
114             {
115               0
116             },
117   .partinfo =
118               {
119                 0
120               },
121   .fd = -1,
122   .refs = 0,
123   .erase_state = CONFIG_MCUBOOT_DEFAULT_FLASH_ERASE_STATE
124 };
125 
126 static struct flash_area g_scratch_img0 =
127 {
128   .fa_id = FLASH_AREA_IMAGE_SCRATCH,
129   .fa_device_id = 0,
130   .fa_off = 0,
131   .fa_size = 0,
132   .fa_mtd_path = CONFIG_MCUBOOT_SCRATCH_PATH
133 };
134 
135 static struct flash_device_s g_scratch_priv =
136 {
137   .fa_cfg = &g_scratch_img0,
138   .mtdgeo =
139             {
140               0
141             },
142   .partinfo =
143               {
144                 0
145               },
146   .fd = -1,
147   .refs = 0,
148   .erase_state = CONFIG_MCUBOOT_DEFAULT_FLASH_ERASE_STATE
149 };
150 
151 static struct flash_device_s *g_flash_devices[] =
152 {
153   &g_primary_priv,
154   &g_secondary_priv,
155   &g_scratch_priv,
156 };
157 
158 /****************************************************************************
159  * Private Functions
160  ****************************************************************************/
161 
162 /****************************************************************************
163  * Name: lookup_flash_device_by_id
164  *
165  * Description:
166  *   Retrieve flash device from a given flash area ID.
167  *
168  * Input Parameters:
169  *   fa_id - ID of the flash area.
170  *
171  * Returned Value:
172  *   Reference to the found flash device, or NULL in case it does not exist.
173  *
174  ****************************************************************************/
175 
lookup_flash_device_by_id(uint8_t fa_id)176 static struct flash_device_s *lookup_flash_device_by_id(uint8_t fa_id)
177 {
178   size_t i;
179 
180   for (i = 0; i < ARRAYSIZE(g_flash_devices); i++)
181     {
182       struct flash_device_s *dev = g_flash_devices[i];
183 
184       if (fa_id == dev->fa_cfg->fa_id)
185         {
186           return dev;
187         }
188     }
189 
190   return NULL;
191 }
192 
193 /****************************************************************************
194  * Name: lookup_flash_device_by_offset
195  *
196  * Description:
197  *   Retrieve flash device from a given flash area offset.
198  *
199  * Input Parameters:
200  *   offset - Offset of the flash area.
201  *
202  * Returned Value:
203  *   Reference to the found flash device, or NULL in case it does not exist.
204  *
205  ****************************************************************************/
206 
lookup_flash_device_by_offset(uint32_t offset)207 static struct flash_device_s *lookup_flash_device_by_offset(uint32_t offset)
208 {
209   size_t i;
210 
211   for (i = 0; i < ARRAYSIZE(g_flash_devices); i++)
212     {
213       struct flash_device_s *dev = g_flash_devices[i];
214 
215       if (offset == dev->fa_cfg->fa_off)
216         {
217           return dev;
218         }
219     }
220 
221   return NULL;
222 }
223 
224 /****************************************************************************
225  * Public Functions
226  ****************************************************************************/
227 
228 /****************************************************************************
229  * Name: flash_area_open
230  *
231  * Description:
232  *   Retrieve flash area from the flash map for a given ID.
233  *
234  * Input Parameters:
235  *   id - ID of the flash area.
236  *
237  * Output Parameters:
238  *   fa - Pointer which will contain the reference to flash_area.
239  *        If ID is unknown, it will be NULL on output.
240  *
241  * Returned Value:
242  *   Zero on success, or negative value in case of error.
243  *
244  ****************************************************************************/
245 
flash_area_open(uint8_t id,const struct flash_area ** fa)246 int flash_area_open(uint8_t id, const struct flash_area **fa)
247 {
248   struct flash_device_s *dev;
249   int fd;
250   int ret;
251 
252   BOOT_LOG_INF("ID:%" PRIu8, id);
253 
254   dev = lookup_flash_device_by_id(id);
255   if (dev == NULL)
256     {
257       BOOT_LOG_ERR("Undefined flash area: %" PRIu8, id);
258 
259       return ERROR;
260     }
261 
262   *fa = dev->fa_cfg;
263 
264   if (dev->refs++ > 0)
265     {
266       BOOT_LOG_INF("Flash area ID %" PRIu8 " already open, count: %" PRIu32 " (+)",
267                    id, dev->refs);
268 
269       return OK;
270     }
271 
272   fd = open(dev->fa_cfg->fa_mtd_path, O_RDWR);
273   if (fd < 0)
274     {
275       int errcode = errno;
276 
277       BOOT_LOG_ERR("Error opening MTD device: %d", errcode);
278 
279       goto errout;
280     }
281 
282   ret = ioctl(fd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&dev->mtdgeo));
283   if (ret < 0)
284     {
285       int errcode = errno;
286 
287       BOOT_LOG_ERR("Error retrieving MTD device geometry: %d", errcode);
288 
289       goto errout_with_fd;
290     }
291 
292   ret = ioctl(fd, BIOC_PARTINFO, (unsigned long)((uintptr_t)&dev->partinfo));
293   if (ret < 0)
294     {
295       int errcode = errno;
296 
297       BOOT_LOG_ERR("Error retrieving MTD partition info: %d", errcode);
298 
299       goto errout_with_fd;
300     }
301 
302   ret = ioctl(fd, MTDIOC_ERASESTATE,
303               (unsigned long)((uintptr_t)&dev->erase_state));
304   if (ret < 0)
305     {
306       int errcode = errno;
307 
308       BOOT_LOG_ERR("Error retrieving MTD device erase state: %d", errcode);
309 
310       goto errout_with_fd;
311     }
312 
313   dev->fa_cfg->fa_off = dev->partinfo.startsector * dev->partinfo.sectorsize;
314   dev->fa_cfg->fa_size = dev->partinfo.numsectors * dev->partinfo.sectorsize;
315 
316   BOOT_LOG_INF("Flash area offset: 0x%" PRIx32, dev->fa_cfg->fa_off);
317   BOOT_LOG_INF("Flash area size: %" PRIu32, dev->fa_cfg->fa_size);
318   BOOT_LOG_INF("MTD erase state: 0x%" PRIx8, dev->erase_state);
319 
320   dev->fd = fd;
321 
322   BOOT_LOG_INF("Flash area %" PRIu8 " open, count: %" PRIu32 " (+)", id, dev->refs);
323 
324   return OK;
325 
326 errout_with_fd:
327   close(fd);
328 
329 errout:
330   --dev->refs;
331 
332   return ERROR;
333 }
334 
335 /****************************************************************************
336  * Name: flash_area_close
337  *
338  * Description:
339  *   Close a given flash area.
340  *
341  * Input Parameters:
342  *   fa - Flash area to be closed.
343  *
344  * Returned Value:
345  *   None.
346  *
347  ****************************************************************************/
348 
flash_area_close(const struct flash_area * fa)349 void flash_area_close(const struct flash_area *fa)
350 {
351   BOOT_LOG_INF("ID:%" PRIu8, fa->fa_id);
352 
353   struct flash_device_s *dev = lookup_flash_device_by_id(fa->fa_id);
354 
355   DEBUGASSERT(dev != NULL);
356 
357   if (dev->refs == 0)
358     {
359       /* No need to close an unopened flash area, avoid an overflow of the
360        * counter.
361        */
362 
363       return;
364     }
365 
366   BOOT_LOG_INF("Close request for flash area %" PRIu8 ", count: %" PRIu32 " (-)",
367                fa->fa_id, dev->refs);
368 
369   if (--dev->refs == 0)
370     {
371       close(dev->fd);
372       dev->fd = -1;
373 
374       BOOT_LOG_INF("Flash area %" PRIu8 " closed", fa->fa_id);
375     }
376 }
377 
378 /****************************************************************************
379  * Name: flash_area_read
380  *
381  * Description:
382  *   Read data from flash area.
383  *   Area readout boundaries are asserted before read request. API has the
384  *   same limitation regarding read-block alignment and size as the
385  *   underlying flash driver.
386  *
387  * Input Parameters:
388  *   fa  - Flash area to be read.
389  *   off - Offset relative from beginning of flash area to be read.
390  *   len - Number of bytes to read.
391  *
392  * Output Parameters:
393  *   dst - Buffer to store read data.
394  *
395  * Returned Value:
396  *   Zero on success, or negative value in case of error.
397  *
398  ****************************************************************************/
399 
flash_area_read(const struct flash_area * fa,uint32_t off,void * dst,uint32_t len)400 int flash_area_read(const struct flash_area *fa, uint32_t off,
401                     void *dst, uint32_t len)
402 {
403   struct flash_device_s *dev;
404   off_t seekpos;
405   ssize_t nbytes;
406 
407   BOOT_LOG_INF("ID:%" PRIu8 " offset:%" PRIu32 " length:%" PRIu32,
408                fa->fa_id, off, len);
409 
410   dev = lookup_flash_device_by_id(fa->fa_id);
411 
412   DEBUGASSERT(dev != NULL);
413 
414   if (off + len > fa->fa_size)
415     {
416       BOOT_LOG_ERR("Attempt to read out of flash area bounds");
417 
418       return ERROR;
419     }
420 
421   /* Reposition the file offset from the beginning of the flash area */
422 
423   seekpos = lseek(dev->fd, (off_t)off, SEEK_SET);
424   if (seekpos != (off_t)off)
425     {
426       int errcode = errno;
427 
428       BOOT_LOG_ERR("Seek to offset %" PRIu32 " failed: %d", off, errcode);
429 
430       return ERROR;
431     }
432 
433   /* Read the flash block into memory */
434 
435   nbytes = read(dev->fd, dst, len);
436   if (nbytes < 0)
437     {
438       int errcode = errno;
439 
440       BOOT_LOG_ERR("Read from %s failed: %d", fa->fa_mtd_path, errcode);
441 
442       return ERROR;
443     }
444 
445   return OK;
446 }
447 
448 /****************************************************************************
449  * Name: flash_area_write
450  *
451  * Description:
452  *   Write data to flash area.
453  *   Area write boundaries are asserted before write request. API has the
454  *   same limitation regarding write-block alignment and size as the
455  *   underlying flash driver.
456  *
457  * Input Parameters:
458  *   fa  - Flash area to be written.
459  *   off - Offset relative from beginning of flash area to be written.
460  *   src - Buffer with data to be written.
461  *   len - Number of bytes to write.
462  *
463  * Returned Value:
464  *   Zero on success, or negative value in case of error.
465  *
466  ****************************************************************************/
467 
flash_area_write(const struct flash_area * fa,uint32_t off,const void * src,uint32_t len)468 int flash_area_write(const struct flash_area *fa, uint32_t off,
469                      const void *src, uint32_t len)
470 {
471   struct flash_device_s *dev;
472   off_t seekpos;
473   ssize_t nbytes;
474 
475   BOOT_LOG_INF("ID:%" PRIu8 " offset:%" PRIu32 " length:%" PRIu32,
476                fa->fa_id, off, len);
477 
478   dev = lookup_flash_device_by_id(fa->fa_id);
479 
480   DEBUGASSERT(dev != NULL);
481 
482   if (off + len > fa->fa_size)
483     {
484       BOOT_LOG_ERR("Attempt to write out of flash area bounds");
485 
486       return ERROR;
487     }
488 
489   /* Reposition the file offset from the beginning of the flash area */
490 
491   seekpos = lseek(dev->fd, (off_t)off, SEEK_SET);
492   if (seekpos != (off_t)off)
493     {
494       int errcode = errno;
495 
496       BOOT_LOG_ERR("Seek to offset %" PRIu32 " failed: %d", off, errcode);
497 
498       return ERROR;
499     }
500 
501   /* Write the buffer to the flash block */
502 
503   nbytes = write(dev->fd, src, len);
504   if (nbytes < 0)
505     {
506       int errcode = errno;
507 
508       BOOT_LOG_ERR("Write to %s failed: %d", fa->fa_mtd_path, errcode);
509 
510       return ERROR;
511     }
512 
513   return OK;
514 }
515 
516 /****************************************************************************
517  * Name: flash_area_erase
518  *
519  * Description:
520  *   Erase a given flash area range.
521  *   Area boundaries are asserted before erase request. API has the same
522  *   limitation regarding erase-block alignment and size as the underlying
523  *   flash driver.
524  *
525  * Input Parameters:
526  *   fa  - Flash area to be erased.
527  *   off - Offset relative from beginning of flash area to be erased.
528  *   len - Number of bytes to be erase.
529  *
530  * Returned Value:
531  *   Zero on success, or negative value in case of error.
532  *
533  ****************************************************************************/
534 
flash_area_erase(const struct flash_area * fa,uint32_t off,uint32_t len)535 int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
536 {
537   int ret;
538   void *buffer;
539   size_t i;
540   struct flash_device_s *dev = lookup_flash_device_by_id(fa->fa_id);
541   const size_t sector_size = dev->mtdgeo.erasesize;
542   const uint8_t erase_val = dev->erase_state;
543 
544   BOOT_LOG_INF("ID:%" PRIu8 " offset:%" PRIu32 " length:%" PRIu32,
545                fa->fa_id, off, len);
546 
547   buffer = malloc(sector_size);
548   if (buffer == NULL)
549     {
550       BOOT_LOG_ERR("Failed to allocate erase buffer");
551 
552       return ERROR;
553     }
554 
555   memset(buffer, erase_val, sector_size);
556 
557   i = 0;
558 
559   do
560     {
561       BOOT_LOG_DBG("Erasing %zu bytes at offset %" PRIu32,
562                    sector_size, off + i);
563 
564       ret = flash_area_write(fa, off + i, buffer, sector_size);
565       i += sector_size;
566     }
567   while (ret == OK && i < (len - sector_size));
568 
569   if (ret == OK)
570     {
571       BOOT_LOG_DBG("Erasing %" PRIu32 " bytes at offset %" PRIu32,
572                    len - i, off + i);
573 
574       ret = flash_area_write(fa, off + i, buffer, len - i);
575     }
576 
577   free(buffer);
578 
579   return ret;
580 }
581 
582 /****************************************************************************
583  * Name: flash_area_align
584  *
585  * Description:
586  *   Get write block size of the flash area.
587  *   Write block size might be treated as read block size, although most
588  *   drivers support unaligned readout.
589  *
590  * Input Parameters:
591  *   fa - Flash area.
592  *
593  * Returned Value:
594  *   Alignment restriction for flash writes in the given flash area.
595  *
596  ****************************************************************************/
597 
flash_area_align(const struct flash_area * fa)598 uint32_t flash_area_align(const struct flash_area *fa)
599 {
600   /* MTD access alignment is handled by the character and block device
601    * drivers.
602    */
603 
604   const uint32_t minimum_write_length = 1;
605 
606   BOOT_LOG_INF("ID:%" PRIu8 " align:%" PRIu32,
607                fa->fa_id, minimum_write_length);
608 
609   return minimum_write_length;
610 }
611 
612 /****************************************************************************
613  * Name: flash_area_erased_val
614  *
615  * Description:
616  *   Get the value expected to be read when accessing any erased flash byte.
617  *   This API is compatible with the MCUboot's porting layer.
618  *
619  * Input Parameters:
620  *   fa - Flash area.
621  *
622  * Returned Value:
623  *   Byte value of erased memory.
624  *
625  ****************************************************************************/
626 
flash_area_erased_val(const struct flash_area * fa)627 uint8_t flash_area_erased_val(const struct flash_area *fa)
628 {
629   struct flash_device_s *dev;
630   uint8_t erased_val;
631 
632   dev = lookup_flash_device_by_id(fa->fa_id);
633 
634   DEBUGASSERT(dev != NULL);
635 
636   erased_val = dev->erase_state;
637 
638   BOOT_LOG_INF("ID:%" PRIu8 " erased_val:0x%" PRIx8, fa->fa_id, erased_val);
639 
640   return erased_val;
641 }
642 
643 /****************************************************************************
644  * Name: flash_area_get_sectors
645  *
646  * Description:
647  *   Retrieve info about sectors within the area.
648  *
649  * Input Parameters:
650  *   fa_id   - ID of the flash area whose info will be retrieved.
651  *   count   - On input, represents the capacity of the sectors buffer.
652  *
653  * Output Parameters:
654  *   count   - On output, it shall contain the number of retrieved sectors.
655  *   sectors - Buffer for sectors data.
656  *
657  * Returned Value:
658  *   Zero on success, or negative value in case of error.
659  *
660  ****************************************************************************/
661 
flash_area_get_sectors(int fa_id,uint32_t * count,struct flash_sector * sectors)662 int flash_area_get_sectors(int fa_id, uint32_t *count,
663                            struct flash_sector *sectors)
664 {
665   size_t off;
666   uint32_t total_count = 0;
667   struct flash_device_s *dev = lookup_flash_device_by_id(fa_id);
668   const size_t sector_size = dev->mtdgeo.erasesize;
669   const struct flash_area *fa = fa = dev->fa_cfg;
670 
671   for (off = 0; off < fa->fa_size; off += sector_size)
672     {
673       /* Note: Offset here is relative to flash area, not device */
674 
675       sectors[total_count].fs_off = off;
676       sectors[total_count].fs_size = sector_size;
677       total_count++;
678     }
679 
680   *count = total_count;
681 
682   DEBUGASSERT(total_count == dev->mtdgeo.neraseblocks);
683 
684   BOOT_LOG_INF("ID:%d count:%" PRIu32, fa_id, *count);
685 
686   return OK;
687 }
688 
689 /****************************************************************************
690  * Name: flash_area_id_from_multi_image_slot
691  *
692  * Description:
693  *   Return the flash area ID for a given slot and a given image index
694  *   (in case of a multi-image setup).
695  *
696  * Input Parameters:
697  *   image_index - Index of the image.
698  *   slot        - Image slot, which may be 0 (primary) or 1 (secondary).
699  *
700  * Returned Value:
701  *   Flash area ID (0 or 1), or negative value in case the requested slot
702  *   is invalid.
703  *
704  ****************************************************************************/
705 
flash_area_id_from_multi_image_slot(int image_index,int slot)706 int flash_area_id_from_multi_image_slot(int image_index, int slot)
707 {
708   BOOT_LOG_INF("image_index:%d slot:%d", image_index, slot);
709 
710   switch (slot)
711     {
712       case 0:
713         return FLASH_AREA_IMAGE_PRIMARY(image_index);
714       case 1:
715         return FLASH_AREA_IMAGE_SECONDARY(image_index);
716     }
717 
718   BOOT_LOG_ERR("Unexpected Request: image_index:%d, slot:%d",
719                image_index, slot);
720 
721   return ERROR; /* flash_area_open will fail on that */
722 }
723 
724 /****************************************************************************
725  * Name: flash_area_id_from_image_slot
726  *
727  * Description:
728  *   Return the flash area ID for a given slot.
729  *
730  * Input Parameters:
731  *   slot - Image slot, which may be 0 (primary) or 1 (secondary).
732  *
733  * Returned Value:
734  *   Flash area ID (0 or 1), or negative value in case the requested slot
735  *   is invalid.
736  *
737  ****************************************************************************/
738 
flash_area_id_from_image_slot(int slot)739 int flash_area_id_from_image_slot(int slot)
740 {
741   BOOT_LOG_INF("slot:%d", slot);
742 
743   return flash_area_id_from_multi_image_slot(0, slot);
744 }
745 
746 /****************************************************************************
747  * Name: flash_area_id_to_multi_image_slot
748  *
749  * Description:
750  *   Convert the specified flash area ID and image index (in case of a
751  *   multi-image setup) to an image slot index.
752  *
753  * Input Parameters:
754  *   image_index - Index of the image.
755  *   area_id     - Unique identifier that is represented by fa_id in the
756  *                 flash_area struct.
757  * Returned Value:
758  *   Image slot index (0 or 1), or negative value in case ID doesn't
759  *   correspond to an image slot.
760  *
761  ****************************************************************************/
762 
flash_area_id_to_multi_image_slot(int image_index,int area_id)763 int flash_area_id_to_multi_image_slot(int image_index, int area_id)
764 {
765   BOOT_LOG_INF("image_index:%d area_id:%d", image_index, area_id);
766 
767   if (area_id == FLASH_AREA_IMAGE_PRIMARY(image_index))
768     {
769       return 0;
770     }
771 
772   if (area_id == FLASH_AREA_IMAGE_SECONDARY(image_index))
773     {
774       return 1;
775     }
776 
777   BOOT_LOG_ERR("Unexpected Request: image_index:%d, area_id:%d",
778                image_index, area_id);
779 
780   return ERROR; /* flash_area_open will fail on that */
781 }
782 
783 /****************************************************************************
784  * Name: flash_area_id_from_image_offset
785  *
786  * Description:
787  *   Return the flash area ID for a given image offset.
788  *
789  * Input Parameters:
790  *   offset - Image offset.
791  *
792  * Returned Value:
793  *   Flash area ID (0 or 1), or negative value in case the requested offset
794  *   is invalid.
795  *
796  ****************************************************************************/
797 
flash_area_id_from_image_offset(uint32_t offset)798 int flash_area_id_from_image_offset(uint32_t offset)
799 {
800   struct flash_device_s *dev = lookup_flash_device_by_offset(offset);
801 
802   BOOT_LOG_INF("offset:%" PRIu32, offset);
803 
804   if (dev != NULL)
805     {
806       return dev->fa_cfg->fa_id;
807     }
808 
809   BOOT_LOG_ERR("Unexpected Request: offset:%" PRIu32, offset);
810 
811   return ERROR; /* flash_area_open will fail on that */
812 }
813 
814 /****************************************************************************
815  * Name: flash_area_get_sector
816  *
817  * Description:
818  *   Retrieve the flash sector a given offset belongs to.
819  *
820  * Input Parameters:
821  *   fap - flash area structure
822  *   off - address offset.
823  *   sector - flash sector
824  *
825  * Returned Value:
826  *   Returns 0 on success, or an error code on failure.
827  *
828  ****************************************************************************/
829 
flash_area_get_sector(const struct flash_area * fap,off_t off,struct flash_sector * fs)830 int flash_area_get_sector(const struct flash_area *fap, off_t off,
831                           struct flash_sector *fs)
832 {
833   off_t offset = fap->fa_off + off;
834   struct flash_device_s *dev = lookup_flash_device_by_offset(offset);
835   if (dev == NULL)
836     {
837       return -errno;
838     }
839 
840   fs->fs_off = (offset / dev->mtdgeo.erasesize) * dev->mtdgeo.erasesize;
841   fs->fs_size = dev->mtdgeo.erasesize;
842 
843   return 0;
844 }
845