1 /*
2 * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3 */
4
5 #include <aos/hal/flash.h>
6 #include <vfsdev/flash_dev.h>
7 #include <devicevfs/devicevfs.h>
8
9 #define PLATFORM_FLASH_NUM HAL_PARTITION_MAX
10 // FLASH device node will be named with "/dev/flash<x>", where <x> is flash port id
11 #define FLASH_DEV_NAME_FORMAT "flash%d"
12
hal_flash_init(hal_partition_t in_partition)13 __weak int32_t hal_flash_init(hal_partition_t in_partition) {
14 ddkc_warn("weak %s\r\n", __FUNCTION__);
15 return 0;
16 }
17
18 #ifdef AOS_MCU_OTA_ADAPT
19 // temp usage
20 #define IOCTL_FLASH_BOOT_VALIDATE() \
21 if (in_partition == HAL_PARTITION_LITTLEFS) { \
22 ddkc_warn("fs is not allowed to access boot operations\r\n"); \
23 return -EINVAL; \
24 }
25
26 extern int ota_set_user_bootinfo(void *param);
27 extern int ota_clear_reboot_count(void);
28 extern int ota_get_boot_type();
29 #endif
30 /*
31 offset set by lseek
32 */
flash_device_read(file_t * f,void * buffer,size_t size)33 ssize_t flash_device_read (file_t *f, void *buffer, size_t size) {
34 int ret;
35 ssize_t s = 0;
36 hal_partition_t in_partition = (hal_partition_t)f->node->i_arg;
37 size_t offset = f->offset;
38
39 if (!buffer || !size) {
40 ddkc_warn("invalid flash:%d, offset:%d, buffer:%p or size:%d\r\n", in_partition, offset, buffer, size);
41 return -EINVAL;
42 }
43
44 ddkc_dbg("f->offset:%d, buffer:%p, size:%d\r\n", f->offset, buffer, size);
45 ret = hal_flash_read(in_partition, &f->offset, buffer, size);
46 if(ret < 0){
47 return -1;
48 } else {
49 if ((f->offset - offset) != size) {
50 ddkc_err("hal_flash_write returns success, but offset is not set\r\n");
51 }
52 }
53 s = f->offset - offset;
54 ddkc_dbg("read return %d\r\n", s);
55 return s;
56 }
57
58 /*
59 offset set by lseek
60 */
flash_device_write(file_t * f,const void * buffer,size_t size)61 ssize_t flash_device_write (file_t *f, const void *buffer, size_t size) {
62 int ret = 0;
63 ssize_t s = 0;
64 hal_partition_t in_partition = (hal_partition_t)f->node->i_arg;
65 size_t offset = f->offset;
66
67 if (!buffer || !size) {
68 ddkc_warn("invalid flash:%d, offset:%d, buffer:%p or size:%d\r\n", in_partition, offset, buffer, size);
69 return -EINVAL;
70 }
71
72 ret = hal_flash_write(in_partition, &f->offset, buffer, size);
73 ddkc_dbg("f->offset:%d, ret:%d\r\n", f->offset, ret);
74
75 if(ret < 0){
76 return -1;
77 } else {
78 if ((f->offset - offset) != size) {
79 ddkc_err("hal_flash_write returns success, but offset is not set\r\n");
80 }
81 }
82 s = f->offset - offset;
83 ddkc_dbg("write return %d\r\n", s);
84 return s;
85 }
86
flash_device_lseek(file_t * f,int64_t off,int32_t whence)87 static uint32_t flash_device_lseek(file_t *f, int64_t off, int32_t whence){
88 ddkc_dbg("f->offset:%x, off:%llx, whence:%d\r\n", f->offset, off, whence);
89 switch (whence) {
90 case SEEK_CUR:
91 off = f->offset + off;
92 break;
93 /* case SEEK_END: break; */
94 case SEEK_SET:
95 f->offset = off;
96 break;
97 }
98
99 return off;
100 }
101
102 /*
103 offset set by lseek
104 */
flash_device_ioctl(file_t * f,int cmd,unsigned long arg)105 int flash_device_ioctl (file_t *f, int cmd, unsigned long arg) {
106 int ret = 0;
107 hal_partition_t in_partition = (hal_partition_t)f->node->i_arg;
108 uint32_t offset = f->offset;
109 uint32_t size ;
110 hal_logic_partition_t *partition;
111 hal_logic_partition_t p;
112
113 if(!arg){
114 ddkc_warn("i_name:%s, flash:%d, cmd:%d, arg:0x%lx\r\n", f->node->i_name, in_partition, cmd, arg);
115 }
116
117 switch (cmd) {
118 case IOC_FLASH_ERASE_FLASH:
119 if (!arg)
120 return -EINVAL;
121 size = (uint32_t)arg;
122 ddkc_dbg("IOC_FLASH_ERASE_FLASH i_name:%s, flash:%d, cmd:%d, off_set:0x%x, size:0x%x\r\n", f->node->i_name, in_partition, cmd, offset, size);
123 ret = hal_flash_erase(in_partition,offset, size);
124 if (ret) {
125 ddkc_warn("hal_flash_erase failed, ret:%d\r\n", ret);
126 return -1;
127 }
128 break;
129 case IOC_FLASH_INFO_GET:
130 if (!arg)
131 return -EINVAL;
132 partition = (hal_logic_partition_t *)arg;
133 ddkc_dbg("IOC_FLASH_INFO_GET i_name:%s, flash:%d, cmd:%d\r\n", f->node->i_name, in_partition, cmd);
134 ret = hal_flash_info_get(in_partition, &p);
135 if (ret) {
136 ddkc_warn("hal_flash_info_get failed, ret:%d\r\n", ret);
137 return -1;
138 }
139 p.partition_description = NULL;
140 aos_ipc_copy(partition, &p, sizeof(hal_logic_partition_t));
141 break;
142
143 case IOC_FLASH_ENABLE_SECURE:
144 size = (uint32_t)arg;
145 ddkc_dbg("i_name:%s, flash:%d, cmd:%d, off_set:0x%x, size:0x%x\r\n", f->node->i_name, in_partition, cmd, offset, size);
146 ret = hal_flash_enable_secure(in_partition,offset, size);
147 if (ret) {
148 ddkc_warn("hal_flash_enable_secure failed, ret:%d\r\n", ret);
149 return -1;
150 }
151 break;
152
153 case IOC_FLASH_DISABLE_SECURE:
154 size = (uint32_t)arg;
155 ddkc_dbg("IOC_FLASH_DISABLE_SECURE i_name:%s, flash:%d, cmd:%d, off_set:0x%x, size:0x%x\r\n", f->node->i_name, in_partition, cmd, offset, size);
156 ret = hal_flash_dis_secure(in_partition,offset, size);
157 if (ret) {
158 ddkc_warn("hal_flash_dis_secure failed, ret:%d\r\n", ret);
159 return -1;
160 }
161 break;
162
163 #ifdef AOS_MCU_OTA_ADAPT
164 case IOC_FLASH_SET_BOOT_INFO:
165 IOCTL_FLASH_BOOT_VALIDATE();
166 ret = ota_set_user_bootinfo((void*)arg);
167 break;
168
169 case IOC_FLASH_CLEAR_BOOT_COUNT:
170 IOCTL_FLASH_BOOT_VALIDATE();
171 ret = ota_clear_reboot_count();
172 break;
173
174 case IOC_FLASH_GET_BOOT_TYPE:
175 IOCTL_FLASH_BOOT_VALIDATE();
176 ret = ota_get_boot_type();
177 break;
178 #endif
179 default:
180 break;
181 }
182
183 return ret;
184 }
185
flash_device_open(inode_t * node,file_t * f)186 int flash_device_open (inode_t *node, file_t *f) {
187 ddkc_dbg("open %s done\r\n", node->i_name);
188 return 0;
189 }
190
flash_device_close(file_t * f)191 int flash_device_close (file_t *f) {
192 ddkc_dbg("close %s done\r\n", f->node->i_name);
193 return 0;
194 }
195
196
197 /************************** device ****************************/
198
199
200 subsys_file_ops_t flash_device_fops = {
201 .open = flash_device_open,
202 .close = flash_device_close,
203 .read = flash_device_read,
204 .write = flash_device_write,
205 .ioctl = flash_device_ioctl,
206 .poll = NULL,
207 .lseek = flash_device_lseek,
208 };
209
flash_device_init(struct u_platform_device * pdev)210 int flash_device_init (struct u_platform_device *pdev) {
211 // make sure 0 is returned if init operation success
212 // or aos_dev_reg procedure will break and no device node will be registered
213 int ret = 0;
214 void *user_data = NULL;
215
216 user_data = u_platform_get_user_data(pdev);
217 #if defined(USER_SPACE_DRIVER)
218 ret = hal_flash_init((hal_partition_t)user_data);
219 ddkc_info("%s hal_flash_init ret:%d\r\n", __func__, ret);
220 #else
221 ddkc_info("%s hal_flash_init USER_SPACE_DRIVER not defined\r\n", __func__);
222 #endif
223 return 0;
224 }
225
flash_device_deinit(struct u_platform_device * pdev)226 int flash_device_deinit (struct u_platform_device *pdev) {
227 ddkc_info("%s\r\n", __func__);
228 return 0;
229 }
230
flash_device_pm(struct u_platform_device * pdev,u_pm_ops_t state)231 int flash_device_pm (struct u_platform_device *pdev, u_pm_ops_t state) {
232 ddkc_info("%s\r\n", __func__);
233 return 0;
234 }
235
236 struct subsys_drv flash_device_drv = {
237 .drv_name = "flash",
238 .init = flash_device_init,
239 .deinit = flash_device_deinit,
240 .pm = flash_device_pm,
241 };
242
243 struct subsys_dev *g_flash_device_array[PLATFORM_FLASH_NUM];
244
245 extern const size_t hal_partitions_amount;
246 extern const hal_logic_partition_t hal_partitions[];
247
vfs_flash_drv_init(void)248 int vfs_flash_drv_init (void) {
249 int i = 0;
250 int j = 0;
251 int ret = 0;
252 int node_name_len = 0;
253 struct subsys_dev **ppsdev = NULL;
254
255 ddkc_info("flash vfs driver init starts, hal_partitions_amount:%d\r\n", hal_partitions_amount);
256
257 node_name_len = strlen(FLASH_DEV_NAME_FORMAT) + 1;
258
259 memset(g_flash_device_array, 0, sizeof(g_flash_device_array));
260 ppsdev = g_flash_device_array;
261
262 for (i = 0; i < hal_partitions_amount; i++) {
263 if(0 == hal_partitions[i].partition_length){
264 continue;
265 }
266
267 *ppsdev = malloc(sizeof(struct subsys_dev) + node_name_len);
268
269 if (!(*ppsdev)) {
270 ddkc_info("malloc for subsys_dev failed, \r\n");
271 goto err;
272 }
273
274 memset(*ppsdev, 0, sizeof(struct subsys_dev) + node_name_len);
275
276 (*ppsdev)->node_name = (char *)((*ppsdev) + 1);
277 snprintf((*ppsdev)->node_name, node_name_len, FLASH_DEV_NAME_FORMAT, i);
278
279 (*ppsdev)->permission = 0;
280 // please refer to definitions in enum SUBSYS_BUS_TYPE
281 (*ppsdev)->type = BUS_TYPE_PLATFORM;
282 // user_data will be passed to open operation via node->i_arg
283 (*ppsdev)->user_data = (void *)i;
284
285 ret = aos_dev_reg(*ppsdev, &flash_device_fops, &flash_device_drv);
286 if (ret) {
287 ddkc_err("aos_dev_reg for flash%d failed, ret:%d\r\n", i, ret);
288
289 free(*ppsdev);
290 *ppsdev = NULL;
291
292 goto err;
293 }
294
295 ppsdev++;
296 }
297
298 ddkc_dbg("flash vfs driver init finish, ret:%d\r\n", ret);
299 return 0;
300
301 err:
302 ppsdev = g_flash_device_array;
303
304 for (j = 0; j < i; j++) {
305 if (*ppsdev) {
306 aos_dev_unreg(*ppsdev);
307
308 ddkc_info("free memory for flash%d\r\n", j);
309 free(*ppsdev);
310 *ppsdev = NULL;
311 }
312 ppsdev++;
313 }
314 ddkc_err("flash vfs driver init failed, ret:%d\r\n", ret);
315
316 return ret;
317 }
318
319 VFS_DRIVER_ENTRY(vfs_flash_drv_init)
320
321