1 /*
2  * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <stdbool.h>
9 #include "target.h"
10 #include "flash_map/flash_map.h"
11 #include "flash_map_backend/flash_map_backend.h"
12 #include "bootutil_priv.h"
13 #include "bootutil/bootutil_log.h"
14 #include "bootutil/fault_injection_hardening.h"
15 #include "Driver_Flash.h"
16 #ifdef PLATFORM_HAS_BOOT_DMA
17 #include "boot_dma.h"
18 #endif /* PLATFORM_HAS_BOOT_DMA */
19 
20 #define FLASH_PROGRAM_UNIT    TFM_HAL_FLASH_PROGRAM_UNIT
21 
22 /**
23  * Return the greatest value not greater than `value` that is aligned to
24  * `alignment`.
25  */
26 #define FLOOR_ALIGN(value, alignment) ((value) & ~((alignment) - 1))
27 
28 /**
29  * Return the least value not less than `value` that is aligned to `alignment`.
30  */
31 #define CEILING_ALIGN(value, alignment) \
32                          (((value) + ((alignment) - 1)) & ~((alignment) - 1))
33 
34 extern const struct flash_area flash_map[];
35 extern const int flash_map_entry_num;
36 
37 extern const ARM_DRIVER_FLASH  *flash_driver[];
38 extern const int flash_driver_entry_num;
39 
40 /* Valid entries for data item width */
41 static const uint32_t data_width_byte[] = {
42     sizeof(uint8_t),
43     sizeof(uint16_t),
44     sizeof(uint32_t),
45 };
46 
47 /*
48  * Check the target address in the flash_area_xxx operation.
49  */
is_range_valid(const struct flash_area * area,uint32_t off,uint32_t len)50 static bool is_range_valid(const struct flash_area *area,
51                            uint32_t off,
52                            uint32_t len)
53 {
54     uint32_t size;
55 
56     if (!area) {
57         return false;
58     }
59 
60     if (!boot_u32_safe_add(&size, off, len)) {
61         return false;
62     }
63 
64     if (area->fa_size < size) {
65         return false;
66     }
67 
68     return true;
69 }
flash_area_driver_init(void)70 int flash_area_driver_init(void)
71 {
72     int i;
73 
74     for (i = 0; i < flash_driver_entry_num; i++) {
75         if (flash_driver[i]->Initialize(NULL) != ARM_DRIVER_OK)
76             return -1;
77     }
78 
79     return 0;
80 }
81 /*
82  * `open` a flash area.  The `area` in this case is not the individual
83  * sectors, but describes the particular flash area in question.
84  */
flash_area_open(uint8_t id,const struct flash_area ** area)85 int flash_area_open(uint8_t id, const struct flash_area **area)
86 {
87     int i;
88 
89     BOOT_LOG_DBG("area %d", id);
90 
91     for (i = 0; i < flash_map_entry_num; i++) {
92         if (id == flash_map[i].fa_id) {
93             break;
94         }
95     }
96     if (i == flash_map_entry_num) {
97         return -1;
98     }
99 
100     *area = &flash_map[i];
101     return 0;
102 }
103 
flash_area_close(const struct flash_area * area)104 void flash_area_close(const struct flash_area *area)
105 {
106     /* Nothing to do. */
107 }
108 
109 /*
110  * Read/write/erase. Offset is relative from beginning of flash area.
111  * `off` and `len` can be any alignment.
112  * Return 0 on success, other value on failure.
113  */
flash_area_read(const struct flash_area * area,uint32_t off,void * dst,uint32_t len)114 int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
115                     uint32_t len)
116 {
117     volatile uint32_t remaining_len;
118     uint32_t read_length;
119     uint32_t aligned_off;
120     uint32_t item_number;
121 #ifdef PLATFORM_HAS_BOOT_DMA
122     uint32_t dma_src_addr;
123 #endif /* PLATFORM_HAS_BOOT_DMA */
124 
125     /* The maximum value of data_width is 4 bytes. */
126     uint8_t temp_buffer[sizeof(uint32_t)];
127     uint8_t data_width, i = 0, j;
128     int ret = 0;
129 
130     ARM_FLASH_CAPABILITIES DriverCapabilities;
131 
132     BOOT_LOG_DBG("read area=%d, off=%#x, len=%#x", area->fa_id, off, len);
133 
134     if (!is_range_valid(area, off, len)) {
135         return -1;
136     }
137 
138     remaining_len = len;
139 
140     /* CMSIS ARM_FLASH_ReadData API requires the `addr` data type size aligned.
141      * Data type size is specified by the data_width in ARM_FLASH_CAPABILITIES.
142      */
143     DriverCapabilities = DRV_FLASH_AREA(area)->GetCapabilities();
144     data_width = data_width_byte[DriverCapabilities.data_width];
145     aligned_off = FLOOR_ALIGN(off, data_width);
146 
147 #ifdef PLATFORM_HAS_BOOT_DMA
148     if (len >= BOOT_DMA_MIN_SIZE_REQ) {
149         dma_src_addr = FLASH_BASE_ADDRESS + area->fa_off + off;
150         BOOT_LOG_DBG("dma memcpy call:src_addr=%#x, dest_addr=%#x, len=%#x",
151                       dma_src_addr, dst, len);
152 
153         ret = boot_dma_memcpy(dma_src_addr, (uint32_t)dst, len, 0);
154         if (ret == 0) {
155             /* DMA transfer copy success */
156             return 0;
157         }
158     }
159 #endif /* PLATFORM_HAS_BOOT_DMA */
160 
161     /* Either DMA is not supported or DMA transfer copy failure or
162      * memory transaction size is less than required.
163      * Continue to use default flash driver.
164      */
165 
166     /* Read the first data_width long data if `off` is not aligned. */
167     if (aligned_off != off) {
168         ret = DRV_FLASH_AREA(area)->ReadData(area->fa_off + aligned_off,
169                                              temp_buffer,
170                                              1);
171         if (ret < 0) {
172             return ret;
173         }
174 
175         /* Record how many target data have been read. */
176         read_length = ((off - aligned_off + len) >= data_width) ?
177                                         (data_width - (off - aligned_off)) : len;
178 
179         /* Copy the read data from off. */
180         for (i = 0; i < read_length; i++) {
181             ((uint8_t *)dst)[i] = temp_buffer[i + off - aligned_off];
182         }
183         remaining_len -= read_length;
184     }
185 
186     if (remaining_len == 0) {
187         return 0;
188     }
189 
190     /* The `cnt` parameter in CMSIS ARM_FLASH_ReadData indicates number of data
191      * items to read. The size of a data item is equal to the data_width value.
192      *
193      * When using the FIH library with at least the medium profile the below
194      * division operation is repeated and the results are checked for consistency
195      * (remaining_len is declared volatile to avoid compiler optimization).
196      * This helps to prevent a FI assisted overflow of the 'dst' buffer.
197      */
198     FIH_SET(item_number, (remaining_len / data_width));
199 
200     if (item_number) {
201         /* There is at least one data item (of size data_width) to read. */
202         ret = DRV_FLASH_AREA(area)->ReadData(area->fa_off + off + i,
203                                             (uint8_t *)dst + i,
204                                             item_number);
205         if (ret < 0) {
206             return ret;
207         }
208         remaining_len -= item_number * data_width;
209 
210         if (remaining_len == 0) {
211             return 0;
212         }
213     }
214 
215     /* The number of remaining bytes is less than data_width (of the driver) */
216     ret = DRV_FLASH_AREA(area)->ReadData(
217                         area->fa_off + off + i + (item_number * data_width),
218                         temp_buffer,
219                         1);
220 
221     /* CMSIS ARM_FLASH_ReadData can return the number of data items read or
222      * Status Error Codes which are negative for failures.
223      */
224     if (ret < 0) {
225         return ret;
226     }
227 
228     for (j = 0; j < remaining_len; j++) {
229         ((uint8_t *)dst)[i + (item_number * data_width) + j] = temp_buffer[j];
230     }
231 
232     return 0;
233 }
234 
235 /* Writes `len` bytes of flash memory at `off` from the buffer at `src`.
236  * `off` and `len` can be any alignment.
237  */
flash_area_write(const struct flash_area * area,uint32_t off,const void * src,uint32_t len)238 int flash_area_write(const struct flash_area *area, uint32_t off,
239                      const void *src, uint32_t len)
240 {
241     uint8_t add_padding[FLASH_PROGRAM_UNIT];
242 #if (FLASH_PROGRAM_UNIT == 1)
243     uint8_t len_padding[FLASH_PROGRAM_UNIT]; /* zero sized arrayas are illegal C */
244 #else
245     uint8_t len_padding[FLASH_PROGRAM_UNIT - 1];
246 #endif
247     ARM_FLASH_CAPABILITIES DriverCapabilities;
248     uint8_t data_width;
249     /* The PROGRAM_UNIT aligned value of `off` */
250     uint32_t aligned_off;
251 
252     /* The total write length. */
253     uint32_t aligned_len;
254     uint32_t i, k;
255 
256     /* The index in src[] that has been programmed. */
257     uint32_t src_written_idx = 0;
258     uint32_t add_padding_size, len_padding_size;
259     uint32_t write_size;
260     uint32_t last_unit_start_off;
261     /*
262      *    aligned_off           off           last_unit_start_off
263      *        |                  |                     |
264      *        | add_padding_size |                     |   | len_padding_size  |
265      *        |+++++++++++++++++++**|******************|***@@@@@@@@@@@@@@@@@@@@|
266      *        |                     |                  |                       |
267      * ---->--|---- PROGRAM UNIT ---|-- PROGRAM UNIT --|---- PROGRAM UNIT -----|
268      *        |                     |                  |                       |
269      *        |+++++++++++++++++++**|******************|***@@@@@@@@@@@@@@@@@@@@|
270      *                            |<-------- len --------->|
271      */
272 
273     BOOT_LOG_DBG("write area=%d, off=%#x, len=%#x", area->fa_id, off, len);
274 
275     /* Align the target address. The area->fa_off should already be aligned. */
276     aligned_off = FLOOR_ALIGN(off, FLASH_PROGRAM_UNIT);
277     add_padding_size = off - aligned_off;
278     if (!is_range_valid(area, off, len)) {
279         return -1;
280     }
281 
282     DriverCapabilities = DRV_FLASH_AREA(area)->GetCapabilities();
283     data_width = data_width_byte[DriverCapabilities.data_width];
284 
285     if (FLASH_PROGRAM_UNIT) {
286         /* Read the bytes from aligned_off to off. */
287         if (flash_area_read(area, aligned_off, add_padding, add_padding_size)) {
288             return -1;
289         }
290     }
291 
292     /* Align the write size */
293     aligned_len = CEILING_ALIGN(len + add_padding_size, FLASH_PROGRAM_UNIT);
294     len_padding_size = aligned_len - len - add_padding_size;
295     if (!is_range_valid(area, aligned_off, aligned_len)) {
296         return -1;
297     }
298 
299     /* Read the bytes from (off + len) to (off + aligned_len). */
300     if (flash_area_read(area, off + len, len_padding,
301                         len_padding_size)) {
302         return -1;
303     }
304 
305     /* Program the first FLASH_PROGRAM_UNIT. */
306     if (add_padding_size) {
307         /* Fill the first program unit bytes with data from src. */
308         for (i = add_padding_size, src_written_idx = 0;
309              (i < FLASH_PROGRAM_UNIT) && (src_written_idx < len);
310              i++, src_written_idx++) {
311             add_padding[i] = ((uint8_t *)src)[src_written_idx];
312         }
313         if (src_written_idx == len) {
314             /* aligned_len equals to FLASH_PROGRAM_UNIT in this case.
315              * Fill the len_padding_size datas into add_padding.
316              */
317             for (k = 0; (i < FLASH_PROGRAM_UNIT) && (k < len_padding_size);
318                  i++, k++) {
319                 add_padding[i] = len_padding[k];
320             }
321             if (k != len_padding_size) {
322                 return -1;
323             }
324         }
325 
326         /* Check the first program unit bytes are all filled. */
327         if (i != FLASH_PROGRAM_UNIT) {
328             return -1;
329         }
330         if (DRV_FLASH_AREA(area)->ProgramData(area->fa_off + aligned_off,
331                                         add_padding,
332                                         FLASH_PROGRAM_UNIT / data_width) < 0) {
333             return -1;
334         }
335     }
336 
337     /* 'src_written_idx' indicates the number of the src data which has already
338      * been programed into flash. 'src_written_idx' equals to 'len' means that
339      * all the data in src has been programmed and aligned_len equals to
340      * FLASH_PROGRAM_UNIT. This case has been handled above.
341      * 'src_written_idx' less than 'len' means that not all the data in src has
342      * been programmed.
343      */
344     if (src_written_idx < len) {
345         /* Program from the first aligned bytes(src_written_idx) to the last
346          * aligned bytes in src.
347          */
348         write_size = FLOOR_ALIGN(len - src_written_idx, FLASH_PROGRAM_UNIT);
349         if (write_size > 0) {
350             if (DRV_FLASH_AREA(area)->ProgramData(
351                                            area->fa_off + off + src_written_idx,
352                                            src,
353                                            write_size / data_width) < 0) {
354                 return -1;
355             }
356             src_written_idx += write_size;
357         }
358         last_unit_start_off = src_written_idx;
359 
360         /* Program the last program unit data into flash. */
361         if (len_padding_size) {
362             /* Copy the last unaligned bytes in src to add_padding. */
363             for (i = 0; (i < FLASH_PROGRAM_UNIT) && (src_written_idx < len);
364                  i++, src_written_idx++) {
365                 add_padding[i] = ((uint8_t *)src)[src_written_idx];
366             }
367 
368             if (src_written_idx != len) {
369                 return -1;
370             }
371             /* Copy the len_padding_size bytes in len_padding to add_padding. */
372             for (k = 0; (i < FLASH_PROGRAM_UNIT) && (k < len_padding_size);
373                  i++, k++) {
374                 add_padding[i] = len_padding[k];
375             }
376             write_size = add_padding_size + last_unit_start_off +
377                          FLASH_PROGRAM_UNIT;
378             if ((i != FLASH_PROGRAM_UNIT) || (k != len_padding_size) ||
379                 (aligned_len != write_size)) {
380                 return -1;
381             }
382             if (DRV_FLASH_AREA(area)->ProgramData(
383                                 area->fa_off + off + last_unit_start_off,
384                                 add_padding,
385                                 FLASH_PROGRAM_UNIT / data_width) < 0) {
386                 return -1;
387             }
388         }
389     }
390 
391     return 0;
392 }
393 
flash_area_erase(const struct flash_area * area,uint32_t off,uint32_t len)394 int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
395 {
396     ARM_FLASH_INFO *flash_info;
397     uint32_t deleted_len = 0;
398     int32_t rc = 0;
399 
400     BOOT_LOG_DBG("erase area=%d, off=%#x, len=%#x", area->fa_id, off, len);
401 
402     if (!is_range_valid(area, off, len)) {
403         return -1;
404     }
405 
406     flash_info = DRV_FLASH_AREA(area)->GetInfo();
407 
408     if (flash_info->sector_info == NULL) {
409         /* Uniform sector layout */
410         while (deleted_len < len) {
411             rc = DRV_FLASH_AREA(area)->EraseSector(area->fa_off + off);
412             if (rc != 0) {
413                 break;
414             }
415             deleted_len += flash_info->sector_size;
416             off         += flash_info->sector_size;
417         }
418     } else {
419         /* Inhomogeneous sector layout, explicitly defined
420          * Currently not supported.
421          */
422     }
423 
424     return rc;
425 }
426 
flash_area_align(const struct flash_area * area)427 uint32_t flash_area_align(const struct flash_area *area)
428 {
429     ARM_FLASH_INFO *flash_info;
430 
431     flash_info = DRV_FLASH_AREA(area)->GetInfo();
432     return flash_info->program_unit;
433 }
434