kernel: mtdsplit: add support for brnImages
authorFelix Fietkau <nbd@openwrt.org>
Sun, 17 Jan 2016 10:40:51 +0000 (10:40 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 17 Jan 2016 10:40:51 +0000 (10:40 +0000)
This adds brnImage (used with the brnboot bootloader) firmware parsing
support. brnboot verifies the integrity of the firmware stored on the
"Code Image" partitions by looking at the 12 byte footer at the very end
of the partition. This footer contains the checksum of the original
brnImage (kernel + rootfs/squashfs) and must not be touched (by our JFFS2
rootfs_data - otherwise the image will not be bootable anymore).

Big thanks to Mathias Kresin for analyzing the brnImage structure and
finding out the information how to keep images valid even when adding a
nested rootfs_data partition.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
SVN-Revision: 48261

target/linux/generic/config-3.18
target/linux/generic/config-4.1
target/linux/generic/config-4.3
target/linux/generic/config-4.4
target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig
target/linux/generic/files/drivers/mtd/mtdsplit/Makefile
target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c [new file with mode: 0644]

index 36d85907f9cdf6e5fc11cb6221720aad63432ae7..c8ba32802c989582707935e13d78b9707200b1cc 100644 (file)
@@ -2265,6 +2265,7 @@ CONFIG_MTD_ROOTFS_SPLIT=y
 # CONFIG_MTD_SPI_NOR is not set
 # CONFIG_MTD_SPINAND_MT29F is not set
 CONFIG_MTD_SPLIT=y
+# CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set
 # CONFIG_MTD_SPLIT_FIRMWARE is not set
 CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware"
 # CONFIG_MTD_SPLIT_FIT_FW is not set
index 0f76041a6dc7a5c7b893a706b2bd687f99dd7194..ade6807b2100f8d9fe844746ea12318756feb209 100644 (file)
@@ -2357,6 +2357,7 @@ CONFIG_MTD_ROOTFS_ROOT_DEV=y
 # CONFIG_MTD_SPI_NOR is not set
 # CONFIG_MTD_SPINAND_MT29F is not set
 CONFIG_MTD_SPLIT=y
+# CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set
 # CONFIG_MTD_SPLIT_FIRMWARE is not set
 CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware"
 # CONFIG_MTD_SPLIT_FIT_FW is not set
index 5ec85fee97c3178ac87210dcf271bab766b43b10..f5d8ce88a256d136667a4cf7fc3912f641a72fa0 100644 (file)
@@ -2415,6 +2415,7 @@ CONFIG_MTD_ROOTFS_ROOT_DEV=y
 # CONFIG_MTD_SPI_NOR is not set
 # CONFIG_MTD_SPINAND_MT29F is not set
 CONFIG_MTD_SPLIT=y
+# CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set
 # CONFIG_MTD_SPLIT_FIRMWARE is not set
 CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware"
 # CONFIG_MTD_SPLIT_FIT_FW is not set
index 53132221ccfd2093cb16a62a926cc878fec8c57c..c27192d3858a5f013a51dc251c655f2b94d5024d 100644 (file)
@@ -2318,6 +2318,7 @@ CONFIG_MTD_ROOTFS_ROOT_DEV=y
 # CONFIG_MTD_SPI_NOR is not set
 # CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
 CONFIG_MTD_SPLIT=y
+# CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set
 # CONFIG_MTD_SPLIT_FIRMWARE is not set
 CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware"
 # CONFIG_MTD_SPLIT_FIT_FW is not set
index c4e3418854641fea17aac3de727c8aee0e6c5ec5..0370a21c9f36dd80e752af159a2810475a97a06e 100644 (file)
@@ -49,3 +49,8 @@ config MTD_SPLIT_TRX_FW
        bool "TRX image based firmware partition parser"
        depends on MTD_SPLIT_SUPPORT
        select MTD_SPLIT
+
+config MTD_SPLIT_BRNIMAGE_FW
+       bool "brnImage (brnboot image) firmware parser"
+       depends on MTD_SPLIT_SUPPORT
+       select MTD_SPLIT
index e09476bc202aafe9b11a4737920163ccbc301a0d..ca24c717dccf6897e869bf5ce5d1430e13e64161 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_MTD_SPLIT_FIT_FW) += mtdsplit_fit.o
 obj-$(CONFIG_MTD_SPLIT_LZMA_FW) += mtdsplit_lzma.o
 obj-$(CONFIG_MTD_SPLIT_TPLINK_FW) += mtdsplit_tplink.o
 obj-$(CONFIG_MTD_SPLIT_TRX_FW) += mtdsplit_trx.o
