[PATCH] kernel: mtdsplit: add erofs support
Jonas Lochmann
openwrt at jonaslochmann.de
Sun Dec 28 11:45:34 PST 2025
Previously, read only root partitions were not detected if they did
not use a squashfs filesystem.
Signed-off-by: Jonas Lochmann <openwrt at jonaslochmann.de>
---
target/linux/generic/config-6.12 | 1 +
.../files/drivers/mtd/mtdsplit/Kconfig | 9 ++
.../files/drivers/mtd/mtdsplit/Makefile | 1 +
.../files/drivers/mtd/mtdsplit/mtdsplit.c | 13 ++
.../files/drivers/mtd/mtdsplit/mtdsplit.h | 2 +
.../drivers/mtd/mtdsplit/mtdsplit_erofs.c | 138 ++++++++++++++++++
6 files changed, 164 insertions(+)
create mode 100644 target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_erofs.c
diff --git a/target/linux/generic/config-6.12 b/target/linux/generic/config-6.12
index fda78b422e..5e7d9af098 100644
--- a/target/linux/generic/config-6.12
+++ b/target/linux/generic/config-6.12
@@ -3913,6 +3913,7 @@ CONFIG_MTD_SPLIT=y
# CONFIG_MTD_SPLIT_BCM_WFI_FW is not set
# CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set
# CONFIG_MTD_SPLIT_ELF_FW is not set
+CONFIG_MTD_SPLIT_EROFS_ROOT=y
# CONFIG_MTD_SPLIT_EVA_FW is not set
# CONFIG_MTD_SPLIT_FIRMWARE is not set
CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware"
diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig b/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig
index 396becf160..3d64428470 100644
--- a/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig
+++ b/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig
@@ -17,6 +17,15 @@ config MTD_SPLIT_SQUASHFS_ROOT
offset and size of the unused portion of a rootfs partition
containing a squashfs.
+config MTD_SPLIT_EROFS_ROOT
+ bool "EROFS based root partition parser"
+ depends on MTD_SPLIT_SUPPORT
+ select MTD_SPLIT
+ help
+ This provides a parsing function which allows to detect the
+ offset and size of the unused portion of a rootfs partition
+ containing a erofs.
+
comment "Firmware partition parsers"
config MTD_SPLIT_BCM63XX_FW
diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile b/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile
index b85ce5d21f..e6f3d2c3e4 100644
--- a/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile
+++ b/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_MTD_SPLIT_CFE_BOOTFS) += mtdsplit_cfe_bootfs.o
obj-$(CONFIG_MTD_SPLIT_SEAMA_FW) += mtdsplit_seama.o
obj-$(CONFIG_MTD_SPLIT_SEIL_FW) += mtdsplit_seil.o
obj-$(CONFIG_MTD_SPLIT_SQUASHFS_ROOT) += mtdsplit_squashfs.o
+obj-$(CONFIG_MTD_SPLIT_EROFS_ROOT) += mtdsplit_erofs.o
obj-$(CONFIG_MTD_SPLIT_UIMAGE_FW) += mtdsplit_uimage.o
obj-$(CONFIG_MTD_SPLIT_FIT_FW) += mtdsplit_fit.o
obj-$(CONFIG_MTD_SPLIT_LZMA_FW) += mtdsplit_lzma.o
diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit.c
index 42edb97c3a..ce72e8939b 100644
--- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit.c
+++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit.c
@@ -3,6 +3,7 @@
* Copyright (C) 2009-2013 Gabor Juhos <juhosg at openwrt.org>
* Copyright (C) 2012 Jonas Gorski <jogo at openwrt.org>
* Copyright (C) 2013 Hauke Mehrtens <hauke at hauke-m.de>
+ * Copyright (C) 2025 Jonas Lochmann <openwrt at jonaslochmann.de>
*
* 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
@@ -101,6 +102,18 @@ int mtd_check_rootfs_magic(struct mtd_info *mtd, size_t offset,
return 0;
}
+ ret = mtd_read(mtd, offset + 1024, sizeof(magic), &retlen,
+ (unsigned char *) &magic);
+
+ if (ret)
+ return ret;
+
+ if (magic == EROFS_SUPER_MAGIC_V1) {
+ if (type)
+ *type = MTDSPLIT_PART_TYPE_EROFS;
+ return 0;
+ }
+
return -EINVAL;
}
EXPORT_SYMBOL_GPL(mtd_check_rootfs_magic);
diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit.h b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit.h
index 1d3f031733..8d9c084f28 100644
--- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit.h
+++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit.h
@@ -3,6 +3,7 @@
* Copyright (C) 2009-2013 Gabor Juhos <juhosg at openwrt.org>
* Copyright (C) 2012 Jonas Gorski <jogo at openwrt.org>
* Copyright (C) 2013 Hauke Mehrtens <hauke at hauke-m.de>
+ * Copyright (C) 2025 Jonas Lochmann <openwrt at jonaslochmann.de>
*
* 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
@@ -24,6 +25,7 @@ enum mtdsplit_part_type {
MTDSPLIT_PART_TYPE_SQUASHFS,
MTDSPLIT_PART_TYPE_JFFS2,
MTDSPLIT_PART_TYPE_UBI,
+ MTDSPLIT_PART_TYPE_EROFS,
};
#ifdef CONFIG_MTD_SPLIT
diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_erofs.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_erofs.c
new file mode 100644
index 0000000000..bf1287cf59
--- /dev/null
+++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_erofs.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2009-2013 Gabor Juhos <juhosg at openwrt.org>
+ * Copyright (C) 2012 Jonas Gorski <jogo at openwrt.org>
+ * Copyright (C) 2013 Hauke Mehrtens <hauke at hauke-m.de>
+ * Copyright (C) 2013 Felix Fietkau <nbd at nbd.name>
+ * Copyright (C) 2025 Jonas Lochmann <openwrt at jonaslochmann.de>
+ *
+ * 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.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/magic.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/byteorder/generic.h>
+
+#include "mtdsplit.h"
+
+struct erofs_super_block {
+ __le32 magic;
+ __le32 pad1[2];
+ __u8 blkszbits;
+ __u8 pad2;
+ __le16 pad3;
+ __le32 pad4[5];
+ __le32 blocks;
+};
+
+static int mtd_get_erofs_len(struct mtd_info *master,
+ size_t offset,
+ size_t *erofs_len)
+{
+ struct erofs_super_block sb;
+ size_t retlen, blksz;
+ int err;
+
+ err = mtd_read(master, offset + 1024, sizeof(sb), &retlen, (void *)&sb);
+ if (err || (retlen != sizeof(sb))) {
+ pr_alert("error occured while reading from \"%s\"\n",
+ master->name);
+ return -EIO;
+ }
+
+ if (le32_to_cpu(sb.magic) != EROFS_SUPER_MAGIC_V1) {
+ pr_alert("no erofs found in \"%s\"\n", master->name);
+ return -EINVAL;
+ }
+
+ blksz = 1 << sb.blkszbits;
+
+ // this catches overflows too as the number goes negative
+ // or reaches zero in case of an overflow
+ if (blksz < 512) {
+ pr_alert("erofs has invalid blkszbits in \"%s\"\n", master->name);
+ return -EINVAL;
+ }
+
+ int blocks = le32_to_cpu(sb.blocks);
+
+ retlen = blksz * blocks;
+
+ if (retlen / blksz != blocks) {
+ pr_alert("erofs size overflow in \"%s\"\n", master->name);
+ return -ENOENT;
+ }
+
+ if (retlen <= 0) {
+ pr_alert("erofs is empty in \"%s\"\n", master->name);
+ return -ENOENT;
+ }
+
+ if (offset + retlen > master->size) {
+ pr_alert("erofs has invalid size in \"%s\"\n",
+ master->name);
+ return -EINVAL;
+ }
+
+ *erofs_len = retlen;
+ return 0;
+}
+
+static int
+mtdsplit_parse_erofs(struct mtd_info *master,
+ const struct mtd_partition **pparts,
+ struct mtd_part_parser_data *data)
+{
+ struct mtd_partition *part;
+ struct mtd_info *parent_mtd;
+ size_t part_offset;
+ size_t erofs_len;
+ int err;
+
+ err = mtd_get_erofs_len(master, 0, &erofs_len);
+ if (err)
+ return err;
+
+ parent_mtd = mtd_get_master(master);
+ part_offset = mtdpart_get_offset(master);
+
+ part = kzalloc(sizeof(*part), GFP_KERNEL);
+ if (!part) {
+ pr_alert("unable to allocate memory for \"%s\" partition\n",
+ ROOTFS_SPLIT_NAME);
+ return -ENOMEM;
+ }
+
+ part->name = ROOTFS_SPLIT_NAME;
+ part->offset = mtd_roundup_to_eb(part_offset + erofs_len,
+ parent_mtd) - part_offset;
+ part->size = mtd_rounddown_to_eb(master->size - part->offset, master);
+
+ *pparts = part;
+ return 1;
+}
+
+static struct mtd_part_parser mtdsplit_erofs_parser = {
+ .owner = THIS_MODULE,
+ .name = "erofs-split",
+ .parse_fn = mtdsplit_parse_erofs,
+ .type = MTD_PARSER_TYPE_ROOTFS,
+};
+
+static int __init mtdsplit_erofs_init(void)
+{
+ register_mtd_parser(&mtdsplit_erofs_parser);
+
+ return 0;
+}
+
+subsys_initcall(mtdsplit_erofs_init);
--
2.47.3
More information about the openwrt-devel
mailing list