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
|
--- a/drivers/mtd/maps/lantiq.c
+++ b/drivers/mtd/maps/lantiq.c
@@ -24,6 +24,10 @@
#include <lantiq.h>
#include <lantiq_platform.h>
+#ifdef CONFIG_SOC_LANTIQ_XWAY
+#include <xway.h>
+#endif
+
static map_word
lq_read16(struct map_info *map, unsigned long adr)
{
@@ -77,6 +81,75 @@ lq_copy_to(struct map_info *map, unsigne
spin_unlock_irqrestore(&ebu_lock, flags);
}
+static unsigned long
+find_uImage_size(struct map_info *map, unsigned long offset)
+{
+#define UBOOT_MAGIC 0x56190527
+ unsigned long magic;
+ unsigned long temp;
+ map->copy_from(map, &magic, offset, 4);
+ if (le32_to_cpu(magic) != UBOOT_MAGIC)
+ return 0;
+ map->copy_from(map, &temp, offset + 12, 4);
+ return temp + 0x40;
+}
+
+static int
+detect_squashfs_partition(struct map_info *map, unsigned long offset)
+{
+ unsigned long temp;
+ map->copy_from(map, &temp, offset, 4);
+ return le32_to_cpu(temp) == SQUASHFS_MAGIC;
+}
+
+static struct mtd_partition split_partitions[] = {
+ {
+ .name = "kernel",
+ .offset = 0x0,
+ .size = 0x0,
+ }, {
+ .name = "rootfs",
+ .offset = 0x0,
+ .size = 0x0,
+ },
+};
+
+static int
+mtd_split_linux(struct map_info *map, struct mtd_info *mtd,
+ struct mtd_partition *parts, int nr_parts)
+{
+ int base_part = 0;
+ int i;
+ for (i = 0; i < nr_parts && !base_part; i++) {
+ if(!strcmp("linux", parts[i].name))
+ base_part = i;
+ }
+ if (!base_part)
+ return 0;
+ split_partitions[0].size = find_uImage_size(map, parts[base_part].offset);
+ if (!split_partitions[0].size) {
+ printk(KERN_INFO "lq_nor: no uImage found in linux partition");
+ return -1;
+ }
+ if (!detect_squashfs_partition(map,
+ parts[base_part].offset + split_partitions[0].size)) {
+ split_partitions[0].size &= ~(mtd->erasesize - 1);
+ split_partitions[0].size += mtd->erasesize;
+ }
+ split_partitions[0].offset = parts[base_part].offset;
+ split_partitions[1].offset =
+ parts[base_part].offset + split_partitions[0].size;
+ split_partitions[1].size =
+ parts[base_part].size - split_partitions[0].size;
+
+ base_part++;
+ add_mtd_partitions(mtd, parts, base_part);
+ add_mtd_partitions(mtd, split_partitions, 2);
+ if(nr_parts != base_part)
+ add_mtd_partitions(mtd, &parts[base_part], nr_parts - base_part);
+ return nr_parts + 2;
+}
+
static const char *part_probe_types[] = { "cmdlinepart", NULL };
static struct map_info lq_map = {
@@ -142,7 +215,8 @@ lq_mtd_probe(struct platform_device *pde
parts = lq_mtd_data->parts;
}
- add_mtd_partitions(lq_mtd, parts, nr_parts);
+ if (!mtd_split_linux(&lq_map, lq_mtd, parts, nr_parts))
+ add_mtd_partitions(lq_mtd, parts, nr_parts);
return 0;
}
|