in firmware_loader/fallback.c [237:301]
static ssize_t firmware_loading_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev);
struct fw_priv *fw_priv;
ssize_t written = count;
int loading = simple_strtol(buf, NULL, 10);
mutex_lock(&fw_lock);
fw_priv = fw_sysfs->fw_priv;
if (fw_state_is_aborted(fw_priv))
goto out;
switch (loading) {
case 1:
/* discarding any previous partial load */
if (!fw_sysfs_done(fw_priv)) {
fw_free_paged_buf(fw_priv);
fw_state_start(fw_priv);
}
break;
case 0:
if (fw_sysfs_loading(fw_priv)) {
int rc;
/*
* Several loading requests may be pending on
* one same firmware buf, so let all requests
* see the mapped 'buf->data' once the loading
* is completed.
* */
rc = fw_map_paged_buf(fw_priv);
if (rc)
dev_err(dev, "%s: map pages failed\n",
__func__);
else
rc = security_kernel_post_load_data(fw_priv->data,
fw_priv->size,
LOADING_FIRMWARE, "blob");
/*
* Same logic as fw_load_abort, only the DONE bit
* is ignored and we set ABORT only on failure.
*/
if (rc) {
fw_state_aborted(fw_priv);
written = rc;
} else {
fw_state_done(fw_priv);
}
break;
}
fallthrough;
default:
dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading);
fallthrough;
case -1:
fw_load_abort(fw_sysfs);
break;
}
out:
mutex_unlock(&fw_lock);
return written;
}