• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
56 struct disk_divide_info *StorageBlockGetEmmc(void);
57 struct block_operations *StorageBlockGetMmcOps(void);
58 char *StorageBlockGetEmmcNodeName(void *block);
59 
AddEmmcParts(INT32 rootAddr,INT32 rootSize,INT32 userAddr,INT32 userSize)60 STATIC 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 
77     struct disk_divide_info *emmc = StorageBlockGetEmmc();
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 
AddPartitions(CHAR * dev,UINT64 rootAddr,UINT64 rootSize,UINT64 userAddr,UINT64 userSize)129 STATIC 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);
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 
ParseRootArgs(CHAR ** dev,CHAR ** fstype,UINT64 * rootAddr,UINT64 * rootSize,UINT32 * mountFlags)170 STATIC 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);
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 
ParseUserArgs(UINT64 rootAddr,UINT64 rootSize,UINT64 * userAddr,UINT64 * userSize)213 STATIC 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 
MountPartitions(CHAR * fsType,UINT32 mountFlags)236 STATIC 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);
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);
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 
CheckValidation(UINT64 rootAddr,UINT64 rootSize,UINT64 userAddr,UINT64 userSize)321 STATIC INT32 CheckValidation(UINT64 rootAddr, UINT64 rootSize, UINT64 userAddr, UINT64 userSize)
322 {
323     UINT64 alignSize = LOS_GetAlignsize();
324     if (alignSize == 0) {
325         return LOS_OK;
326     }
327 
328     if ((rootAddr & (alignSize - 1)) || (rootSize & (alignSize - 1)) ||
329         (userAddr & (alignSize - 1)) || (userSize & (alignSize - 1))) {
330         PRINT_ERR("The address or size value should be 0x%llx aligned!\n", alignSize);
331         return LOS_NOK;
332     }
333 
334     return LOS_OK;
335 }
336 
OsMountRootfs()337 INT32 OsMountRootfs()
338 {
339     INT32 ret;
340     CHAR *dev = NULL;
341     CHAR *fstype = NULL;
342     UINT64 rootAddr;
343     UINT64 rootSize;
344     UINT64 userAddr;
345     UINT64 userSize;
346     UINT32 mountFlags;
347 
348     ret = ParseRootArgs(&dev, &fstype, &rootAddr, &rootSize, &mountFlags);
349     if (ret != LOS_OK) {
350         return ret;
351     }
352 
353     ret = ParseUserArgs(rootAddr, rootSize, &userAddr, &userSize);
354     if (ret != LOS_OK) {
355         return ret;
356     }
357 
358     ret = CheckValidation(rootAddr, rootSize, userAddr, userSize);
359     if (ret != LOS_OK) {
360         return ret;
361     }
362 
363     ret = AddPartitions(dev, rootAddr, rootSize, userAddr, userSize);
364     if (ret != LOS_OK) {
365         return ret;
366     }
367 
368     ret = MountPartitions(fstype, mountFlags);
369     if (ret != LOS_OK) {
370         return ret;
371     }
372 
373     return LOS_OK;
374 }
375