From ee54c6bce17c48a725eadcc313b6ca8445f9ec8c Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 18 Oct 2022 17:17:29 +0100 Subject: libfstools: skip JFFS2 padding on block devices Images also used on devices with NOR flash may come with JFFS2 deadc0de marking and padding up to the largest NOR erase size. Skip that padding and take it into account when extracting sysupgrade backup from mmc/block partition. Signed-off-by: Daniel Golle --- libfstools/common.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/libfstools/common.c b/libfstools/common.c index 55c1b87..e5b7bc3 100644 --- a/libfstools/common.c +++ b/libfstools/common.c @@ -63,9 +63,11 @@ int block_file_identify(FILE *f, uint64_t offset) return -1; n = fread(&magic, sizeof(magic), 1, f); - if (magic == cpu_to_le32(0x88b1f)) { + if (magic == cpu_to_le32(0x88b1f)) return FS_TARGZ; - } + + if (magic == cpu_to_be32(0xdeadc0de)) + return FS_DEADCODE; if (fseeko(f, offset + 0x400, SEEK_SET) < 0) return -1; @@ -113,17 +115,53 @@ int block_volume_format(struct volume *v, uint64_t offset, const char *bdev) { int ret = 0; char str[128]; + unsigned int skip_blocks = 0; + int fd; + __u32 deadc0de; + size_t sz; switch (volume_identify(v)) { + case FS_DEADCODE: + /* skip padding */ + fd = open(v->blk, O_RDONLY); + if (fd < 0) { + ret = EIO; + break; + } + do { + if (lseek(fd, (skip_blocks + 1) * 512, SEEK_SET) == (off_t) -1) { + ret = EIO; + break; + } + sz = read(fd, &deadc0de, sizeof(deadc0de)); + if (sz != sizeof(deadc0de)) { + ret = EIO; + break; + } + } while(++skip_blocks <= 512 && + (deadc0de == cpu_to_be32(0xdeadc0de) || deadc0de == 0xffffffff)); + + close(fd); + if (ret) + break; + + /* only try extracting in case gzip header is present */ + if (deadc0de != cpu_to_le32(0x88b1f)) + goto do_format; + + /* fall-through */ case FS_TARGZ: - snprintf(str, sizeof(str), "gzip -cd %s > /tmp/sysupgrade.tar", v->blk); + snprintf(str, sizeof(str), + "dd if=%s bs=512 skip=%u 2>/dev/null | gzip -cd > /tmp/sysupgrade.tar 2>/dev/null", + v->blk, skip_blocks); ret = system(str); if (ret < 0) { - ULOG_ERR("failed extracting %s\n", v->blk); + ULOG_ERR("failed extracting config backup from %s\n", v->blk); break; } /* fall-through */ case FS_NONE: +do_format: ULOG_INFO("overlay filesystem in %s has not been formatted yet\n", v->blk); if (use_f2fs(v, offset, bdev)) snprintf(str, sizeof(str), "mkfs.f2fs -q -l rootfs_data %s", v->blk); -- cgit v1.2.1