los_rootfs.c 11.6 KB
Newer Older
W
wenjun 已提交
1
/*
M
mamingshuai 已提交
2 3
 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
W
wenjun 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
31 32 33

#include "los_rootfs.h"
#include "los_bootargs.h"
W
wenjun 已提交
34 35 36
#include "los_base.h"
#include "string.h"
#include "sys/mount.h"
37 38
#include "sys/stat.h"
#include "sys/types.h"
W
wenjun 已提交
39

40 41
#if defined(LOSCFG_STORAGE_SPINOR) || defined(LOSCFG_STORAGE_SPINAND) || defined(LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7)
#include "mtd_list.h"
42
#include "mtd_partition.h"
M
mamingshuai 已提交
43 44
#endif

45 46
#ifdef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7
#include "cfiflash.h"
W
wenjun 已提交
47 48
#endif

M
mamingshuai 已提交
49
#ifdef LOSCFG_STORAGE_EMMC
50
#include "disk.h"
L
li_zan 已提交
51
#include "ff.h"
W
wenjun 已提交
52 53 54
#endif


M
mamingshuai 已提交
55
#ifdef LOSCFG_STORAGE_EMMC
L
lzl 已提交
56 57 58 59
struct disk_divide_info *StorageBlockGetEmmc(void);
struct block_operations *StorageBlockGetMmcOps(void);
char *StorageBlockGetEmmcNodeName(void *block);

60
STATIC INT32 AddEmmcParts(INT32 rootAddr, INT32 rootSize, INT32 userAddr, INT32 userSize)
W
wenjun 已提交
61 62 63
{
    INT32 ret;

64 65 66 67 68 69 70
    los_disk *emmcDisk = los_get_mmcdisk_bytype(EMMC);
    if (emmcDisk == NULL) {
        PRINT_ERR("Get EMMC disk failed!\n");
        return LOS_NOK;
    }

    void *block = ((struct drv_data *)emmcDisk->dev->data)->priv;
L
lzl 已提交
71
    const char *node_name = StorageBlockGetEmmcNodeName(block);
72
    if (los_disk_deinit(emmcDisk->disk_id) != ENOERR) {
W
wenjun 已提交
73
        PRINT_ERR("Failed to deinit emmc disk!\n");
74
        return LOS_NOK;
W
wenjun 已提交
75 76
    }

L
lzl 已提交
77
    struct disk_divide_info *emmc = StorageBlockGetEmmc();
W
wenjun 已提交
78 79 80
    ret = add_mmc_partition(emmc, rootAddr / EMMC_SEC_SIZE, rootSize / EMMC_SEC_SIZE);
    if (ret != LOS_OK) {
        PRINT_ERR("Failed to add mmc root partition!\n");
81 82 83
        return LOS_NOK;
    }

J
jason_gitee 已提交
84 85 86 87 88 89 90 91 92 93 94
#ifdef LOSCFG_PLATFORM_PATCHFS
    UINT64 patchStartCnt = userAddr / EMMC_SEC_SIZE;
    UINT64 patchSizeCnt = PATCH_SIZE / EMMC_SEC_SIZE;
    ret = add_mmc_partition(emmc, patchStartCnt, patchSizeCnt);
    if (ret != LOS_OK) {
        PRINT_ERR("Failed to add mmc patch partition!\n");
        return LOS_NOK;
    }
    userAddr += PATCH_SIZE;
#endif

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
    UINT64 storageStartCnt = userAddr / EMMC_SEC_SIZE;
    UINT64 storageSizeCnt = userSize / EMMC_SEC_SIZE;
    UINT64 userdataStartCnt = storageStartCnt + storageSizeCnt;
    UINT64 userdataSizeCnt = emmcDisk->sector_count - userdataStartCnt;
    ret = add_mmc_partition(emmc, storageStartCnt, storageSizeCnt);
    if (ret != LOS_OK) {
        PRINT_ERR("Failed to add mmc storage partition!\n");
        return LOS_NOK;
    }

    ret = add_mmc_partition(emmc, userdataStartCnt, userdataSizeCnt);
    if (ret != LOS_OK) {
        PRINT_ERR("Failed to add mmc userdata partition!\n");
        return LOS_NOK;
    }

W
wangchen 已提交
111
    LOS_Msleep(10); /* 100, sleep time. waiting for device identification */
