From ece50ef6d4b5191636c971ee3896ca22fa538625 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 5 Nov 2013 16:16:03 +0100 Subject: [PATCH] mount_root: fix jffs2 handling on MTD devices emulated by gluebi The jffs2_ready() function in mount_root.c checks the presence of various JFFS2 markers at the start of a given MTD device. The function works on NOR flashes because JFFS2 puts 'cleanmarker' nodes at the start of freshly erased blocks. However if jffs2 is used on a MTD device emulated by the gluebi layer, the 'cleanmarker' nodes are not present and the jffs2_ready() function fails. Update the code to handle jffs2 correctly even on MTD devices emulated by the gluebi layer. Signed-off-by: Gabor Juhos --- mount_root.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 7 deletions(-) --- a/mount_root.c +++ b/mount_root.c @@ -54,6 +54,14 @@ enum { FS_DEADCODE, }; +enum mtd_type { + MTD_TYPE_NOT_FOUND, + MTD_TYPE_NOR, + MTD_TYPE_NAND, + MTD_TYPE_UBI, + MTD_TYPE_UNKNOWN, +}; + static const char *argv0; /* this is a raw syscall - man 2 pivot_root */ @@ -223,6 +231,64 @@ static int find_mtd_char(char *name, cha return 0; } +static enum mtd_type mtd_get_type(char *index) +{ + static char p[256]; + static char buf[32]; + FILE *fp; + size_t sz; + + snprintf(p, sizeof(p), "/sys/class/mtd/mtd%s/type", index); + + fp = fopen(p, "r"); + if (!fp) { + ERROR("unable to open %s\n", p); + return MTD_TYPE_NOT_FOUND; + } + + memset(buf, 0, sizeof(buf)); + sz = fread(buf, 1, sizeof(buf) - 1, fp); + fclose(fp); + + if (sz <= 1) { + ERROR("unable to read from %s\n", p); + return MTD_TYPE_UNKNOWN; + } + + while (sz > 0) { + sz--; + + if (buf[sz] != '\n') + break; + + buf[sz] = 0; + } + + if (strcmp(buf, "nor") == 0) + return MTD_TYPE_NOR; + + if (strcmp(buf, "nand") == 0) + return MTD_TYPE_NAND; + + if (strcmp(buf, "ubi") == 0) + return MTD_TYPE_UBI; + + ERROR("mtd%s has unknow type '%s'\n", index, buf); + return MTD_TYPE_UNKNOWN; +} + +static enum mtd_type mtd_get_type_by_name(char *name) +{ + char *index; + + index = find_mtd_index(name); + if (!index) + return MTD_TYPE_NOT_FOUND; + + return mtd_get_type(index); +} + + static int mtd_unlock(char *mtd) { struct erase_info_user mtdlock; @@ -277,7 +343,7 @@ static int mtd_mount_jffs2(void) return mtd_unlock(rootfs_data); } -static int jffs2_ready(char *mtd) +static int jffs2_ready(char *mtd, enum mtd_type type) { FILE *fp = fopen(mtd, "r"); __u32 deadc0de; @@ -298,16 +364,21 @@ static int jffs2_ready(char *mtd) } deadc0de = __be32_to_cpu(deadc0de); - jffs2 = __be16_to_cpu(deadc0de >> 16); + if (deadc0de == 0xdeadc0de) { + LOG("jffs2 is not ready - EOF marker found\n"); + return FS_DEADCODE; + } + jffs2 = __be16_to_cpu(deadc0de >> 16); if (jffs2 == 0x1985) { LOG("jffs2 is ready\n"); return FS_JFFS2; } - if (deadc0de == 0xdeadc0de) { - LOG("jffs2 is not ready - marker found\n"); - return FS_DEADCODE; + if (type == MTD_TYPE_UBI && + deadc0de == 0xffffffff) { + LOG("jffs2 is ready\n"); + return FS_JFFS2; } ERROR("No jffs2 marker was found\n"); @@ -638,6 +709,7 @@ static int main_switch2jffs(int argc, ch char mtd[32]; char *mp; int ret = -1; + enum mtd_type type; if (find_overlay_mount("overlayfs:/tmp/root")) return -1; @@ -659,7 +731,8 @@ static int main_switch2jffs(int argc, ch return ret; } - switch (jffs2_ready(mtd)) { + type = mtd_get_type_by_name("rootfs_data"); + switch (jffs2_ready(mtd, type)) { case FS_NONE: ERROR("no jffs2 marker found\n"); /* fall through */ @@ -781,12 +854,15 @@ int main(int argc, char **argv) LOG("mounting /dev/root\n"); mount("/dev/root", "/", NULL, MS_NOATIME | MS_REMOUNT, 0); } else { + enum mtd_type type; + if (!extroot("")) { fprintf(stderr, "mount_root: switched to extroot\n"); return 0; } - switch (jffs2_ready(mtd)) { + type = mtd_get_type_by_name("rootfs_data"); + switch (jffs2_ready(mtd, type)) { case FS_NONE: case FS_DEADCODE: return ramoverlay();