• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************/
18 #include <sys/mount.h>
19 
20 #include <device_resource_if.h>
21 #include <hdf_device_desc.h>
22 #include <hdf_log.h>
23 #include <lfs_adapter.h>
24 #include <los_config.h>
25 
26 #include <los_fs.h>
27 
28 #include <B91/flash.h>
29 
30 #define LITTLEFS_PHYS_ADDR (1024 * 1024)
31 #define LITTLEFS_PHYS_SIZE (128 * 1024)
32 
33 #define READ_SIZE      16
34 #define PROG_SIZE      16
35 #define BLOCK_SIZE     4096
36 #define BLOCK_COUNT    32
37 #define CACHE_SIZE     512
38 #define LOOKAHEAD_SIZE 64
39 #define BLOCK_CYCLES   500
40 
41 struct fs_cfg {
42     char *mount_point;
43     struct lfs_config lfs_cfg;
44 };
45 
46 static struct fs_cfg fs[LOSCFG_LFS_MAX_MOUNT_SIZE] = {0};
47 
readFunc(int partition,UINT32 * offset,unsigned char * buf,UINT32 size)48 static int readFunc(int partition, UINT32 *offset, unsigned char *buf, UINT32 size)
49 {
50     flash_read_page(LITTLEFS_PHYS_ADDR + *offset, size, buf);
51     return LFS_ERR_OK;
52 }
53 
54 /* partition low-level write func */
writeFunc(int partition,UINT32 * offset,const unsigned char * buf,UINT32 size)55 static int writeFunc(int partition, UINT32 *offset, const unsigned char *buf, UINT32 size)
56 {
57     flash_write_page(LITTLEFS_PHYS_ADDR + *offset, size, (unsigned char *)buf);
58     return LFS_ERR_OK;
59 }
60 
61 /* partition low-level erase func */
eraseFunc(int partition,UINT32 offset,UINT32 size)62 static int eraseFunc(int partition, UINT32 offset, UINT32 size)
63 {
64     flash_erase_sector(LITTLEFS_PHYS_ADDR + offset);
65     return LFS_ERR_OK;
66 }
67 
FsGetResource(struct fs_cfg * fs,const struct DeviceResourceNode * resourceNode)68 static uint32_t FsGetResource(struct fs_cfg *fs, const struct DeviceResourceNode *resourceNode)
69 {
70     struct DeviceResourceIface *resource = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
71     if (resource == NULL) {
72         HDF_LOGE("Invalid DeviceResourceIface");
73         return HDF_FAILURE;
74     }
75     int32_t num = resource->GetElemNum(resourceNode, "mount_points");
76     if (num < 0 || num > LOSCFG_LFS_MAX_MOUNT_SIZE) {
77         HDF_LOGE("%s: invalid mount_points num %d", __func__, num);
78         return HDF_FAILURE;
79     }
80     for (int32_t i = 0; i < num; i++) {
81         if (resource->GetStringArrayElem(resourceNode, "mount_points", i, &fs[i].mount_point, NULL) != HDF_SUCCESS) {
82             HDF_LOGE("%s: failed to get mount_points", __func__);
83             return HDF_FAILURE;
84         }
85         if (resource->GetUint32ArrayElem(resourceNode, "partitions", i, (uint32_t *)&fs[i].lfs_cfg.context, 0) !=
86             HDF_SUCCESS) {
87             HDF_LOGE("%s: failed to get partitions", __func__);
88             return HDF_FAILURE;
89         }
90         if (resource->GetUint32ArrayElem(resourceNode, "block_size", i, &fs[i].lfs_cfg.block_size, 0) !=
91             HDF_SUCCESS) {
92             HDF_LOGE("%s: failed to get block_size", __func__);
93             return HDF_FAILURE;
94         }
95         if (resource->GetUint32ArrayElem(resourceNode, "block_count", i, &fs[i].lfs_cfg.block_count, 0) !=
96             HDF_SUCCESS) {
97             HDF_LOGE("%s: failed to get block_count", __func__);
98             return HDF_FAILURE;
99         }
100         HDF_LOGD("%s: fs[%d] mount_point=%s, partition=%u, block_size=%u, block_count=%u", __func__, i,
101             fs[i].mount_point, (uint32_t)fs[i].lfs_cfg.context, fs[i].lfs_cfg.block_size, fs[i].lfs_cfg.block_count);
102     }
103     return HDF_SUCCESS;
104 }
105 
PartitionsInit(void)106 void PartitionsInit(void)
107 {
108     int lengthArray[LOSCFG_LFS_MAX_MOUNT_SIZE];
109     int addrArray[LOSCFG_LFS_MAX_MOUNT_SIZE];
110     int nextAddr = 0;
111 
112     for (int i = 0; i < sizeof(fs) / sizeof(fs[0]); i++) {
113         lengthArray[i] = fs[i].lfs_cfg.block_count * fs[i].lfs_cfg.block_size;
114         addrArray[i] = nextAddr;
115         nextAddr += lengthArray[i];
116     }
117 
118     (VOID) LOS_DiskPartition("flash0", "littlefs", lengthArray, addrArray, LOSCFG_LFS_MAX_MOUNT_SIZE);
119 }
120 
FsDriverInit(struct HdfDeviceObject * object)121 int32_t FsDriverInit(struct HdfDeviceObject *object)
122 {
123     struct FileOpInfo *fileOpInfo = NULL;
124 
125     if (object == NULL) {
126         return HDF_FAILURE;
127     }
128     if (object->property) {
129         if (FsGetResource(fs, object->property) != HDF_SUCCESS) {
130             HDF_LOGE("%s: FsGetResource failed", __func__);
131             return HDF_FAILURE;
132         }
133     }
134 
135     struct PartitionCfg partCfg = {.readSize = READ_SIZE,
136         .writeSize = PROG_SIZE,
137         .cacheSize = CACHE_SIZE,
138         .partNo = 0,
139         .blockCycles = BLOCK_CYCLES,
140         .lookaheadSize = LOOKAHEAD_SIZE,
141         .readFunc = readFunc,
142         .writeFunc = writeFunc,
143         .eraseFunc = eraseFunc};
144 
145     for (int i = 0; i < sizeof(fs) / sizeof(fs[0]); i++) {
146         if (fs[i].mount_point == NULL) {
147             continue;
148         }
149 
150         partCfg.blockSize = fs[i].lfs_cfg.block_size;
151         partCfg.blockCount = fs[i].lfs_cfg.block_count;
152 
153         int ret = mount(NULL, fs[i].mount_point, "littlefs", 0, &partCfg);
154         HDF_LOGI("%s: mount fs on '%s' %s\n", __func__, fs[i].mount_point, (ret == 0) ? "succeed" : "failed");
155         if (ret == 0) {
156             ret = mkdir(fs[i].mount_point, S_IRWXU | S_IRWXG | S_IRWXO);
157             if (ret == 0) {
158                 HDF_LOGI("create root dir success.");
159             } else if (errno == EEXIST) {
160                 HDF_LOGI("root dir exist.");
161             } else {
162                 HDF_LOGI("create root dir failed.");
163             }
164         }
165     }
166 
167     return HDF_SUCCESS;
168 }
169 
FsDriverBind(struct HdfDeviceObject * device)170 static int32_t FsDriverBind(struct HdfDeviceObject *device)
171 {
172     (void)device;
173     return HDF_SUCCESS;
174 }
175 
FsDriverRelease(struct HdfDeviceObject * device)176 static void FsDriverRelease(struct HdfDeviceObject *device)
177 {
178     (void)device;
179 }
180 
181 static struct HdfDriverEntry g_fsDriverEntry = {
182     .moduleVersion = 1,
183     .moduleName = "HDF_FS_LITTLEFS",
184     .Bind = FsDriverBind,
185     .Init = FsDriverInit,
186     .Release = FsDriverRelease,
187 };
188 
189 HDF_INIT(g_fsDriverEntry);
190