From: Takashi Iwai <tiwai@suse.de>
To: Luis Chamberlain <mcgrof@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J . Wysocki" <rafael@kernel.org>,
linux-kernel@vger.kernel.org
Subject: [PATCH RFC 1/4] firmware: Add the support for ZSTD-compressed firmware files
Date: Wed, 27 Jan 2021 16:49:36 +0100 [thread overview]
Message-ID: <20210127154939.13288-2-tiwai@suse.de> (raw)
In-Reply-To: <20210127154939.13288-1-tiwai@suse.de>
Due to the popular demands on ZSTD, here is a patch to add a support
of ZSTD-compressed firmware files via the direct firmware loader.
It's just like XZ-compressed file support, providing a decompressor
with ZSTD. Since ZSTD API can give the decompression size beforehand,
the code is even simpler than XZ.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
drivers/base/firmware_loader/Kconfig | 21 ++++++--
drivers/base/firmware_loader/main.c | 74 ++++++++++++++++++++++++++--
2 files changed, 87 insertions(+), 8 deletions(-)
diff --git a/drivers/base/firmware_loader/Kconfig b/drivers/base/firmware_loader/Kconfig
index 5b24f3959255..f5307978927c 100644
--- a/drivers/base/firmware_loader/Kconfig
+++ b/drivers/base/firmware_loader/Kconfig
@@ -157,17 +157,28 @@ config FW_LOADER_USER_HELPER_FALLBACK
config FW_LOADER_COMPRESS
bool "Enable compressed firmware support"
- select FW_LOADER_PAGED_BUF
- select XZ_DEC
help
This option enables the support for loading compressed firmware
files. The caller of firmware API receives the decompressed file
content. The compressed file is loaded as a fallback, only after
loading the raw file failed at first.
- Currently only XZ-compressed files are supported, and they have to
- be compressed with either none or crc32 integrity check type (pass
- "-C crc32" option to xz command).
+if FW_LOADER_COMPRESS
+config FW_LOADER_COMPRESS_XZ
+ bool "Enable XZ-compressed firmware support"
+ select FW_LOADER_PAGED_BUF
+ select XZ_DEC
+ help
+ This option adds the support for XZ-compressed files.
+ The files have to be compressed with either none or crc32
+ integrity check type (pass "-C crc32" option to xz command).
+
+config FW_LOADER_COMPRESS_ZSTD
+ bool "Enable ZSTD-compressed firmware support"
+ select ZSTD_DECOMPRESS
+ help
+ This option adds the support for ZSTD-compressed files.
+endif # FW_LOADER_COMPRESS
config FW_CACHE
bool "Enable firmware caching during suspend"
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index 78355095e00d..71332ed4959d 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -34,6 +34,7 @@
#include <linux/syscore_ops.h>
#include <linux/reboot.h>
#include <linux/security.h>
+#include <linux/zstd.h>
#include <linux/xz.h>
#include <generated/utsrelease.h>
@@ -362,10 +363,72 @@ int fw_map_paged_buf(struct fw_priv *fw_priv)
}
#endif
+/*
+ * ZSTD-compressed firmware support
+ */
+#ifdef CONFIG_FW_LOADER_COMPRESS_ZSTD
+static int fw_decompress_zstd(struct device *dev, struct fw_priv *fw_priv,
+ size_t in_size, const void *in_buffer)
+{
+ size_t len, out_size, workspace_size;
+ void *workspace, *out_buf;
+ ZSTD_DCtx *ctx;
+ int err;
+
+ if (fw_priv->data) {
+ out_size = fw_priv->allocated_size;
+ out_buf = fw_priv->data;
+ } else {
+ out_size = ZSTD_findDecompressedSize(in_buffer, in_size);
+ if (out_size == ZSTD_CONTENTSIZE_UNKNOWN ||
+ out_size == ZSTD_CONTENTSIZE_ERROR) {
+ dev_dbg(dev, "%s: invalid decompression size\n", __func__);
+ return -EINVAL;
+ }
+ out_buf = vzalloc(out_size);
+ if (!out_buf)
+ return -ENOMEM;
+ }
+
+ workspace_size = ZSTD_DCtxWorkspaceBound();
+ workspace = kvzalloc(workspace_size, GFP_KERNEL);
+ if (!workspace) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ ctx = ZSTD_initDCtx(workspace, workspace_size);
+ if (!ctx) {
+ dev_dbg(dev, "%s: failed to initialize context\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ len = ZSTD_decompressDCtx(ctx, out_buf, out_size, in_buffer, in_size);
+ if (ZSTD_isError(len)) {
+ dev_dbg(dev, "%s: failed to decompress: %d\n", __func__,
+ ZSTD_getErrorCode(len));
+ err = -EINVAL;
+ goto error;
+ }
+
+ fw_priv->size = len;
+ if (!fw_priv->data)
+ fw_priv->data = out_buf;
+ err = 0;
+
+ error:
+ kvfree(workspace);
+ if (!fw_priv->data)
+ vfree(out_buf);
+ return err;
+}
+#endif /* CONFIG_FW_LOADER_COMPRESS_ZSTD */
+
/*
* XZ-compressed firmware support
*/
-#ifdef CONFIG_FW_LOADER_COMPRESS
+#ifdef CONFIG_FW_LOADER_COMPRESS_XZ
/* show an error and return the standard error code */
static int fw_decompress_xz_error(struct device *dev, enum xz_ret xz_ret)
{
@@ -459,7 +522,7 @@ static int fw_decompress_xz(struct device *dev, struct fw_priv *fw_priv,
else
return fw_decompress_xz_pages(dev, fw_priv, in_size, in_buffer);
}
-#endif /* CONFIG_FW_LOADER_COMPRESS */
+#endif /* CONFIG_FW_LOADER_COMPRESS_XZ */
/* direct firmware loading support */
static char fw_path_para[256];
@@ -814,7 +877,12 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
if (!(opt_flags & FW_OPT_PARTIAL))
nondirect = true;
-#ifdef CONFIG_FW_LOADER_COMPRESS
+#ifdef CONFIG_FW_LOADER_COMPRESS_ZSTD
+ if (ret == -ENOENT && nondirect)
+ ret = fw_get_filesystem_firmware(device, fw->priv, ".zst",
+ fw_decompress_zstd);
+#endif
+#ifdef CONFIG_FW_LOADER_COMPRESS_XZ
if (ret == -ENOENT && nondirect)
ret = fw_get_filesystem_firmware(device, fw->priv, ".xz",
fw_decompress_xz);
--
2.26.2
next prev parent reply other threads:[~2021-01-27 15:51 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-27 15:49 [PATCH RFC 0/4] firmware: Add ZSTD-compressed file support Takashi Iwai
2021-01-27 15:49 ` Takashi Iwai [this message]
2021-02-17 13:16 ` [PATCH RFC 1/4] firmware: Add the support for ZSTD-compressed firmware files Luis Chamberlain
2021-02-17 13:22 ` Takashi Iwai
2021-02-17 13:24 ` Luis Chamberlain
2021-02-17 13:34 ` Takashi Iwai
2021-02-17 14:17 ` Greg Kroah-Hartman
2021-02-17 14:21 ` Takashi Iwai
2021-01-27 15:49 ` [PATCH RFC 2/4] selftests: firmware: Simplify test patterns Takashi Iwai
2021-01-27 15:49 ` [PATCH RFC 3/4] selftest: firmware: Fix the request_firmware_into_buf() test for XZ format Takashi Iwai
2021-01-27 15:49 ` [PATCH RFC 4/4] selftest: firmware: Add ZSTD compressed file tests Takashi Iwai
2021-01-27 17:09 ` [PATCH RFC 0/4] firmware: Add ZSTD-compressed file support Greg Kroah-Hartman
2022-01-27 18:22 ` Hideki Yamane
2022-01-27 18:41 ` Greg Kroah-Hartman
2022-01-28 0:33 ` Hideki Yamane
2022-01-28 6:54 ` Greg Kroah-Hartman
2022-01-28 8:13 ` Takashi Iwai
2022-02-01 17:36 ` Hideki Yamane
2022-02-02 10:56 ` Takashi Iwai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210127154939.13288-2-tiwai@suse.de \
--to=tiwai@suse.de \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mcgrof@kernel.org \
--cc=rafael@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).