1 /**************************************************************************//**
2 *
3 * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date            Author       Notes
9 * 2020-12-12      Wayne        First version
10 *
11 ******************************************************************************/
12 
13 #include "rtconfig.h"
14 
15 #include <rtthread.h>
16 
17 #define LOG_TAG         "mnt"
18 #define DBG_ENABLE
19 #define DBG_SECTION_NAME "mnt"
20 #define DBG_LEVEL DBG_ERROR
21 #define DBG_COLOR
22 #include <rtdbg.h>
23 
24 #include <dfs_fs.h>
25 #include <dfs_file.h>
26 #include <unistd.h>
27 #include <stdio.h>
28 #include <sys/stat.h>
29 #include <sys/statfs.h>
30 
31 #if defined(RT_USING_FAL)
32     #include <fal.h>
33 #endif
34 
35 #if defined(PKG_USING_RAMDISK)
36     #define RAMDISK_NAME         "ramdisk0"
37     #define RAMDISK_UDC          "ramdisk1"
38     #define MOUNT_POINT_RAMDISK0 "/"
39 #endif
40 
41 #if defined(BOARD_USING_STORAGE_SPIFLASH)
42     #define PARTITION_NAME_FILESYSTEM "filesystem"
43     #define MOUNT_POINT_SPIFLASH0 "/mnt/"PARTITION_NAME_FILESYSTEM
44 #endif
45 
46 #ifdef RT_USING_DFS_MNTTABLE
47 
48 /*
49 const char   *device_name;
50 const char   *path;
51 const char   *filesystemtype;
52 unsigned long rwflag;
53 const void   *data;
54 */
55 
56 const struct dfs_mount_tbl mount_table[] =
57 {
58 #if defined(PKG_USING_RAMDISK)
59     { RAMDISK_UDC, "/mnt/ram_usbd", "elm", 0, RT_NULL },
60 #endif
61 #if defined(PKG_USING_DFS_YAFFS)
62     { "nand1", "/mnt/filesystem", "yaffs", 0, RT_NULL },
63 #elif defined(RT_USING_DFS_UFFS)
64     { "nand1", "/mnt/filesystem", "uffs", 0, RT_NULL },
65 #endif
66     {0},
67 };
68 #endif
69 
70 
71 #if defined(PKG_USING_RAMDISK)
72 
73 extern rt_err_t ramdisk_init(const char *dev_name, rt_uint8_t *disk_addr, rt_size_t block_size, rt_size_t num_block);
ramdisk_device_init(void)74 int ramdisk_device_init(void)
75 {
76     rt_err_t result = RT_EOK;
77 
78     /* Create a 8MB RAMDISK */
79     result = ramdisk_init(RAMDISK_NAME, NULL, 512, 2 * 8192);
80     RT_ASSERT(result == RT_EOK);
81 
82     /* Create a 4MB RAMDISK */
83     result = ramdisk_init(RAMDISK_UDC, NULL, 512, 2 * 4096);
84     RT_ASSERT(result == RT_EOK);
85 
86     return 0;
87 }
88 INIT_DEVICE_EXPORT(ramdisk_device_init);
89 
90 /* Recursive mkdir */
mkdir_p(const char * dir,const mode_t mode)91 static int mkdir_p(const char *dir, const mode_t mode)
92 {
93     int ret = -1;
94     char *tmp = NULL;
95     char *p = NULL;
96     struct stat sb;
97     rt_size_t len;
98 
99     if (!dir)
100         goto exit_mkdir_p;
101 
102     /* Copy path */
103     /* Get the string length */
104     len = strlen(dir);
105     tmp = rt_strdup(dir);
106 
107     /* Remove trailing slash */
108     if (tmp[len - 1] == '/')
109     {
110         tmp[len - 1] = '\0';
111         len--;
112     }
113 
114     /* check if path exists and is a directory */
115     if (stat(tmp, &sb) == 0)
116     {
117         if (S_ISDIR(sb.st_mode))
118         {
119             ret = 0;
120             goto exit_mkdir_p;
121         }
122     }
123 
124     /* Recursive mkdir */
125     for (p = tmp + 1; p - tmp <= len; p++)
126     {
127         if ((*p == '/') || (p - tmp == len))
128         {
129             *p = 0;
130 
131             /* Test path */
132             if (stat(tmp, &sb) != 0)
133             {
134                 /* Path does not exist - create directory */
135                 if (mkdir(tmp, mode) < 0)
136                 {
137                     goto exit_mkdir_p;
138                 }
139             }
140             else if (!S_ISDIR(sb.st_mode))
141             {
142                 /* Not a directory */
143                 goto exit_mkdir_p;
144             }
145             if (p - tmp != len)
146                 *p = '/';
147         }
148     }
149 
150     ret = 0;
151 
152 exit_mkdir_p:
153 
154     if (tmp)
155         rt_free(tmp);
156 
157     return ret;
158 }
159 
160 /* Initialize the filesystem */
filesystem_init(void)161 int filesystem_init(void)
162 {
163     rt_err_t result = RT_EOK;
164 
165     // ramdisk as root
166     if (!rt_device_find(RAMDISK_NAME))
167     {
168         LOG_E("cannot find %s device", RAMDISK_NAME);
169         goto exit_filesystem_init;
170     }
171     else
172     {
173         /* Format these ramdisk */
174         result = (rt_err_t)dfs_mkfs("elm", RAMDISK_NAME);
175         RT_ASSERT(result == RT_EOK);
176 
177         /* mount ramdisk0 as root directory */
178         if (dfs_mount(RAMDISK_NAME, "/", "elm", 0, RT_NULL) == 0)
179         {
180             LOG_I("ramdisk mounted on \"/\".");
181 
182             /* now you can create dir dynamically. */
183             mkdir_p("/mnt", 0x777);
184             mkdir_p("/cache", 0x777);
185             mkdir_p("/download", 0x777);
186             mkdir_p("/mnt/ram_usbd", 0x777);
187             mkdir_p("/mnt/filesystem", 0x777);
188 #if defined(RT_USBH_MSTORAGE) && defined(UDISK_MOUNTPOINT)
189             mkdir_p(UDISK_MOUNTPOINT, 0x777);
190 #endif
191         }
192         else
193         {
194             LOG_E("root folder creation failed!\n");
195             goto exit_filesystem_init;
196         }
197     }
198 
199     if (!rt_device_find(RAMDISK_UDC))
200     {
201         LOG_E("cannot find %s device", RAMDISK_UDC);
202         goto exit_filesystem_init;
203     }
204     else
205     {
206         /* Format these ramdisk */
207         result = (rt_err_t)dfs_mkfs("elm", RAMDISK_UDC);
208         RT_ASSERT(result == RT_EOK);
209     }
210 
211 exit_filesystem_init:
212 
213     return -result;
214 }
215 INIT_ENV_EXPORT(filesystem_init);
216 #endif
217 
218 #if defined(PKG_USING_DFS_YAFFS) && defined(RT_USING_DFS_MNTTABLE)
219 #include "yaffs_guts.h"
yaffs_dev_init(void)220 int yaffs_dev_init(void)
221 {
222     int i;
223     for (i=0; i<sizeof(mount_table)/sizeof(struct dfs_mount_tbl);i++)
224     {
225         if ( mount_table[i].filesystemtype && !rt_strcmp( mount_table[i].filesystemtype, "yaffs") )
226         {
227              struct rt_mtd_nand_device* psMtdNandDev = RT_MTD_NAND_DEVICE(rt_device_find(mount_table[i].device_name));
228              if ( psMtdNandDev )
229              {
230                   yaffs_start_up(psMtdNandDev, (const char*)mount_table[i].path);
231              }
232         }
233     }
234 
235     return 0;
236 }
237 INIT_ENV_EXPORT(yaffs_dev_init);
238 #endif
239 
240 #if defined(BOARD_USING_STORAGE_SPIFLASH)
mnt_init_spiflash0(void)241 int mnt_init_spiflash0(void)
242 {
243 #if defined(RT_USING_FAL)
244     extern int fal_init_check(void);
245     if (!fal_init_check())
246         fal_init();
247 #endif
248     struct rt_device *psNorFlash = fal_blk_device_create(PARTITION_NAME_FILESYSTEM);
249     if (!psNorFlash)
250     {
251         rt_kprintf("Failed to create block device for %s.\n", PARTITION_NAME_FILESYSTEM);
252         goto exit_mnt_init_spiflash0;
253     }
254     else if (dfs_mount(psNorFlash->parent.name, MOUNT_POINT_SPIFLASH0, "elm", 0, 0) != 0)
255     {
256         rt_kprintf("Failed to mount elm on %s.\n", MOUNT_POINT_SPIFLASH0);
257         rt_kprintf("Try to execute 'mkfs -t elm %s' first, then reboot.\n", PARTITION_NAME_FILESYSTEM);
258         goto exit_mnt_init_spiflash0;
259     }
260     rt_kprintf("mount %s with elmfat type: ok\n", PARTITION_NAME_FILESYSTEM);
261 
262 exit_mnt_init_spiflash0:
263 
264     return 0;
265 }
266 INIT_APP_EXPORT(mnt_init_spiflash0);
267 #endif
268 
269