112 113 114 115 116 117 118 119 120 121

    INT32 diskId = los_alloc_diskid_byname(node_name);
    if (diskId < 0) {
        PRINT_ERR("Failed to alloc disk %s!\n", node_name);
        return LOS_NOK;
    }

    if (los_disk_init(node_name, StorageBlockGetMmcOps(), block, diskId, emmc) != ENOERR) {
        PRINT_ERR("Failed to init emmc disk!\n");
        return LOS_NOK;
W
wenjun 已提交
122
    }
123 124

    return LOS_OK;
W
wenjun 已提交
125 126 127
}
#endif

128 129

STATIC INT32 AddPartitions(CHAR *dev, UINT64 rootAddr, UINT64 rootSize, UINT64 userAddr, UINT64 userSize)
W
wenjun 已提交
130
{
131 132 133 134 135 136
#ifdef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7
    if ((strcmp(dev, "cfi-flash") == 0) && (rootAddr != CFIFLASH_ROOT_ADDR)) {
        PRINT_ERR("Error rootAddr, must be %#0x!\n", CFIFLASH_ROOT_ADDR);
        return LOS_NOK;
    }
#endif
W
wenjun 已提交
137

138
#if defined(LOSCFG_STORAGE_SPINOR) || defined(LOSCFG_STORAGE_SPINAND) || defined(LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7)
W
wenjun 已提交
139
    INT32 ret;
140 141 142 143
    INT32 blk0 = 0;
    INT32 blk2 = 2;
    if (strcmp(dev, "flash") == 0 || strcmp(dev, FLASH_TYPE) == 0) {
        ret = add_mtd_partition(FLASH_TYPE, rootAddr, rootSize, blk0);
W
wenjun 已提交
144
        if (ret != LOS_OK) {
145 146
            PRINT_ERR("Failed to add mtd root partition!\n");
            return LOS_NOK;
W
wenjun 已提交
147 148
        }

149 150 151 152
        ret = add_mtd_partition(FLASH_TYPE, userAddr, userSize, blk2);
        if (ret != LOS_OK) {
            PRINT_ERR("Failed to add mtd storage partition!\n");
            return LOS_NOK;
W
wenjun 已提交
153
        }
154 155 156

        return LOS_OK;
    }
W
wenjun 已提交
157 158
#endif

M
mamingshuai 已提交
159
#ifdef LOSCFG_STORAGE_EMMC
160 161 162
    if (strcmp(dev, "emmc") == 0) {
        return AddEmmcParts(rootAddr, rootSize, userAddr, userSize);
    }
W
wenjun 已提交
163
#endif
164

165 166
    PRINT_ERR("Unsupport dev type: %s\n", dev);
    return LOS_NOK;
W
wenjun 已提交
167 168
}

M
mamingshuai 已提交
169

W
wangchen 已提交
170 171
STATIC INT32 ParseRootArgs(CHAR **dev, CHAR **fstype, UINT64 *rootAddr, UINT64 *rootSize, UINT32 *mountFlags)
{
W
wenjun 已提交
172
    INT32 ret;
W
wangchen 已提交
173 174 175
    CHAR *rootAddrStr = NULL;
    CHAR *rootSizeStr = NULL;
    CHAR *rwTag = NULL;
W
wenjun 已提交
176

177 178 179 180
    ret = LOS_GetArgValue("root", dev);
    if (ret != LOS_OK) {
        PRINT_ERR("Cannot find root!");
        return ret;
W
wenjun 已提交
181 182
    }

183 184 185 186
    ret = LOS_GetArgValue("fstype", fstype);
    if (ret != LOS_OK) {
        PRINT_ERR("Cannot find fstype!");
        return ret;
187
    }
188 189 190 191 192 193

    ret = LOS_GetArgValue("rootaddr", &rootAddrStr);
    if (ret != LOS_OK) {
        *rootAddr = ROOTFS_ADDR;
    } else {
        *rootAddr = LOS_SizeStrToNum(rootAddrStr);
194
    }
195

196 197 198 199 200
    ret = LOS_GetArgValue("rootsize", &rootSizeStr);
    if (ret != LOS_OK) {
        *rootSize = ROOTFS_SIZE;
    } else {
        *rootSize = LOS_SizeStrToNum(rootSizeStr);
W
wenjun 已提交
201
    }
W
wangchen 已提交
202

203 204 205 206 207 208
    ret = LOS_GetArgValue("ro", &rwTag);
    if (ret == LOS_OK) {
        *mountFlags = MS_RDONLY;
    } else {
        *mountFlags = 0;
    }
W
wenjun 已提交
209

210
    return LOS_OK;
W
wenjun 已提交
211 212
}

