[source] kernel: mtdsplit: Add support for Mikrotik NOR firmware

LEDE Commits lede-commits at lists.infradead.org
Wed Feb 22 13:53:06 PST 2017


nbd pushed a commit to source.git, branch master:
https://git.lede-project.org/890daca9e2596359808bcffcab31202288bef63f

commit 890daca9e2596359808bcffcab31202288bef63f
Author: Thibaut VARENE <hacks at slashdirt.org>
AuthorDate: Tue Feb 14 14:42:10 2017 +0100

    kernel: mtdsplit: Add support for Mikrotik NOR firmware
    
    The RouterBOOT bootloader does not care where the kernel lives in the SPI
    flash, all that matters is that the kernel is wrapped in the custom yaffs
    container as generated by kernel2minor.
    
    This container has a fixed signature as follows:
    00000000  00 00 00 01 00 00 00 01  ff ff 6b 65 72 6e 65 6c  |..........kernel|
    
    This patch adds mtdsplit support for identifying that signature and
    triggering the search for the rootfs. rootfs is expected at EB boundary since
    we use wget mtd_find_rootfs_from(). We make no use of the yaffs file size
    field because it contains invalid data in the image generated by kernel2minor.
    
    Signed-off-by: Thibaut VARENE <hacks at slashdirt.org>
---
 target/linux/generic/config-4.4                    |   1 +
 target/linux/generic/config-4.9                    |   1 +
 .../generic/files/drivers/mtd/mtdsplit/Kconfig     |   5 +
 .../generic/files/drivers/mtd/mtdsplit/Makefile    |   1 +
 .../files/drivers/mtd/mtdsplit/mtdsplit_minor.c    | 117 +++++++++++++++++++++
 5 files changed, 125 insertions(+)

diff --git a/target/linux/generic/config-4.4 b/target/linux/generic/config-4.4
index ebc54bc..e76359a 100644
--- a/target/linux/generic/config-4.4
+++ b/target/linux/generic/config-4.4
@@ -2367,6 +2367,7 @@ CONFIG_MTD_SPLIT=y
 CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware"
 # CONFIG_MTD_SPLIT_FIT_FW is not set
 # CONFIG_MTD_SPLIT_LZMA_FW is not set
+# CONFIG_MTD_SPLIT_MINOR_FW is not set
 # CONFIG_MTD_SPLIT_SEAMA_FW is not set
 CONFIG_MTD_SPLIT_SQUASHFS_ROOT=y
 CONFIG_MTD_SPLIT_SUPPORT=y
diff --git a/target/linux/generic/config-4.9 b/target/linux/generic/config-4.9
index 99ba19f..e36d77c 100644
--- a/target/linux/generic/config-4.9
+++ b/target/linux/generic/config-4.9
@@ -2578,6 +2578,7 @@ CONFIG_MTD_SPLIT=y
 CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware"
 # CONFIG_MTD_SPLIT_FIT_FW is not set
 # CONFIG_MTD_SPLIT_LZMA_FW is not set
+# CONFIG_MTD_SPLIT_MINOR_FW is not set
 # CONFIG_MTD_SPLIT_SEAMA_FW is not set
 CONFIG_MTD_SPLIT_SQUASHFS_ROOT=y
 CONFIG_MTD_SPLIT_SUPPORT=y
diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig b/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig
index 7e653e7..4a15d48 100644
--- a/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig
+++ b/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig
@@ -64,3 +64,8 @@ config MTD_SPLIT_EVA_FW
 	bool "EVA image based firmware partition parser"
 	depends on MTD_SPLIT_SUPPORT
 	select MTD_SPLIT
+
+config MTD_SPLIT_MINOR_FW
+	bool "Mikrotik NOR image based firmware partition parser"
+	depends on MTD_SPLIT_SUPPORT
+	select MTD_SPLIT
diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile b/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile
index c843025..fab85ca 100644
--- a/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile
+++ b/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_MTD_SPLIT_TRX_FW) += mtdsplit_trx.o
 obj-$(CONFIG_MTD_SPLIT_BRNIMAGE_FW) += mtdsplit_brnimage.o
 obj-$(CONFIG_MTD_SPLIT_EVA_FW) += mtdsplit_eva.o
 obj-$(CONFIG_MTD_SPLIT_WRGG_FW) += mtdsplit_wrgg.o
