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