W
wangchen 已提交
213 214
STATIC INT32 ParseUserArgs(UINT64 rootAddr, UINT64 rootSize, UINT64 *userAddr, UINT64 *userSize)
{
215
    INT32 ret;
W
wangchen 已提交
216 217
    CHAR *userAddrStr = NULL;
    CHAR *userSizeStr = NULL;
218 219 220 221 222 223

    ret = LOS_GetArgValue("useraddr", &userAddrStr);
    if (ret != LOS_OK) {
        *userAddr = rootAddr + rootSize;
    } else {
        *userAddr = LOS_SizeStrToNum(userAddrStr);
W
wenjun 已提交
224 225
    }

226 227 228 229 230
    ret = LOS_GetArgValue("usersize", &userSizeStr);
    if (ret != LOS_OK) {
        *userSize = USERFS_SIZE;
    } else {
        *userSize = LOS_SizeStrToNum(userSizeStr);
W
wenjun 已提交
231 232
    }

233
    return LOS_OK;
W
wenjun 已提交
234 235
}

W
wangchen 已提交
236 237
STATIC INT32 MountPartitions(CHAR *fsType, UINT32 mountFlags)
{
238 239 240 241
    INT32 ret;
    INT32 err;

    /* Mount rootfs */
242
    ret = mount(ROOT_DEV_NAME, ROOT_DIR_NAME, fsType, mountFlags, NULL);
243 244 245 246
    if (ret != LOS_OK) {
        err = get_errno();
        PRINT_ERR("Failed to mount %s, rootDev %s, errno %d: %s\n", ROOT_DIR_NAME, ROOT_DEV_NAME, err, strerror(err));
        return ret;
W
wenjun 已提交
247 248
    }

J
jason_gitee 已提交
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
#ifdef LOSCFG_STORAGE_EMMC
#ifdef LOSCFG_PLATFORM_PATCHFS
    /* Mount patch */
    ret = mkdir(PATCH_DIR_NAME, DEFAULT_MOUNT_DIR_MODE);
    if ((ret != LOS_OK) && ((err = get_errno()) != EEXIST)) {
        PRINT_ERR("Failed to mkdir %s, errno %d: %s\n", PATCH_DIR_NAME, err, strerror(err));
        return ret;
    }

    ret = mount(PATCH_DEV_NAME, PATCH_DIR_NAME, fsType, 0, DEFAULT_MOUNT_DATA);
    if ((ret != LOS_OK) && ((err = get_errno()) == ENOTSUP)) {
        ret = format(PATCH_DEV_NAME, 0, FM_FAT32);
        if (ret != LOS_OK) {
            PRINT_ERR("Failed to format %s\n", PATCH_DEV_NAME);
            return ret;
        }

        ret = mount(PATCH_DEV_NAME, PATCH_DIR_NAME, fsType, 0, DEFAULT_MOUNT_DATA);
        if (ret != LOS_OK) {
            err = get_errno();
        }
    }
    if (ret != LOS_OK) {
        PRINT_ERR("Failed to mount %s, errno %d: %s\n", PATCH_DIR_NAME, err, strerror(err));
        return ret;
    }
#endif
#endif

278 279 280 281 282
    /* Mount userfs */
    ret = mkdir(STORAGE_DIR_NAME, DEFAULT_MOUNT_DIR_MODE);
    if ((ret != LOS_OK) && ((err = get_errno()) != EEXIST)) {
        PRINT_ERR("Failed to mkdir %s, errno %d: %s\n", STORAGE_DIR_NAME, err, strerror(err));
        return ret;
W
wenjun 已提交
283 284
    }

285 286 287 288 289
    ret = mount(USER_DEV_NAME, STORAGE_DIR_NAME, fsType, 0, DEFAULT_MOUNT_DATA);
    if (ret != LOS_OK) {
        err = get_errno();
        PRINT_ERR("Failed to mount %s, errno %d: %s\n", STORAGE_DIR_NAME, err, strerror(err));
        return ret;
W
wenjun 已提交
290 291
    }

292 293 294 295 296 297
#ifdef LOSCFG_STORAGE_EMMC
    /* Mount userdata */
    ret = mkdir(USERDATA_DIR_NAME, DEFAULT_MOUNT_DIR_MODE);
    if ((ret != LOS_OK) && ((err = get_errno()) != EEXIST)) {
        PRINT_ERR("Failed to mkdir %s, errno %d: %s\n", USERDATA_DIR_NAME, err, strerror(err));
        return ret;
W
wenjun 已提交
298 299
    }

300 301 302 303 304 305
    ret = mount(USERDATA_DEV_NAME, USERDATA_DIR_NAME, fsType, 0, DEFAULT_MOUNT_DATA);
    if ((ret != LOS_OK) && ((err = get_errno()) == ENOTSUP)) {
        ret = format(USERDATA_DEV_NAME, 0, FM_FAT32);
        if (ret != LOS_OK) {
            PRINT_ERR("Failed to format %s\n", USERDATA_DEV_NAME);
            return ret;
306 307
        }

308 309 310
        ret = mount(USERDATA_DEV_NAME, USERDATA_DIR_NAME, fsType, 0, DEFAULT_MOUNT_DATA);
        if (ret != LOS_OK) {
            err = get_errno();
311 312
        }
    }
313 314 315 316 317
    if (ret != LOS_OK) {
        PRINT_ERR("Failed to mount %s, errno %d: %s\n", USERDATA_DIR_NAME, err, strerror(err));
        return ret;
    }
#endif
W
wenjun 已提交
318 319 320
    return LOS_OK;
}

