1 /*
2  * Copyright (c) 2022 FuZhou Lockzhiner Electronic Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <sys/mount.h>
16 #include <string.h>
17 #include "los_config.h"
18 #include "hdf_log.h"
19 #include "hdf_device_desc.h"
20 #include "device_resource_if.h"
21 #include "osal_mem.h"
22 #include "lfs.h"
23 #include "lfs_adapter.h"
24 
25 #include "lz_hardware.h"
26 
27 #define PRINT_ERR(fmt, args...)     do { \
28     printf("%s, %d, error: "fmt, __func__, __LINE__, ##args); \
29 } while (0)
30 
31 #define PRINT_WARR(fmt, args...)    do { \
32     if (1) printf("%s, %d, warr: "fmt, __func__, __LINE__, ##args); \
33 } while (0)
34 
35 #define PRINT_LOG(fmt, args...)    do { \
36     if (1) printf("%s, %d, log: "fmt, __func__, __LINE__, ##args); \
37 } while (0)
38 
39 /* 分配给用户的Flash空间为4M ~ 8MB */
40 #define FLASH_ADDRESS_USER_START       (0x400000)
41 #define FLASH_ADDRESS_USER_END         (0x800000)
42 
43 struct fs_cfg {
44     char *mount_point;
45     uint32_t block_start;
46     struct lfs_config lfs_cfg;
47 };
48 
49 static struct fs_cfg m_fs_cfg[LOSCFG_LFS_MAX_MOUNT_SIZE] = {0};
50 
51 /* 定义lfs_cfg的相关参数 */
52 #define LFSCFG_READSIZE_MAX             4
53 #define LFSCFG_PROGSIZE_MAX             4
54 #define LFSCFG_CACHESIZE_MAX            256
55 #define LFSCFG_LOCKAHEADSIZE_MAX        64
56 #define LFSCFG_BLOCKCYCLES_MAX          1000
57 
fs_get_partition(void *str, uint32_t *partition)58 static int32_t fs_get_partition(void *str, uint32_t *partition)
59 {
60     int i;
61     char *src = (char *)str;
62 
63     for (i = 0; i < (sizeof(m_fs_cfg) / sizeof(struct fs_cfg)); i++) {
64         if (strcmp(m_fs_cfg[i].mount_point, src) == 0) {
65             *partition = i;
66             return HDF_SUCCESS;
67         }
68     }
69 
70     return HDF_ERR_NOT_SUPPORT;
71 }
72 
fs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *dst, lfs_size_t size)73 static int32_t fs_read(const struct lfs_config *c,
74                        lfs_block_t block,
75                        lfs_off_t off,
76                        void *dst,
77                        lfs_size_t size)
78 {
79     int32_t ret;
80     struct fs_cfg *fs;
81     uint32_t addr;
82     uint32_t partition_offset;
83     unsigned char *str;
84 
85     if (c == NULL) {
86         PRINT_ERR("c is null\n");
87         return LFS_ERR_INVAL;
88     }
89     if ((block * c->block_size + off) >= (c->block_size * c->block_count)) {
90         PRINT_ERR("read_start(%d) >= block_count(%d)\n", (block * c->block_size + off),
91                 (c->block_size * c->block_count));
92         return LFS_ERR_INVAL;
93     }
94     if ((block * c->block_size + off + size) > (c->block_size * c->block_count)) {
95         PRINT_ERR("read_end(%d) > maxsize(%d)\n", (block * c->block_size + off + size),
96                 (c->block_size * c->block_count));
97         return LFS_ERR_INVAL;
98     }
99     if (dst == NULL) {
100         PRINT_ERR("dst is null\n");
101         return LFS_ERR_INVAL;
102     }
103 
104     ret = fs_get_partition(c->context, &partition_offset);
105     if (ret != HDF_SUCCESS) {
106         PRINT_ERR("c->context(%s) is not support\n", c->context);
107         return LFS_ERR_INVAL;
108     }
109 
110     fs = &m_fs_cfg[partition_offset];
111     addr = ((fs->block_start + block) * c->block_size) + off;
112     str = (unsigned char *)dst;
113 
114     ret = (unsigned int)FlashRead(addr, size, str);
115     if (ret != LZ_HARDWARE_SUCCESS) {
116         PRINT_ERR("FlashRead failed(%d)\n", ret);
117         return LFS_ERR_IO;
118     }
119 
120     return LFS_ERR_OK;
121 }
122 
fs_write(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *src, lfs_size_t size)123 static int32_t fs_write(const struct lfs_config *c,
124                         lfs_block_t block,
125                         lfs_off_t off,
126                         const void *src,
127                         lfs_size_t size)
128 {
129     unsigned int res;
130     int32_t ret;
131     struct fs_cfg *fs;
132     uint32_t addr;
133     uint32_t partition_offset;
134     unsigned char *buffer;
135     uint32_t buffer_length;
136     uint32_t block_size;
137     uint32_t block_start, block_offset, block_end;
138     uint32_t flash_block_address;
139     unsigned char *str;
140     uint32_t str_offset;
141     uint32_t write_offset, write_length;
142 
143     if (c == NULL) {
144         PRINT_ERR("c is null\n");
145         return LFS_ERR_INVAL;
146     }
147     if ((c->block_size * block + off) >= (c->block_size * c->block_count)) {
148         PRINT_ERR("write_start(%d) >= maxsize(%d)\n", (c->block_size * block + off),
149                 (c->block_size * c->block_count));
150         return LFS_ERR_INVAL;
151     }
152     if ((c->block_size * block + off + size) > (c->block_size * c->block_count)) {
153         PRINT_ERR("write_end(%d) > maxsize(%d)\n", (c->block_size * block + off + size),
154                 (c->block_size * c->block_count));
155         return LFS_ERR_INVAL;
156     }
157     if (src == NULL) {
158         PRINT_ERR("src is null\n");
159         return LFS_ERR_INVAL;
160     }
161 
162     ret = fs_get_partition(c->context, &partition_offset);
163     if (ret != HDF_SUCCESS) {
164         PRINT_ERR("c->context(%s) is not support\n", c->context);
165         return LFS_ERR_INVAL;
166     }
167 
168     block_size = c->block_size;
169     addr = ((m_fs_cfg[partition_offset].block_start + block) * block_size) + off;
170     block_start = addr / block_size;
171     block_end = (addr + size) / block_size;
172     if (((addr + size) % block_size) != 0) {
173         block_end++;
174     }
175 
176     buffer = (unsigned char *)malloc(sizeof(unsigned char) * block_size);
177     if (buffer == NULL) {
178         PRINT_ERR("malloc failed\n");
179         return LFS_ERR_NOMEM;
180     }
181 
182     str = (unsigned char *)src;
183     str_offset = 0;
184 
185     for (block_offset = block_start; block_offset < block_end; block_offset++) {
186         if (block_offset == block_start) {
187             /* 开头特殊处理 */
188             flash_block_address = block_offset * block_size;
189             write_offset = (addr - flash_block_address);
190             write_length = block_size - write_offset;
191             /* 读取整块数据,擦除整块数据,修改部分数据,最后写入Flash */
192             res = FlashRead(flash_block_address, block_size, buffer);
193             if (res != LZ_HARDWARE_SUCCESS) {
194                 PRINT_ERR("FlashRead(%d, %d, buffer) failed(%u)\n", flash_block_address, block_size, res);
195                 return LFS_ERR_IO;
196             }
197             res = FlashErase(flash_block_address, block_size);
198             if (res != LZ_HARDWARE_SUCCESS) {
199                 PRINT_ERR("FlashErase(%d, %d) failed(%u)\n", flash_block_address, block_size, res);
200                 return LFS_ERR_IO;
201             }
202             memcpy_s(&buffer[write_offset], block_size - write_offset,  &src[str_offset], write_length);
203             res = FlashWrite(flash_block_address, block_size, buffer, 0);
204             if (res != LZ_HARDWARE_SUCCESS) {
205                 PRINT_ERR("FlashWrite(%d, %d, buffer) failed(%u)\n", flash_block_address, block_size, res);
206                 return LFS_ERR_IO;
207             }
208             str_offset += write_length;
209         } else if (block_offset == (block_end - 1)) {
210             /* 结尾特殊处理 */
211             flash_block_address = block_offset * block_size;
212             write_offset = 0;
213             write_length = (addr + size) - flash_block_address;
214             /* 读取整块数据,擦除整块数据,修改部分数据,最后写入Flash */
215             res = FlashRead(flash_block_address, block_size, buffer);
216             if (res != LZ_HARDWARE_SUCCESS) {
217                 PRINT_ERR("FlashRead(%d, %d, buffer) failed(%u)\n", flash_block_address, block_size, res);
218                 return LFS_ERR_IO;
219             }
220             res = FlashErase(flash_block_address, block_size);
221             if (res != LZ_HARDWARE_SUCCESS) {
222                 PRINT_ERR("FlashErase(%d, %d) failed(%u)\n", flash_block_address, block_size, res);
223                 return LFS_ERR_IO;
224             }
225             memcpy_s(&buffer[write_offset], block_size - write_offset, &src[str_offset], write_length);
226             res = FlashWrite(flash_block_address, block_size, buffer, 0);
227             if (res != LZ_HARDWARE_SUCCESS) {
228                 PRINT_ERR("FlashWrite(%d, %d, buffer) failed(%u)\n", flash_block_address, block_size, res);
229                 return LFS_ERR_IO;
230             }
231             str_offset += write_length;
232         } else {
233             /* 中间的部分数据,整块处理 */
234             flash_block_address = block_offset * block_size;
235             write_offset = 0;
236             write_length = block_size;
237             /* 读取整块数据,擦除整块数据,最后写入Flash */
238             res = FlashErase(flash_block_address, block_size);
239             if (res != LZ_HARDWARE_SUCCESS) {
240                 PRINT_ERR("FlashErase(%d, %d) failed(%u)\n", flash_block_address, block_size, res);
241                 return LFS_ERR_IO;
242             }
243             res = FlashWrite(flash_block_address, block_size, &src[str_offset], 0);
244             if (res != LZ_HARDWARE_SUCCESS) {
245                 PRINT_ERR("FlashWrite(%d, %d, buffer) failed(%u)\n", flash_block_address, block_size, res);
246                 return LFS_ERR_IO;
247             }
248             str_offset += write_length;
249         }
250     }
251 
252     if (buffer != NULL) {
253         free(buffer);
254         buffer = NULL;
255     }
256 
257     return LFS_ERR_OK;
258 }
259 
fs_erase(const struct lfs_config *c, lfs_block_t block)260 static int32_t fs_erase(const struct lfs_config *c, lfs_block_t block)
261 {
262     int32_t ret;
263     struct fs_cfg *fs;
264     uint32_t addr;
265     uint32_t partition_offset;
266 
267     if (c == NULL) {
268         PRINT_ERR("c is null\n");
269         return LFS_ERR_INVAL;
270     }
271     if (block >= c->block_count) {
272         PRINT_ERR("block(%d) >= block_count(%d)\n", block, c->block_count);
273         return LFS_ERR_INVAL;
274     }
275 
276     ret = fs_get_partition(c->context, &partition_offset);
277     if (ret != HDF_SUCCESS) {
278         PRINT_ERR("c->context(%s) is not support\n", c->context);
279         return LFS_ERR_INVAL;
280     }
281 
282     fs = &m_fs_cfg[partition_offset];
283     addr = ((fs->block_start + block) * c->block_size);
284     FlashErase(addr, c->block_size);
285 
286     return LFS_ERR_OK;
287 }
288 
fs_sync(const struct lfs_config *c)289 static int32_t fs_sync(const struct lfs_config *c)
290 {
291     return LFS_ERR_OK;
292 }
293 
fsdrv_readdrs(const struct DeviceResourceNode *node, struct fs_cfg *fs)294 static uint32_t fsdrv_readdrs(const struct DeviceResourceNode *node, struct fs_cfg *fs)
295 {
296     int32_t ret;
297     struct DeviceResourceIface *iface = NULL;
298     int32_t num = 0;
299     uint32_t block_size = FlashGetBlockSize();
300     uint32_t address_start, address_end;
301 
302     if (node == NULL) {
303         PRINT_ERR("node is null\n");
304         return HDF_ERR_INVALID_PARAM;
305     }
306     if (fs == NULL) {
307         PRINT_ERR("fs  is null\n");
308         return HDF_ERR_INVALID_PARAM;
309     }
310 
311     iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
312     if (iface == NULL) {
313         PRINT_ERR("iface is null\n");
314         return HDF_ERR_INVALID_PARAM;
315     }
316     if (iface->GetElemNum == NULL) {
317         PRINT_ERR("GetElemNum is null\n");
318         return HDF_ERR_INVALID_PARAM;
319     }
320     if (iface->GetStringArrayElem == NULL) {
321         PRINT_ERR("GetStringArrayElem is null\n");
322         return HDF_ERR_INVALID_PARAM;
323     }
324     if (iface->GetUint32ArrayElem == NULL) {
325         PRINT_ERR("GetStringArrayElem is null\n");
326         return HDF_ERR_INVALID_PARAM;
327     }
328 
329     num = iface->GetElemNum(node, "mount_points");
330     if (num < 0 || num > LOSCFG_LFS_MAX_MOUNT_SIZE) {
331         PRINT_ERR("invalid mount_points num %d", num);
332         return HDF_FAILURE;
333     }
334 
335     for (int32_t i = 0; i < num; i++) {
336         ret = iface->GetStringArrayElem(node, "mount_points", i, &fs[i].mount_point, NULL);
337         if (ret != HDF_SUCCESS) {
338             PRINT_ERR("failed to get mount_points");
339             return HDF_FAILURE;
340         }
341 
342         fs[i].lfs_cfg.context = (void *)fs[i].mount_point;
343 
344         ret = iface->GetUint32ArrayElem(node, "block_size", i, &fs[i].lfs_cfg.block_size, NULL);
345         if (ret != HDF_SUCCESS) {
346             PRINT_ERR("failed to get block_size");
347             return HDF_FAILURE;
348         }
349 
350         ret = iface->GetUint32ArrayElem(node, "block_count", i, &fs[i].lfs_cfg.block_count, NULL);
351         if (ret != HDF_SUCCESS) {
352             PRINT_ERR("failed to get block_count");
353             return HDF_FAILURE;
354         }
355 
356         ret = iface->GetUint32ArrayElem(node, "block_start", i, &fs[i].block_start, NULL);
357         if (ret != HDF_SUCCESS) {
358             PRINT_ERR("failed to get block_start");
359             return HDF_FAILURE;
360         }
361     }
362 
363     /* 检查相关参数是否正确 */
364     for (int32_t i = 0; i < num; i++) {
365         if (fs[i].mount_point == NULL) {
366             break;
367         }
368 
369         PRINT_LOG("fs[%d]:\n", i);
370         PRINT_LOG("     mount_points = %s\n", fs[i].mount_point);
371         PRINT_LOG("     context = %s\n", (char *)fs[i].lfs_cfg.context);
372         PRINT_LOG("     block_size = %d\n", fs[i].lfs_cfg.block_size);
373         PRINT_LOG("     block_count = %d\n", fs[i].lfs_cfg.block_count);
374         PRINT_LOG("     block_start = %d\n", fs[i].block_start);
375 
376         /* 检查 */
377         if (fs[i].lfs_cfg.block_size != block_size) {
378             PRINT_ERR("littefs[%d].lfs_cfg.block_size(%d) != flash_block_size(%d)\n",
379                     i, fs[i].lfs_cfg.block_size, block_size);
380             return HDF_ERR_INVALID_PARAM;
381         }
382 
383         address_start = (uint32_t)(fs[i].block_start * fs[i].lfs_cfg.block_size);
384         if (address_start < FLASH_ADDRESS_USER_START) {
385             PRINT_ERR("partition[%d].address_start(%d) < FLASH_ADDRESS_USER_START(%d)\n",
386                 i, address_start, FLASH_ADDRESS_USER_START);
387             return HDF_FAILURE;
388         }
389 
390         address_end = (uint32_t)((fs[i].block_start + fs[i].lfs_cfg.block_count) * fs[i].lfs_cfg.block_size);
391         if (address_end > FLASH_ADDRESS_USER_END) {
392             PRINT_ERR("partition[%d].address_end(%d) < FLASH_ADDRESS_USER_END(%d)\n",
393                 i, address_end, FLASH_ADDRESS_USER_END);
394             return HDF_FAILURE;
395         }
396     }
397 
398     return HDF_SUCCESS;
399 }
400 
fsdrv_init(struct HdfDeviceObject *device)401 static int32_t fsdrv_init(struct HdfDeviceObject *device)
402 {
403     int result;
404     int32_t ret;
405     struct FileOpInfo *file_op_info = NULL;
406 
407     if (device == NULL) {
408         PRINT_ERR("device is null\n");
409         return HDF_ERR_INVALID_OBJECT;
410     }
411     if (device->property == NULL) {
412         PRINT_ERR("device is null\n");
413         return HDF_ERR_INVALID_OBJECT;
414     }
415 
416     /* Flash设备初始化 */
417     FlashInit();
418 
419     ret = fsdrv_readdrs(device->property, &m_fs_cfg[0]);
420     if (ret != HDF_SUCCESS) {
421         PRINT_ERR("%s: fsdrv_readdrs failed(%d)\n", __func__, ret);
422         return ret;
423     }
424 
425     for (int i = 0; i < sizeof(m_fs_cfg) / sizeof(m_fs_cfg[0]); i++) {
426         if (m_fs_cfg[i].mount_point == NULL) {
427             PRINT_LOG("m_fs_cfg[%d].mount_point is null\n", i);
428             continue;
429         }
430 
431         m_fs_cfg[i].lfs_cfg.read = fs_read;
432         m_fs_cfg[i].lfs_cfg.prog = fs_write;
433         m_fs_cfg[i].lfs_cfg.erase = fs_erase;
434         m_fs_cfg[i].lfs_cfg.sync = fs_sync;
435 
436         m_fs_cfg[i].lfs_cfg.read_size = LFSCFG_READSIZE_MAX;
437         m_fs_cfg[i].lfs_cfg.prog_size = LFSCFG_PROGSIZE_MAX;
438         m_fs_cfg[i].lfs_cfg.cache_size = LFSCFG_CACHESIZE_MAX;
439         m_fs_cfg[i].lfs_cfg.lookahead_size = LFSCFG_LOCKAHEADSIZE_MAX;
440         m_fs_cfg[i].lfs_cfg.block_cycles = LFSCFG_BLOCKCYCLES_MAX;
441 
442         m_fs_cfg[i].lfs_cfg.file_max = LFS_FILE_MAX;
443         m_fs_cfg[i].lfs_cfg.name_max = LFS_NAME_MAX;
444 
445         result = mount(NULL, m_fs_cfg[i].mount_point, "littlefs", 0, &m_fs_cfg[i].lfs_cfg);
446         printf("%s: mount fs on '%s' %s\n", __func__, m_fs_cfg[i].mount_point, (result == 0) ? "succeed" : "failed");
447         if (ret == 0) {
448             ret = mkdir(m_fs_cfg[i].mount_point, S_IRWXU | S_IRWXG | S_IRWXO);
449             if (ret == 0) {
450                 PRINT_LOG("create root dir(%s) success.\n", m_fs_cfg[i].mount_point);
451             } else if (errno == EEXIST) {
452                 PRINT_LOG("root dir(%s) exist.\n", m_fs_cfg[i].mount_point);
453             } else {
454                 PRINT_LOG("create root dir(%s) failed.", m_fs_cfg[i].mount_point);
455             }
456         }
457     }
458 
459     PRINT_LOG("LittleFS service: %s init success!\n", HdfDeviceGetServiceName(device));
460     return HDF_SUCCESS;
461 }
462 
fsdrv_bind(struct HdfDeviceObject *device)463 static int32_t fsdrv_bind(struct HdfDeviceObject *device)
464 {
465     (void)device;
466     return HDF_SUCCESS;
467 }
468 
fsdrv_release(struct HdfDeviceObject *device)469 static void fsdrv_release(struct HdfDeviceObject *device)
470 {
471     (void)device;
472     PRINT_LOG("LittleFS service: %s release\n", HdfDeviceGetServiceName(device));
473 }
474 
475 static struct HdfDriverEntry g_fsDriverEntry = {
476     .moduleVersion = 1,
477     .moduleName = "HDF_PLATFORM_FS_LITTLEFS",
478     .Bind = fsdrv_bind,
479     .Init = fsdrv_init,
480     .Release = fsdrv_release,
481 };
482 
483 HDF_INIT(g_fsDriverEntry);
484