blob: ffb04ee3706eb1069202a22bfd0aa5b4136291ba [file] [log] [blame]
David Vinczecea8b592019-10-29 16:09:51 +01001/*
Sherry Zhang6e0f3242021-03-08 12:18:31 +08002 * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
David Vinczecea8b592019-10-29 16:09:51 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <stdbool.h>
9#include "target.h"
David Vinczecea8b592019-10-29 16:09:51 +010010#include "flash_map/flash_map.h"
David Vincze225c58f2019-12-09 17:32:48 +010011#include "flash_map_backend/flash_map_backend.h"
Sherry Zhang6e0f3242021-03-08 12:18:31 +080012#include "bootutil_priv.h"
David Vinczecea8b592019-10-29 16:09:51 +010013#include "bootutil/bootutil_log.h"
14#include "Driver_Flash.h"
15
Michel Jaouen26f6c022020-12-03 10:37:22 +010016/* When undefined FLASH_DEV_NAME_0 or FLASH_DEVICE_ID_0 , default */
17#if !defined(FLASH_DEV_NAME_0) || !defined(FLASH_DEVICE_ID_0)
18#define FLASH_DEV_NAME_0 FLASH_DEV_NAME
19#define FLASH_DEVICE_ID_0 FLASH_DEVICE_ID
20#endif
21
22/* When undefined FLASH_DEV_NAME_1 or FLASH_DEVICE_ID_1 , default */
23#if !defined(FLASH_DEV_NAME_1) || !defined(FLASH_DEVICE_ID_1)
24#define FLASH_DEV_NAME_1 FLASH_DEV_NAME
25#define FLASH_DEVICE_ID_1 FLASH_DEVICE_ID
26#endif
27
28/* When undefined FLASH_DEV_NAME_2 or FLASH_DEVICE_ID_2 , default */
29#if !defined(FLASH_DEV_NAME_2) || !defined(FLASH_DEVICE_ID_2)
30#define FLASH_DEV_NAME_2 FLASH_DEV_NAME
31#define FLASH_DEVICE_ID_2 FLASH_DEVICE_ID
32#endif
33
34/* When undefined FLASH_DEV_NAME_3 or FLASH_DEVICE_ID_3 , default */
35#if !defined(FLASH_DEV_NAME_3) || !defined(FLASH_DEVICE_ID_3)
36#define FLASH_DEV_NAME_3 FLASH_DEV_NAME
37#define FLASH_DEVICE_ID_3 FLASH_DEVICE_ID
38#endif
39
40/* When undefined FLASH_DEV_NAME_SCRATCH or FLASH_DEVICE_ID_SCRATCH , default */
41#if !defined(FLASH_DEV_NAME_SCRATCH) || !defined(FLASH_DEVICE_ID_SCRATCH)
42#define FLASH_DEV_NAME_SCRATCH FLASH_DEV_NAME
43#define FLASH_DEVICE_ID_SCRATCH FLASH_DEVICE_ID
44#endif
David Vinczecea8b592019-10-29 16:09:51 +010045
Balint Matyi69e2d2e2020-07-08 10:53:54 +010046#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]))
47
Michel Jaouen26f6c022020-12-03 10:37:22 +010048/* Flash device names must be specified by target */
49extern ARM_DRIVER_FLASH FLASH_DEV_NAME_0;
50extern ARM_DRIVER_FLASH FLASH_DEV_NAME_1;
51extern ARM_DRIVER_FLASH FLASH_DEV_NAME_2;
52extern ARM_DRIVER_FLASH FLASH_DEV_NAME_3;
53extern ARM_DRIVER_FLASH FLASH_DEV_NAME_SCRATCH;
54
David Vinczecea8b592019-10-29 16:09:51 +010055static const struct flash_area flash_map[] = {
56 {
57 .fa_id = FLASH_AREA_0_ID,
Michel Jaouen26f6c022020-12-03 10:37:22 +010058 .fa_device_id = FLASH_DEVICE_ID_0,
59 .fa_driver = &FLASH_DEV_NAME_0,
David Vinczecea8b592019-10-29 16:09:51 +010060 .fa_off = FLASH_AREA_0_OFFSET,
61 .fa_size = FLASH_AREA_0_SIZE,
62 },
63 {
64 .fa_id = FLASH_AREA_2_ID,
Michel Jaouen26f6c022020-12-03 10:37:22 +010065 .fa_device_id = FLASH_DEVICE_ID_2,
66 .fa_driver = &FLASH_DEV_NAME_2,
David Vinczecea8b592019-10-29 16:09:51 +010067 .fa_off = FLASH_AREA_2_OFFSET,
68 .fa_size = FLASH_AREA_2_SIZE,
69 },
70#if (MCUBOOT_IMAGE_NUMBER == 2)
71 {
72 .fa_id = FLASH_AREA_1_ID,
Michel Jaouen26f6c022020-12-03 10:37:22 +010073 .fa_device_id = FLASH_DEVICE_ID_1,
74 .fa_driver = &FLASH_DEV_NAME_1,
David Vinczecea8b592019-10-29 16:09:51 +010075 .fa_off = FLASH_AREA_1_OFFSET,
76 .fa_size = FLASH_AREA_1_SIZE,
77 },
78 {
79 .fa_id = FLASH_AREA_3_ID,
Michel Jaouen26f6c022020-12-03 10:37:22 +010080 .fa_device_id = FLASH_DEVICE_ID_3,
81 .fa_driver = &FLASH_DEV_NAME_3,
David Vinczecea8b592019-10-29 16:09:51 +010082 .fa_off = FLASH_AREA_3_OFFSET,
83 .fa_size = FLASH_AREA_3_SIZE,
84 },
85#endif
86 {
87 .fa_id = FLASH_AREA_SCRATCH_ID,
Michel Jaouen26f6c022020-12-03 10:37:22 +010088 .fa_device_id = FLASH_DEVICE_ID_SCRATCH,
89 .fa_driver = &FLASH_DEV_NAME_SCRATCH,
David Vinczecea8b592019-10-29 16:09:51 +010090 .fa_off = FLASH_AREA_SCRATCH_OFFSET,
91 .fa_size = FLASH_AREA_SCRATCH_SIZE,
92 },
93};
94
95static const int flash_map_entry_num = ARRAY_SIZE(flash_map);
96
97/*
Sherry Zhang6e0f3242021-03-08 12:18:31 +080098 * Check the target address in the flash_area_xxx operation.
99 */
100static bool is_range_valid(const struct flash_area *area,
101 uint32_t off,
102 uint32_t len)
103{
104 uint32_t size;
105
106 if (!area) {
107 return false;
108 }
109
110 if (!boot_u32_safe_add(&size, off, len)) {
111 return false;
112 }
113
114 if (area->fa_size < size) {
115 return false;
116 }
117
118 return true;
119}
120
121/*
David Vinczecea8b592019-10-29 16:09:51 +0100122 * `open` a flash area. The `area` in this case is not the individual
123 * sectors, but describes the particular flash area in question.
124 */
125int flash_area_open(uint8_t id, const struct flash_area **area)
126{
127 int i;
128
129 BOOT_LOG_DBG("area %d", id);
130
131 for (i = 0; i < flash_map_entry_num; i++) {
132 if (id == flash_map[i].fa_id) {
133 break;
134 }
135 }
136 if (i == flash_map_entry_num) {
137 return -1;
138 }
139
140 *area = &flash_map[i];
141 return 0;
142}
143
144void flash_area_close(const struct flash_area *area)
145{
146 /* Nothing to do. */
147}
148
149int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
150 uint32_t len)
151{
152 BOOT_LOG_DBG("read area=%d, off=%#x, len=%#x", area->fa_id, off, len);
Sherry Zhang6e0f3242021-03-08 12:18:31 +0800153
154 if (!is_range_valid(area, off, len)) {
155 return -1;
156 }
157
Michel Jaouen26f6c022020-12-03 10:37:22 +0100158 return DRV_FLASH_AREA(area)->ReadData(area->fa_off + off, dst, len);
David Vinczecea8b592019-10-29 16:09:51 +0100159}
160
161int flash_area_write(const struct flash_area *area, uint32_t off,
162 const void *src, uint32_t len)
163{
164 BOOT_LOG_DBG("write area=%d, off=%#x, len=%#x", area->fa_id, off, len);
Sherry Zhang6e0f3242021-03-08 12:18:31 +0800165
166 if (!is_range_valid(area, off, len)) {
167 return -1;
168 }
169
Michel Jaouen26f6c022020-12-03 10:37:22 +0100170 return DRV_FLASH_AREA(area)->ProgramData(area->fa_off + off, src, len);
David Vinczecea8b592019-10-29 16:09:51 +0100171}
172
173int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
174{
175 ARM_FLASH_INFO *flash_info;
176 uint32_t deleted_len = 0;
177 int32_t rc = 0;
178
179 BOOT_LOG_DBG("erase area=%d, off=%#x, len=%#x", area->fa_id, off, len);
Sherry Zhang6e0f3242021-03-08 12:18:31 +0800180
181 if (!is_range_valid(area, off, len)) {
182 return -1;
183 }
184
Michel Jaouen26f6c022020-12-03 10:37:22 +0100185 flash_info = DRV_FLASH_AREA(area)->GetInfo();
David Vinczecea8b592019-10-29 16:09:51 +0100186
187 if (flash_info->sector_info == NULL) {
188 /* Uniform sector layout */
189 while (deleted_len < len) {
Michel Jaouen26f6c022020-12-03 10:37:22 +0100190 rc = DRV_FLASH_AREA(area)->EraseSector(area->fa_off + off);
David Vinczecea8b592019-10-29 16:09:51 +0100191 if (rc != 0) {
192 break;
193 }
194 deleted_len += flash_info->sector_size;
195 off += flash_info->sector_size;
196 }
197 } else {
198 /* Inhomogeneous sector layout, explicitly defined
199 * Currently not supported.
200 */
201 }
202
203 return rc;
204}
205
206uint32_t flash_area_align(const struct flash_area *area)
207{
208 ARM_FLASH_INFO *flash_info;
209
Michel Jaouen26f6c022020-12-03 10:37:22 +0100210 flash_info = DRV_FLASH_AREA(area)->GetInfo();
David Vinczecea8b592019-10-29 16:09:51 +0100211 return flash_info->program_unit;
212}