summaryrefslogtreecommitdiffstats
path: root/target/linux/ramips/patches-3.9/0208-owrt-mtd-split.patch
blob: f15d16f6da5ffe6e57cb88c018a081bb021380da (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
From 2a295753a10823a47542c779a25bbb1f52c71281 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 3 Aug 2012 10:27:13 +0200
Subject: [PATCH 19/25] owrt mtd split

---
 .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    1 +
 arch/mips/lantiq/setup.c                           |    7 +
 drivers/mtd/Kconfig                                |    4 +
 drivers/mtd/mtdpart.c                              |  173 +++++++++++++++++++-
 4 files changed, 184 insertions(+), 1 deletions(-)

--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -31,6 +31,10 @@ config MTD_ROOTFS_SPLIT
 	bool "Automatically split 'rootfs' partition for squashfs"
 	default y
 
+config MTD_UIMAGE_SPLIT
+	bool "Automatically split 'linux' partition into 'kernel' and 'rootfs'"
+	default y
+
 config MTD_REDBOOT_PARTS
 	tristate "RedBoot partition table parsing"
 	---help---
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -833,6 +833,99 @@ static int refresh_rootfs_split(struct m
 }
 #endif /* CONFIG_MTD_ROOTFS_SPLIT */
 
+#ifdef CONFIG_MTD_UIMAGE_SPLIT
+static unsigned long find_uimage_size(struct mtd_info *mtd,
+				      unsigned long offset)
+{
+#define UBOOT_MAGIC	0x56190527
+	unsigned long magic = 0;
+	unsigned long temp;
+	size_t len;
+	int ret;
+
+	ret = mtd_read(mtd, offset, 4, &len, (void *)&magic);
+	if (ret || len != sizeof(magic))
+		return 0;
+
+	if (le32_to_cpu(magic) != UBOOT_MAGIC)
+		return 0;
+
+	ret = mtd_read(mtd, offset + 12, 4, &len, (void *)&temp);
+	if (ret || len != sizeof(temp))
+		return 0;
+
+	return be32_to_cpu(temp) + 0x40;
+}
+
+static int detect_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
+{
+	unsigned long temp;
+	size_t len;
+	int ret;
+
+	ret = mtd_read(mtd, offset, 4, &len, (void *)&temp);
+	if (ret || len != sizeof(temp))
+		return 0;
+
+	return le32_to_cpu(temp) == SQUASHFS_MAGIC;
+}
+
+static unsigned long find_squashfs_offset(struct mtd_info *mtd, unsigned long _offset)
+{
+	/* scan the first 2MB at 64K offsets */
+	int i;
+
+	for (i = 0; i < 32; i++) {
+		unsigned long offset = i * 64 * 1024;
+		if (detect_squashfs_partition(mtd, _offset + offset))
+			return offset;
+	}
+	return 0;
+}
+
+static int split_uimage(struct mtd_info *mtd,
+			const struct mtd_partition *part)
+{
+	static struct mtd_partition split_partitions[] = {
+		{
+			.name = "kernel",
+			.offset = 0x0,
+			.size = 0x0,
+		}, {
+			.name = "rootfs",
+			.offset = 0x0,
+			.size = 0x0,
+		},
+	};
+
+	split_partitions[0].size = find_uimage_size(mtd, part->offset);
+	if (!split_partitions[0].size) {
+		split_partitions[0].size = find_squashfs_offset(mtd, part->offset);
+		if (!split_partitions[0].size) {
+			pr_err("failed to split firmware partition\n");
+			return -1;
+		}
+	}
+
+	if (!detect_squashfs_partition(mtd,
+				       part->offset
+				       + split_partitions[0].size)) {
+		split_partitions[0].size &= ~(mtd->erasesize - 1);
+		split_partitions[0].size += mtd->erasesize;
+	} else {
+		pr_info("found squashfs behind kernel\n");
+	}
+
+	split_partitions[0].offset = part->offset;
+	split_partitions[1].offset = part->offset + split_partitions[0].size;
+	split_partitions[1].size = part->size - split_partitions[0].size;
+
+	add_mtd_partitions(mtd, split_partitions, 2);
+
+	return 0;
+}
+#endif
+
 /*
  * This function, given a master MTD object and a partition table, creates
  * and registers slave MTD objects which are bound to the master according to
@@ -849,7 +942,7 @@ int add_mtd_partitions(struct mtd_info *
 	struct mtd_part *slave;
 	uint64_t cur_offset = 0;
 	int i;
-#ifdef CONFIG_MTD_ROOTFS_SPLIT
+#if defined(CONFIG_MTD_ROOTFS_SPLIT) || defined(CONFIG_MTD_UIMAGE_SPLIT)
 	int ret;
 #endif
 
@@ -866,6 +959,14 @@ int add_mtd_partitions(struct mtd_info *
 
 		add_mtd_device(&slave->mtd);
 
+#ifdef CONFIG_MTD_UIMAGE_SPLIT
+		if (!strcmp(parts[i].name, "firmware")) {
+			ret = split_uimage(master, &parts[i]);
+			if (ret)
+				printk(KERN_WARNING "Can't split firmware partition\n");
+		}
+#endif
+
 		if (!strcmp(parts[i].name, "rootfs")) {
 #ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
 			if (ROOT_DEV == 0) {