All of lore.kernel.org
 help / color / mirror / Atom feed
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


  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.