fstools: support for ext4fs overlay
authorRam Chandra Jangir <rjangi@codeaurora.org>
Fri, 11 Mar 2016 16:31:42 +0000 (22:01 +0530)
committerJohn Crispin <blogic@openwrt.org>
Fri, 22 Apr 2016 20:07:28 +0000 (22:07 +0200)
This change will enables eMMC (ext4 fs) boot support, when we try to boot
from eMMC card then it will read partition names from
/sys/block/mmcblkX/mmcblkXY/uevent
file and will mount the rootfs_data partition as ext4fs overlay.

Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org>
CMakeLists.txt
libfstools/ext4.c [new file with mode: 0644]
libfstools/find.c
libfstools/libfstools.h
libfstools/overlay.c
libfstools/volume.h
mount_root.c

index a6002e5fe9e0b2a390d59d38ce75b8cffeaa8122..5117e8e93194b38bef7b5588431dacf4d5130dff 100644 (file)
@@ -11,6 +11,7 @@ ADD_LIBRARY(fstools SHARED
                libfstools/overlay.c
                libfstools/volume.c
                libfstools/mtd.c
+               libfstools/ext4.c
                libfstools/mount.c
                libfstools/ubi.c
                libfstools/find.c)
diff --git a/libfstools/ext4.c b/libfstools/ext4.c
new file mode 100644 (file)
index 0000000..f648aa8
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <asm/byteorder.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <mtd/mtd-user.h>
+#include <glob.h>
+
+#include "libfstools.h"
+
+#include "volume.h"
+
+#define ext4_sysfs_path "/sys/block/mmcblk*/mmcblk*/uevent"
+#define MAX_SIZE       128
+
+#define EXT_SB_OFF     0x400
+#define EXT_SB_KBOFF   (EXT_SB_OFF >> 10)
+#define EXT_SB_MAGIC   "\123\357"
+#define EXT_MAG_OFF    0x38
+
+struct ext4_priv {
+       char    *name;
+       char    *devname;
+};
+
+static struct driver ext4_driver;
+
+static int ext4_volume_init(struct volume *v)
+{
+       char buf[MAX_SIZE];
+       struct ext4_priv *p;
+
+       p = (struct ext4_priv*)v->priv;
+       snprintf(buf, sizeof(buf), "/dev/%s",p->devname);
+
+       v->name = strdup(p->name);
+       v->type = EXT4VOLUME;
+       v->blk = strdup(buf);
+       return 0;
+}
+
+static int
+ext4_part_match(char *dev, char *name, char *filename)
+{
+       FILE *fp;
+       char buf[MAX_SIZE];
+       char devname[MAX_SIZE];
+       int i;
+       int ret = -1;
+
+       fp = fopen(filename, "r");
+       if (!fp)
+               return ret;
+
+       while (fgets(buf, sizeof(buf), fp))  {
+               if (strstr(buf, "DEVNAME"))  {
+                       strcpy(devname, buf + strlen("DEVNAME="));
+                       continue;
+               }
+               /* Match partition name */
+               if (strstr(buf, name))  {
+                       ret = 0;
+                       break;
+               }
+       }
+
+       fclose(fp);
+
+       /* make sure the string is \0 terminated */
+       devname[sizeof(devname) - 1] = '\0';
+
+       /* remove trailing whitespace */
+       i = strlen(devname) - 1;
+       while (i > 0 && devname[i] <= ' ')
+               devname[i--] = '\0';
+
+       strcpy(dev, devname);
+       return ret;
+}
+
+static int ext4_find_devname(char *dev, char *name)
+{
+       int i;
+       glob_t gl;
+
+       if (glob(ext4_sysfs_path, GLOB_NOESCAPE | GLOB_MARK, NULL, &gl) < 0)
+               return -1;
+
+       for (i = 0; i < gl.gl_pathc; i++) {
+               if (!ext4_part_match(dev, name, gl.gl_pathv[i])) {
+                       globfree(&gl);
+                       return 0;
+               }
+       }
+
+       globfree(&gl);
+       return -1;
+}
+
+static int check_for_mtd(const char *mtd)
+{
+       FILE *fp;
+       char dev[MAX_SIZE];
+
+       if ((fp = fopen("/proc/mtd", "r"))) {
+               while (fgets(dev, sizeof(dev), fp)) {
+                       if (strstr(dev, mtd)) {
+                               fclose(fp);
+                               return -1;
+                       }
+               }
+       }
+       fclose(fp);
+       return 0;
+}
+
+static int ext4_volume_find(struct volume *v, char *name)
+{
+       char buf[MAX_SIZE];
+       struct ext4_priv *p;
+
+       if (find_filesystem("ext4"))
+               return -1;
+
+       if (check_for_mtd(name))
+               return -1;
+
+       if (ext4_find_devname(buf, name))
+               return -1;
+
+        p = calloc(1, sizeof(struct ext4_priv));
+        if (!p)
+                return -1;
+
+        v->priv = p;
+        v->drv = &ext4_driver;
+
+        p->devname = strdup(buf);
+        p->name = strdup(name);
+        return ext4_volume_init(v);
+}
+
+static int ext4_volume_identify(struct volume *v)
+{
+       char magic[32] = { 0 };
+       int off = (EXT_SB_KBOFF * 1024) + EXT_MAG_OFF;
+       int fd;
+
+       fd = open(v->blk, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       lseek(fd, off, SEEK_SET);
+       read(fd, magic, sizeof(EXT_SB_MAGIC) - 1);
+       close(fd);
+
+       if (v->type == EXT4VOLUME &&
+           !memcmp(EXT_SB_MAGIC, magic, sizeof(EXT_SB_MAGIC) - 1)) {
+               return FS_EXT4FS;
+       }
+
+       ULOG_ERR("ext4 is not ready - marker found\n");
+       return FS_DEADCODE;
+}
+
+static struct driver ext4_driver = {
+        .name = "ext4",
+        .find = ext4_volume_find,
+        .init = ext4_volume_init,
+        .identify = ext4_volume_identify,
+};
+
+DRIVER(ext4_driver);
index 0440052bf51c42bd7be2ff876e9ddd1a228263b4..9fd83c9d3396e04d4eb7572958e3e5b573cbe40e 100644 (file)
@@ -102,7 +102,8 @@ find_mount_point(char *block, int mtd_only)
 
                        if (mtd_only &&
                            strncmp(t, "jffs2", 5) &&
-                           strncmp(t, "ubifs", 5)) {
+                           strncmp(t, "ubifs", 5) &&
+                           strncmp(t, "ext4", 4)) {
                                fclose(fp);
                                ULOG_ERR("block is mounted with wrong fs\n");
                                return NULL;
index 31d9f9e0364ebc2782dce118eea404dbe2ec06e9..940c504dc8341a3de6ce6e542b9732a28200ec87 100644 (file)
@@ -26,6 +26,7 @@ enum {
        FS_JFFS2,
        FS_DEADCODE,
        FS_UBIFS,
+       FS_EXT4FS,
 };
 
 enum fs_state {
index cdac23e0d04bb6c707d9ca873085936a9749c545..f8088f98e704eba6eaf9400d50ecc892321189fa 100644 (file)
@@ -245,6 +245,16 @@ jffs2_switch(struct volume *v)
                        ret = -1;
                }
                break;
+
+       case FS_EXT4FS:
+               ret = overlay_mount(v, "ext4");
+               if (ret)
+                       break;
+               if (mount_move("/tmp", "", "/overlay") || fopivot("/overlay", "/rom")) {
+                       ULOG_ERR("switching to ext4fs failed\n");
+                       ret = -1;
+               }
+               break;
        }
 
        if (ret)
@@ -270,6 +280,10 @@ static int overlay_mount_fs(struct volume *v)
        case FS_UBIFS:
                fstype = "ubifs";
                break;
+
+       case FS_EXT4FS:
+               fstype = "ext4";
+               break;
        }
 
        volume_init(v);
index 9c679f7fb126665886d59e9399d0930ddca30768..b74bd505c72040d920faae8813d618b67b9c2378 100644 (file)
@@ -47,6 +47,7 @@ enum {
        NANDFLASH,
        NORFLASH,
        UBIVOLUME,
+       EXT4VOLUME,
 };
 
 struct volume {
index bf70265d45cc49568562e58ecfe6bd6cf41929be..47a3409dfcd48361dd77dfd40a41b5068b4bb08d 100644 (file)
@@ -68,6 +68,7 @@ start(int argc, char *argv[1])
 
        case FS_JFFS2:
        case FS_UBIFS:
+       case FS_EXT4FS:
                mount_overlay(data);
                break;
 
@@ -106,6 +107,7 @@ done(int argc, char *argv[1])
 
        case FS_JFFS2:
        case FS_UBIFS:
+       case FS_EXT4FS:
                fs_state_set("/overlay", FS_STATE_READY);
                break;
        }