+obj-$(CONFIG_MTD_SPLIT_MINOR_FW) += mtdsplit_minor.o
diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c
new file mode 100644
index 0000000..f971f0a
--- /dev/null
+++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c
@@ -0,0 +1,117 @@
+/*
+ *  MTD splitter for MikroTik NOR devices
+ *
+ *  Copyright (C) 2017 Thibaut VARENE <varenet at parisc-linux.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  The rootfs is expected at erase-block boundary due to the use of
+ *  mtd_find_rootfs_from(). We use a trimmed down version of the yaffs header
+ *  for two main reasons:
+ *  - the original header uses weakly defined types (int, enum...) which can
+ *    vary in length depending on build host (and the struct is not packed),
+ *    and the name field can have a different total length depending on
+ *    whether or not the yaffs code was _built_ with unicode support.
+ *  - the only field that could be of real use here (file_size_low) contains
+ *    invalid data in the header generated by kernel2minor, so we cannot use
+ *    it to infer the exact position of the rootfs and do away with
+ *    mtd_find_rootfs_from() (and thus have non-EB-aligned rootfs).
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/string.h>
+
+#include "mtdsplit.h"
+
+#define YAFFS_OBJECT_TYPE_FILE	0x1
+#define YAFFS_OBJECTID_ROOT	0x1
+#define YAFFS_SUM_UNUSED	0xFFFF
+#define YAFFS_NAME		"kernel"
+
+#define MINOR_NR_PARTS		2
+
+/*
+ * This structure is based on yaffs_obj_hdr from yaffs_guts.h
+ * The weak types match upstream. The fields have cpu-endianness
+ */
+struct minor_header {
+	int yaffs_type;
+	int yaffs_obj_id;
+	u16 yaffs_sum_unused;
+	char yaffs_name[sizeof(YAFFS_NAME)];
+};
+
+static int mtdsplit_parse_minor(struct mtd_info *master,
+				const struct mtd_partition **pparts,
+				struct mtd_part_parser_data *data)
+{
+	struct minor_header hdr;
+	size_t hdr_len, retlen;
+	size_t rootfs_offset;
+	struct mtd_partition *parts;
+	int err;
+
+	hdr_len = sizeof(hdr);
+	err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr);
+	if (err)
+		return err;
+
+	if (retlen != hdr_len)
+		return -EIO;
+
+	/* match header */
+	if (hdr.yaffs_type != YAFFS_OBJECT_TYPE_FILE)
+		return -EINVAL;
+
+	if (hdr.yaffs_obj_id != YAFFS_OBJECTID_ROOT)
+		return -EINVAL;
+
+	if (hdr.yaffs_sum_unused != YAFFS_SUM_UNUSED)
+		return -EINVAL;
+
+	if (memcmp(hdr.yaffs_name, YAFFS_NAME, sizeof(YAFFS_NAME)))
+		return -EINVAL;
+
+	err = mtd_find_rootfs_from(master, master->erasesize, master->size,
+				   &rootfs_offset, NULL);
+	if (err)
+		return err;
+
+	parts = kzalloc(MINOR_NR_PARTS * sizeof(*parts), GFP_KERNEL);
+	if (!parts)
+		return -ENOMEM;
+
+	parts[0].name = KERNEL_PART_NAME;
+	parts[0].offset = 0;
+	parts[0].size = rootfs_offset;
+
+	parts[1].name = ROOTFS_PART_NAME;
+	parts[1].offset = rootfs_offset;
+	parts[1].size = master->size - rootfs_offset;
+
+	*pparts = parts;
+	return MINOR_NR_PARTS;
+}
+
+static struct mtd_part_parser mtdsplit_minor_parser = {
+	.owner = THIS_MODULE,
+	.name = "minor-fw",
+	.parse_fn = mtdsplit_parse_minor,
+	.type = MTD_PARSER_TYPE_FIRMWARE,
+};
+
+static int __init mtdsplit_minor_init(void)
+{
+	register_mtd_parser(&mtdsplit_minor_parser);
+
+	return 0;
+}
+
+subsys_initcall(mtdsplit_minor_init);



More information about the lede-commits mailing list