mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-02 09:46:37 +03:00
Merge patch series "Introduce SQUASHFS support in SPL"
Richard Genoud <richard.genoud@bootlin.com> 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/20260313104229.1555236-1-richard.genoud@bootlin.com
This commit is contained in:
@@ -1783,13 +1783,15 @@ F: drivers/spmi/
|
||||
F: include/spmi/
|
||||
|
||||
SQUASHFS
|
||||
M: Joao Marcos Costa <jmcosta944@gmail.com>
|
||||
M: Joao Marcos Costa <joaomarcos.costa@bootlin.com>
|
||||
M: Richard Genoud <richard.genoud@bootlin.com>
|
||||
R: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
|
||||
R: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
78
common/spl/spl_squashfs.c
Normal file
78
common/spl/spl_squashfs.c
Normal file
@@ -0,0 +1,78 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2020 Paratronic
|
||||
* Copyright (C) 2026 Bootlin
|
||||
*
|
||||
* Author: Richard Genoud <richard.genoud@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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user