From f0b4f502bdd5f17da58aca9ebf86e16e96e0d347 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Fri, 13 Mar 2026 11:42:23 +0100 Subject: [PATCH 1/7] fs/squashfs: fix sqfs_decompressor.c build in SPL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CONFIG_IS_ENABLED() must be used in place of IS_ENABLED() for config options that have a _SPL_ counterpart. Signed-off-by: Richard Genoud Reviewed-by: Miquel Raynal Reviewed-by: João Marcos Costa --- fs/squashfs/sqfs_decompressor.c | 36 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/fs/squashfs/sqfs_decompressor.c b/fs/squashfs/sqfs_decompressor.c index cfd1153fd74..d54f087274c 100644 --- a/fs/squashfs/sqfs_decompressor.c +++ b/fs/squashfs/sqfs_decompressor.c @@ -10,19 +10,19 @@ #include #include -#if IS_ENABLED(CONFIG_LZO) +#if CONFIG_IS_ENABLED(LZO) #include #endif -#if IS_ENABLED(CONFIG_ZLIB) +#if CONFIG_IS_ENABLED(ZLIB) #include #endif -#if IS_ENABLED(CONFIG_LZ4) +#if CONFIG_IS_ENABLED(LZ4) #include #endif -#if IS_ENABLED(CONFIG_ZSTD) +#if CONFIG_IS_ENABLED(ZSTD) #include #endif @@ -34,19 +34,19 @@ int sqfs_decompressor_init(struct squashfs_ctxt *ctxt) u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression); switch (comp_type) { -#if IS_ENABLED(CONFIG_LZO) +#if CONFIG_IS_ENABLED(LZO) case SQFS_COMP_LZO: break; #endif -#if IS_ENABLED(CONFIG_ZLIB) +#if CONFIG_IS_ENABLED(ZLIB) case SQFS_COMP_ZLIB: break; #endif -#if IS_ENABLED(CONFIG_LZ4) +#if CONFIG_IS_ENABLED(LZ4) case SQFS_COMP_LZ4: break; #endif -#if IS_ENABLED(CONFIG_ZSTD) +#if CONFIG_IS_ENABLED(ZSTD) case SQFS_COMP_ZSTD: ctxt->zstd_workspace = malloc(zstd_dctx_workspace_bound()); if (!ctxt->zstd_workspace) @@ -66,19 +66,19 @@ void sqfs_decompressor_cleanup(struct squashfs_ctxt *ctxt) u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression); switch (comp_type) { -#if IS_ENABLED(CONFIG_LZO) +#if CONFIG_IS_ENABLED(LZO) case SQFS_COMP_LZO: break; #endif -#if IS_ENABLED(CONFIG_ZLIB) +#if CONFIG_IS_ENABLED(ZLIB) case SQFS_COMP_ZLIB: break; #endif -#if IS_ENABLED(CONFIG_LZ4) +#if CONFIG_IS_ENABLED(LZ4) case SQFS_COMP_LZ4: break; #endif -#if IS_ENABLED(CONFIG_ZSTD) +#if CONFIG_IS_ENABLED(ZSTD) case SQFS_COMP_ZSTD: free(ctxt->zstd_workspace); break; @@ -86,7 +86,7 @@ void sqfs_decompressor_cleanup(struct squashfs_ctxt *ctxt) } } -#if IS_ENABLED(CONFIG_ZLIB) +#if CONFIG_IS_ENABLED(ZLIB) static void zlib_decompression_status(int ret) { switch (ret) { @@ -103,7 +103,7 @@ static void zlib_decompression_status(int ret) } #endif -#if IS_ENABLED(CONFIG_ZSTD) +#if CONFIG_IS_ENABLED(ZSTD) static int sqfs_zstd_decompress(struct squashfs_ctxt *ctxt, void *dest, unsigned long dest_len, void *source, u32 src_len) { @@ -129,7 +129,7 @@ int sqfs_decompress(struct squashfs_ctxt *ctxt, void *dest, int ret = 0; switch (comp_type) { -#if IS_ENABLED(CONFIG_LZO) +#if CONFIG_IS_ENABLED(LZO) case SQFS_COMP_LZO: { size_t lzo_dest_len = *dest_len; ret = lzo1x_decompress_safe(source, src_len, dest, &lzo_dest_len); @@ -141,7 +141,7 @@ int sqfs_decompress(struct squashfs_ctxt *ctxt, void *dest, break; } #endif -#if IS_ENABLED(CONFIG_ZLIB) +#if CONFIG_IS_ENABLED(ZLIB) case SQFS_COMP_ZLIB: ret = uncompress(dest, dest_len, source, src_len); if (ret) { @@ -151,7 +151,7 @@ int sqfs_decompress(struct squashfs_ctxt *ctxt, void *dest, break; #endif -#if IS_ENABLED(CONFIG_LZ4) +#if CONFIG_IS_ENABLED(LZ4) case SQFS_COMP_LZ4: ret = LZ4_decompress_safe(source, dest, src_len, *dest_len); if (ret < 0) { @@ -162,7 +162,7 @@ int sqfs_decompress(struct squashfs_ctxt *ctxt, void *dest, ret = 0; break; #endif -#if IS_ENABLED(CONFIG_ZSTD) +#if CONFIG_IS_ENABLED(ZSTD) case SQFS_COMP_ZSTD: ret = sqfs_zstd_decompress(ctxt, dest, *dest_len, source, src_len); if (ret) { From 0fe2801730edb99e24b601b043ec5595af319274 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Fri, 13 Mar 2026 11:42:24 +0100 Subject: [PATCH 2/7] fs/squashfs: sqfs_decompressor: simplify code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to if (CONFIG_IS_ENABLED()) instead of #if when possible and remove unnecessary cases. Signed-off-by: Richard Genoud Reviewed-by: Miquel Raynal Reviewed-by: João Marcos Costa --- fs/squashfs/sqfs_decompressor.c | 49 ++++++++------------------------- 1 file changed, 12 insertions(+), 37 deletions(-) diff --git a/fs/squashfs/sqfs_decompressor.c b/fs/squashfs/sqfs_decompressor.c index d54f087274c..a156cfe6f65 100644 --- a/fs/squashfs/sqfs_decompressor.c +++ b/fs/squashfs/sqfs_decompressor.c @@ -33,57 +33,32 @@ int sqfs_decompressor_init(struct squashfs_ctxt *ctxt) { u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression); - switch (comp_type) { -#if CONFIG_IS_ENABLED(LZO) - case SQFS_COMP_LZO: - break; -#endif -#if CONFIG_IS_ENABLED(ZLIB) - case SQFS_COMP_ZLIB: - break; -#endif -#if CONFIG_IS_ENABLED(LZ4) - case SQFS_COMP_LZ4: - break; -#endif + if (((CONFIG_IS_ENABLED(LZO) && comp_type == SQFS_COMP_LZO)) || + ((CONFIG_IS_ENABLED(ZLIB) && comp_type == SQFS_COMP_ZLIB)) || + ((CONFIG_IS_ENABLED(LZ4) && comp_type == SQFS_COMP_LZ4))) + return 0; + #if CONFIG_IS_ENABLED(ZSTD) - case SQFS_COMP_ZSTD: + if (comp_type == SQFS_COMP_ZSTD) { ctxt->zstd_workspace = malloc(zstd_dctx_workspace_bound()); if (!ctxt->zstd_workspace) return -ENOMEM; - break; -#endif - default: - printf("Error: unknown compression type.\n"); - return -EINVAL; + return 0; } +#endif - return 0; + printf("Error: unknown compression type.\n"); + return -EINVAL; } void sqfs_decompressor_cleanup(struct squashfs_ctxt *ctxt) { +#if CONFIG_IS_ENABLED(ZSTD) u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression); - switch (comp_type) { -#if CONFIG_IS_ENABLED(LZO) - case SQFS_COMP_LZO: - break; -#endif -#if CONFIG_IS_ENABLED(ZLIB) - case SQFS_COMP_ZLIB: - break; -#endif -#if CONFIG_IS_ENABLED(LZ4) - case SQFS_COMP_LZ4: - break; -#endif -#if CONFIG_IS_ENABLED(ZSTD) - case SQFS_COMP_ZSTD: + if (comp_type == SQFS_COMP_ZSTD) free(ctxt->zstd_workspace); - break; #endif - } } #if CONFIG_IS_ENABLED(ZLIB) From 5e23f7f9f3b3c8fe78ed3aadeed9b187ba8930da Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Fri, 13 Mar 2026 11:42:25 +0100 Subject: [PATCH 3/7] fs/squashfs: squashfs.h: include file should be self dependent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise, we get a lot of errors when including this file. Signed-off-by: Richard Genoud Reviewed-by: Tom Rini Reviewed-by: Miquel Raynal Reviewed-by: João Marcos Costa --- include/squashfs.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/squashfs.h b/include/squashfs.h index 7489eefa1f2..83ed8a49442 100644 --- a/include/squashfs.h +++ b/include/squashfs.h @@ -10,7 +10,10 @@ #ifndef _SQFS_H_ #define _SQFS_H_ -struct disk_partition; +#include +#include +#include +#include int sqfs_opendir(const char *filename, struct fs_dir_stream **dirsp); int sqfs_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp); From 6494e823b46ced400764b6203d7480c9e3badc20 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Fri, 13 Mar 2026 11:42:26 +0100 Subject: [PATCH 4/7] spl: add squashfs support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement spl_load_image_sqfs() in spl code. This will be used in MMC to read a file from a squashfs partition. Also, loosen squashfs read checks on file size by not failing when a bigger size than the actual file size is requested. (Just read the file) This is needed for FIT loading, because the length is ALIGNed. Signed-off-by: Richard Genoud Reviewed-by: Miquel Raynal Reviewed-by: João Marcos Costa --- common/spl/Makefile | 1 + common/spl/spl_squashfs.c | 78 +++++++++++++++++++++++++++++++++++++++ fs/squashfs/sqfs.c | 12 +++--- include/part.h | 1 + include/spl.h | 6 +++ 5 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 common/spl/spl_squashfs.c diff --git a/common/spl/Makefile b/common/spl/Makefile index 4c9482bd309..53cc45fc5b9 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_$(PHASE_)OPENSBI) += spl_opensbi.o obj-$(CONFIG_$(PHASE_)USB_STORAGE) += spl_usb.o obj-$(CONFIG_$(PHASE_)FS_FAT) += spl_fat.o obj-$(CONFIG_$(PHASE_)FS_EXT4) += spl_ext.o +obj-$(CONFIG_$(PHASE_)FS_SQUASHFS) += spl_squashfs.o obj-$(CONFIG_$(PHASE_)LOAD_IMX_CONTAINER) += spl_imx_container.o obj-$(CONFIG_$(PHASE_)SATA) += spl_sata.o obj-$(CONFIG_$(PHASE_)NVME) += spl_nvme.o diff --git a/common/spl/spl_squashfs.c b/common/spl/spl_squashfs.c new file mode 100644 index 00000000000..d3b1c70bfc4 --- /dev/null +++ b/common/spl/spl_squashfs.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Paratronic + * Copyright (C) 2026 Bootlin + * + * Author: Richard Genoud + * + */ + +#include +#include +#include +#include +#include +#include +#include + +static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset, + ulong size, void *buf) +{ + struct legacy_img_hdr *header; + char *filename = load->priv; + loff_t actread; + int ret; + + ret = sqfs_read(filename, buf, file_offset, size, &actread); + if (ret) + return ret; + + if (CONFIG_IS_ENABLED(OS_BOOT)) { + header = (struct legacy_img_hdr *)buf; + if (image_get_magic(header) != FDT_MAGIC) + return size; + } + + return actread; +} + +int spl_load_image_sqfs(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev, + struct blk_desc *block_dev, int partition, + const char *filename) +{ + int err; + loff_t size = 0; + struct spl_load_info load; + struct disk_partition part_info = {}; + + err = part_get_info(block_dev, partition, &part_info); + if (err) { + printf("spl: no partition table found\n"); + goto end; + } + + err = sqfs_probe(block_dev, &part_info); + if (err) { + printf("spl: sqfs probe err part_name:%s type=%s err=%d\n", + part_info.name, part_info.type, err); + goto end; + } + + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL)) { + err = sqfs_size(filename, &size); + if (err) + goto end; + } + + spl_load_init(&load, spl_fit_read, (void *)filename, 1); + + err = spl_load(spl_image, bootdev, &load, size, 0); + +end: + if (err < 0) + printf("%s: error reading image %s, err - %d\n", + __func__, filename, err); + + return err; +} diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c index 9cb8b4afcdd..543db8c7e9e 100644 --- a/fs/squashfs/sqfs.c +++ b/fs/squashfs/sqfs.c @@ -1490,13 +1490,11 @@ static int sqfs_read_nest(const char *filename, void *buf, loff_t offset, goto out; } - /* If the user specifies a length, check its sanity */ - if (len) { - if (len > finfo.size) { - ret = -EINVAL; - goto out; - } - + /* + * For FIT loading, the len is ALIGN, so it may exceed the actual size. + * Let's just read the max. + */ + if (len && len < finfo.size) { finfo.size = len; } else { len = finfo.size; diff --git a/include/part.h b/include/part.h index daebbbc2e68..9679521825f 100644 --- a/include/part.h +++ b/include/part.h @@ -461,6 +461,7 @@ ulong disk_blk_erase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt); #ifdef CONFIG_XPL_BUILD # define part_print_ptr(x) NULL # if defined(CONFIG_SPL_FS_EXT4) || defined(CONFIG_SPL_FS_FAT) || \ + defined(CONFIG_SPL_FS_SQUASHFS) || \ defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION) || \ defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE) # define part_get_info_ptr(x) x diff --git a/include/spl.h b/include/spl.h index 06dc28362d3..5078d7525ab 100644 --- a/include/spl.h +++ b/include/spl.h @@ -882,6 +882,12 @@ int spl_blk_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, enum uclass_id uclass_id, int devnum, int partnum); +/* SPL SQUASHFS image functions */ +int spl_load_image_sqfs(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev, + struct blk_desc *block_dev, int partition, + const char *filename); + /** * spl_early_init() - Set up device tree and driver model in SPL if enabled * From fb0df3552892ff150edaf7579989fd4750ee85ee Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Fri, 13 Mar 2026 11:42:27 +0100 Subject: [PATCH 5/7] spl: mmc: support squashfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spl_mmc_do_fs_boot supports now loading an image from squashfs. Also, convert #if defined(CONFIG_SPL_xx) to if (CONFIG_IS_ENABLED(xx)) Signed-off-by: Richard Genoud Reviewed-by: Miquel Raynal Reviewed-by: João Marcos Costa --- common/spl/spl_mmc.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 47cfe4aef58..cc16709dc9b 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -226,6 +226,11 @@ static int __maybe_unused spl_mmc_fs_load(struct spl_image_info *spl_image, if (!err) return 0; } + if (CONFIG_IS_ENABLED(FS_SQUASHFS)) { + err = spl_load_image_sqfs(spl_image, bootdev, blk_dev, part, file); + if (!err) + return 0; + } return err; } @@ -284,13 +289,15 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, u32 __weak spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device) { -#if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4) - return MMCSD_MODE_FS; -#elif defined(CONFIG_SUPPORT_EMMC_BOOT) - return MMCSD_MODE_EMMCBOOT; -#else + if (CONFIG_IS_ENABLED(FS_FAT) || + CONFIG_IS_ENABLED(FS_EXT4) || + CONFIG_IS_ENABLED(FS_SQUASHFS)) + return MMCSD_MODE_FS; + + if (IS_ENABLED(CONFIG_SUPPORT_EMMC_BOOT)) + return MMCSD_MODE_EMMCBOOT; + return MMCSD_MODE_RAW; -#endif } #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION From eed18b1e25051123804d26525d600c9d2cd76e2c Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Fri, 13 Mar 2026 11:42:28 +0100 Subject: [PATCH 6/7] =?UTF-8?q?MAINTAINERS:=20SQUASHFS:=20update=20Jo?= =?UTF-8?q?=C3=A3o=20Marcos=20Costa=20email?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit João is using his Bootlin address now. Signed-off-by: Richard Genoud Reviewed-by: Miquel Raynal Reviewed-by: João Marcos Costa --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index d2040fee252..73be3d545fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1768,7 +1768,7 @@ F: drivers/spmi/ F: include/spmi/ SQUASHFS -M: Joao Marcos Costa +M: Joao Marcos Costa R: Thomas Petazzoni R: Miquel Raynal S: Maintained From 868233099d873cc8e2f8b99f609bdbaed421eab7 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Fri, 13 Mar 2026 11:42:29 +0100 Subject: [PATCH 7/7] MAINTAINERS: SQUASHFS: Add myself as co-maintainer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I propose myself to maintain the squashfs files with João. Also, reorder patterns in alphabetical order. Signed-off-by: Richard Genoud Reviewed-by: Tom Rini Reviewed-by: Miquel Raynal Reviewed-by: João Marcos Costa --- MAINTAINERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 73be3d545fb..e9b04bbfea5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1769,12 +1769,14 @@ F: include/spmi/ SQUASHFS M: Joao Marcos Costa +M: Richard Genoud R: Thomas Petazzoni R: Miquel Raynal S: Maintained +F: cmd/sqfs.c +F: common/spl/spl_squashfs.c F: fs/squashfs/ F: include/sqfs.h -F: cmd/sqfs.c F: test/py/tests/test_fs/test_squashfs/ STACKPROTECTOR