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