diff options
| author | Luis Chamberlain <mcgrof@kernel.org> | 2021-09-03 22:38:20 +0000 |
|---|---|---|
| committer | Luis Chamberlain <mcgrof@kernel.org> | 2021-09-10 17:49:11 -0700 |
| commit | 901fa5ebf866856ccd05ebc532f3a27786f7966e (patch) | |
| tree | 5866d85c653bc2fddb53986f5f87b0c4a657cfe1 | |
| parent | b9da4cb28e29a8bcc2d24a79e8f339107faca091 (diff) | |
| download | linux-next-901fa5ebf866856ccd05ebc532f3a27786f7966e.tar.gz | |
firmware_loader: formalize built-in firmware API
Now that we have a kconfig entry to represent built-in firmware
support, formalize its use witha a proper API. This can later be
used by other callers where all they need is built-in firmware.
We export the firmware_request_builtin() call for now only
under the TEST_FIRMWARE symbol namespace as there are no
direct modular users for it. If they pop up they are free
to export it generally. Built-in code always gets access to
the callers and we'll demonstrate a hidden user which has been
lurking in the kernel for a while and the reason why using a
proper API was better long term.
Reviewed-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
| -rw-r--r-- | drivers/base/firmware_loader/builtin/Makefile | 6 | ||||
| -rw-r--r-- | drivers/base/firmware_loader/builtin/main.c | 45 | ||||
| -rw-r--r-- | drivers/base/firmware_loader/firmware.h | 9 | ||||
| -rw-r--r-- | drivers/base/firmware_loader/main.c | 65 | ||||
| -rw-r--r-- | include/linux/firmware.h | 13 |
5 files changed, 74 insertions, 64 deletions
diff --git a/drivers/base/firmware_loader/builtin/Makefile b/drivers/base/firmware_loader/builtin/Makefile index 101754ad48d91..eb4be452062a0 100644 --- a/drivers/base/firmware_loader/builtin/Makefile +++ b/drivers/base/firmware_loader/builtin/Makefile @@ -1,11 +1,13 @@ # SPDX-License-Identifier: GPL-2.0 +obj-y += main.o # Create $(fwdir) from $(CONFIG_EXTRA_FIRMWARE_DIR) -- if it doesn't have a # leading /, it's relative to $(srctree). fwdir := $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE_DIR)) fwdir := $(addprefix $(srctree)/,$(filter-out /%,$(fwdir)))$(filter /%,$(fwdir)) -obj-y := $(addsuffix .gen.o, $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE))) +firmware := $(addsuffix .gen.o, $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE))) +obj-y += $(firmware) FWNAME = $(patsubst $(obj)/%.gen.S,%,$@) FWSTR = $(subst $(comma),_,$(subst /,_,$(subst .,_,$(subst -,_,$(FWNAME))))) @@ -34,7 +36,7 @@ $(obj)/%.gen.S: FORCE $(call filechk,fwbin) # The .o files depend on the binaries directly; the .S files don't. -$(addprefix $(obj)/, $(obj-y)): $(obj)/%.gen.o: $(fwdir)/% +$(addprefix $(obj)/, $(firmware)): $(obj)/%.gen.o: $(fwdir)/% targets := $(patsubst $(obj)/%,%, \ $(shell find $(obj) -name \*.gen.S 2>/dev/null)) diff --git a/drivers/base/firmware_loader/builtin/main.c b/drivers/base/firmware_loader/builtin/main.c new file mode 100644 index 0000000000000..385cf8379378a --- /dev/null +++ b/drivers/base/firmware_loader/builtin/main.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Builtin firmware support */ + +#include <linux/firmware.h> + +extern struct builtin_fw __start_builtin_fw[]; +extern struct builtin_fw __end_builtin_fw[]; + +static void fw_copy_to_prealloc_buf(struct firmware *fw, + void *buf, size_t size) +{ + if (!buf || size < fw->size) + return; + memcpy(buf, fw->data, fw->size); +} + +bool firmware_request_builtin(struct firmware *fw, const char *name, + void *buf, size_t size) +{ + struct builtin_fw *b_fw; + + for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) { + if (strcmp(name, b_fw->name) == 0) { + fw->size = b_fw->size; + fw->data = b_fw->data; + fw_copy_to_prealloc_buf(fw, buf, size); + + return true; + } + } + + return false; +} +EXPORT_SYMBOL_NS_GPL(firmware_request_builtin, TEST_FIRMWARE); + +bool firmware_is_builtin(const struct firmware *fw) +{ + struct builtin_fw *b_fw; + + for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) + if (fw->data == b_fw->data) + return true; + + return false; +} diff --git a/drivers/base/firmware_loader/firmware.h b/drivers/base/firmware_loader/firmware.h index a3014e9e2c852..5da4364879017 100644 --- a/drivers/base/firmware_loader/firmware.h +++ b/drivers/base/firmware_loader/firmware.h @@ -151,6 +151,15 @@ static inline void fw_state_done(struct fw_priv *fw_priv) int assign_fw(struct firmware *fw, struct device *device); +#ifdef CONFIG_FW_LOADER_BUILTIN +bool firmware_is_builtin(const struct firmware *fw); +#else +static inline bool firmware_is_builtin(const struct firmware *fw) +{ + return false; +} +#endif + #ifdef CONFIG_FW_LOADER_PAGED_BUF void fw_free_paged_buf(struct fw_priv *fw_priv); int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed); diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 9dcd07be7a2f1..0b6f3d1ef1dc4 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -93,65 +93,6 @@ DEFINE_MUTEX(fw_lock); static struct firmware_cache fw_cache; -/* Builtin firmware support */ - -#ifdef CONFIG_FW_LOADER_BUILTIN - -extern struct builtin_fw __start_builtin_fw[]; -extern struct builtin_fw __end_builtin_fw[]; - -static void fw_copy_to_prealloc_buf(struct firmware *fw, - void *buf, size_t size) -{ - if (!buf || size < fw->size) - return; - memcpy(buf, fw->data, fw->size); -} - -static bool fw_get_builtin_firmware(struct firmware *fw, const char *name, - void *buf, size_t size) -{ - struct builtin_fw *b_fw; - - for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) { - if (strcmp(name, b_fw->name) == 0) { - fw->size = b_fw->size; - fw->data = b_fw->data; - fw_copy_to_prealloc_buf(fw, buf, size); - - return true; - } - } - - return false; -} - -static bool fw_is_builtin_firmware(const struct firmware *fw) -{ - struct builtin_fw *b_fw; - - for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) - if (fw->data == b_fw->data) - return true; - - return false; -} - -#else - -static inline bool fw_get_builtin_firmware(struct firmware *fw, - const char *name, void *buf, - size_t size) -{ - return false; -} - -static inline bool fw_is_builtin_firmware(const struct firmware *fw) -{ - return false; -} -#endif - static void fw_state_init(struct fw_priv *fw_priv) { struct fw_state *fw_st = &fw_priv->fw_st; @@ -736,7 +677,7 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name, return -ENOMEM; } - if (fw_get_builtin_firmware(firmware, name, dbuf, size)) { + if (firmware_request_builtin(firmware, name, dbuf, size)) { dev_dbg(device, "using built-in %s\n", name); return 0; /* assigned */ } @@ -1051,7 +992,7 @@ EXPORT_SYMBOL(request_partial_firmware_into_buf); void release_firmware(const struct firmware *fw) { if (fw) { - if (!fw_is_builtin_firmware(fw)) + if (!firmware_is_builtin(fw)) firmware_free_data(fw); kfree(fw); } @@ -1215,7 +1156,7 @@ static int uncache_firmware(const char *fw_name) pr_debug("%s: %s\n", __func__, fw_name); - if (fw_get_builtin_firmware(&fw, fw_name, NULL, 0)) + if (firmware_request_builtin(&fw, fw_name, NULL, 0)) return 0; fw_priv = lookup_fw_priv(fw_name); diff --git a/include/linux/firmware.h b/include/linux/firmware.h index 25109192cebec..1f8df57ecacff 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -20,12 +20,16 @@ struct firmware { struct module; struct device; +#ifdef CONFIG_FW_LOADER_BUILTIN struct builtin_fw { char *name; void *data; unsigned long size; }; +bool firmware_request_builtin(struct firmware *fw, const char *name, + void *buf, size_t size); + /* We have to play tricks here much like stringify() to get the __COUNTER__ macro to be expanded as we want it */ #define __fw_concat1(x, y) x##y @@ -38,6 +42,15 @@ struct builtin_fw { static const struct builtin_fw __fw_concat(__builtin_fw,__COUNTER__) \ __used __section(".builtin_fw") = { name, blob, size } +#else +static inline bool firmware_request_builtin(struct firmware *fw, + const char *name, + void *buf, size_t size) +{ + return false; +} +#endif + #if defined(CONFIG_FW_LOADER) || (defined(CONFIG_FW_LOADER_MODULE) && defined(MODULE)) int request_firmware(const struct firmware **fw, const char *name, struct device *device); |
