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