los_rootfs.c 10.3 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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
        return LOS_NOK;
    }

    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 已提交
100
    LOS_Msleep(10); /* 100, sleep time. waiting for device identification */
101 102 103 104 105 106 107 108 109 110

    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 已提交
111
    }
112 113

    return LOS_OK;
W
wenjun 已提交
114 115 116
}
#endif

117 118

STATIC INT32 AddPartitions(CHAR *dev, UINT64 rootAddr, UINT64 rootSize, UINT64 userAddr, UINT64 userSize)
W
wenjun 已提交
119
{
120 121 122 123 124 125
#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 已提交
126

127
#if defined(LOSCFG_STORAGE_SPINOR) || defined(LOSCFG_STORAGE_SPINAND) || defined(LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7)
W
wenjun 已提交
128
    INT32 ret;
129 130 131 132
    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 已提交
133
        if (ret != LOS_OK) {
134 135
            PRINT_ERR("Failed to add mtd root partition!\n");
            return LOS_NOK;
W
wenjun 已提交
136 137
        }

138 139 140 141
        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 已提交
142
        }
143 144 145

        return LOS_OK;
    }
W
wenjun 已提交
146 147
#endif

M
mamingshuai 已提交
148
#ifdef LOSCFG_STORAGE_EMMC
149 150 151
    if (strcmp(dev, "emmc") == 0) {
        return AddEmmcParts(rootAddr, rootSize, userAddr, userSize);
    }
W
wenjun 已提交
152
#endif
153

154 155
    PRINT_ERR("Unsupport dev type: %s\n", dev);
    return LOS_NOK;
W
wenjun 已提交
156 157
}

M
mamingshuai 已提交
158

W
wangchen 已提交
159 160
STATIC INT32 ParseRootArgs(CHAR **dev, CHAR **fstype, UINT64 *rootAddr, UINT64 *rootSize, UINT32 *mountFlags)
{
W
wenjun 已提交
161
    INT32 ret;
W
wangchen 已提交
162 163 164
    CHAR *rootAddrStr = NULL;
    CHAR *rootSizeStr = NULL;
    CHAR *rwTag = NULL;
W
wenjun 已提交
165

166 167 168 169
    ret = LOS_GetArgValue("root", dev);
    if (ret != LOS_OK) {
        PRINT_ERR("Cannot find root!");
        return ret;
W
wenjun 已提交
170 171
    }

172 173 174 175
    ret = LOS_GetArgValue("fstype", fstype);
    if (ret != LOS_OK) {
        PRINT_ERR("Cannot find fstype!");
        return ret;
176
    }
177 178 179 180 181 182

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

185 186 187 188 189
    ret = LOS_GetArgValue("rootsize", &rootSizeStr);
    if (ret != LOS_OK) {
        *rootSize = ROOTFS_SIZE;
    } else {
        *rootSize = LOS_SizeStrToNum(rootSizeStr);
W
wenjun 已提交
190
    }
W
wangchen 已提交
191

192 193 194 195 196 197
    ret = LOS_GetArgValue("ro", &rwTag);
    if (ret == LOS_OK) {
        *mountFlags = MS_RDONLY;
    } else {
        *mountFlags = 0;
    }
W
wenjun 已提交
198

199
    return LOS_OK;
W
wenjun 已提交
200 201
}

W
wangchen 已提交
202 203
STATIC INT32 ParseUserArgs(UINT64 rootAddr, UINT64 rootSize, UINT64 *userAddr, UINT64 *userSize)
{
204
    INT32 ret;
W
wangchen 已提交
205 206
    CHAR *userAddrStr = NULL;
    CHAR *userSizeStr = NULL;
207 208 209 210 211 212

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

215 216 217 218 219
    ret = LOS_GetArgValue("usersize", &userSizeStr);
    if (ret != LOS_OK) {
        *userSize = USERFS_SIZE;
    } else {
        *userSize = LOS_SizeStrToNum(userSizeStr);
W
wenjun 已提交
220 221
    }

222
    return LOS_OK;
W
wenjun 已提交
223 224
}

W
wangchen 已提交
225 226
STATIC INT32 MountPartitions(CHAR *fsType, UINT32 mountFlags)
{
227 228 229 230
    INT32 ret;
    INT32 err;

    /* Mount rootfs */
231
    ret = mount(ROOT_DEV_NAME, ROOT_DIR_NAME, fsType, mountFlags, NULL);
232 233 234 235
    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 已提交
236 237
    }

238 239 240 241 242
    /* 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 已提交
243 244
    }

245 246 247 248 249
    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 已提交
250 251
    }

252 253 254 255 256 257
#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 已提交
258 259
    }

260 261 262 263 264 265
    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;
266 267
        }

268 269 270
        ret = mount(USERDATA_DEV_NAME, USERDATA_DIR_NAME, fsType, 0, DEFAULT_MOUNT_DATA);
        if (ret != LOS_OK) {
            err = get_errno();
271 272
        }
    }
273 274 275 276 277
    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 已提交
278 279 280
    return LOS_OK;
}

W
wangchen 已提交
281 282
STATIC INT32 CheckValidation(UINT64 rootAddr, UINT64 rootSize, UINT64 userAddr, UINT64 userSize)
{
283
    UINT64 alignSize = LOS_GetAlignsize();
W
wenjun 已提交
284

285
    if (alignSize == 0) {
W
wenjun 已提交
286 287 288
        return LOS_OK;
    }

289 290 291 292
    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 已提交
293
    }
294 295

    return LOS_OK;
W
wenjun 已提交
296 297
}

W
wangchen 已提交
298 299
INT32 OsMountRootfs()
{
W
wenjun 已提交
300
    INT32 ret;
W
wangchen 已提交
301 302
    CHAR *dev = NULL;
    CHAR *fstype = NULL;
303 304 305 306
    UINT64 rootAddr;
    UINT64 rootSize;
    UINT64 userAddr;
    UINT64 userSize;
307
    UINT32 mountFlags;
308

309
    ret = ParseRootArgs(&dev, &fstype, &rootAddr, &rootSize, &mountFlags);
310 311
    if (ret != LOS_OK) {
        return ret;
W
wenjun 已提交
312
    }
313 314 315 316

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

319 320 321
    ret = CheckValidation(rootAddr, rootSize, userAddr, userSize);
    if (ret != LOS_OK) {
        return ret;
W
wenjun 已提交
322 323
    }

324
    ret = AddPartitions(dev, rootAddr, rootSize, userAddr, userSize);
W
wenjun 已提交
325 326 327 328
    if (ret != LOS_OK) {
        return ret;
    }

329
    ret = MountPartitions(fstype, mountFlags);
330 331
    if (ret != LOS_OK) {
        return ret;
W
wenjun 已提交
332 333
    }

334 335
    return LOS_OK;
}