+obj-$(CONFIG_MTD_SPLIT_BRNIMAGE_FW) += mtdsplit_brnimage.o
diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c
new file mode 100644 (file)
index 0000000..7ddd69b
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2015 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ *
+ *  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.
+ *
+ */
+
+#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/byteorder/generic.h>
+
+#include "mtdsplit.h"
+
+#define BRNIMAGE_NR_PARTS      2
+
+#define BRNIMAGE_ALIGN_BYTES   0x400
+#define BRNIMAGE_FOOTER_SIZE   12
+
+#define BRNIMAGE_MIN_OVERHEAD  (BRNIMAGE_FOOTER_SIZE)
+#define BRNIMAGE_MAX_OVERHEAD  (BRNIMAGE_ALIGN_BYTES + BRNIMAGE_FOOTER_SIZE)
+
+static int mtdsplit_parse_brnimage(struct mtd_info *master,
+                               struct mtd_partition **pparts,
+                               struct mtd_part_parser_data *data)
+{
+       struct mtd_partition *parts;
+       uint32_t buf;
+       unsigned long rootfs_offset, rootfs_size, kernel_size;
+       size_t len;
+       int ret;
+
+       for (rootfs_offset = 0; rootfs_offset < master->size;
+            rootfs_offset += BRNIMAGE_ALIGN_BYTES) {
+               ret = mtd_check_rootfs_magic(master, rootfs_offset);
+               if (!ret)
+                       break;
+       }
+
+       if (ret)
+               return ret;
+
+       if (rootfs_offset >= master->size)
+               return -EINVAL;
+
+       ret = mtd_read(master, rootfs_offset - BRNIMAGE_FOOTER_SIZE, 4, &len,
+                       (void *)&buf);
+       if (ret)
+               return ret;
+
+       if (len != 4)
+               return -EIO;
+
+       kernel_size = le32_to_cpu(buf);
+
+       if (kernel_size > (rootfs_offset - BRNIMAGE_MIN_OVERHEAD))
+               return -EINVAL;
+
+       if (kernel_size < (rootfs_offset - BRNIMAGE_MAX_OVERHEAD))
+               return -EINVAL;
+
+       /*
+        * The footer must be untouched as it contains the checksum of the
+        * original brnImage (kernel + squashfs)!
+        */
+       rootfs_size = master->size - rootfs_offset - BRNIMAGE_FOOTER_SIZE;
+
+       parts = kzalloc(BRNIMAGE_NR_PARTS * sizeof(*parts), GFP_KERNEL);
+       if (!parts)
+               return -ENOMEM;
+
+       parts[0].name = KERNEL_PART_NAME;
+       parts[0].offset = 0;
+       parts[0].size = kernel_size;
+
+       parts[1].name = ROOTFS_PART_NAME;
+       parts[1].offset = rootfs_offset;
+       parts[1].size = rootfs_size;
+
+       *pparts = parts;
+       return BRNIMAGE_NR_PARTS;
+}
+
+static struct mtd_part_parser mtdsplit_brnimage_parser = {
+       .owner = THIS_MODULE,
+       .name = "brnimage-fw",
+       .parse_fn = mtdsplit_parse_brnimage,
+       .type = MTD_PARSER_TYPE_FIRMWARE,
+};
+
+static int __init mtdsplit_brnimage_init(void)
+{
+       register_mtd_parser(&mtdsplit_brnimage_parser);
+
+       return 0;
+}
+
+subsys_initcall(mtdsplit_brnimage_init);