Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware_loader: Split sysfs support from fallback

In preparation for sharing the "loading" and "data" sysfs nodes with the
new firmware upload support, split out sysfs functionality from fallback.c
and fallback.h into sysfs.c and sysfs.h. This includes the firmware
class driver code that is associated with the sysfs files and the
fw_fallback_config support for the timeout sysfs node.

CONFIG_FW_LOADER_SYSFS is created and is selected by
CONFIG_FW_LOADER_USER_HELPER in order to include sysfs.o in
firmware_class-objs.

This is mostly just a code reorganization. There are a few symbols that
change in scope, and these can be identified by looking at the header
file changes. A few white-space warnings from checkpatch are also
addressed in this patch.

Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
Reviewed-by: Tianfei zhang <tianfei.zhang@intel.com>
Tested-by: Matthew Gerlach <matthew.gerlach@linux.intel.com>
Signed-off-by: Russ Weight <russell.h.weight@intel.com>
Link: https://lore.kernel.org/r/20220421212204.36052-4-russell.h.weight@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Russ Weight and committed by
Greg Kroah-Hartman
e0c11a8b 5b5bfeca

+503 -463
+4
drivers/base/firmware_loader/Kconfig
··· 29 29 config FW_LOADER_PAGED_BUF 30 30 bool 31 31 32 + config FW_LOADER_SYSFS 33 + bool 34 + 32 35 config EXTRA_FIRMWARE 33 36 string "Build named firmware blobs into the kernel binary" 34 37 help ··· 75 72 76 73 config FW_LOADER_USER_HELPER 77 74 bool "Enable the firmware sysfs fallback mechanism" 75 + select FW_LOADER_SYSFS 78 76 select FW_LOADER_PAGED_BUF 79 77 help 80 78 This option enables a sysfs loading facility to enable firmware
+1
drivers/base/firmware_loader/Makefile
··· 6 6 firmware_class-objs := main.o 7 7 firmware_class-$(CONFIG_FW_LOADER_USER_HELPER) += fallback.o 8 8 firmware_class-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += fallback_platform.o 9 + firmware_class-$(CONFIG_FW_LOADER_SYSFS) += sysfs.o 9 10 10 11 obj-y += builtin/
-418
drivers/base/firmware_loader/fallback.c
··· 3 3 #include <linux/types.h> 4 4 #include <linux/kconfig.h> 5 5 #include <linux/list.h> 6 - #include <linux/slab.h> 7 6 #include <linux/security.h> 8 - #include <linux/highmem.h> 9 7 #include <linux/umh.h> 10 8 #include <linux/sysctl.h> 11 - #include <linux/vmalloc.h> 12 9 #include <linux/module.h> 13 10 14 11 #include "fallback.h" ··· 14 17 /* 15 18 * firmware fallback mechanism 16 19 */ 17 - 18 - MODULE_IMPORT_NS(FIRMWARE_LOADER_PRIVATE); 19 - 20 - extern struct firmware_fallback_config fw_fallback_config; 21 - 22 - /* These getters are vetted to use int properly */ 23 - static inline int __firmware_loading_timeout(void) 24 - { 25 - return fw_fallback_config.loading_timeout; 26 - } 27 - 28 - /* These setters are vetted to use int properly */ 29 - static void __fw_fallback_set_timeout(int timeout) 30 - { 31 - fw_fallback_config.loading_timeout = timeout; 32 - } 33 20 34 21 /* 35 22 * use small loading timeout for caching devices' firmware because all these ··· 44 63 return __fw_state_wait_common(fw_priv, timeout); 45 64 } 46 65 47 - struct fw_sysfs { 48 - bool nowait; 49 - struct device dev; 50 - struct fw_priv *fw_priv; 51 - struct firmware *fw; 52 - }; 53 - 54 - static struct fw_sysfs *to_fw_sysfs(struct device *dev) 55 - { 56 - return container_of(dev, struct fw_sysfs, dev); 57 - } 58 - 59 - static void __fw_load_abort(struct fw_priv *fw_priv) 60 - { 61 - /* 62 - * There is a small window in which user can write to 'loading' 63 - * between loading done/aborted and disappearance of 'loading' 64 - */ 65 - if (fw_state_is_aborted(fw_priv) || fw_state_is_done(fw_priv)) 66 - return; 67 - 68 - fw_state_aborted(fw_priv); 69 - } 70 - 71 - static void fw_load_abort(struct fw_sysfs *fw_sysfs) 72 - { 73 - struct fw_priv *fw_priv = fw_sysfs->fw_priv; 74 - 75 - __fw_load_abort(fw_priv); 76 - } 77 - 78 66 static LIST_HEAD(pending_fw_head); 79 67 80 68 void kill_pending_fw_fallback_reqs(bool only_kill_custom) ··· 58 108 __fw_load_abort(fw_priv); 59 109 } 60 110 mutex_unlock(&fw_lock); 61 - } 62 - 63 - static ssize_t timeout_show(struct class *class, struct class_attribute *attr, 64 - char *buf) 65 - { 66 - return sysfs_emit(buf, "%d\n", __firmware_loading_timeout()); 67 - } 68 - 69 - /** 70 - * timeout_store() - set number of seconds to wait for firmware 71 - * @class: device class pointer 72 - * @attr: device attribute pointer 73 - * @buf: buffer to scan for timeout value 74 - * @count: number of bytes in @buf 75 - * 76 - * Sets the number of seconds to wait for the firmware. Once 77 - * this expires an error will be returned to the driver and no 78 - * firmware will be provided. 79 - * 80 - * Note: zero means 'wait forever'. 81 - **/ 82 - static ssize_t timeout_store(struct class *class, struct class_attribute *attr, 83 - const char *buf, size_t count) 84 - { 85 - int tmp_loading_timeout = simple_strtol(buf, NULL, 10); 86 - 87 - if (tmp_loading_timeout < 0) 88 - tmp_loading_timeout = 0; 89 - 90 - __fw_fallback_set_timeout(tmp_loading_timeout); 91 - 92 - return count; 93 - } 94 - static CLASS_ATTR_RW(timeout); 95 - 96 - static struct attribute *firmware_class_attrs[] = { 97 - &class_attr_timeout.attr, 98 - NULL, 99 - }; 100 - ATTRIBUTE_GROUPS(firmware_class); 101 - 102 - static void fw_dev_release(struct device *dev) 103 - { 104 - struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 105 - 106 - kfree(fw_sysfs); 107 - } 108 - 109 - static int do_firmware_uevent(struct fw_sysfs *fw_sysfs, struct kobj_uevent_env *env) 110 - { 111 - if (add_uevent_var(env, "FIRMWARE=%s", fw_sysfs->fw_priv->fw_name)) 112 - return -ENOMEM; 113 - if (add_uevent_var(env, "TIMEOUT=%i", __firmware_loading_timeout())) 114 - return -ENOMEM; 115 - if (add_uevent_var(env, "ASYNC=%d", fw_sysfs->nowait)) 116 - return -ENOMEM; 117 - 118 - return 0; 119 - } 120 - 121 - static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) 122 - { 123 - struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 124 - int err = 0; 125 - 126 - mutex_lock(&fw_lock); 127 - if (fw_sysfs->fw_priv) 128 - err = do_firmware_uevent(fw_sysfs, env); 129 - mutex_unlock(&fw_lock); 130 - return err; 131 - } 132 - 133 - static struct class firmware_class = { 134 - .name = "firmware", 135 - .class_groups = firmware_class_groups, 136 - .dev_uevent = firmware_uevent, 137 - .dev_release = fw_dev_release, 138 - }; 139 - 140 - int register_sysfs_loader(void) 141 - { 142 - int ret = class_register(&firmware_class); 143 - 144 - if (ret != 0) 145 - return ret; 146 - return register_firmware_config_sysctl(); 147 - } 148 - 149 - void unregister_sysfs_loader(void) 150 - { 151 - unregister_firmware_config_sysctl(); 152 - class_unregister(&firmware_class); 153 - } 154 - 155 - static ssize_t firmware_loading_show(struct device *dev, 156 - struct device_attribute *attr, char *buf) 157 - { 158 - struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 159 - int loading = 0; 160 - 161 - mutex_lock(&fw_lock); 162 - if (fw_sysfs->fw_priv) 163 - loading = fw_state_is_loading(fw_sysfs->fw_priv); 164 - mutex_unlock(&fw_lock); 165 - 166 - return sysfs_emit(buf, "%d\n", loading); 167 - } 168 - 169 - /** 170 - * firmware_loading_store() - set value in the 'loading' control file 171 - * @dev: device pointer 172 - * @attr: device attribute pointer 173 - * @buf: buffer to scan for loading control value 174 - * @count: number of bytes in @buf 175 - * 176 - * The relevant values are: 177 - * 178 - * 1: Start a load, discarding any previous partial load. 179 - * 0: Conclude the load and hand the data to the driver code. 180 - * -1: Conclude the load with an error and discard any written data. 181 - **/ 182 - static ssize_t firmware_loading_store(struct device *dev, 183 - struct device_attribute *attr, 184 - const char *buf, size_t count) 185 - { 186 - struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 187 - struct fw_priv *fw_priv; 188 - ssize_t written = count; 189 - int loading = simple_strtol(buf, NULL, 10); 190 - 191 - mutex_lock(&fw_lock); 192 - fw_priv = fw_sysfs->fw_priv; 193 - if (fw_state_is_aborted(fw_priv) || fw_state_is_done(fw_priv)) 194 - goto out; 195 - 196 - switch (loading) { 197 - case 1: 198 - /* discarding any previous partial load */ 199 - fw_free_paged_buf(fw_priv); 200 - fw_state_start(fw_priv); 201 - break; 202 - case 0: 203 - if (fw_state_is_loading(fw_priv)) { 204 - int rc; 205 - 206 - /* 207 - * Several loading requests may be pending on 208 - * one same firmware buf, so let all requests 209 - * see the mapped 'buf->data' once the loading 210 - * is completed. 211 - * */ 212 - rc = fw_map_paged_buf(fw_priv); 213 - if (rc) 214 - dev_err(dev, "%s: map pages failed\n", 215 - __func__); 216 - else 217 - rc = security_kernel_post_load_data(fw_priv->data, 218 - fw_priv->size, 219 - LOADING_FIRMWARE, "blob"); 220 - 221 - /* 222 - * Same logic as fw_load_abort, only the DONE bit 223 - * is ignored and we set ABORT only on failure. 224 - */ 225 - if (rc) { 226 - fw_state_aborted(fw_priv); 227 - written = rc; 228 - } else { 229 - fw_state_done(fw_priv); 230 - } 231 - break; 232 - } 233 - fallthrough; 234 - default: 235 - dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading); 236 - fallthrough; 237 - case -1: 238 - fw_load_abort(fw_sysfs); 239 - break; 240 - } 241 - out: 242 - mutex_unlock(&fw_lock); 243 - return written; 244 - } 245 - 246 - static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); 247 - 248 - static void firmware_rw_data(struct fw_priv *fw_priv, char *buffer, 249 - loff_t offset, size_t count, bool read) 250 - { 251 - if (read) 252 - memcpy(buffer, fw_priv->data + offset, count); 253 - else 254 - memcpy(fw_priv->data + offset, buffer, count); 255 - } 256 - 257 - static void firmware_rw(struct fw_priv *fw_priv, char *buffer, 258 - loff_t offset, size_t count, bool read) 259 - { 260 - while (count) { 261 - void *page_data; 262 - int page_nr = offset >> PAGE_SHIFT; 263 - int page_ofs = offset & (PAGE_SIZE-1); 264 - int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count); 265 - 266 - page_data = kmap(fw_priv->pages[page_nr]); 267 - 268 - if (read) 269 - memcpy(buffer, page_data + page_ofs, page_cnt); 270 - else 271 - memcpy(page_data + page_ofs, buffer, page_cnt); 272 - 273 - kunmap(fw_priv->pages[page_nr]); 274 - buffer += page_cnt; 275 - offset += page_cnt; 276 - count -= page_cnt; 277 - } 278 - } 279 - 280 - static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj, 281 - struct bin_attribute *bin_attr, 282 - char *buffer, loff_t offset, size_t count) 283 - { 284 - struct device *dev = kobj_to_dev(kobj); 285 - struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 286 - struct fw_priv *fw_priv; 287 - ssize_t ret_count; 288 - 289 - mutex_lock(&fw_lock); 290 - fw_priv = fw_sysfs->fw_priv; 291 - if (!fw_priv || fw_state_is_done(fw_priv)) { 292 - ret_count = -ENODEV; 293 - goto out; 294 - } 295 - if (offset > fw_priv->size) { 296 - ret_count = 0; 297 - goto out; 298 - } 299 - if (count > fw_priv->size - offset) 300 - count = fw_priv->size - offset; 301 - 302 - ret_count = count; 303 - 304 - if (fw_priv->data) 305 - firmware_rw_data(fw_priv, buffer, offset, count, true); 306 - else 307 - firmware_rw(fw_priv, buffer, offset, count, true); 308 - 309 - out: 310 - mutex_unlock(&fw_lock); 311 - return ret_count; 312 - } 313 - 314 - static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size) 315 - { 316 - int err; 317 - 318 - err = fw_grow_paged_buf(fw_sysfs->fw_priv, 319 - PAGE_ALIGN(min_size) >> PAGE_SHIFT); 320 - if (err) 321 - fw_load_abort(fw_sysfs); 322 - return err; 323 - } 324 - 325 - /** 326 - * firmware_data_write() - write method for firmware 327 - * @filp: open sysfs file 328 - * @kobj: kobject for the device 329 - * @bin_attr: bin_attr structure 330 - * @buffer: buffer being written 331 - * @offset: buffer offset for write in total data store area 332 - * @count: buffer size 333 - * 334 - * Data written to the 'data' attribute will be later handed to 335 - * the driver as a firmware image. 336 - **/ 337 - static ssize_t firmware_data_write(struct file *filp, struct kobject *kobj, 338 - struct bin_attribute *bin_attr, 339 - char *buffer, loff_t offset, size_t count) 340 - { 341 - struct device *dev = kobj_to_dev(kobj); 342 - struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 343 - struct fw_priv *fw_priv; 344 - ssize_t retval; 345 - 346 - if (!capable(CAP_SYS_RAWIO)) 347 - return -EPERM; 348 - 349 - mutex_lock(&fw_lock); 350 - fw_priv = fw_sysfs->fw_priv; 351 - if (!fw_priv || fw_state_is_done(fw_priv)) { 352 - retval = -ENODEV; 353 - goto out; 354 - } 355 - 356 - if (fw_priv->data) { 357 - if (offset + count > fw_priv->allocated_size) { 358 - retval = -ENOMEM; 359 - goto out; 360 - } 361 - firmware_rw_data(fw_priv, buffer, offset, count, false); 362 - retval = count; 363 - } else { 364 - retval = fw_realloc_pages(fw_sysfs, offset + count); 365 - if (retval) 366 - goto out; 367 - 368 - retval = count; 369 - firmware_rw(fw_priv, buffer, offset, count, false); 370 - } 371 - 372 - fw_priv->size = max_t(size_t, offset + count, fw_priv->size); 373 - out: 374 - mutex_unlock(&fw_lock); 375 - return retval; 376 - } 377 - 378 - static struct bin_attribute firmware_attr_data = { 379 - .attr = { .name = "data", .mode = 0644 }, 380 - .size = 0, 381 - .read = firmware_data_read, 382 - .write = firmware_data_write, 383 - }; 384 - 385 - static struct attribute *fw_dev_attrs[] = { 386 - &dev_attr_loading.attr, 387 - NULL 388 - }; 389 - 390 - static struct bin_attribute *fw_dev_bin_attrs[] = { 391 - &firmware_attr_data, 392 - NULL 393 - }; 394 - 395 - static const struct attribute_group fw_dev_attr_group = { 396 - .attrs = fw_dev_attrs, 397 - .bin_attrs = fw_dev_bin_attrs, 398 - }; 399 - 400 - static const struct attribute_group *fw_dev_attr_groups[] = { 401 - &fw_dev_attr_group, 402 - NULL 403 - }; 404 - 405 - static struct fw_sysfs * 406 - fw_create_instance(struct firmware *firmware, const char *fw_name, 407 - struct device *device, u32 opt_flags) 408 - { 409 - struct fw_sysfs *fw_sysfs; 410 - struct device *f_dev; 411 - 412 - fw_sysfs = kzalloc(sizeof(*fw_sysfs), GFP_KERNEL); 413 - if (!fw_sysfs) { 414 - fw_sysfs = ERR_PTR(-ENOMEM); 415 - goto exit; 416 - } 417 - 418 - fw_sysfs->nowait = !!(opt_flags & FW_OPT_NOWAIT); 419 - fw_sysfs->fw = firmware; 420 - f_dev = &fw_sysfs->dev; 421 - 422 - device_initialize(f_dev); 423 - dev_set_name(f_dev, "%s", fw_name); 424 - f_dev->parent = device; 425 - f_dev->class = &firmware_class; 426 - f_dev->groups = fw_dev_attr_groups; 427 - exit: 428 - return fw_sysfs; 429 111 } 430 112 431 113 /**
+1 -45
drivers/base/firmware_loader/fallback.h
··· 6 6 #include <linux/device.h> 7 7 8 8 #include "firmware.h" 9 - 10 - /** 11 - * struct firmware_fallback_config - firmware fallback configuration settings 12 - * 13 - * Helps describe and fine tune the fallback mechanism. 14 - * 15 - * @force_sysfs_fallback: force the sysfs fallback mechanism to be used 16 - * as if one had enabled CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y. 17 - * Useful to help debug a CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y 18 - * functionality on a kernel where that config entry has been disabled. 19 - * @ignore_sysfs_fallback: force to disable the sysfs fallback mechanism. 20 - * This emulates the behaviour as if we had set the kernel 21 - * config CONFIG_FW_LOADER_USER_HELPER=n. 22 - * @old_timeout: for internal use 23 - * @loading_timeout: the timeout to wait for the fallback mechanism before 24 - * giving up, in seconds. 25 - */ 26 - struct firmware_fallback_config { 27 - unsigned int force_sysfs_fallback; 28 - unsigned int ignore_sysfs_fallback; 29 - int old_timeout; 30 - int loading_timeout; 31 - }; 9 + #include "sysfs.h" 32 10 33 11 #ifdef CONFIG_FW_LOADER_USER_HELPER 34 12 int firmware_fallback_sysfs(struct firmware *fw, const char *name, ··· 17 39 18 40 void fw_fallback_set_cache_timeout(void); 19 41 void fw_fallback_set_default_timeout(void); 20 - 21 - int register_sysfs_loader(void); 22 - void unregister_sysfs_loader(void); 23 - #ifdef CONFIG_SYSCTL 24 - extern int register_firmware_config_sysctl(void); 25 - extern void unregister_firmware_config_sysctl(void); 26 - #else 27 - static inline int register_firmware_config_sysctl(void) 28 - { 29 - return 0; 30 - } 31 - static inline void unregister_firmware_config_sysctl(void) { } 32 - #endif /* CONFIG_SYSCTL */ 33 42 34 43 #else /* CONFIG_FW_LOADER_USER_HELPER */ 35 44 static inline int firmware_fallback_sysfs(struct firmware *fw, const char *name, ··· 31 66 static inline void kill_pending_fw_fallback_reqs(bool only_kill_custom) { } 32 67 static inline void fw_fallback_set_cache_timeout(void) { } 33 68 static inline void fw_fallback_set_default_timeout(void) { } 34 - 35 - static inline int register_sysfs_loader(void) 36 - { 37 - return 0; 38 - } 39 - 40 - static inline void unregister_sysfs_loader(void) 41 - { 42 - } 43 69 #endif /* CONFIG_FW_LOADER_USER_HELPER */ 44 70 45 71 #ifdef CONFIG_EFI_EMBEDDED_FIRMWARE
+401
drivers/base/firmware_loader/sysfs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/highmem.h> 4 + #include <linux/module.h> 5 + #include <linux/security.h> 6 + #include <linux/slab.h> 7 + #include <linux/types.h> 8 + 9 + #include "firmware.h" 10 + #include "sysfs.h" 11 + 12 + /* 13 + * sysfs support for firmware loader 14 + */ 15 + 16 + void __fw_load_abort(struct fw_priv *fw_priv) 17 + { 18 + /* 19 + * There is a small window in which user can write to 'loading' 20 + * between loading done/aborted and disappearance of 'loading' 21 + */ 22 + if (fw_state_is_aborted(fw_priv) || fw_state_is_done(fw_priv)) 23 + return; 24 + 25 + fw_state_aborted(fw_priv); 26 + } 27 + 28 + #ifdef CONFIG_FW_LOADER_USER_HELPER 29 + static ssize_t timeout_show(struct class *class, struct class_attribute *attr, 30 + char *buf) 31 + { 32 + return sysfs_emit(buf, "%d\n", __firmware_loading_timeout()); 33 + } 34 + 35 + /** 36 + * timeout_store() - set number of seconds to wait for firmware 37 + * @class: device class pointer 38 + * @attr: device attribute pointer 39 + * @buf: buffer to scan for timeout value 40 + * @count: number of bytes in @buf 41 + * 42 + * Sets the number of seconds to wait for the firmware. Once 43 + * this expires an error will be returned to the driver and no 44 + * firmware will be provided. 45 + * 46 + * Note: zero means 'wait forever'. 47 + **/ 48 + static ssize_t timeout_store(struct class *class, struct class_attribute *attr, 49 + const char *buf, size_t count) 50 + { 51 + int tmp_loading_timeout = simple_strtol(buf, NULL, 10); 52 + 53 + if (tmp_loading_timeout < 0) 54 + tmp_loading_timeout = 0; 55 + 56 + __fw_fallback_set_timeout(tmp_loading_timeout); 57 + 58 + return count; 59 + } 60 + static CLASS_ATTR_RW(timeout); 61 + 62 + static struct attribute *firmware_class_attrs[] = { 63 + &class_attr_timeout.attr, 64 + NULL, 65 + }; 66 + ATTRIBUTE_GROUPS(firmware_class); 67 + 68 + static int do_firmware_uevent(struct fw_sysfs *fw_sysfs, struct kobj_uevent_env *env) 69 + { 70 + if (add_uevent_var(env, "FIRMWARE=%s", fw_sysfs->fw_priv->fw_name)) 71 + return -ENOMEM; 72 + if (add_uevent_var(env, "TIMEOUT=%i", __firmware_loading_timeout())) 73 + return -ENOMEM; 74 + if (add_uevent_var(env, "ASYNC=%d", fw_sysfs->nowait)) 75 + return -ENOMEM; 76 + 77 + return 0; 78 + } 79 + 80 + static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) 81 + { 82 + struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 83 + int err = 0; 84 + 85 + mutex_lock(&fw_lock); 86 + if (fw_sysfs->fw_priv) 87 + err = do_firmware_uevent(fw_sysfs, env); 88 + mutex_unlock(&fw_lock); 89 + return err; 90 + } 91 + #endif /* CONFIG_FW_LOADER_USER_HELPER */ 92 + 93 + static void fw_dev_release(struct device *dev) 94 + { 95 + struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 96 + 97 + kfree(fw_sysfs); 98 + } 99 + 100 + static struct class firmware_class = { 101 + .name = "firmware", 102 + #ifdef CONFIG_FW_LOADER_USER_HELPER 103 + .class_groups = firmware_class_groups, 104 + .dev_uevent = firmware_uevent, 105 + #endif 106 + .dev_release = fw_dev_release, 107 + }; 108 + 109 + #ifdef CONFIG_FW_LOADER_USER_HELPER 110 + int register_sysfs_loader(void) 111 + { 112 + int ret = class_register(&firmware_class); 113 + 114 + if (ret != 0) 115 + return ret; 116 + return register_firmware_config_sysctl(); 117 + } 118 + 119 + void unregister_sysfs_loader(void) 120 + { 121 + unregister_firmware_config_sysctl(); 122 + class_unregister(&firmware_class); 123 + } 124 + #endif 125 + 126 + static ssize_t firmware_loading_show(struct device *dev, 127 + struct device_attribute *attr, char *buf) 128 + { 129 + struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 130 + int loading = 0; 131 + 132 + mutex_lock(&fw_lock); 133 + if (fw_sysfs->fw_priv) 134 + loading = fw_state_is_loading(fw_sysfs->fw_priv); 135 + mutex_unlock(&fw_lock); 136 + 137 + return sysfs_emit(buf, "%d\n", loading); 138 + } 139 + 140 + /** 141 + * firmware_loading_store() - set value in the 'loading' control file 142 + * @dev: device pointer 143 + * @attr: device attribute pointer 144 + * @buf: buffer to scan for loading control value 145 + * @count: number of bytes in @buf 146 + * 147 + * The relevant values are: 148 + * 149 + * 1: Start a load, discarding any previous partial load. 150 + * 0: Conclude the load and hand the data to the driver code. 151 + * -1: Conclude the load with an error and discard any written data. 152 + **/ 153 + static ssize_t firmware_loading_store(struct device *dev, 154 + struct device_attribute *attr, 155 + const char *buf, size_t count) 156 + { 157 + struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 158 + struct fw_priv *fw_priv; 159 + ssize_t written = count; 160 + int loading = simple_strtol(buf, NULL, 10); 161 + 162 + mutex_lock(&fw_lock); 163 + fw_priv = fw_sysfs->fw_priv; 164 + if (fw_state_is_aborted(fw_priv) || fw_state_is_done(fw_priv)) 165 + goto out; 166 + 167 + switch (loading) { 168 + case 1: 169 + /* discarding any previous partial load */ 170 + fw_free_paged_buf(fw_priv); 171 + fw_state_start(fw_priv); 172 + break; 173 + case 0: 174 + if (fw_state_is_loading(fw_priv)) { 175 + int rc; 176 + 177 + /* 178 + * Several loading requests may be pending on 179 + * one same firmware buf, so let all requests 180 + * see the mapped 'buf->data' once the loading 181 + * is completed. 182 + */ 183 + rc = fw_map_paged_buf(fw_priv); 184 + if (rc) 185 + dev_err(dev, "%s: map pages failed\n", 186 + __func__); 187 + else 188 + rc = security_kernel_post_load_data(fw_priv->data, 189 + fw_priv->size, 190 + LOADING_FIRMWARE, 191 + "blob"); 192 + 193 + /* 194 + * Same logic as fw_load_abort, only the DONE bit 195 + * is ignored and we set ABORT only on failure. 196 + */ 197 + if (rc) { 198 + fw_state_aborted(fw_priv); 199 + written = rc; 200 + } else { 201 + fw_state_done(fw_priv); 202 + } 203 + break; 204 + } 205 + fallthrough; 206 + default: 207 + dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading); 208 + fallthrough; 209 + case -1: 210 + fw_load_abort(fw_sysfs); 211 + break; 212 + } 213 + out: 214 + mutex_unlock(&fw_lock); 215 + return written; 216 + } 217 + 218 + static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); 219 + 220 + static void firmware_rw_data(struct fw_priv *fw_priv, char *buffer, 221 + loff_t offset, size_t count, bool read) 222 + { 223 + if (read) 224 + memcpy(buffer, fw_priv->data + offset, count); 225 + else 226 + memcpy(fw_priv->data + offset, buffer, count); 227 + } 228 + 229 + static void firmware_rw(struct fw_priv *fw_priv, char *buffer, 230 + loff_t offset, size_t count, bool read) 231 + { 232 + while (count) { 233 + void *page_data; 234 + int page_nr = offset >> PAGE_SHIFT; 235 + int page_ofs = offset & (PAGE_SIZE - 1); 236 + int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count); 237 + 238 + page_data = kmap(fw_priv->pages[page_nr]); 239 + 240 + if (read) 241 + memcpy(buffer, page_data + page_ofs, page_cnt); 242 + else 243 + memcpy(page_data + page_ofs, buffer, page_cnt); 244 + 245 + kunmap(fw_priv->pages[page_nr]); 246 + buffer += page_cnt; 247 + offset += page_cnt; 248 + count -= page_cnt; 249 + } 250 + } 251 + 252 + static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj, 253 + struct bin_attribute *bin_attr, 254 + char *buffer, loff_t offset, size_t count) 255 + { 256 + struct device *dev = kobj_to_dev(kobj); 257 + struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 258 + struct fw_priv *fw_priv; 259 + ssize_t ret_count; 260 + 261 + mutex_lock(&fw_lock); 262 + fw_priv = fw_sysfs->fw_priv; 263 + if (!fw_priv || fw_state_is_done(fw_priv)) { 264 + ret_count = -ENODEV; 265 + goto out; 266 + } 267 + if (offset > fw_priv->size) { 268 + ret_count = 0; 269 + goto out; 270 + } 271 + if (count > fw_priv->size - offset) 272 + count = fw_priv->size - offset; 273 + 274 + ret_count = count; 275 + 276 + if (fw_priv->data) 277 + firmware_rw_data(fw_priv, buffer, offset, count, true); 278 + else 279 + firmware_rw(fw_priv, buffer, offset, count, true); 280 + 281 + out: 282 + mutex_unlock(&fw_lock); 283 + return ret_count; 284 + } 285 + 286 + static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size) 287 + { 288 + int err; 289 + 290 + err = fw_grow_paged_buf(fw_sysfs->fw_priv, 291 + PAGE_ALIGN(min_size) >> PAGE_SHIFT); 292 + if (err) 293 + fw_load_abort(fw_sysfs); 294 + return err; 295 + } 296 + 297 + /** 298 + * firmware_data_write() - write method for firmware 299 + * @filp: open sysfs file 300 + * @kobj: kobject for the device 301 + * @bin_attr: bin_attr structure 302 + * @buffer: buffer being written 303 + * @offset: buffer offset for write in total data store area 304 + * @count: buffer size 305 + * 306 + * Data written to the 'data' attribute will be later handed to 307 + * the driver as a firmware image. 308 + **/ 309 + static ssize_t firmware_data_write(struct file *filp, struct kobject *kobj, 310 + struct bin_attribute *bin_attr, 311 + char *buffer, loff_t offset, size_t count) 312 + { 313 + struct device *dev = kobj_to_dev(kobj); 314 + struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 315 + struct fw_priv *fw_priv; 316 + ssize_t retval; 317 + 318 + if (!capable(CAP_SYS_RAWIO)) 319 + return -EPERM; 320 + 321 + mutex_lock(&fw_lock); 322 + fw_priv = fw_sysfs->fw_priv; 323 + if (!fw_priv || fw_state_is_done(fw_priv)) { 324 + retval = -ENODEV; 325 + goto out; 326 + } 327 + 328 + if (fw_priv->data) { 329 + if (offset + count > fw_priv->allocated_size) { 330 + retval = -ENOMEM; 331 + goto out; 332 + } 333 + firmware_rw_data(fw_priv, buffer, offset, count, false); 334 + retval = count; 335 + } else { 336 + retval = fw_realloc_pages(fw_sysfs, offset + count); 337 + if (retval) 338 + goto out; 339 + 340 + retval = count; 341 + firmware_rw(fw_priv, buffer, offset, count, false); 342 + } 343 + 344 + fw_priv->size = max_t(size_t, offset + count, fw_priv->size); 345 + out: 346 + mutex_unlock(&fw_lock); 347 + return retval; 348 + } 349 + 350 + static struct bin_attribute firmware_attr_data = { 351 + .attr = { .name = "data", .mode = 0644 }, 352 + .size = 0, 353 + .read = firmware_data_read, 354 + .write = firmware_data_write, 355 + }; 356 + 357 + static struct attribute *fw_dev_attrs[] = { 358 + &dev_attr_loading.attr, 359 + NULL 360 + }; 361 + 362 + static struct bin_attribute *fw_dev_bin_attrs[] = { 363 + &firmware_attr_data, 364 + NULL 365 + }; 366 + 367 + static const struct attribute_group fw_dev_attr_group = { 368 + .attrs = fw_dev_attrs, 369 + .bin_attrs = fw_dev_bin_attrs, 370 + }; 371 + 372 + static const struct attribute_group *fw_dev_attr_groups[] = { 373 + &fw_dev_attr_group, 374 + NULL 375 + }; 376 + 377 + struct fw_sysfs * 378 + fw_create_instance(struct firmware *firmware, const char *fw_name, 379 + struct device *device, u32 opt_flags) 380 + { 381 + struct fw_sysfs *fw_sysfs; 382 + struct device *f_dev; 383 + 384 + fw_sysfs = kzalloc(sizeof(*fw_sysfs), GFP_KERNEL); 385 + if (!fw_sysfs) { 386 + fw_sysfs = ERR_PTR(-ENOMEM); 387 + goto exit; 388 + } 389 + 390 + fw_sysfs->nowait = !!(opt_flags & FW_OPT_NOWAIT); 391 + fw_sysfs->fw = firmware; 392 + f_dev = &fw_sysfs->dev; 393 + 394 + device_initialize(f_dev); 395 + dev_set_name(f_dev, "%s", fw_name); 396 + f_dev->parent = device; 397 + f_dev->class = &firmware_class; 398 + f_dev->groups = fw_dev_attr_groups; 399 + exit: 400 + return fw_sysfs; 401 + }
+96
drivers/base/firmware_loader/sysfs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __FIRMWARE_SYSFS_H 3 + #define __FIRMWARE_SYSFS_H 4 + 5 + #include <linux/device.h> 6 + 7 + MODULE_IMPORT_NS(FIRMWARE_LOADER_PRIVATE); 8 + 9 + extern struct firmware_fallback_config fw_fallback_config; 10 + 11 + #ifdef CONFIG_FW_LOADER_USER_HELPER 12 + /** 13 + * struct firmware_fallback_config - firmware fallback configuration settings 14 + * 15 + * Helps describe and fine tune the fallback mechanism. 16 + * 17 + * @force_sysfs_fallback: force the sysfs fallback mechanism to be used 18 + * as if one had enabled CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y. 19 + * Useful to help debug a CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y 20 + * functionality on a kernel where that config entry has been disabled. 21 + * @ignore_sysfs_fallback: force to disable the sysfs fallback mechanism. 22 + * This emulates the behaviour as if we had set the kernel 23 + * config CONFIG_FW_LOADER_USER_HELPER=n. 24 + * @old_timeout: for internal use 25 + * @loading_timeout: the timeout to wait for the fallback mechanism before 26 + * giving up, in seconds. 27 + */ 28 + struct firmware_fallback_config { 29 + unsigned int force_sysfs_fallback; 30 + unsigned int ignore_sysfs_fallback; 31 + int old_timeout; 32 + int loading_timeout; 33 + }; 34 + 35 + /* These getters are vetted to use int properly */ 36 + static inline int __firmware_loading_timeout(void) 37 + { 38 + return fw_fallback_config.loading_timeout; 39 + } 40 + 41 + /* These setters are vetted to use int properly */ 42 + static inline void __fw_fallback_set_timeout(int timeout) 43 + { 44 + fw_fallback_config.loading_timeout = timeout; 45 + } 46 + 47 + int register_sysfs_loader(void); 48 + void unregister_sysfs_loader(void); 49 + #ifdef CONFIG_SYSCTL 50 + int register_firmware_config_sysctl(void); 51 + void unregister_firmware_config_sysctl(void); 52 + #else 53 + static inline int register_firmware_config_sysctl(void) 54 + { 55 + return 0; 56 + } 57 + 58 + static inline void unregister_firmware_config_sysctl(void) { } 59 + #endif /* CONFIG_SYSCTL */ 60 + #else /* CONFIG_FW_LOADER_USER_HELPER */ 61 + static inline int register_sysfs_loader(void) 62 + { 63 + return 0; 64 + } 65 + 66 + static inline void unregister_sysfs_loader(void) 67 + { 68 + } 69 + #endif /* CONFIG_FW_LOADER_USER_HELPER */ 70 + 71 + struct fw_sysfs { 72 + bool nowait; 73 + struct device dev; 74 + struct fw_priv *fw_priv; 75 + struct firmware *fw; 76 + }; 77 + 78 + static inline struct fw_sysfs *to_fw_sysfs(struct device *dev) 79 + { 80 + return container_of(dev, struct fw_sysfs, dev); 81 + } 82 + 83 + void __fw_load_abort(struct fw_priv *fw_priv); 84 + 85 + static inline void fw_load_abort(struct fw_sysfs *fw_sysfs) 86 + { 87 + struct fw_priv *fw_priv = fw_sysfs->fw_priv; 88 + 89 + __fw_load_abort(fw_priv); 90 + } 91 + 92 + struct fw_sysfs * 93 + fw_create_instance(struct firmware *firmware, const char *fw_name, 94 + struct device *device, u32 opt_flags); 95 + 96 + #endif /* __FIRMWARE_SYSFS_H */