[lantiq]
[openwrt.git] / target / linux / lantiq / patches-3.0 / 201-owrt-mtd_uimage_split.patch
1 --- a/drivers/mtd/Kconfig
2 +++ b/drivers/mtd/Kconfig
3 @@ -41,6 +41,10 @@ config MTD_ROOTFS_SPLIT
4         bool "Automatically split 'rootfs' partition for squashfs"
5         default y
6  
7 +config MTD_UIMAGE_SPLIT
8 +       bool "Automatically split 'linux' partition into 'kernel' and 'rootfs'"
9 +       default y
10 +
11  config MTD_REDBOOT_PARTS
12         tristate "RedBoot partition table parsing"
13         ---help---
14 --- a/drivers/mtd/mtdpart.c
15 +++ b/drivers/mtd/mtdpart.c
16 @@ -861,6 +861,82 @@ static int refresh_rootfs_split(struct m
17  }
18  #endif /* CONFIG_MTD_ROOTFS_SPLIT */
19  
20 +
21 +#ifdef CONFIG_MTD_UIMAGE_SPLIT
22 +static unsigned long find_uimage_size(struct mtd_info *mtd,
23 +                                     unsigned long offset)
24 +{
25 +#define UBOOT_MAGIC    0x56190527
26 +       unsigned long magic = 0;
27 +       unsigned long temp;
28 +       size_t len;
29 +       int ret;
30 +
31 +       ret = mtd->read(mtd, offset, 4, &len, (void *)&magic);
32 +       if (ret || len != sizeof(magic))
33 +               return 0;
34 +
35 +       if (le32_to_cpu(magic) != UBOOT_MAGIC)
36 +               return 0;
37 +
38 +       ret = mtd->read(mtd, offset + 12, 4, &len, (void *)&temp);
39 +       if (ret || len != sizeof(temp))
40 +               return 0;
41 +
42 +       return temp + 0x40;
43 +}
44 +
45 +static int detect_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
46 +{
47 +       unsigned long temp;
48 +       size_t len;
49 +       int ret;
50 +
51 +       ret = mtd->read(mtd, offset, 4, &len, (void *)&temp);
52 +       if (ret || len != sizeof(temp))
53 +               return 0;
54 +
55 +       return le32_to_cpu(temp) == SQUASHFS_MAGIC;
56 +}
57 +
58 +static int split_uimage(struct mtd_info *mtd,
59 +                       const struct mtd_partition *part)
60 +{
61 +       static struct mtd_partition split_partitions[] = {
62 +               {
63 +                       .name = "kernel",
64 +                       .offset = 0x0,
65 +                       .size = 0x0,
66 +               }, {
67 +                       .name = "rootfs",
68 +                       .offset = 0x0,
69 +                       .size = 0x0,
70 +               },
71 +       };
72 +
73 +       split_partitions[0].size = find_uimage_size(mtd, part->offset);
74 +       if (!split_partitions[0].size) {
75 +               printk(KERN_NOTICE "no uImage found in linux partition\n");
76 +               return -1;
77 +       }
78 +
79 +       if (!detect_squashfs_partition(mtd,
80 +                                      part->offset
81 +                                      + split_partitions[0].size)) {
82 +               split_partitions[0].size &= ~(mtd->erasesize - 1);
83 +               split_partitions[0].size += mtd->erasesize;
84 +       }
85 +
86 +       split_partitions[0].offset = part->offset;
87 +       split_partitions[1].offset = part->offset + split_partitions[0].size;
88 +       split_partitions[1].size = part->size - split_partitions[0].size;
89 +
90 +       add_mtd_partitions(mtd, split_partitions, 2);
91 +
92 +       return 0;
93 +}
94 +#endif
95 +
96  /*
97   * This function, given a master MTD object and a partition table, creates
98   * and registers slave MTD objects which are bound to the master according to
99 @@ -894,6 +970,17 @@ int add_mtd_partitions(struct mtd_info *
100  
101                 add_mtd_device(&slave->mtd);
102  
103 +#ifdef CONFIG_MTD_UIMAGE_SPLIT
104 +               if (!strcmp(parts[i].name, "linux")) {
105 +                       ret = split_uimage(master, &parts[i]);
106 +
107 +                       if (ret) {
108 +                               printk(KERN_WARNING
109 +                                      "Can't split linux partition\n");
110 +                       }
111 +               }
112 +#endif
113 +
114                 if (!strcmp(parts[i].name, "rootfs")) {
115  #ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
116                         if (ROOT_DEV == 0) {