mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
The main change in this cycle was to add support for ZSTD-compressed
kernel and initrd images. ZSTD has a very fast decompressor, yet it compresses better than gzip. Signed-off-by: Ingo Molnar <mingo@kernel.org> -----BEGIN PGP SIGNATURE----- iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAl8oNX0RHG1pbmdvQGtl cm5lbC5vcmcACgkQEnMQ0APhK1jdcg/9GaPGjmNgMqi3tbfzU3z11OrbraRBgMj5 jHIZ89DuzwsqU+jbwGHGiF45ge85iPK6i2ovR3ePzL0LAlLYT3gqzPcl3kkog4E9 0E0JAddx974uW4toc8cGFEHNf4vXtvvi45FL2yvDoap9xLEcpJsQRdu9upPB4U3s +qotO6wJitM74g4l2WdbStzCAcL4ZXFA/ix19nUyLh4QlFBDqUHwufIhW1G0ciL4 txMXJ23L7e+b6FUvGyK3vFhba1isPdz5xQdQTy2DCK20rQhGu1IBsqzymEibbgIp /j4yHfUKSpxdblFcpZfknI1VM1mbt/WN5dKDKm9UnYBhA/R/2PN0klfrAQAT4SOS sP3bxXqTRXBjmop0NjOLCdjGCySYnPLFPlB6REIrMcvs6LYUSTqMZEusj7McwD7h IqS4zGEMa5A+c6Q4160Qz+zrXIyh/n/bTR/6uOKUktkUQaJ+079P64NK9RtCYZTk dkIHJChjmWZGxxXHEbo+4e7bM8gAMHDmX2pdWE5u72oYJRqBv7PVyl+SHBk+onxM crtKvqOp8Q8coirlfjx5UynZeZmH1VuIFjpvnwlAtqxZGvuTWZ0ojq3E3Y/XwHQj bVejr9AQ1gS9ZBTKwwd5cf7mnOuiXrHrBP3E7buoRw8bWtL+yqHyybqccZnSOUVN lGFshs+7J5o= =bARW -----END PGP SIGNATURE----- Merge tag 'x86-boot-2020-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull x86 boot updates from Ingo Molnar: "The main change in this cycle was to add support for ZSTD-compressed kernel and initrd images. ZSTD has a very fast decompressor, yet it compresses better than gzip" * tag 'x86-boot-2020-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: Documentation: dontdiff: Add zstd compressed files .gitignore: Add ZSTD-compressed files x86: Add support for ZSTD compressed kernel x86: Bump ZO_z_extra_bytes margin for zstd usr: Add support for zstd compressed initramfs init: Add support for zstd compressed kernel lib: Add zstd support to decompress lib: Prepare zstd for preboot environment, improve performance
This commit is contained in:
commit
c0dfadfed8
1
.gitignore
vendored
1
.gitignore
vendored
@ -44,6 +44,7 @@
|
|||||||
*.tab.[ch]
|
*.tab.[ch]
|
||||||
*.tar
|
*.tar
|
||||||
*.xz
|
*.xz
|
||||||
|
*.zst
|
||||||
Module.symvers
|
Module.symvers
|
||||||
modules.builtin
|
modules.builtin
|
||||||
modules.order
|
modules.order
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
*.ver
|
*.ver
|
||||||
*.xml
|
*.xml
|
||||||
*.xz
|
*.xz
|
||||||
|
*.zst
|
||||||
*_MODULES
|
*_MODULES
|
||||||
*_vga16.c
|
*_vga16.c
|
||||||
*~
|
*~
|
||||||
|
@ -782,9 +782,9 @@ Protocol: 2.08+
|
|||||||
uncompressed data should be determined using the standard magic
|
uncompressed data should be determined using the standard magic
|
||||||
numbers. The currently supported compression formats are gzip
|
numbers. The currently supported compression formats are gzip
|
||||||
(magic numbers 1F 8B or 1F 9E), bzip2 (magic number 42 5A), LZMA
|
(magic numbers 1F 8B or 1F 9E), bzip2 (magic number 42 5A), LZMA
|
||||||
(magic number 5D 00), XZ (magic number FD 37), and LZ4 (magic number
|
(magic number 5D 00), XZ (magic number FD 37), LZ4 (magic number
|
||||||
02 21). The uncompressed payload is currently always ELF (magic
|
02 21) and ZSTD (magic number 28 B5). The uncompressed payload is
|
||||||
number 7F 45 4C 46).
|
currently always ELF (magic number 7F 45 4C 46).
|
||||||
|
|
||||||
============ ==============
|
============ ==============
|
||||||
Field name: payload_length
|
Field name: payload_length
|
||||||
|
3
Makefile
3
Makefile
@ -464,6 +464,7 @@ KLZOP = lzop
|
|||||||
LZMA = lzma
|
LZMA = lzma
|
||||||
LZ4 = lz4c
|
LZ4 = lz4c
|
||||||
XZ = xz
|
XZ = xz
|
||||||
|
ZSTD = zstd
|
||||||
|
|
||||||
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
|
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
|
||||||
-Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
|
-Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
|
||||||
@ -512,7 +513,7 @@ CLANG_FLAGS :=
|
|||||||
export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC
|
export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC
|
||||||
export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE READELF PAHOLE LEX YACC AWK INSTALLKERNEL
|
export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE READELF PAHOLE LEX YACC AWK INSTALLKERNEL
|
||||||
export PERL PYTHON PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
|
export PERL PYTHON PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
|
||||||
export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ
|
export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD
|
||||||
export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
|
export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
|
||||||
|
|
||||||
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
|
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
|
||||||
|
@ -188,6 +188,7 @@ config X86
|
|||||||
select HAVE_KERNEL_LZMA
|
select HAVE_KERNEL_LZMA
|
||||||
select HAVE_KERNEL_LZO
|
select HAVE_KERNEL_LZO
|
||||||
select HAVE_KERNEL_XZ
|
select HAVE_KERNEL_XZ
|
||||||
|
select HAVE_KERNEL_ZSTD
|
||||||
select HAVE_KPROBES
|
select HAVE_KPROBES
|
||||||
select HAVE_KPROBES_ON_FTRACE
|
select HAVE_KPROBES_ON_FTRACE
|
||||||
select HAVE_FUNCTION_ERROR_INJECTION
|
select HAVE_FUNCTION_ERROR_INJECTION
|
||||||
|
@ -26,7 +26,7 @@ OBJECT_FILES_NON_STANDARD := y
|
|||||||
KCOV_INSTRUMENT := n
|
KCOV_INSTRUMENT := n
|
||||||
|
|
||||||
targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
|
targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
|
||||||
vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4
|
vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4 vmlinux.bin.zst
|
||||||
|
|
||||||
KBUILD_CFLAGS := -m$(BITS) -O2
|
KBUILD_CFLAGS := -m$(BITS) -O2
|
||||||
KBUILD_CFLAGS += -fno-strict-aliasing $(call cc-option, -fPIE, -fPIC)
|
KBUILD_CFLAGS += -fno-strict-aliasing $(call cc-option, -fPIE, -fPIC)
|
||||||
@ -42,6 +42,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
|
|||||||
KBUILD_CFLAGS += -Wno-pointer-sign
|
KBUILD_CFLAGS += -Wno-pointer-sign
|
||||||
KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
|
KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
|
||||||
KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
|
KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
|
||||||
|
KBUILD_CFLAGS += -D__DISABLE_EXPORTS
|
||||||
|
|
||||||
KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
|
KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
|
||||||
GCOV_PROFILE := n
|
GCOV_PROFILE := n
|
||||||
@ -145,6 +146,8 @@ $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) FORCE
|
|||||||
$(call if_changed,lzo)
|
$(call if_changed,lzo)
|
||||||
$(obj)/vmlinux.bin.lz4: $(vmlinux.bin.all-y) FORCE
|
$(obj)/vmlinux.bin.lz4: $(vmlinux.bin.all-y) FORCE
|
||||||
$(call if_changed,lz4)
|
$(call if_changed,lz4)
|
||||||
|
$(obj)/vmlinux.bin.zst: $(vmlinux.bin.all-y) FORCE
|
||||||
|
$(call if_changed,zstd22)
|
||||||
|
|
||||||
suffix-$(CONFIG_KERNEL_GZIP) := gz
|
suffix-$(CONFIG_KERNEL_GZIP) := gz
|
||||||
suffix-$(CONFIG_KERNEL_BZIP2) := bz2
|
suffix-$(CONFIG_KERNEL_BZIP2) := bz2
|
||||||
@ -152,6 +155,7 @@ suffix-$(CONFIG_KERNEL_LZMA) := lzma
|
|||||||
suffix-$(CONFIG_KERNEL_XZ) := xz
|
suffix-$(CONFIG_KERNEL_XZ) := xz
|
||||||
suffix-$(CONFIG_KERNEL_LZO) := lzo
|
suffix-$(CONFIG_KERNEL_LZO) := lzo
|
||||||
suffix-$(CONFIG_KERNEL_LZ4) := lz4
|
suffix-$(CONFIG_KERNEL_LZ4) := lz4
|
||||||
|
suffix-$(CONFIG_KERNEL_ZSTD) := zst
|
||||||
|
|
||||||
quiet_cmd_mkpiggy = MKPIGGY $@
|
quiet_cmd_mkpiggy = MKPIGGY $@
|
||||||
cmd_mkpiggy = $(obj)/mkpiggy $< > $@
|
cmd_mkpiggy = $(obj)/mkpiggy $< > $@
|
||||||
|
@ -19,13 +19,6 @@
|
|||||||
*/
|
*/
|
||||||
#define BOOT_CTYPE_H
|
#define BOOT_CTYPE_H
|
||||||
|
|
||||||
/*
|
|
||||||
* _ctype[] in lib/ctype.c is needed by isspace() of linux/ctype.h.
|
|
||||||
* While both lib/ctype.c and lib/cmdline.c will bring EXPORT_SYMBOL
|
|
||||||
* which is meaningless and will cause compiling error in some cases.
|
|
||||||
*/
|
|
||||||
#define __DISABLE_EXPORTS
|
|
||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "../string.h"
|
#include "../string.h"
|
||||||
|
@ -77,6 +77,10 @@ static int lines, cols;
|
|||||||
#ifdef CONFIG_KERNEL_LZ4
|
#ifdef CONFIG_KERNEL_LZ4
|
||||||
#include "../../../../lib/decompress_unlz4.c"
|
#include "../../../../lib/decompress_unlz4.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KERNEL_ZSTD
|
||||||
|
#include "../../../../lib/decompress_unzstd.c"
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* NOTE: When adding a new decompressor, please update the analysis in
|
* NOTE: When adding a new decompressor, please update the analysis in
|
||||||
* ../header.S.
|
* ../header.S.
|
||||||
|
@ -539,8 +539,14 @@ pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr
|
|||||||
# the size-dependent part now grows so fast.
|
# the size-dependent part now grows so fast.
|
||||||
#
|
#
|
||||||
# extra_bytes = (uncompressed_size >> 8) + 65536
|
# extra_bytes = (uncompressed_size >> 8) + 65536
|
||||||
|
#
|
||||||
|
# ZSTD compressed data grows by at most 3 bytes per 128K, and only has a 22
|
||||||
|
# byte fixed overhead but has a maximum block size of 128K, so it needs a
|
||||||
|
# larger margin.
|
||||||
|
#
|
||||||
|
# extra_bytes = (uncompressed_size >> 8) + 131072
|
||||||
|
|
||||||
#define ZO_z_extra_bytes ((ZO_z_output_len >> 8) + 65536)
|
#define ZO_z_extra_bytes ((ZO_z_output_len >> 8) + 131072)
|
||||||
#if ZO_z_output_len > ZO_z_input_len
|
#if ZO_z_output_len > ZO_z_input_len
|
||||||
# define ZO_z_extract_offset (ZO_z_output_len + ZO_z_extra_bytes - \
|
# define ZO_z_extract_offset (ZO_z_output_len + ZO_z_extra_bytes - \
|
||||||
ZO_z_input_len)
|
ZO_z_input_len)
|
||||||
|
@ -24,9 +24,16 @@
|
|||||||
# error "Invalid value for CONFIG_PHYSICAL_ALIGN"
|
# error "Invalid value for CONFIG_PHYSICAL_ALIGN"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_KERNEL_BZIP2
|
#if defined(CONFIG_KERNEL_BZIP2)
|
||||||
# define BOOT_HEAP_SIZE 0x400000
|
# define BOOT_HEAP_SIZE 0x400000
|
||||||
#else /* !CONFIG_KERNEL_BZIP2 */
|
#elif defined(CONFIG_KERNEL_ZSTD)
|
||||||
|
/*
|
||||||
|
* Zstd needs to allocate the ZSTD_DCtx in order to decompress the kernel.
|
||||||
|
* The ZSTD_DCtx is ~160KB, so set the heap size to 192KB because it is a
|
||||||
|
* round number and to allow some slack.
|
||||||
|
*/
|
||||||
|
# define BOOT_HEAP_SIZE 0x30000
|
||||||
|
#else
|
||||||
# define BOOT_HEAP_SIZE 0x10000
|
# define BOOT_HEAP_SIZE 0x10000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
11
include/linux/decompress/unzstd.h
Normal file
11
include/linux/decompress/unzstd.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef LINUX_DECOMPRESS_UNZSTD_H
|
||||||
|
#define LINUX_DECOMPRESS_UNZSTD_H
|
||||||
|
|
||||||
|
int unzstd(unsigned char *inbuf, long len,
|
||||||
|
long (*fill)(void*, unsigned long),
|
||||||
|
long (*flush)(void*, unsigned long),
|
||||||
|
unsigned char *output,
|
||||||
|
long *pos,
|
||||||
|
void (*error_fn)(char *x));
|
||||||
|
#endif
|
15
init/Kconfig
15
init/Kconfig
@ -191,13 +191,16 @@ config HAVE_KERNEL_LZO
|
|||||||
config HAVE_KERNEL_LZ4
|
config HAVE_KERNEL_LZ4
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config HAVE_KERNEL_ZSTD
|
||||||
|
bool
|
||||||
|
|
||||||
config HAVE_KERNEL_UNCOMPRESSED
|
config HAVE_KERNEL_UNCOMPRESSED
|
||||||
bool
|
bool
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Kernel compression mode"
|
prompt "Kernel compression mode"
|
||||||
default KERNEL_GZIP
|
default KERNEL_GZIP
|
||||||
depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO || HAVE_KERNEL_LZ4 || HAVE_KERNEL_UNCOMPRESSED
|
depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO || HAVE_KERNEL_LZ4 || HAVE_KERNEL_ZSTD || HAVE_KERNEL_UNCOMPRESSED
|
||||||
help
|
help
|
||||||
The linux kernel is a kind of self-extracting executable.
|
The linux kernel is a kind of self-extracting executable.
|
||||||
Several compression algorithms are available, which differ
|
Several compression algorithms are available, which differ
|
||||||
@ -276,6 +279,16 @@ config KERNEL_LZ4
|
|||||||
is about 8% bigger than LZO. But the decompression speed is
|
is about 8% bigger than LZO. But the decompression speed is
|
||||||
faster than LZO.
|
faster than LZO.
|
||||||
|
|
||||||
|
config KERNEL_ZSTD
|
||||||
|
bool "ZSTD"
|
||||||
|
depends on HAVE_KERNEL_ZSTD
|
||||||
|
help
|
||||||
|
ZSTD is a compression algorithm targeting intermediate compression
|
||||||
|
with fast decompression speed. It will compress better than GZIP and
|
||||||
|
decompress around the same speed as LZO, but slower than LZ4. You
|
||||||
|
will need at least 192 KB RAM or more for booting. The zstd command
|
||||||
|
line tool is required for compression.
|
||||||
|
|
||||||
config KERNEL_UNCOMPRESSED
|
config KERNEL_UNCOMPRESSED
|
||||||
bool "None"
|
bool "None"
|
||||||
depends on HAVE_KERNEL_UNCOMPRESSED
|
depends on HAVE_KERNEL_UNCOMPRESSED
|
||||||
|
@ -342,6 +342,10 @@ config DECOMPRESS_LZ4
|
|||||||
select LZ4_DECOMPRESS
|
select LZ4_DECOMPRESS
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
|
config DECOMPRESS_ZSTD
|
||||||
|
select ZSTD_DECOMPRESS
|
||||||
|
tristate
|
||||||
|
|
||||||
#
|
#
|
||||||
# Generic allocator support is selected if needed
|
# Generic allocator support is selected if needed
|
||||||
#
|
#
|
||||||
|
@ -170,6 +170,7 @@ lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o
|
|||||||
lib-$(CONFIG_DECOMPRESS_XZ) += decompress_unxz.o
|
lib-$(CONFIG_DECOMPRESS_XZ) += decompress_unxz.o
|
||||||
lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o
|
lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o
|
||||||
lib-$(CONFIG_DECOMPRESS_LZ4) += decompress_unlz4.o
|
lib-$(CONFIG_DECOMPRESS_LZ4) += decompress_unlz4.o
|
||||||
|
lib-$(CONFIG_DECOMPRESS_ZSTD) += decompress_unzstd.o
|
||||||
|
|
||||||
obj-$(CONFIG_TEXTSEARCH) += textsearch.o
|
obj-$(CONFIG_TEXTSEARCH) += textsearch.o
|
||||||
obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
|
obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <linux/decompress/inflate.h>
|
#include <linux/decompress/inflate.h>
|
||||||
#include <linux/decompress/unlzo.h>
|
#include <linux/decompress/unlzo.h>
|
||||||
#include <linux/decompress/unlz4.h>
|
#include <linux/decompress/unlz4.h>
|
||||||
|
#include <linux/decompress/unzstd.h>
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
@ -37,6 +38,9 @@
|
|||||||
#ifndef CONFIG_DECOMPRESS_LZ4
|
#ifndef CONFIG_DECOMPRESS_LZ4
|
||||||
# define unlz4 NULL
|
# define unlz4 NULL
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef CONFIG_DECOMPRESS_ZSTD
|
||||||
|
# define unzstd NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
struct compress_format {
|
struct compress_format {
|
||||||
unsigned char magic[2];
|
unsigned char magic[2];
|
||||||
@ -52,6 +56,7 @@ static const struct compress_format compressed_formats[] __initconst = {
|
|||||||
{ {0xfd, 0x37}, "xz", unxz },
|
{ {0xfd, 0x37}, "xz", unxz },
|
||||||
{ {0x89, 0x4c}, "lzo", unlzo },
|
{ {0x89, 0x4c}, "lzo", unlzo },
|
||||||
{ {0x02, 0x21}, "lz4", unlz4 },
|
{ {0x02, 0x21}, "lz4", unlz4 },
|
||||||
|
{ {0x28, 0xb5}, "zstd", unzstd },
|
||||||
{ {0, 0}, NULL, NULL }
|
{ {0, 0}, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
345
lib/decompress_unzstd.c
Normal file
345
lib/decompress_unzstd.c
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Important notes about in-place decompression
|
||||||
|
*
|
||||||
|
* At least on x86, the kernel is decompressed in place: the compressed data
|
||||||
|
* is placed to the end of the output buffer, and the decompressor overwrites
|
||||||
|
* most of the compressed data. There must be enough safety margin to
|
||||||
|
* guarantee that the write position is always behind the read position.
|
||||||
|
*
|
||||||
|
* The safety margin for ZSTD with a 128 KB block size is calculated below.
|
||||||
|
* Note that the margin with ZSTD is bigger than with GZIP or XZ!
|
||||||
|
*
|
||||||
|
* The worst case for in-place decompression is that the beginning of
|
||||||
|
* the file is compressed extremely well, and the rest of the file is
|
||||||
|
* uncompressible. Thus, we must look for worst-case expansion when the
|
||||||
|
* compressor is encoding uncompressible data.
|
||||||
|
*
|
||||||
|
* The structure of the .zst file in case of a compresed kernel is as follows.
|
||||||
|
* Maximum sizes (as bytes) of the fields are in parenthesis.
|
||||||
|
*
|
||||||
|
* Frame Header: (18)
|
||||||
|
* Blocks: (N)
|
||||||
|
* Checksum: (4)
|
||||||
|
*
|
||||||
|
* The frame header and checksum overhead is at most 22 bytes.
|
||||||
|
*
|
||||||
|
* ZSTD stores the data in blocks. Each block has a header whose size is
|
||||||
|
* a 3 bytes. After the block header, there is up to 128 KB of payload.
|
||||||
|
* The maximum uncompressed size of the payload is 128 KB. The minimum
|
||||||
|
* uncompressed size of the payload is never less than the payload size
|
||||||
|
* (excluding the block header).
|
||||||
|
*
|
||||||
|
* The assumption, that the uncompressed size of the payload is never
|
||||||
|
* smaller than the payload itself, is valid only when talking about
|
||||||
|
* the payload as a whole. It is possible that the payload has parts where
|
||||||
|
* the decompressor consumes more input than it produces output. Calculating
|
||||||
|
* the worst case for this would be tricky. Instead of trying to do that,
|
||||||
|
* let's simply make sure that the decompressor never overwrites any bytes
|
||||||
|
* of the payload which it is currently reading.
|
||||||
|
*
|
||||||
|
* Now we have enough information to calculate the safety margin. We need
|
||||||
|
* - 22 bytes for the .zst file format headers;
|
||||||
|
* - 3 bytes per every 128 KiB of uncompressed size (one block header per
|
||||||
|
* block); and
|
||||||
|
* - 128 KiB (biggest possible zstd block size) to make sure that the
|
||||||
|
* decompressor never overwrites anything from the block it is currently
|
||||||
|
* reading.
|
||||||
|
*
|
||||||
|
* We get the following formula:
|
||||||
|
*
|
||||||
|
* safety_margin = 22 + uncompressed_size * 3 / 131072 + 131072
|
||||||
|
* <= 22 + (uncompressed_size >> 15) + 131072
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Preboot environments #include "path/to/decompress_unzstd.c".
|
||||||
|
* All of the source files we depend on must be #included.
|
||||||
|
* zstd's only source dependeny is xxhash, which has no source
|
||||||
|
* dependencies.
|
||||||
|
*
|
||||||
|
* When UNZSTD_PREBOOT is defined we declare __decompress(), which is
|
||||||
|
* used for kernel decompression, instead of unzstd().
|
||||||
|
*
|
||||||
|
* Define __DISABLE_EXPORTS in preboot environments to prevent symbols
|
||||||
|
* from xxhash and zstd from being exported by the EXPORT_SYMBOL macro.
|
||||||
|
*/
|
||||||
|
#ifdef STATIC
|
||||||
|
# define UNZSTD_PREBOOT
|
||||||
|
# include "xxhash.c"
|
||||||
|
# include "zstd/entropy_common.c"
|
||||||
|
# include "zstd/fse_decompress.c"
|
||||||
|
# include "zstd/huf_decompress.c"
|
||||||
|
# include "zstd/zstd_common.c"
|
||||||
|
# include "zstd/decompress.c"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <linux/decompress/mm.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/zstd.h>
|
||||||
|
|
||||||
|
/* 128MB is the maximum window size supported by zstd. */
|
||||||
|
#define ZSTD_WINDOWSIZE_MAX (1 << ZSTD_WINDOWLOG_MAX)
|
||||||
|
/*
|
||||||
|
* Size of the input and output buffers in multi-call mode.
|
||||||
|
* Pick a larger size because it isn't used during kernel decompression,
|
||||||
|
* since that is single pass, and we have to allocate a large buffer for
|
||||||
|
* zstd's window anyway. The larger size speeds up initramfs decompression.
|
||||||
|
*/
|
||||||
|
#define ZSTD_IOBUF_SIZE (1 << 17)
|
||||||
|
|
||||||
|
static int INIT handle_zstd_error(size_t ret, void (*error)(char *x))
|
||||||
|
{
|
||||||
|
const int err = ZSTD_getErrorCode(ret);
|
||||||
|
|
||||||
|
if (!ZSTD_isError(ret))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case ZSTD_error_memory_allocation:
|
||||||
|
error("ZSTD decompressor ran out of memory");
|
||||||
|
break;
|
||||||
|
case ZSTD_error_prefix_unknown:
|
||||||
|
error("Input is not in the ZSTD format (wrong magic bytes)");
|
||||||
|
break;
|
||||||
|
case ZSTD_error_dstSize_tooSmall:
|
||||||
|
case ZSTD_error_corruption_detected:
|
||||||
|
case ZSTD_error_checksum_wrong:
|
||||||
|
error("ZSTD-compressed data is corrupt");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("ZSTD-compressed data is probably corrupt");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the case where we have the entire input and output in one segment.
|
||||||
|
* We can allocate less memory (no circular buffer for the sliding window),
|
||||||
|
* and avoid some memcpy() calls.
|
||||||
|
*/
|
||||||
|
static int INIT decompress_single(const u8 *in_buf, long in_len, u8 *out_buf,
|
||||||
|
long out_len, long *in_pos,
|
||||||
|
void (*error)(char *x))
|
||||||
|
{
|
||||||
|
const size_t wksp_size = ZSTD_DCtxWorkspaceBound();
|
||||||
|
void *wksp = large_malloc(wksp_size);
|
||||||
|
ZSTD_DCtx *dctx = ZSTD_initDCtx(wksp, wksp_size);
|
||||||
|
int err;
|
||||||
|
size_t ret;
|
||||||
|
|
||||||
|
if (dctx == NULL) {
|
||||||
|
error("Out of memory while allocating ZSTD_DCtx");
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Find out how large the frame actually is, there may be junk at
|
||||||
|
* the end of the frame that ZSTD_decompressDCtx() can't handle.
|
||||||
|
*/
|
||||||
|
ret = ZSTD_findFrameCompressedSize(in_buf, in_len);
|
||||||
|
err = handle_zstd_error(ret, error);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
in_len = (long)ret;
|
||||||
|
|
||||||
|
ret = ZSTD_decompressDCtx(dctx, out_buf, out_len, in_buf, in_len);
|
||||||
|
err = handle_zstd_error(ret, error);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (in_pos != NULL)
|
||||||
|
*in_pos = in_len;
|
||||||
|
|
||||||
|
err = 0;
|
||||||
|
out:
|
||||||
|
if (wksp != NULL)
|
||||||
|
large_free(wksp);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int INIT __unzstd(unsigned char *in_buf, long in_len,
|
||||||
|
long (*fill)(void*, unsigned long),
|
||||||
|
long (*flush)(void*, unsigned long),
|
||||||
|
unsigned char *out_buf, long out_len,
|
||||||
|
long *in_pos,
|
||||||
|
void (*error)(char *x))
|
||||||
|
{
|
||||||
|
ZSTD_inBuffer in;
|
||||||
|
ZSTD_outBuffer out;
|
||||||
|
ZSTD_frameParams params;
|
||||||
|
void *in_allocated = NULL;
|
||||||
|
void *out_allocated = NULL;
|
||||||
|
void *wksp = NULL;
|
||||||
|
size_t wksp_size;
|
||||||
|
ZSTD_DStream *dstream;
|
||||||
|
int err;
|
||||||
|
size_t ret;
|
||||||
|
|
||||||
|
if (out_len == 0)
|
||||||
|
out_len = LONG_MAX; /* no limit */
|
||||||
|
|
||||||
|
if (fill == NULL && flush == NULL)
|
||||||
|
/*
|
||||||
|
* We can decompress faster and with less memory when we have a
|
||||||
|
* single chunk.
|
||||||
|
*/
|
||||||
|
return decompress_single(in_buf, in_len, out_buf, out_len,
|
||||||
|
in_pos, error);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If in_buf is not provided, we must be using fill(), so allocate
|
||||||
|
* a large enough buffer. If it is provided, it must be at least
|
||||||
|
* ZSTD_IOBUF_SIZE large.
|
||||||
|
*/
|
||||||
|
if (in_buf == NULL) {
|
||||||
|
in_allocated = large_malloc(ZSTD_IOBUF_SIZE);
|
||||||
|
if (in_allocated == NULL) {
|
||||||
|
error("Out of memory while allocating input buffer");
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
in_buf = in_allocated;
|
||||||
|
in_len = 0;
|
||||||
|
}
|
||||||
|
/* Read the first chunk, since we need to decode the frame header. */
|
||||||
|
if (fill != NULL)
|
||||||
|
in_len = fill(in_buf, ZSTD_IOBUF_SIZE);
|
||||||
|
if (in_len < 0) {
|
||||||
|
error("ZSTD-compressed data is truncated");
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* Set the first non-empty input buffer. */
|
||||||
|
in.src = in_buf;
|
||||||
|
in.pos = 0;
|
||||||
|
in.size = in_len;
|
||||||
|
/* Allocate the output buffer if we are using flush(). */
|
||||||
|
if (flush != NULL) {
|
||||||
|
out_allocated = large_malloc(ZSTD_IOBUF_SIZE);
|
||||||
|
if (out_allocated == NULL) {
|
||||||
|
error("Out of memory while allocating output buffer");
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
out_buf = out_allocated;
|
||||||
|
out_len = ZSTD_IOBUF_SIZE;
|
||||||
|
}
|
||||||
|
/* Set the output buffer. */
|
||||||
|
out.dst = out_buf;
|
||||||
|
out.pos = 0;
|
||||||
|
out.size = out_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to know the window size to allocate the ZSTD_DStream.
|
||||||
|
* Since we are streaming, we need to allocate a buffer for the sliding
|
||||||
|
* window. The window size varies from 1 KB to ZSTD_WINDOWSIZE_MAX
|
||||||
|
* (8 MB), so it is important to use the actual value so as not to
|
||||||
|
* waste memory when it is smaller.
|
||||||
|
*/
|
||||||
|
ret = ZSTD_getFrameParams(¶ms, in.src, in.size);
|
||||||
|
err = handle_zstd_error(ret, error);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
if (ret != 0) {
|
||||||
|
error("ZSTD-compressed data has an incomplete frame header");
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (params.windowSize > ZSTD_WINDOWSIZE_MAX) {
|
||||||
|
error("ZSTD-compressed data has too large a window size");
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate the ZSTD_DStream now that we know how much memory is
|
||||||
|
* required.
|
||||||
|
*/
|
||||||
|
wksp_size = ZSTD_DStreamWorkspaceBound(params.windowSize);
|
||||||
|
wksp = large_malloc(wksp_size);
|
||||||
|
dstream = ZSTD_initDStream(params.windowSize, wksp, wksp_size);
|
||||||
|
if (dstream == NULL) {
|
||||||
|
error("Out of memory while allocating ZSTD_DStream");
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decompression loop:
|
||||||
|
* Read more data if necessary (error if no more data can be read).
|
||||||
|
* Call the decompression function, which returns 0 when finished.
|
||||||
|
* Flush any data produced if using flush().
|
||||||
|
*/
|
||||||
|
if (in_pos != NULL)
|
||||||
|
*in_pos = 0;
|
||||||
|
do {
|
||||||
|
/*
|
||||||
|
* If we need to reload data, either we have fill() and can
|
||||||
|
* try to get more data, or we don't and the input is truncated.
|
||||||
|
*/
|
||||||
|
if (in.pos == in.size) {
|
||||||
|
if (in_pos != NULL)
|
||||||
|
*in_pos += in.pos;
|
||||||
|
in_len = fill ? fill(in_buf, ZSTD_IOBUF_SIZE) : -1;
|
||||||
|
if (in_len < 0) {
|
||||||
|
error("ZSTD-compressed data is truncated");
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
in.pos = 0;
|
||||||
|
in.size = in_len;
|
||||||
|
}
|
||||||
|
/* Returns zero when the frame is complete. */
|
||||||
|
ret = ZSTD_decompressStream(dstream, &out, &in);
|
||||||
|
err = handle_zstd_error(ret, error);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
/* Flush all of the data produced if using flush(). */
|
||||||
|
if (flush != NULL && out.pos > 0) {
|
||||||
|
if (out.pos != flush(out.dst, out.pos)) {
|
||||||
|
error("Failed to flush()");
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
out.pos = 0;
|
||||||
|
}
|
||||||
|
} while (ret != 0);
|
||||||
|
|
||||||
|
if (in_pos != NULL)
|
||||||
|
*in_pos += in.pos;
|
||||||
|
|
||||||
|
err = 0;
|
||||||
|
out:
|
||||||
|
if (in_allocated != NULL)
|
||||||
|
large_free(in_allocated);
|
||||||
|
if (out_allocated != NULL)
|
||||||
|
large_free(out_allocated);
|
||||||
|
if (wksp != NULL)
|
||||||
|
large_free(wksp);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef UNZSTD_PREBOOT
|
||||||
|
STATIC int INIT unzstd(unsigned char *buf, long len,
|
||||||
|
long (*fill)(void*, unsigned long),
|
||||||
|
long (*flush)(void*, unsigned long),
|
||||||
|
unsigned char *out_buf,
|
||||||
|
long *pos,
|
||||||
|
void (*error)(char *x))
|
||||||
|
{
|
||||||
|
return __unzstd(buf, len, fill, flush, out_buf, 0, pos, error);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
STATIC int INIT __decompress(unsigned char *buf, long len,
|
||||||
|
long (*fill)(void*, unsigned long),
|
||||||
|
long (*flush)(void*, unsigned long),
|
||||||
|
unsigned char *out_buf, long out_len,
|
||||||
|
long *pos,
|
||||||
|
void (*error)(char *x))
|
||||||
|
{
|
||||||
|
return __unzstd(buf, len, fill, flush, out_buf, out_len, pos, error);
|
||||||
|
}
|
||||||
|
#endif
|
@ -47,6 +47,7 @@
|
|||||||
****************************************************************/
|
****************************************************************/
|
||||||
#include "bitstream.h"
|
#include "bitstream.h"
|
||||||
#include "fse.h"
|
#include "fse.h"
|
||||||
|
#include "zstd_internal.h"
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/string.h> /* memcpy, memset */
|
#include <linux/string.h> /* memcpy, memset */
|
||||||
@ -60,14 +61,6 @@
|
|||||||
enum { FSE_static_assert = 1 / (int)(!!(c)) }; \
|
enum { FSE_static_assert = 1 / (int)(!!(c)) }; \
|
||||||
} /* use only *after* variable declarations */
|
} /* use only *after* variable declarations */
|
||||||
|
|
||||||
/* check and forward error code */
|
|
||||||
#define CHECK_F(f) \
|
|
||||||
{ \
|
|
||||||
size_t const e = f; \
|
|
||||||
if (FSE_isError(e)) \
|
|
||||||
return e; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* **************************************************************
|
/* **************************************************************
|
||||||
* Templates
|
* Templates
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
@ -127,7 +127,14 @@ static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
|
|||||||
* Shared functions to include for inlining
|
* Shared functions to include for inlining
|
||||||
*********************************************/
|
*********************************************/
|
||||||
ZSTD_STATIC void ZSTD_copy8(void *dst, const void *src) {
|
ZSTD_STATIC void ZSTD_copy8(void *dst, const void *src) {
|
||||||
memcpy(dst, src, 8);
|
/*
|
||||||
|
* zstd relies heavily on gcc being able to analyze and inline this
|
||||||
|
* memcpy() call, since it is called in a tight loop. Preboot mode
|
||||||
|
* is compiled in freestanding mode, which stops gcc from analyzing
|
||||||
|
* memcpy(). Use __builtin_memcpy() to tell gcc to analyze this as a
|
||||||
|
* regular memcpy().
|
||||||
|
*/
|
||||||
|
__builtin_memcpy(dst, src, 8);
|
||||||
}
|
}
|
||||||
/*! ZSTD_wildcopy() :
|
/*! ZSTD_wildcopy() :
|
||||||
* custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */
|
* custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */
|
||||||
@ -137,13 +144,16 @@ ZSTD_STATIC void ZSTD_wildcopy(void *dst, const void *src, ptrdiff_t length)
|
|||||||
const BYTE* ip = (const BYTE*)src;
|
const BYTE* ip = (const BYTE*)src;
|
||||||
BYTE* op = (BYTE*)dst;
|
BYTE* op = (BYTE*)dst;
|
||||||
BYTE* const oend = op + length;
|
BYTE* const oend = op + length;
|
||||||
/* Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81388.
|
#if defined(GCC_VERSION) && GCC_VERSION >= 70000 && GCC_VERSION < 70200
|
||||||
|
/*
|
||||||
|
* Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81388.
|
||||||
* Avoid the bad case where the loop only runs once by handling the
|
* Avoid the bad case where the loop only runs once by handling the
|
||||||
* special case separately. This doesn't trigger the bug because it
|
* special case separately. This doesn't trigger the bug because it
|
||||||
* doesn't involve pointer/integer overflow.
|
* doesn't involve pointer/integer overflow.
|
||||||
*/
|
*/
|
||||||
if (length <= 8)
|
if (length <= 8)
|
||||||
return ZSTD_copy8(dst, src);
|
return ZSTD_copy8(dst, src);
|
||||||
|
#endif
|
||||||
do {
|
do {
|
||||||
ZSTD_copy8(op, ip);
|
ZSTD_copy8(op, ip);
|
||||||
op += 8;
|
op += 8;
|
||||||
|
@ -413,6 +413,28 @@ quiet_cmd_xzkern = XZKERN $@
|
|||||||
quiet_cmd_xzmisc = XZMISC $@
|
quiet_cmd_xzmisc = XZMISC $@
|
||||||
cmd_xzmisc = cat $(real-prereqs) | $(XZ) --check=crc32 --lzma2=dict=1MiB > $@
|
cmd_xzmisc = cat $(real-prereqs) | $(XZ) --check=crc32 --lzma2=dict=1MiB > $@
|
||||||
|
|
||||||
|
# ZSTD
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Appends the uncompressed size of the data using size_append. The .zst
|
||||||
|
# format has the size information available at the beginning of the file too,
|
||||||
|
# but it's in a more complex format and it's good to avoid changing the part
|
||||||
|
# of the boot code that reads the uncompressed size.
|
||||||
|
#
|
||||||
|
# Note that the bytes added by size_append will make the zstd tool think that
|
||||||
|
# the file is corrupt. This is expected.
|
||||||
|
#
|
||||||
|
# zstd uses a maximum window size of 8 MB. zstd22 uses a maximum window size of
|
||||||
|
# 128 MB. zstd22 is used for kernel compression because it is decompressed in a
|
||||||
|
# single pass, so zstd doesn't need to allocate a window buffer. When streaming
|
||||||
|
# decompression is used, like initramfs decompression, zstd22 should likely not
|
||||||
|
# be used because it would require zstd to allocate a 128 MB buffer.
|
||||||
|
|
||||||
|
quiet_cmd_zstd = ZSTD $@
|
||||||
|
cmd_zstd = { cat $(real-prereqs) | $(ZSTD) -19; $(size_append); } > $@
|
||||||
|
|
||||||
|
quiet_cmd_zstd22 = ZSTD22 $@
|
||||||
|
cmd_zstd22 = { cat $(real-prereqs) | $(ZSTD) -22 --ultra; $(size_append); } > $@
|
||||||
|
|
||||||
# ASM offsets
|
# ASM offsets
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
20
usr/Kconfig
20
usr/Kconfig
@ -100,6 +100,15 @@ config RD_LZ4
|
|||||||
Support loading of a LZ4 encoded initial ramdisk or cpio buffer
|
Support loading of a LZ4 encoded initial ramdisk or cpio buffer
|
||||||
If unsure, say N.
|
If unsure, say N.
|
||||||
|
|
||||||
|
config RD_ZSTD
|
||||||
|
bool "Support initial ramdisk/ramfs compressed using ZSTD"
|
||||||
|
default y
|
||||||
|
depends on BLK_DEV_INITRD
|
||||||
|
select DECOMPRESS_ZSTD
|
||||||
|
help
|
||||||
|
Support loading of a ZSTD encoded initial ramdisk or cpio buffer.
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Built-in initramfs compression mode"
|
prompt "Built-in initramfs compression mode"
|
||||||
depends on INITRAMFS_SOURCE != ""
|
depends on INITRAMFS_SOURCE != ""
|
||||||
@ -196,6 +205,17 @@ config INITRAMFS_COMPRESSION_LZ4
|
|||||||
If you choose this, keep in mind that most distros don't provide lz4
|
If you choose this, keep in mind that most distros don't provide lz4
|
||||||
by default which could cause a build failure.
|
by default which could cause a build failure.
|
||||||
|
|
||||||
|
config INITRAMFS_COMPRESSION_ZSTD
|
||||||
|
bool "ZSTD"
|
||||||
|
depends on RD_ZSTD
|
||||||
|
help
|
||||||
|
ZSTD is a compression algorithm targeting intermediate compression
|
||||||
|
with fast decompression speed. It will compress better than GZIP and
|
||||||
|
decompress around the same speed as LZO, but slower than LZ4.
|
||||||
|
|
||||||
|
If you choose this, keep in mind that you may need to install the zstd
|
||||||
|
tool to be able to compress the initram.
|
||||||
|
|
||||||
config INITRAMFS_COMPRESSION_NONE
|
config INITRAMFS_COMPRESSION_NONE
|
||||||
bool "None"
|
bool "None"
|
||||||
help
|
help
|
||||||
|
@ -15,6 +15,7 @@ compress-$(CONFIG_INITRAMFS_COMPRESSION_LZMA) := lzma
|
|||||||
compress-$(CONFIG_INITRAMFS_COMPRESSION_XZ) := xzmisc
|
compress-$(CONFIG_INITRAMFS_COMPRESSION_XZ) := xzmisc
|
||||||
compress-$(CONFIG_INITRAMFS_COMPRESSION_LZO) := lzo
|
compress-$(CONFIG_INITRAMFS_COMPRESSION_LZO) := lzo
|
||||||
compress-$(CONFIG_INITRAMFS_COMPRESSION_LZ4) := lz4
|
compress-$(CONFIG_INITRAMFS_COMPRESSION_LZ4) := lz4
|
||||||
|
compress-$(CONFIG_INITRAMFS_COMPRESSION_ZSTD) := zstd
|
||||||
|
|
||||||
obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data.o
|
obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data.o
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user