diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/Kconfig | 64 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 35 |
2 files changed, 96 insertions, 3 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index d7da109c24fd..d47482fa1d21 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
@@ -34,6 +34,70 @@ config FW_LOADER | |||
34 | require userspace firmware loading support, but a module built outside | 34 | require userspace firmware loading support, but a module built outside |
35 | the kernel tree does. | 35 | the kernel tree does. |
36 | 36 | ||
37 | config FIRMWARE_IN_KERNEL | ||
38 | bool "Include in-kernel firmware blobs in kernel binary" | ||
39 | depends on FW_LOADER | ||
40 | default y | ||
41 | help | ||
42 | The kernel source tree includes a number of firmware 'blobs' | ||
43 | which are used by various drivers. The recommended way to | ||
44 | use these is to run "make firmware_install" and to copy the | ||
45 | resulting binary files created in usr/lib/firmware directory | ||
46 | of the kernel tree to the /lib/firmware on your system so | ||
47 | that they can be loaded by userspace helpers on request. | ||
48 | |||
49 | Enabling this option will build each required firmware blob | ||
50 | into the kernel directly, where request_firmware() will find | ||
51 | them without having to call out to userspace. This may be | ||
52 | useful if your root file system requires a device which uses | ||
53 | such firmware, and do not wish to use an initrd. | ||
54 | |||
55 | This single option controls the inclusion of firmware for | ||
56 | every driver which usees request_firmare() and ships its | ||
57 | firmware in the kernel source tree, to avoid a proliferation | ||
58 | of 'Include firmware for xxx device' options. | ||
59 | |||
60 | Say 'N' and let firmware be loaded from userspace. | ||
61 | |||
62 | config EXTRA_FIRMWARE | ||
63 | string "External firmware blobs to build into the kernel binary" | ||
64 | depends on FW_LOADER | ||
65 | help | ||
66 | This option allows firmware to be built into the kernel, for the | ||
67 | cases where the user either cannot or doesn't want to provide it from | ||
68 | userspace at runtime (for example, when the firmware in question is | ||
69 | required for accessing the boot device, and the user doesn't want to | ||
70 | use an initrd). | ||
71 | |||
72 | This option is a string, and takes the (space-separated) names of the | ||
73 | firmware files -- the same names which appear in MODULE_FIRMWARE() | ||
74 | and request_firmware() in the source. These files should exist under | ||
75 | the directory specified by the EXTRA_FIRMWARE_DIR option, which is | ||
76 | by default the firmware/ subdirectory of the kernel source tree. | ||
77 | |||
78 | So, for example, you might set CONFIG_EXTRA_FIRMWARE="usb8388.bin", | ||
79 | copy the usb8388.bin file into the firmware/ directory, and build the | ||
80 | kernel. Then any request_firmware("usb8388.bin") will be | ||
81 | satisfied internally without needing to call out to userspace. | ||
82 | |||
83 | WARNING: If you include additional firmware files into your binary | ||
84 | kernel image which are not available under the terms of the GPL, | ||
85 | then it may be a violation of the GPL to distribute the resulting | ||
86 | image -- since it combines both GPL and non-GPL work. You should | ||
87 | consult a lawyer of your own before distributing such an image. | ||
88 | |||
89 | config EXTRA_FIRMWARE_DIR | ||
90 | string "Firmware blobs root directory" | ||
91 | depends on EXTRA_FIRMWARE != "" | ||
92 | default "firmware" | ||
93 | help | ||
94 | This option controls the directory in which the kernel build system | ||
95 | looks for the firmware files listed in the EXTRA_FIRMWARE option. | ||
96 | The default is the firmware/ directory in the kernel source tree, | ||
97 | but by changing this option you can point it elsewhere, such as | ||
98 | the /lib/firmware/ directory or another separate directory | ||
99 | containing firmware files. | ||
100 | |||
37 | config DEBUG_DRIVER | 101 | config DEBUG_DRIVER |
38 | bool "Driver Core verbose debug messages" | 102 | bool "Driver Core verbose debug messages" |
39 | depends on DEBUG_KERNEL | 103 | depends on DEBUG_KERNEL |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 9fd4a8534146..b0be1d18fee2 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -49,6 +49,14 @@ struct firmware_priv { | |||
49 | struct timer_list timeout; | 49 | struct timer_list timeout; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | #ifdef CONFIG_FW_LOADER | ||
53 | extern struct builtin_fw __start_builtin_fw[]; | ||
54 | extern struct builtin_fw __end_builtin_fw[]; | ||
55 | #else /* Module case. Avoid ifdefs later; it'll all optimise out */ | ||
56 | static struct builtin_fw *__start_builtin_fw; | ||
57 | static struct builtin_fw *__end_builtin_fw; | ||
58 | #endif | ||
59 | |||
52 | static void | 60 | static void |
53 | fw_load_abort(struct firmware_priv *fw_priv) | 61 | fw_load_abort(struct firmware_priv *fw_priv) |
54 | { | 62 | { |
@@ -257,7 +265,7 @@ firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
257 | if (retval) | 265 | if (retval) |
258 | goto out; | 266 | goto out; |
259 | 267 | ||
260 | memcpy(fw->data + offset, buffer, count); | 268 | memcpy((u8 *)fw->data + offset, buffer, count); |
261 | 269 | ||
262 | fw->size = max_t(size_t, offset + count, fw->size); | 270 | fw->size = max_t(size_t, offset + count, fw->size); |
263 | retval = count; | 271 | retval = count; |
@@ -391,13 +399,12 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
391 | struct device *f_dev; | 399 | struct device *f_dev; |
392 | struct firmware_priv *fw_priv; | 400 | struct firmware_priv *fw_priv; |
393 | struct firmware *firmware; | 401 | struct firmware *firmware; |
402 | struct builtin_fw *builtin; | ||
394 | int retval; | 403 | int retval; |
395 | 404 | ||
396 | if (!firmware_p) | 405 | if (!firmware_p) |
397 | return -EINVAL; | 406 | return -EINVAL; |
398 | 407 | ||
399 | printk(KERN_INFO "firmware: requesting %s\n", name); | ||
400 | |||
401 | *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); | 408 | *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); |
402 | if (!firmware) { | 409 | if (!firmware) { |
403 | printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", | 410 | printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", |
@@ -406,6 +413,20 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
406 | goto out; | 413 | goto out; |
407 | } | 414 | } |
408 | 415 | ||
416 | for (builtin = __start_builtin_fw; builtin != __end_builtin_fw; | ||
417 | builtin++) { | ||
418 | if (strcmp(name, builtin->name)) | ||
419 | continue; | ||
420 | printk(KERN_INFO "firmware: using built-in firmware %s\n", | ||
421 | name); | ||
422 | firmware->size = builtin->size; | ||
423 | firmware->data = builtin->data; | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | if (uevent) | ||
428 | printk(KERN_INFO "firmware: requesting %s\n", name); | ||
429 | |||
409 | retval = fw_setup_device(firmware, &f_dev, name, device, uevent); | 430 | retval = fw_setup_device(firmware, &f_dev, name, device, uevent); |
410 | if (retval) | 431 | if (retval) |
411 | goto error_kfree_fw; | 432 | goto error_kfree_fw; |
@@ -473,8 +494,16 @@ request_firmware(const struct firmware **firmware_p, const char *name, | |||
473 | void | 494 | void |
474 | release_firmware(const struct firmware *fw) | 495 | release_firmware(const struct firmware *fw) |
475 | { | 496 | { |
497 | struct builtin_fw *builtin; | ||
498 | |||
476 | if (fw) { | 499 | if (fw) { |
500 | for (builtin = __start_builtin_fw; builtin != __end_builtin_fw; | ||
501 | builtin++) { | ||
502 | if (fw->data == builtin->data) | ||
503 | goto free_fw; | ||
504 | } | ||
477 | vfree(fw->data); | 505 | vfree(fw->data); |
506 | free_fw: | ||
478 | kfree(fw); | 507 | kfree(fw); |
479 | } | 508 | } |
480 | } | 509 | } |