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

firmware: allow firmware files to be built into kernel image

Some drivers have their own hacks to bypass the kernel's firmware loader
and build their firmware into the kernel; this renders those unnecessary.

Other drivers don't use the firmware loader at all, because they always
want the firmware to be available. This allows them to start using the
firmware loader.

A third set of drivers already use the firmware loader, but can't be
used without help from userspace, which sometimes requires an initrd.
This allows them to work in a static kernel.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

authored by

David Woodhouse and committed by
David Woodhouse
5658c769 b7a39bd0

+59 -2
+31 -2
drivers/base/firmware_class.c
··· 49 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 60 static void 53 61 fw_load_abort(struct firmware_priv *fw_priv) 54 62 { ··· 399 391 struct device *f_dev; 400 392 struct firmware_priv *fw_priv; 401 393 struct firmware *firmware; 394 + struct builtin_fw *builtin; 402 395 int retval; 403 396 404 397 if (!firmware_p) 405 398 return -EINVAL; 406 - 407 - printk(KERN_INFO "firmware: requesting %s\n", name); 408 399 409 400 *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); 410 401 if (!firmware) { ··· 412 405 retval = -ENOMEM; 413 406 goto out; 414 407 } 408 + 409 + for (builtin = __start_builtin_fw; builtin != __end_builtin_fw; 410 + builtin++) { 411 + if (strcmp(name, builtin->name)) 412 + continue; 413 + printk(KERN_INFO "firmware: using built-in firmware %s\n", 414 + name); 415 + firmware->size = builtin->size; 416 + firmware->data = builtin->data; 417 + return 0; 418 + } 419 + 420 + if (uevent) 421 + printk(KERN_INFO "firmware: requesting %s\n", name); 415 422 416 423 retval = fw_setup_device(firmware, &f_dev, name, device, uevent); 417 424 if (retval) ··· 494 473 void 495 474 release_firmware(const struct firmware *fw) 496 475 { 476 + struct builtin_fw *builtin; 477 + 497 478 if (fw) { 479 + for (builtin = __start_builtin_fw; builtin != __end_builtin_fw; 480 + builtin++) { 481 + if (fw->data == builtin->data) 482 + goto free_fw; 483 + } 498 484 vfree(fw->data); 485 + free_fw: 499 486 kfree(fw); 500 487 } 501 488 }
+7
include/asm-generic/vmlinux.lds.h
··· 86 86 VMLINUX_SYMBOL(__end_pci_fixups_resume) = .; \ 87 87 } \ 88 88 \ 89 + /* Built-in firmware blobs */ \ 90 + .builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) { \ 91 + VMLINUX_SYMBOL(__start_builtin_fw) = .; \ 92 + *(.builtin_fw) \ 93 + VMLINUX_SYMBOL(__end_builtin_fw) = .; \ 94 + } \ 95 + \ 89 96 /* RapidIO route ops */ \ 90 97 .rio_route : AT(ADDR(.rio_route) - LOAD_OFFSET) { \ 91 98 VMLINUX_SYMBOL(__start_rio_route_ops) = .; \
+21
include/linux/firmware.h
··· 1 1 #ifndef _LINUX_FIRMWARE_H 2 2 #define _LINUX_FIRMWARE_H 3 + 3 4 #include <linux/module.h> 4 5 #include <linux/types.h> 6 + #include <linux/compiler.h> 7 + 5 8 #define FIRMWARE_NAME_MAX 30 6 9 #define FW_ACTION_NOHOTPLUG 0 7 10 #define FW_ACTION_HOTPLUG 1 ··· 15 12 }; 16 13 17 14 struct device; 15 + 16 + struct builtin_fw { 17 + char *name; 18 + void *data; 19 + unsigned long size; 20 + }; 21 + 22 + /* We have to play tricks here much like stringify() to get the 23 + __COUNTER__ macro to be expanded as we want it */ 24 + #define __fw_concat1(x, y) x##y 25 + #define __fw_concat(x, y) __fw_concat1(x, y) 26 + 27 + #define DECLARE_BUILTIN_FIRMWARE(name, blob) \ 28 + DECLARE_BUILTIN_FIRMWARE_SIZE(name, &(blob), sizeof(blob)) 29 + 30 + #define DECLARE_BUILTIN_FIRMWARE_SIZE(name, blob, size) \ 31 + static const struct builtin_fw __fw_concat(__builtin_fw,__COUNTER__) \ 32 + __used __section(.builtin_fw) = { name, blob, size } 18 33 19 34 #if defined(CONFIG_FW_LOADER) || (defined(CONFIG_FW_LOADER_MODULE) && defined(MODULE)) 20 35 int request_firmware(const struct firmware **fw, const char *name,