summaryrefslogtreecommitdiff
path: root/package/system/ubox/patches/0001-mount_root-fix-jffs2-handling-on-MTD-devices-emulate.patch
blob: 67805450ba5bbe3ec76b1a6ced32d3b66a48972a (plain)
1
2
3
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
From ece50ef6d4b5191636c971ee3896ca22fa538625 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
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 <juhosg@openwrt.org>
---
 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();