Path: blob/master/drivers/base/firmware_loader/fallback.c
26428 views
// SPDX-License-Identifier: GPL-2.012#include <linux/types.h>3#include <linux/kconfig.h>4#include <linux/list.h>5#include <linux/security.h>6#include <linux/umh.h>7#include <linux/sysctl.h>8#include <linux/module.h>910#include "fallback.h"11#include "firmware.h"1213/*14* firmware fallback mechanism15*/1617/*18* use small loading timeout for caching devices' firmware because all these19* firmware images have been loaded successfully at lease once, also system is20* ready for completing firmware loading now. The maximum size of firmware in21* current distributions is about 2M bytes, so 10 secs should be enough.22*/23void fw_fallback_set_cache_timeout(void)24{25fw_fallback_config.old_timeout = __firmware_loading_timeout();26__fw_fallback_set_timeout(10);27}2829/* Restores the timeout to the value last configured during normal operation */30void fw_fallback_set_default_timeout(void)31{32__fw_fallback_set_timeout(fw_fallback_config.old_timeout);33}3435static long firmware_loading_timeout(void)36{37return __firmware_loading_timeout() > 0 ?38__firmware_loading_timeout() * HZ : MAX_JIFFY_OFFSET;39}4041static inline int fw_sysfs_wait_timeout(struct fw_priv *fw_priv, long timeout)42{43return __fw_state_wait_common(fw_priv, timeout);44}4546static LIST_HEAD(pending_fw_head);4748void kill_pending_fw_fallback_reqs(bool kill_all)49{50struct fw_priv *fw_priv;51struct fw_priv *next;5253mutex_lock(&fw_lock);54list_for_each_entry_safe(fw_priv, next, &pending_fw_head,55pending_list) {56if (kill_all || !fw_priv->need_uevent)57__fw_load_abort(fw_priv);58}5960if (kill_all)61fw_load_abort_all = true;6263mutex_unlock(&fw_lock);64}6566/**67* fw_load_sysfs_fallback() - load a firmware via the sysfs fallback mechanism68* @fw_sysfs: firmware sysfs information for the firmware to load69* @timeout: timeout to wait for the load70*71* In charge of constructing a sysfs fallback interface for firmware loading.72**/73static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, long timeout)74{75int retval = 0;76struct device *f_dev = &fw_sysfs->dev;77struct fw_priv *fw_priv = fw_sysfs->fw_priv;7879/* fall back on userspace loading */80if (!fw_priv->data)81fw_priv->is_paged_buf = true;8283dev_set_uevent_suppress(f_dev, true);8485retval = device_add(f_dev);86if (retval) {87dev_err(f_dev, "%s: device_register failed\n", __func__);88goto err_put_dev;89}9091mutex_lock(&fw_lock);92if (fw_load_abort_all || fw_state_is_aborted(fw_priv)) {93mutex_unlock(&fw_lock);94retval = -EINTR;95goto out;96}97list_add(&fw_priv->pending_list, &pending_fw_head);98mutex_unlock(&fw_lock);99100if (fw_priv->opt_flags & FW_OPT_UEVENT) {101fw_priv->need_uevent = true;102dev_set_uevent_suppress(f_dev, false);103dev_dbg(f_dev, "firmware: requesting %s\n", fw_priv->fw_name);104kobject_uevent(&fw_sysfs->dev.kobj, KOBJ_ADD);105} else {106timeout = MAX_JIFFY_OFFSET;107}108109retval = fw_sysfs_wait_timeout(fw_priv, timeout);110if (retval < 0 && retval != -ENOENT) {111mutex_lock(&fw_lock);112fw_load_abort(fw_sysfs);113mutex_unlock(&fw_lock);114}115116if (fw_state_is_aborted(fw_priv)) {117if (retval == -ERESTARTSYS)118retval = -EINTR;119} else if (fw_priv->is_paged_buf && !fw_priv->data)120retval = -ENOMEM;121122out:123device_del(f_dev);124err_put_dev:125put_device(f_dev);126return retval;127}128129static int fw_load_from_user_helper(struct firmware *firmware,130const char *name, struct device *device,131u32 opt_flags)132{133struct fw_sysfs *fw_sysfs;134long timeout;135int ret;136137timeout = firmware_loading_timeout();138if (opt_flags & FW_OPT_NOWAIT) {139timeout = usermodehelper_read_lock_wait(timeout);140if (!timeout) {141dev_dbg(device, "firmware: %s loading timed out\n",142name);143return -EBUSY;144}145} else {146ret = usermodehelper_read_trylock();147if (WARN_ON(ret)) {148dev_err(device, "firmware: %s will not be loaded\n",149name);150return ret;151}152}153154fw_sysfs = fw_create_instance(firmware, name, device, opt_flags);155if (IS_ERR(fw_sysfs)) {156ret = PTR_ERR(fw_sysfs);157goto out_unlock;158}159160fw_sysfs->fw_priv = firmware->priv;161ret = fw_load_sysfs_fallback(fw_sysfs, timeout);162163if (!ret)164ret = assign_fw(firmware, device);165166out_unlock:167usermodehelper_read_unlock();168169return ret;170}171172static bool fw_force_sysfs_fallback(u32 opt_flags)173{174if (fw_fallback_config.force_sysfs_fallback)175return true;176if (!(opt_flags & FW_OPT_USERHELPER))177return false;178return true;179}180181static bool fw_run_sysfs_fallback(u32 opt_flags)182{183int ret;184185if (fw_fallback_config.ignore_sysfs_fallback) {186pr_info_once("Ignoring firmware sysfs fallback due to sysctl knob\n");187return false;188}189190if ((opt_flags & FW_OPT_NOFALLBACK_SYSFS))191return false;192193/* Also permit LSMs and IMA to fail firmware sysfs fallback */194ret = security_kernel_load_data(LOADING_FIRMWARE, true);195if (ret < 0)196return false;197198return fw_force_sysfs_fallback(opt_flags);199}200201/**202* firmware_fallback_sysfs() - use the fallback mechanism to find firmware203* @fw: pointer to firmware image204* @name: name of firmware file to look for205* @device: device for which firmware is being loaded206* @opt_flags: options to control firmware loading behaviour, as defined by207* &enum fw_opt208* @ret: return value from direct lookup which triggered the fallback mechanism209*210* This function is called if direct lookup for the firmware failed, it enables211* a fallback mechanism through userspace by exposing a sysfs loading212* interface. Userspace is in charge of loading the firmware through the sysfs213* loading interface. This sysfs fallback mechanism may be disabled completely214* on a system by setting the proc sysctl value ignore_sysfs_fallback to true.215* If this is false we check if the internal API caller set the216* @FW_OPT_NOFALLBACK_SYSFS flag, if so it would also disable the fallback217* mechanism. A system may want to enforce the sysfs fallback mechanism at all218* times, it can do this by setting ignore_sysfs_fallback to false and219* force_sysfs_fallback to true.220* Enabling force_sysfs_fallback is functionally equivalent to build a kernel221* with CONFIG_FW_LOADER_USER_HELPER_FALLBACK.222**/223int firmware_fallback_sysfs(struct firmware *fw, const char *name,224struct device *device,225u32 opt_flags,226int ret)227{228if (!fw_run_sysfs_fallback(opt_flags))229return ret;230231if (!(opt_flags & FW_OPT_NO_WARN))232dev_warn(device, "Falling back to sysfs fallback for: %s\n",233name);234else235dev_dbg(device, "Falling back to sysfs fallback for: %s\n",236name);237return fw_load_from_user_helper(fw, name, device, opt_flags);238}239240241