From e8cd820cdbb8fba990fd79efda90c5dc10d8e45c Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Fri, 27 Jun 2025 09:59:44 +0800 Subject: [PATCH] libfstools: add support for EroFS based images Add support to libfstools to parse and support EroFS based images to permit correct mounting of OverlayFS with it. (in addition to SquashFS support) While at it rework the code to better handle the 2 different filesystem introducing a similar pattern. Signed-off-by: Gao Xiang Co-Developed-by: Christian Marangi Signed-off-by: Christian Marangi --- libfstools/rootdisk.c | 83 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/libfstools/rootdisk.c b/libfstools/rootdisk.c index 910899a..c54ea2a 100644 --- a/libfstools/rootdisk.c +++ b/libfstools/rootdisk.c @@ -15,6 +15,8 @@ #include +#define SQUASHFS_MAGIC "hsqs" +#define EROFS_MAGIC 0xE0F5E1E2 #define ROOTDEV_OVERLAY_ALIGN (64ULL * 1024ULL) struct squashfs_super_block { @@ -23,6 +25,14 @@ struct squashfs_super_block { uint64_t bytes_used; }; +struct erofs_super_block { + uint32_t s_magic; + uint32_t pad0[2]; + uint8_t blkszbits; + uint8_t pad1[23]; + uint32_t blocks; +}; + struct rootdev_volume { struct volume v; uint64_t offset; @@ -92,10 +102,66 @@ static int get_squashfs(struct squashfs_super_block *sb) return 0; } -static struct volume *rootdisk_volume_find(char *name) +static int check_squashfs(uint64_t *offset) { + const char *s_magic = SQUASHFS_MAGIC; struct squashfs_super_block sb; + int ret; + + ret = get_squashfs(&sb); + if (ret) + return ret; + + if (memcmp(&sb.s_magic, s_magic, sizeof(sb.s_magic))) + return -1; + + *offset = le64_to_cpu(sb.bytes_used); + return 0; +} + +static int get_erofs(struct erofs_super_block *sb) +{ + FILE *f; + int len; + + f = fopen(rootdev, "r"); + if (!f) + return -1; + + if (fseek(f, 1024, SEEK_SET)) + return -1; + + len = fread(sb, sizeof(*sb), 1, f); + fclose(f); + + if (len != 1) + return -1; + + return 0; +} + +static int check_erofs(uint64_t *offset) +{ + uint32_t s_magic = cpu_to_le32(EROFS_MAGIC); + struct erofs_super_block sb; + int ret; + + ret = get_erofs(&sb); + if (ret) + return ret; + + if (memcmp(&sb.s_magic, &s_magic, sizeof(sb.s_magic))) + return -1; + + *offset = (uint64_t)le32_to_cpu(sb.blocks) << sb.blkszbits; + return 0; +} + +static struct volume *rootdisk_volume_find(char *name) +{ struct rootdev_volume *p; + uint64_t offset; + int ret; if (strcmp(name, "rootfs_data") != 0) return NULL; @@ -107,17 +173,22 @@ static struct volume *rootdisk_volume_find(char *name) if (!rootdev) return NULL; - if (get_squashfs(&sb)) - return NULL; - - if (memcmp(&sb.s_magic, "hsqs", sizeof(sb.s_magic)) != 0) + /* + * We support both SquashFS and EroFS. + * First check for SquashFS and then check + * for EroFS on new images. + */ + ret = check_squashfs(&offset); + if (ret < 0 || !offset) + ret = check_erofs(&offset); + if (ret < 0 || !offset) return NULL; p = calloc(1, sizeof(*p)); p->v.drv = &rootdisk_driver; p->v.name = "rootfs_data"; - p->offset = le64_to_cpu(sb.bytes_used); + p->offset = offset; p->offset = ((p->offset + (ROOTDEV_OVERLAY_ALIGN - 1)) & ~(ROOTDEV_OVERLAY_ALIGN - 1)); -- 2.30.2