[PATCH 4/7] spl: add squashfs support

Richard Genoud richard.genoud at bootlin.com
Fri Mar 13 11:42:26 CET 2026


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 <richard.genoud at bootlin.com>
---
 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 4c9482bd3096..53cc45fc5b9b 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 000000000000..d3b1c70bfc45
--- /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 <richard.genoud at bootlin.com>
+ *
+ */
+
+#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 9cb8b4afcddb..543db8c7e9ec 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 daebbbc2e68f..9679521825f7 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 06dc28362d3f..5078d7525abb 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
  *


More information about the U-Boot mailing list