Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp590959pxb; Wed, 27 Jan 2021 16:04:19 -0800 (PST) X-Google-Smtp-Source: ABdhPJwgcf9BdyR65SY8PM0C4UeeTY2NpaeGAykrYWUtIUe8zCqZk8PL7pX1DlLtL4kcZditXkMn X-Received: by 2002:a17:907:b01:: with SMTP id h1mr8542257ejl.450.1611792259441; Wed, 27 Jan 2021 16:04:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1611792259; cv=none; d=google.com; s=arc-20160816; b=yC8gX+mMyTLgv3Ps/6AooPy2uEeVo3RZzyOSpbqxlubYjaeONFGYPQ+2wCih/nfxwK ULX8d8ubKX5+AKtH+OudbYokoNXJihjevw9sQ0qmvbZvL3ZF6TRAd6q29eFKX8K1/VyS o4RcyV/0M7RDqcwULzIaUz2rcIR3C9bd+m6YmNK6Ru+HCXqhtvB3BpJnXf7cPJIgXyam blkDeiuAncVe5Ekn5Omyk28yIK0YEeA5mpOFpDAvMqaakr6aV+Ei8Exd5+cRYKLVlZUn KLFa3gVKJQIjogG4/7E1Hmgqcy5vZmWpMTZuco3Xhne6iGZY696AJ5DyNcY2z4C3Exsj 244w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=7NuN20+L5K8+zYVp7J5flYWHemP6WjuIYz54q31muFg=; b=PgsE373+dTKOHRDEbHGOhMvIUayHtJMjcPK4PjZ1PYgsRUl6fRvDXWHQBhUFuK6nOE 1jODuTgJZv8eykyxtPwBpD1ixYIJWxuTpWF5JGqjDdion3Uej5ocitS3v90x7znL7kMj YTf/JLIPVJ54j2YANtYcsEsGiKH7hYmi+irOlOnhb/KNJIHfI9OUXlhuUfX88jqj+f+c jN+kz5NvN8H1kfaqxfWRkw5fAPmv4rLvoViNnWVElIv6IerdhR+4Ko8GO3V6HkMtUp9a MiUMi3qv3BcU1G9PIkT6pXlpV8hYhjcvv5PLPMejygvnW22V0vGzQGwTmQu0QlvkViOt uiGg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id f6si1848558edq.152.2021.01.27.16.03.54; Wed, 27 Jan 2021 16:04:19 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236208AbhA0PvK (ORCPT + 99 others); Wed, 27 Jan 2021 10:51:10 -0500 Received: from mx2.suse.de ([195.135.220.15]:50346 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235666AbhA0PuW (ORCPT ); Wed, 27 Jan 2021 10:50:22 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id C0A4EAE05; Wed, 27 Jan 2021 15:49:40 +0000 (UTC) From: Takashi Iwai To: Luis Chamberlain Cc: Greg Kroah-Hartman , "Rafael J . Wysocki" , 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 Message-Id: <20210127154939.13288-2-tiwai@suse.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210127154939.13288-1-tiwai@suse.de> References: <20210127154939.13288-1-tiwai@suse.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- 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 #include #include +#include #include #include @@ -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