summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-03-26 11:04:41 -0600
committerTom Rini <[email protected]>2026-03-26 11:04:41 -0600
commit80a4c49a4ab2ad06fa84a8b7bdf6e33b3b5101bf (patch)
tree94041e641b12a66eef8c35d991d83fb05409d698
parent5673d25fd82a00eb5a2bf5761b3aa92de0e9e4e1 (diff)
parent868233099d873cc8e2f8b99f609bdbaed421eab7 (diff)
Merge patch series "Introduce SQUASHFS support in SPL"
Richard Genoud <[email protected]> says: SquashFS has support in U-Boot, but not in SPL. This series adds the possibility for the SPL to load files from SquashFS partitions. This is useful, for instance, when there's a SquashFS rootfs containing U-Boot binary. NB: falcon mode is not supported yet. Link: https://lore.kernel.org/r/[email protected]
-rw-r--r--MAINTAINERS6
-rw-r--r--common/spl/Makefile1
-rw-r--r--common/spl/spl_mmc.c19
-rw-r--r--common/spl/spl_squashfs.c78
-rw-r--r--fs/squashfs/sqfs.c12
-rw-r--r--fs/squashfs/sqfs_decompressor.c71
-rw-r--r--include/part.h1
-rw-r--r--include/spl.h6
-rw-r--r--include/squashfs.h5
9 files changed, 135 insertions, 64 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index fb9c28c33ca..4d168349ae6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1783,13 +1783,15 @@ F: drivers/spmi/
F: include/spmi/
SQUASHFS
-M: Joao Marcos Costa <[email protected]>
+M: Joao Marcos Costa <[email protected]>
+M: Richard Genoud <[email protected]>
R: Thomas Petazzoni <[email protected]>
R: Miquel Raynal <[email protected]>
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
diff --git a/common/spl/Makefile b/common/spl/Makefile
index e18f3cf0948..9c94e8f143e 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_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
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 <[email protected]>
+ *
+ */
+
+#include <env.h>
+#include <part.h>
+#include <spl.h>
+#include <spl_load.h>
+#include <squashfs.h>
+#include <errno.h>
+#include <image.h>
+
+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/fs/squashfs/sqfs_decompressor.c b/fs/squashfs/sqfs_decompressor.c
index cfd1153fd74..a156cfe6f65 100644
--- a/fs/squashfs/sqfs_decompressor.c
+++ b/fs/squashfs/sqfs_decompressor.c
@@ -10,19 +10,19 @@
#include <stdio.h>
#include <stdlib.h>
-#if IS_ENABLED(CONFIG_LZO)
+#if CONFIG_IS_ENABLED(LZO)
#include <linux/lzo.h>
#endif
-#if IS_ENABLED(CONFIG_ZLIB)
+#if CONFIG_IS_ENABLED(ZLIB)
#include <u-boot/zlib.h>
#endif
-#if IS_ENABLED(CONFIG_LZ4)
+#if CONFIG_IS_ENABLED(LZ4)
#include <u-boot/lz4.h>
#endif
-#if IS_ENABLED(CONFIG_ZSTD)
+#if CONFIG_IS_ENABLED(ZSTD)
#include <linux/zstd.h>
#endif
@@ -33,60 +33,35 @@ 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)
- case SQFS_COMP_LZO:
- break;
-#endif
-#if IS_ENABLED(CONFIG_ZLIB)
- case SQFS_COMP_ZLIB:
- break;
-#endif
-#if IS_ENABLED(CONFIG_LZ4)
- case SQFS_COMP_LZ4:
- break;
-#endif
-#if IS_ENABLED(CONFIG_ZSTD)
- case SQFS_COMP_ZSTD:
+ 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)
+ 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 IS_ENABLED(CONFIG_LZO)
- case SQFS_COMP_LZO:
- break;
-#endif
-#if IS_ENABLED(CONFIG_ZLIB)
- case SQFS_COMP_ZLIB:
- break;
-#endif
-#if IS_ENABLED(CONFIG_LZ4)
- case SQFS_COMP_LZ4:
- break;
-#endif
-#if IS_ENABLED(CONFIG_ZSTD)
- case SQFS_COMP_ZSTD:
+ if (comp_type == SQFS_COMP_ZSTD)
free(ctxt->zstd_workspace);
- break;
#endif
- }
}
-#if IS_ENABLED(CONFIG_ZLIB)
+#if CONFIG_IS_ENABLED(ZLIB)
static void zlib_decompression_status(int ret)
{
switch (ret) {
@@ -103,7 +78,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 +104,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 +116,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 +126,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 +137,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) {
diff --git a/include/part.h b/include/part.h
index aed089d00f6..15daacd7faa 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
*
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 <fs.h>
+#include <blk.h>
+#include <part.h>
+#include <linux/types.h>
int sqfs_opendir(const char *filename, struct fs_dir_stream **dirsp);
int sqfs_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp);