更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_rootfs.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "los_rootfs.h"
33#include "los_bootargs.h"
34#include "los_base.h"
35#include "string.h"
36#include "sys/mount.h"
37#include "sys/stat.h"
38#include "sys/types.h"
39
40#if defined(LOSCFG_STORAGE_SPINOR) || defined(LOSCFG_STORAGE_SPINAND) || defined(LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7)
41#include "mtd_list.h"
42#include "mtd_partition.h"
43#endif
44
45#ifdef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7
46#include "cfiflash.h"
47#endif
48
49#ifdef LOSCFG_STORAGE_EMMC
50#include "disk.h"
51#include "ff.h"
52#endif
53
54
55#ifdef LOSCFG_STORAGE_EMMC
57struct block_operations *StorageBlockGetMmcOps(void);
58char *StorageBlockGetEmmcNodeName(void *block);
59
60STATIC INT32 AddEmmcParts(INT32 rootAddr, INT32 rootSize, INT32 userAddr, INT32 userSize)
61{
62 INT32 ret;
63
64 los_disk *emmcDisk = los_get_mmcdisk_bytype(EMMC);
65 if (emmcDisk == NULL) {
66 PRINT_ERR("Get EMMC disk failed!\n");
67 return LOS_NOK;
68 }
69
70 void *block = ((struct drv_data *)emmcDisk->dev->data)->priv;
71 const char *node_name = StorageBlockGetEmmcNodeName(block);
72 if (los_disk_deinit(emmcDisk->disk_id) != ENOERR) {
73 PRINT_ERR("Failed to deinit emmc disk!\n");
74 return LOS_NOK;
75 }
76
78 ret = add_mmc_partition(emmc, rootAddr / EMMC_SEC_SIZE, rootSize / EMMC_SEC_SIZE);
79 if (ret != LOS_OK) {
80 PRINT_ERR("Failed to add mmc root partition!\n");
81 return LOS_NOK;
82 }
83
84#ifdef LOSCFG_PLATFORM_PATCHFS
85 UINT64 patchStartCnt = userAddr / EMMC_SEC_SIZE;
86 UINT64 patchSizeCnt = PATCH_SIZE / EMMC_SEC_SIZE;
87 ret = add_mmc_partition(emmc, patchStartCnt, patchSizeCnt);
88 if (ret != LOS_OK) {
89 PRINT_ERR("Failed to add mmc patch partition!\n");
90 return LOS_NOK;
91 }
92 userAddr += PATCH_SIZE;
93#endif
94
95 UINT64 storageStartCnt = userAddr / EMMC_SEC_SIZE;
96 UINT64 storageSizeCnt = userSize / EMMC_SEC_SIZE;
97 UINT64 userdataStartCnt = storageStartCnt + storageSizeCnt;
98 UINT64 userdataSizeCnt = emmcDisk->sector_count - userdataStartCnt;
99 ret = add_mmc_partition(emmc, storageStartCnt, storageSizeCnt);
100 if (ret != LOS_OK) {
101 PRINT_ERR("Failed to add mmc storage partition!\n");
102 return LOS_NOK;
103 }
104
105 ret = add_mmc_partition(emmc, userdataStartCnt, userdataSizeCnt);
106 if (ret != LOS_OK) {
107 PRINT_ERR("Failed to add mmc userdata partition!\n");
108 return LOS_NOK;
109 }
110
111 LOS_Msleep(10); /* 100, sleep time. waiting for device identification */
112
113 INT32 diskId = los_alloc_diskid_byname(node_name);
114 if (diskId < 0) {
115 PRINT_ERR("Failed to alloc disk %s!\n", node_name);
116 return LOS_NOK;
117 }
118
119 if (los_disk_init(node_name, StorageBlockGetMmcOps(), block, diskId, emmc) != ENOERR) {
120 PRINT_ERR("Failed to init emmc disk!\n");
121 return LOS_NOK;
122 }
123
124 return LOS_OK;
125}
126#endif
127
128//增加一个分
129STATIC INT32 AddPartitions(CHAR *dev, UINT64 rootAddr, UINT64 rootSize, UINT64 userAddr, UINT64 userSize)
130{
131#ifdef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7
132 if ((strcmp(dev, "cfi-flash") == 0) && (rootAddr != CFIFLASH_ROOT_ADDR)) {
133 PRINT_ERR("Error rootAddr, must be %#0x!\n", CFIFLASH_ROOT_ADDR);
134 return LOS_NOK;
135 }
136#endif
137
138#if defined(LOSCFG_STORAGE_SPINOR) || defined(LOSCFG_STORAGE_SPINAND) || defined(LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7)
139 INT32 ret;
140 INT32 blk0 = 0;
141 INT32 blk2 = 2;
142 if (strcmp(dev, "flash") == 0 || strcmp(dev, FLASH_TYPE) == 0) {
143 ret = add_mtd_partition(FLASH_TYPE, rootAddr, rootSize, blk0);//增加一个MTD分区
144 if (ret != LOS_OK) {
145 PRINT_ERR("Failed to add mtd root partition!\n");
146 return LOS_NOK;
147 }
148
149 ret = add_mtd_partition(FLASH_TYPE, userAddr, userSize, blk2);
150 if (ret != LOS_OK) {
151 PRINT_ERR("Failed to add mtd storage partition!\n");
152 return LOS_NOK;
153 }
154
155 return LOS_OK;
156 }
157#endif
158
159#ifdef LOSCFG_STORAGE_EMMC
160 if (strcmp(dev, "emmc") == 0) {
161 return AddEmmcParts(rootAddr, rootSize, userAddr, userSize);
162 }
163#endif
164
165 PRINT_ERR("Unsupport dev type: %s\n", dev);
166 return LOS_NOK;
167}
168
169//获取根文件系统参
170STATIC INT32 ParseRootArgs(CHAR **dev, CHAR **fstype, UINT64 *rootAddr, UINT64 *rootSize, UINT32 *mountFlags)
171{
172 INT32 ret;
173 CHAR *rootAddrStr = NULL;
174 CHAR *rootSizeStr = NULL;
175 CHAR *rwTag = NULL;
176 //获取文件系统放在哪种设备
177 ret = LOS_GetArgValue("root", dev);//root = flash | mmc |
178 if (ret != LOS_OK) {
179 PRINT_ERR("Cannot find root!");
180 return ret;
181 }
182 //获取文件系统类型
183 ret = LOS_GetArgValue("fstype", fstype);
184 if (ret != LOS_OK) {
185 PRINT_ERR("Cannot find fstype!");
186 return ret;
187 }
188 //获取内核地址空间开始位
189 ret = LOS_GetArgValue("rootaddr", &rootAddrStr);
190 if (ret != LOS_OK) {
191 *rootAddr = ROOTFS_ADDR;
192 } else {
193 *rootAddr = LOS_SizeStrToNum(rootAddrStr);
194 }
195 //获取内核地址空间大小
196 ret = LOS_GetArgValue("rootsize", &rootSizeStr);
197 if (ret != LOS_OK) {
198 *rootSize = ROOTFS_SIZE;
199 } else {
200 *rootSize = LOS_SizeStrToNum(rootSizeStr);
201 }
202
203 ret = LOS_GetArgValue("ro", &rwTag);
204 if (ret == LOS_OK) {
205 *mountFlags = MS_RDONLY;
206 } else {
207 *mountFlags = 0;
208 }
209
210 return LOS_OK;
211}
212
213STATIC INT32 ParseUserArgs(UINT64 rootAddr, UINT64 rootSize, UINT64 *userAddr, UINT64 *userSize)
214{
215 INT32 ret;
216 CHAR *userAddrStr = NULL;
217 CHAR *userSizeStr = NULL;
218
219 ret = LOS_GetArgValue("useraddr", &userAddrStr);
220 if (ret != LOS_OK) {
221 *userAddr = rootAddr + rootSize;
222 } else {
223 *userAddr = LOS_SizeStrToNum(userAddrStr);
224 }
225
226 ret = LOS_GetArgValue("usersize", &userSizeStr);
227 if (ret != LOS_OK) {
228 *userSize = USERFS_SIZE;
229 } else {
230 *userSize = LOS_SizeStrToNum(userSizeStr);
231 }
232
233 return LOS_OK;
234}
235///挂载分区,即挂?"/","/storage"
236STATIC INT32 MountPartitions(CHAR *fsType, UINT32 mountFlags)
237{
238 INT32 ret;
239 INT32 err;
240
241 /* Mount rootfs */
242 ret = mount(ROOT_DEV_NAME, ROOT_DIR_NAME, fsType, mountFlags, NULL);//挂载根文件系?
243 if (ret != LOS_OK) {
244 err = get_errno();
245 PRINT_ERR("Failed to mount %s, rootDev %s, errno %d: %s\n", ROOT_DIR_NAME, ROOT_DEV_NAME, err, strerror(err));
246 return ret;
247 }
248
249#ifdef LOSCFG_STORAGE_EMMC
250#ifdef LOSCFG_PLATFORM_PATCHFS
251 /* Mount patch */
252 ret = mkdir(PATCH_DIR_NAME, DEFAULT_MOUNT_DIR_MODE);
253 if ((ret != LOS_OK) && ((err = get_errno()) != EEXIST)) {
254 PRINT_ERR("Failed to mkdir %s, errno %d: %s\n", PATCH_DIR_NAME, err, strerror(err));
255 return ret;
256 }
257
258 ret = mount(PATCH_DEV_NAME, PATCH_DIR_NAME, fsType, 0, DEFAULT_MOUNT_DATA);
259 if ((ret != LOS_OK) && ((err = get_errno()) == ENOTSUP)) {
260 ret = format(PATCH_DEV_NAME, 0, FM_FAT32);
261 if (ret != LOS_OK) {
262 PRINT_ERR("Failed to format %s\n", PATCH_DEV_NAME);
263 return ret;
264 }
265
266 ret = mount(PATCH_DEV_NAME, PATCH_DIR_NAME, fsType, 0, DEFAULT_MOUNT_DATA);
267 if (ret != LOS_OK) {
268 err = get_errno();
269 }
270 }
271 if (ret != LOS_OK) {
272 PRINT_ERR("Failed to mount %s, errno %d: %s\n", PATCH_DIR_NAME, err, strerror(err));
273 return ret;
274 }
275#endif
276#endif
277
278 /* Mount userfs */
279 ret = mkdir(STORAGE_DIR_NAME, DEFAULT_MOUNT_DIR_MODE);//创建目录"/storage"
280 if ((ret != LOS_OK) && ((err = get_errno()) != EEXIST)) {
281 PRINT_ERR("Failed to mkdir %s, errno %d: %s\n", STORAGE_DIR_NAME, err, strerror(err));
282 return ret;
283 }
284
285 ret = mount(USER_DEV_NAME, STORAGE_DIR_NAME, fsType, 0, DEFAULT_MOUNT_DATA);//挂载用户数据文件系统
286 if (ret != LOS_OK) {
287 err = get_errno();
288 PRINT_ERR("Failed to mount %s, errno %d: %s\n", STORAGE_DIR_NAME, err, strerror(err));
289 return ret;
290 }
291
292#ifdef LOSCFG_STORAGE_EMMC
293 /* Mount userdata */
294 ret = mkdir(USERDATA_DIR_NAME, DEFAULT_MOUNT_DIR_MODE);//创建目录"/userdata"
295 if ((ret != LOS_OK) && ((err = get_errno()) != EEXIST)) {
296 PRINT_ERR("Failed to mkdir %s, errno %d: %s\n", USERDATA_DIR_NAME, err, strerror(err));
297 return ret;
298 }
299
300 ret = mount(USERDATA_DEV_NAME, USERDATA_DIR_NAME, fsType, 0, DEFAULT_MOUNT_DATA);//挂载用户数据文件系统
301 if ((ret != LOS_OK) && ((err = get_errno()) == ENOTSUP)) {
302 ret = format(USERDATA_DEV_NAME, 0, FM_FAT32);
303 if (ret != LOS_OK) {
304 PRINT_ERR("Failed to format %s\n", USERDATA_DEV_NAME);
305 return ret;
306 }
307
308 ret = mount(USERDATA_DEV_NAME, USERDATA_DIR_NAME, fsType, 0, DEFAULT_MOUNT_DATA);
309 if (ret != LOS_OK) {
310 err = get_errno();
311 }
312 }
313 if (ret != LOS_OK) {
314 PRINT_ERR("Failed to mount %s, errno %d: %s\n", USERDATA_DIR_NAME, err, strerror(err));
315 return ret;
316 }
317#endif
318 return LOS_OK;
319}
320
321STATIC INT32 CheckValidation(UINT64 rootAddr, UINT64 rootSize, UINT64 userAddr, UINT64 userSize)
322{
323 UINT64 alignSize = LOS_GetAlignsize();
324
325 if (alignSize == 0) {
326 return LOS_OK;
327 }
328
329 if ((rootAddr & (alignSize - 1)) || (rootSize & (alignSize - 1)) ||
330 (userAddr & (alignSize - 1)) || (userSize & (alignSize - 1))) {
331 PRINT_ERR("The address or size value should be 0x%llx aligned!\n", alignSize);
332 return LOS_NOK;
333 }
334
335 return LOS_OK;
336}
337///挂载根文件系??SystemInit 调用
339{
340 INT32 ret;
341 CHAR *dev = NULL;
342 CHAR *fstype = NULL;
343 UINT64 rootAddr;
344 UINT64 rootSize;
345 UINT64 userAddr;
346 UINT64 userSize;
347 UINT32 mountFlags;
348 //获取根文件系统参?
349 ret = ParseRootArgs(&dev, &fstype, &rootAddr, &rootSize, &mountFlags);
350 if (ret != LOS_OK) {
351 return ret;
352 }
353 //获取用户文件参数
354 ret = ParseUserArgs(rootAddr, rootSize, &userAddr, &userSize);
355 if (ret != LOS_OK) {
356 return ret;
357 }
358 //检查内核和用户空间的有效?
359 ret = CheckValidation(rootAddr, rootSize, userAddr, userSize);
360 if (ret != LOS_OK) {
361 return ret;
362 }
363 //添加分区,注册驱动
364 ret = AddPartitions(dev, rootAddr, rootSize, userAddr, userSize);
365 if (ret != LOS_OK) {
366 return ret;
367 }
368 //挂载分区,即挂?`/`
369 ret = MountPartitions(fstype, mountFlags);
370 if (ret != LOS_OK) {
371 return ret;
372 }
373
374 return LOS_OK;
375}
los_disk * los_get_mmcdisk_bytype(UINT8 type)
Definition: disk.c:226
int format(const char *dev, int sectors, int option)
formatting sd card
Definition: format.c:44
INT32 add_mmc_partition(struct disk_divide_info *info, size_t sectorStart, size_t sectorCount)
Add a new mmc partition.
Definition: disk.c:1779
INT32 los_disk_init(const CHAR *diskName, const struct block_operations *bops, VOID *priv, INT32 diskID, VOID *info)
Disk driver initialization.
Definition: disk.c:1481
INT32 los_disk_deinit(INT32 diskID)
Destroy a disk driver.
Definition: disk.c:1544
INT32 los_alloc_diskid_byname(const CHAR *diskName)
alloc a new UNUSED disk id.
Definition: disk.c:134
LITE_OS_SEC_TEXT_MINOR VOID LOS_Msleep(UINT32 msecs)
Sleep the current task.
Definition: los_misc.c:44
INT32 add_mtd_partition(const CHAR *type, UINT32 startAddr, UINT32 length, UINT32 partitionNum)
Add a partition.
UINT64 LOS_GetAlignsize(VOID)
Definition: los_bootargs.c:207
INT32 LOS_GetArgValue(CHAR *argName, CHAR **argValue)
Definition: los_bootargs.c:189
UINT64 LOS_SizeStrToNum(CHAR *value)
Definition: los_bootargs.c:212
STATIC INT32 AddEmmcParts(INT32 rootAddr, INT32 rootSize, INT32 userAddr, INT32 userSize)
Definition: los_rootfs.c:60
STATIC INT32 ParseUserArgs(UINT64 rootAddr, UINT64 rootSize, UINT64 *userAddr, UINT64 *userSize)
Definition: los_rootfs.c:213
STATIC INT32 CheckValidation(UINT64 rootAddr, UINT64 rootSize, UINT64 userAddr, UINT64 userSize)
Definition: los_rootfs.c:321
STATIC INT32 AddPartitions(CHAR *dev, UINT64 rootAddr, UINT64 rootSize, UINT64 userAddr, UINT64 userSize)
Definition: los_rootfs.c:129
STATIC INT32 MountPartitions(CHAR *fsType, UINT32 mountFlags)
挂载分区,即挂?"/","/storage"
Definition: los_rootfs.c:236
char * StorageBlockGetEmmcNodeName(void *block)
struct block_operations * StorageBlockGetMmcOps(void)
struct disk_divide_info * StorageBlockGetEmmc(void)
STATIC INT32 ParseRootArgs(CHAR **dev, CHAR **fstype, UINT64 *rootAddr, UINT64 *rootSize, UINT32 *mountFlags)
Definition: los_rootfs.c:170
INT32 OsMountRootfs()
挂载根文件系??SystemInit 调用
Definition: los_rootfs.c:338
signed int INT32
Definition: los_typedef.h:60
long unsigned int UINT64
Definition: los_typedef.h:66
unsigned int UINT32
Definition: los_typedef.h:57
char CHAR
Definition: los_typedef.h:63
UINT32 disk_id
Definition: disk.h:177
struct Vnode * dev
Definition: disk.h:181
UINT64 sector_count
Definition: disk.h:187
void * data
Definition: vnode.h:176