lantiq: Add support for linux 4.1
[openwrt/openwrt.git] / target / linux / lantiq / patches-4.1 / 0101-mtd-split.patch
diff --git a/target/linux/lantiq/patches-4.1/0101-mtd-split.patch b/target/linux/lantiq/patches-4.1/0101-mtd-split.patch
new file mode 100644 (file)
index 0000000..acda5aa
--- /dev/null
@@ -0,0 +1,192 @@
+--- a/arch/mips/lantiq/xway/Makefile
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -1,6 +1,6 @@
+ obj-y := prom.o sysctrl.o clk.o reset.o dma.o timer.o dcdc.o
+-obj-y += vmmc.o tffs.o
++obj-y += vmmc.o tffs.o mtd_split.o
+ obj-y += eth_mac.o
+ obj-$(CONFIG_PCI) += ath_eep.o rt_eep.o pci-ath-fixup.o
+--- /dev/null
++++ b/arch/mips/lantiq/xway/mtd_split.c
+@@ -0,0 +1,129 @@
++#include <linux/magic.h>
++#include <linux/root_dev.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++
++#define ROOTFS_SPLIT_NAME "rootfs_data"
++
++struct squashfs_super_block {
++      __le32 s_magic;
++      __le32 pad0[9];
++      __le64 bytes_used;
++};
++
++static void split_brnimage_kernel(struct mtd_info *master, const char *name,
++                                       int offset, int size)
++{
++      unsigned long buf[4];
++      // Assume at most 2MB of kernel image
++      unsigned long end = offset + (2 << 20);
++      unsigned long part_size = offset + 0x400 - 12;
++      size_t len;
++      int ret;
++
++      if (strcmp(name, "firmware") != 0)
++              return;
++      while (part_size < end) {
++              long size_min = part_size - 0x400 - 12 - offset;
++              long size_max = part_size + 12 - offset;
++              ret = mtd_read(master, part_size, 16, &len, (void *)buf);
++              if (ret || len != 16)
++                      return;
++
++              if (le32_to_cpu(buf[0]) < size_min ||
++                              le32_to_cpu(buf[0]) > size_max) {
++                      part_size += 0x400;
++                      continue;
++              }
++
++              if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC) {
++                      part_size += 12 - offset;
++                      __mtd_add_partition(master, "rootfs", offset + part_size,
++                                                  size - part_size, false);
++                      return;
++              }
++              part_size += 0x400;
++      }
++}
++
++static void split_eva_kernel(struct mtd_info *master, const char *name,
++                              int offset, int size)
++{
++#define EVA_MAGIC   0xfeed1281
++      unsigned long magic = 0;
++      unsigned long part_size = 0, p;
++      size_t len;
++      int ret;
++
++      if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
++              return;
++
++      ret = mtd_read(master, offset, 4, &len, (void *)&magic);
++      if (ret || len != sizeof(magic))
++              return;
++
++      if (le32_to_cpu(magic) != EVA_MAGIC)
++              return;
++
++      ret = mtd_read(master, offset + 4, 4, &len, (void *)&part_size);
++      if (ret || len != sizeof(part_size))
++              return;
++
++      p = part_size = le32_to_cpu(part_size) + 0x18;
++      p &= ~0xffff;
++      p += 0x10000;
++
++      ret = mtd_read(master, offset + p, 4, &len, (void *)&magic);
++      if (ret || len != sizeof(magic))
++              return;
++
++      if (magic == SQUASHFS_MAGIC)
++              part_size = p + 0x100;
++      else
++              part_size = mtd_pad_erasesize(master, offset, len);
++
++      if (part_size + master->erasesize > size)
++              return;
++
++      __mtd_add_partition(master, "rootfs", offset + part_size,
++                          size - part_size, false);
++}
++
++static void split_tplink_kernel(struct mtd_info *master, const char *name,
++                              int offset, int size)
++{
++#define TPLINK_MAGIC   0x00000002
++      unsigned long magic = 0;
++      unsigned long part_size = 0;
++      size_t len;
++      int ret;
++
++      if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
++              return;
++
++      ret = mtd_read(master, offset, 4, &len, (void *)&magic);
++      if (ret || len != sizeof(magic))
++              return;
++
++      if (le32_to_cpu(magic) != TPLINK_MAGIC)
++              return;
++
++      ret = mtd_read(master, offset + 0x78, 4, &len, (void *)&part_size);
++      if (ret || len != sizeof(part_size))
++              return;
++
++      part_size = be32_to_cpu(part_size) + 0x200;
++      if (part_size + master->erasesize > size)
++              return;
++
++      __mtd_add_partition(master, "rootfs", offset + part_size,
++                          size - part_size, false);
++}
++
++void arch_split_mtd_part(struct mtd_info *master, const char *name,
++                              int offset, int size)
++{
++      split_tplink_kernel(master, name, offset, size);
++      split_eva_kernel(master, name, offset, size);
++      split_brnimage_kernel(master, name, offset, size);
++}
+--- a/include/linux/mtd/partitions.h
++++ b/include/linux/mtd/partitions.h
+@@ -89,12 +89,17 @@ extern void deregister_mtd_parser(struct
+ int mtd_is_partition(const struct mtd_info *mtd);
+ int mtd_add_partition(struct mtd_info *master, const char *name,
+                     long long offset, long long length);
++int __mtd_add_partition(struct mtd_info *master, const char *name,
++                  long long offset, long long length, bool dup_check);
++
+ int mtd_del_partition(struct mtd_info *master, int partno);
+ struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd);
+ uint64_t mtdpart_get_offset(const struct mtd_info *mtd);
+ uint64_t mtd_get_device_size(const struct mtd_info *mtd);
+-extern void __weak arch_split_mtd_part(struct mtd_info *master,
+-                                     const char *name, int offset, int size);
++void __weak arch_split_mtd_part(struct mtd_info *master,
++                                     const char *name, int offset, int size);
++unsigned long
++mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len);
+ int parse_mtd_partitions_by_type(struct mtd_info *master,
+                                enum mtd_parser_type type,
+--- a/drivers/mtd/mtdpart.c
++++ b/drivers/mtd/mtdpart.c
+@@ -658,7 +658,7 @@ static int mtd_add_partition_attrs(struc
+ }
+-static int
++int
+ __mtd_add_partition(struct mtd_info *master, const char *name,
+                   long long offset, long long length, bool dup_check)
+ {
+@@ -762,7 +762,7 @@ run_parsers_by_type(struct mtd_part *sla
+       return nr_parts;
+ }
+-static inline unsigned long
++unsigned long
+ mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len)
+ {
+       unsigned long mask = mtd->erasesize - 1;
+@@ -832,7 +832,6 @@ static void split_uimage(struct mtd_info
+               return;
+       len = be32_to_cpu(hdr.size) + 0x40;
+-      len = mtd_pad_erasesize(master, part->offset, len);
+       if (len + master->erasesize > part->mtd.size)
+               return;