W
wangchen 已提交
321 322
STATIC INT32 CheckValidation(UINT64 rootAddr, UINT64 rootSize, UINT64 userAddr, UINT64 userSize)
{
323 324
    UINT64 alignSize = LOS_GetAlignsize();
    if (alignSize == 0) {
W
wenjun 已提交
325 326 327
        return LOS_OK;
    }

328 329 330 331
    if ((rootAddr & (alignSize - 1)) || (rootSize & (alignSize - 1)) ||
        (userAddr & (alignSize - 1)) || (userSize & (alignSize - 1))) {
        PRINT_ERR("The address or size value should be 0x%x aligned!\n", alignSize);
        return LOS_NOK;
W
wenjun 已提交
332
    }
333 334

    return LOS_OK;
W
wenjun 已提交
335 336
}

W
wangchen 已提交
337 338
INT32 OsMountRootfs()
{
W
wenjun 已提交
339
    INT32 ret;
W
wangchen 已提交
340 341
    CHAR *dev = NULL;
    CHAR *fstype = NULL;
342 343 344 345
    UINT64 rootAddr;
    UINT64 rootSize;
    UINT64 userAddr;
    UINT64 userSize;
346
    UINT32 mountFlags;
347

348
    ret = ParseRootArgs(&dev, &fstype, &rootAddr, &rootSize, &mountFlags);
349 350
    if (ret != LOS_OK) {
        return ret;
W
wenjun 已提交
351
    }
352 353 354 355

    ret = ParseUserArgs(rootAddr, rootSize, &userAddr, &userSize);
    if (ret != LOS_OK) {
        return ret;
W
wenjun 已提交
356 357
    }

358 359 360
    ret = CheckValidation(rootAddr, rootSize, userAddr, userSize);
    if (ret != LOS_OK) {
        return ret;
W
wenjun 已提交
361 362
    }

363
    ret = AddPartitions(dev, rootAddr, rootSize, userAddr, userSize);
W
wenjun 已提交
364 365 366 367
    if (ret != LOS_OK) {
        return ret;
    }

368
    ret = MountPartitions(fstype, mountFlags);
369 370
    if (ret != LOS_OK) {
        return ret;
W
wenjun 已提交
371 372
    }

373 374
    return LOS_OK;
}