Previously, read only root partitions were not detected if they did
not use a squashfs filesystem.

Signed-off-by: Jonas Lochmann <[email protected]>
---
 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 <[email protected]>
  * Copyright (C) 2012 Jonas Gorski <[email protected]>
  * Copyright (C) 2013 Hauke Mehrtens <[email protected]>
+ * Copyright (C) 2025 Jonas Lochmann <[email protected]>
  *
  * 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 <[email protected]>
  * Copyright (C) 2012 Jonas Gorski <[email protected]>
  * Copyright (C) 2013 Hauke Mehrtens <[email protected]>
+ * Copyright (C) 2025 Jonas Lochmann <[email protected]>
  *
  * 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 <[email protected]>
+ * Copyright (C) 2012 Jonas Gorski <[email protected]>
+ * Copyright (C) 2013 Hauke Mehrtens <[email protected]>
+ * Copyright (C) 2013 Felix Fietkau <[email protected]>
+ * Copyright (C) 2025 Jonas Lochmann <[email protected]>
+ *
+ * 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


_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to