Attention is currently required from: Martin L Roth, Julius Werner.
Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/69893 )
Change subject: commonlib/bsd: Add zstd support ......................................................................
commonlib/bsd: Add zstd support
This adds the option to compress ramstage and payloads with ZSTD.
Change-Id: Ic1b1f53327c598d07bd83d4391e8012d41696a16 Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- M Makefile.inc M payloads/Kconfig M src/Kconfig M src/commonlib/Makefile.inc A src/commonlib/bsd/zstd/Makefile.inc A src/commonlib/bsd/zstd_wrapper.c M src/commonlib/include/commonlib/timestamp_serialized.h M src/lib/Makefile.inc M src/lib/cbfs.c M src/lib/selfboot.c 10 files changed, 150 insertions(+), 9 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/93/69893/1
diff --git a/Makefile.inc b/Makefile.inc index 563a2bc..5bc1cec 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -386,16 +386,19 @@ ####################################################################### # a variety of flags for our build CBFS_COMPRESS_FLAG:=none -ifeq ($(CONFIG_COMPRESS_RAMSTAGE),y) +ifeq ($(CONFIG_COMPRESS_RAMSTAGE_LZMA),y) CBFS_COMPRESS_FLAG:=LZMA +else ifeq ($(CONFIG_COMPRESS_RAMSTAGE_ZSTD),y) +CBFS_COMPRESS_FLAG:=ZSTD endif
CBFS_PAYLOAD_COMPRESS_FLAG:=none ifeq ($(CONFIG_COMPRESSED_PAYLOAD_LZMA),y) CBFS_PAYLOAD_COMPRESS_FLAG:=LZMA -endif -ifeq ($(CONFIG_COMPRESSED_PAYLOAD_LZ4),y) +else ifeq ($(CONFIG_COMPRESSED_PAYLOAD_LZ4),y) CBFS_PAYLOAD_COMPRESS_FLAG:=LZ4 +else ifeq ($(CONFIG_COMPRESSED_PAYLOAD_ZSTD),y) +CBFS_PAYLOAD_COMPRESS_FLAG:=ZSTD endif
CBFS_SECONDARY_PAYLOAD_COMPRESS_FLAG:=none diff --git a/payloads/Kconfig b/payloads/Kconfig index 2a2773a..a8381ab 100644 --- a/payloads/Kconfig +++ b/payloads/Kconfig @@ -72,6 +72,12 @@ In order to reduce the size payloads take up in the ROM chip coreboot can compress them using the LZMA algorithm.
+config COMPRESSED_PAYLOAD_ZSTD + bool "Use ZSTD compression for payloads" + help + In order to reduce the size payloads take up in the ROM chip + coreboot can compress them using the ZSTD algorithm. + config COMPRESSED_PAYLOAD_LZ4 bool "Use LZ4 compression for payloads" help diff --git a/src/Kconfig b/src/Kconfig index f30a1bb..671df2a 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -170,13 +170,32 @@ every boot. Use this if you want the NVRAM configuration to never be modified from its default values.
-config COMPRESS_RAMSTAGE - bool "Compress ramstage with LZMA" +choice COMPRESS_RAMSTAGE + bool "Ramstage compression" depends on HAVE_RAMSTAGE + default COMPRESS_RAMSTAGE_LZMA # Default value set at the end of the file help Compress ramstage to save memory in the flash image.
+config COMPRESS_RAMSTAGE_NONE + bool "none" + help + Don't compress ramstage + +config COMPRESS_RAMSTAGE_LZMA + bool "LZMA" + help + Compress ramstage with LZMA. + +config COMPRESS_RAMSTAGE_ZSTD + bool "ZSTD" + help + Compress ramstage with ZSTD. + This is faster than LZMA but uses more stack. + +endchoice + config COMPRESS_PRERAM_STAGES bool "Compress romstage and verstage with LZ4" depends on (HAVE_ROMSTAGE || HAVE_VERSTAGE) && NO_XIP_EARLY_STAGES @@ -660,7 +679,7 @@
config STACK_SIZE hex - default 0x2000 if ARCH_X86 + default 0x20000 if ARCH_X86 default 0x0
config MAX_CPUS diff --git a/src/commonlib/Makefile.inc b/src/commonlib/Makefile.inc index e90ed4f..cb19fd0 100644 --- a/src/commonlib/Makefile.inc +++ b/src/commonlib/Makefile.inc @@ -51,8 +51,12 @@ ramstage-y += bsd/lz4_wrapper.c postcar-y += bsd/lz4_wrapper.c
+all-y += bsd/zstd_wrapper.c + ramstage-y += sort.c
romstage-y += bsd/elog.c ramstage-y += bsd/elog.c smm-y += bsd/elog.c + +subdirs-y += bsd/zstd diff --git a/src/commonlib/bsd/zstd/Makefile.inc b/src/commonlib/bsd/zstd/Makefile.inc new file mode 100644 index 0000000..ceb330a --- /dev/null +++ b/src/commonlib/bsd/zstd/Makefile.inc @@ -0,0 +1,18 @@ +all-y += decompress/huf_decompress.c +all-y += decompress/zstd_ddict.c +all-y += decompress/zstd_decompress_block.c +all-y += decompress/zstd_decompress.c + +all-y += common/debug.c +all-y += common/entropy_common.c +all-y += common/error_private.c +all-y += common/fse_decompress.c +all-y += common/pool.c +all-y += common/threading.c +all-y += common/xxhash_zstd.c # this is renamed to avoid namespace conflicts with lz4 code +all-y += common/zstd_common.c + +subdirs-y += bsd/zstd +CPPFLAGS_common += -I$(src)/commonlib/bsd/zstd -I$(src)/commonlib/bsd/zstd/common +CPPFLAGS_common += -I$(src)/commonlib/bsd/zstd/decompress +CPPFLAGS_common += -DXXH_NAMESPACE=ZSTD_ -DZSTD_DISABLE_ASM=1 -DZSTD_HEAPMODE=0 diff --git a/src/commonlib/bsd/zstd_wrapper.c b/src/commonlib/bsd/zstd_wrapper.c new file mode 100644 index 0000000..4f3d68c1 --- /dev/null +++ b/src/commonlib/bsd/zstd_wrapper.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only */ + +#include <assert.h> +#include <commonlib/bsd/compression.h> +#include <stdint.h> +#include <stddef.h> +#define ZSTD_STATIC_LINKING_ONLY 1 +#include <zstd.h> + +size_t uzstdfn(const void *src, size_t srcn, void *dst, size_t dstn) +{ + static char buffer[95792] __aligned(8); + ASSERT(sizeof(buffer) <= ZSTD_estimateDCtxSize()); + ZSTD_DCtx *dctx = ZSTD_initStaticDCtx(buffer, sizeof(buffer)); + if (!dctx) + return 0; + return ZSTD_decompressDCtx(dctx, dst, dstn, src, srcn); +} + +#if !ENV_HAS_HEAP_SECTION +#include <stdlib.h> +#include <console/console.h> + +/* Fix some linking issues. This should never be called. */ +void free(void *) +{ + printk(BIOS_ERR, "Bogus free called\n"); +} +#endif diff --git a/src/commonlib/include/commonlib/timestamp_serialized.h b/src/commonlib/include/commonlib/timestamp_serialized.h index 4b1001e..074b793 100644 --- a/src/commonlib/include/commonlib/timestamp_serialized.h +++ b/src/commonlib/include/commonlib/timestamp_serialized.h @@ -37,6 +37,8 @@ TS_ULZMA_END = 16, TS_ULZ4F_START = 17, TS_ULZ4F_END = 18, + TS_UZSTDF_START = 19, + TS_UZSTDF_END = 20, TS_DEVICE_ENUMERATE = 30, TS_DEVICE_CONFIGURE = 40, TS_DEVICE_ENABLE = 50, @@ -211,6 +213,8 @@ TS_NAME_DEF(TS_ULZMA_END, 0, "finished LZMA decompress (ignore for x86)"), TS_NAME_DEF(TS_ULZ4F_START, TS_ULZ4F_END, "starting LZ4 decompress (ignore for x86)"), TS_NAME_DEF(TS_ULZ4F_END, 0, "finished LZ4 decompress (ignore for x86)"), + TS_NAME_DEF(TS_UZSTDF_START, TS_ULZ4F_END, "starting ZSTD decompress (ignore for x86)"), + TS_NAME_DEF(TS_UZSTDF_END, 0, "finished ZSTD decompress (ignore for x86)"), TS_NAME_DEF(TS_DEVICE_ENUMERATE, TS_DEVICE_CONFIGURE, "device enumeration"), TS_NAME_DEF(TS_DEVICE_CONFIGURE, TS_DEVICE_ENABLE, "device configuration"), TS_NAME_DEF(TS_DEVICE_ENABLE, TS_DEVICE_INITIALIZE, "device enable"), diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 1c7bc22..c266797 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -95,7 +95,7 @@ romstage-y += fmap.c romstage-y += delay.c romstage-y += cbfs.c -romstage-$(CONFIG_COMPRESS_RAMSTAGE) += lzma.c lzmadecode.c +romstage-$(CONFIG_COMPRESS_RAMSTAGE_LZMA) += lzma.c lzmadecode.c romstage-y += libgcc.c romstage-y += memrange.c romstage-$(CONFIG_PRIMITIVE_MEMTEST) += primitive_memtest.c @@ -294,7 +294,7 @@ postcar-y += gcc.c postcar-y += halt.c postcar-y += libgcc.c -postcar-$(CONFIG_COMPRESS_RAMSTAGE) += lzma.c lzmadecode.c +postcar-$(CONFIG_COMPRESS_RAMSTAGE_LZMA) += lzma.c lzmadecode.c postcar-y += memchr.c postcar-y += memcmp.c postcar-y += prog_loaders.c diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index d2829d1..0f44468 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -142,7 +142,25 @@ return false; if (ENV_ROMSTAGE && CONFIG(POSTCAR_STAGE)) return false; - if ((ENV_ROMSTAGE || ENV_POSTCAR) && !CONFIG(COMPRESS_RAMSTAGE)) + if ((ENV_ROMSTAGE || ENV_POSTCAR) && !CONFIG(COMPRESS_RAMSTAGE_LZMA)) + return false; + if (ENV_SMM) + return false; + return true; +} + +static inline bool cbfs_zstd_enabled(void) +{ + if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_ZSTD)) + return true; + if (fspm_env() && CONFIG(FSP_COMPRESS_FSP_M_ZSTD)) + return true; + /* We assume here romstage and postcar are never compressed. */ + if (ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE) + return false; + if (ENV_ROMSTAGE && CONFIG(POSTCAR_STAGE)) + return false; + if ((ENV_ROMSTAGE || ENV_POSTCAR) && !CONFIG(COMPRESS_RAMSTAGE_ZSTD)) return false; if (ENV_SMM) return false; @@ -255,6 +273,24 @@ rdev_munmap(rdev, map);
return out_size; + case CBFS_COMPRESS_ZSTD: + if (!cbfs_zstd_enabled()) + return 0; + + map = rdev_mmap_full(rdev); + if (map == NULL) + return 0; + + if (!cbfs_file_hash_mismatch(map, in_size, mdata, skip_verification)) { + /* Note: timestamp not useful for memory-mapped media (x86) */ + timestamp_add_now(TS_UZSTDF_START); + out_size = uzstdfn(map, in_size, buffer, buffer_size); + timestamp_add_now(TS_UZSTDF_END); + } + + rdev_munmap(rdev, map); + + return out_size;
default: return 0; diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c index 637ad13..a921c02 100644 --- a/src/lib/selfboot.c +++ b/src/lib/selfboot.c @@ -87,6 +87,16 @@ return 0; break; } + case CBFS_COMPRESS_ZSTD: { + printk(BIOS_DEBUG, "using ZSTD\n"); + timestamp_add_now(TS_UZSTDF_START); + len = uzstdfn(src, len, dest, memsz); + timestamp_add_now(TS_UZSTDF_END); + if (!len) /* Decompression Error. */ + return 0; + break; + } + case CBFS_COMPRESS_NONE: { printk(BIOS_DEBUG, "it's not compressed!\n"); memcpy(dest, src, len);