How to add a Linux kernel driver module as a Buildroot package?

匿名 (未验证) 提交于 2019-12-03 02:01:02

问题:

I am currently building an Embedded Linux for my Zybo Board from Xilinx. For this I use Buildroot. Now I want to add a driver, written in C, which can be used by a user program to write to some specific registers, enabling it to control some LEDs. When I checked the manual, it basically says the first thing to do is create a Config.in in a new package folder, where you write some text explaining the driver. Okay, I did that. But now the makefile: I don't quite understand what needs to be in there. Is it just a compile command like gcc -o ledcontrol hellofunc.c? Is there something else I need to do apart from the Config.in and Makefile?

回答1:

What you are looking for is the kernel-modules infrastructure.You can take a look at the Buildroot manual here:

https://buildroot.org/downloads/manual/manual.html#_infrastructure_for_packages_building_kernel_modules

Or at the numerous examples using the kernel-modules infrastructure provided by Buildroot that assists in kernel modules addition to Buildroot:

$ git grep "(kernel-module)" -- package/ package/amd-catalyst/amd-catalyst.mk:$(eval $(kernel-module)) package/batman-adv/batman-adv.mk:$(eval $(kernel-module)) package/cryptodev-linux/cryptodev-linux.mk:$(eval $(kernel-module)) package/emlog/emlog.mk:$(eval $(kernel-module)) package/freescale-imx/kernel-module-imx-gpu-viv/kernel-module-imx-gpu-viv.mk:$(eval $(kernel-module)) package/igh-ethercat/igh-ethercat.mk:$(eval $(kernel-module)) package/iqvlinux/iqvlinux.mk:$(eval $(kernel-module)) package/ktap/ktap.mk:$(eval $(kernel-module)) package/linux-backports/linux-backports.mk:$(eval $(kernel-module)) package/lttng-modules/lttng-modules.mk:$(eval $(kernel-module)) package/nvidia-driver/nvidia-driver.mk:$(eval $(kernel-module)) package/ocf-linux/ocf-linux.mk:$(eval $(kernel-module)) package/on2-8170-modules/on2-8170-modules.mk:$(eval $(kernel-module)) package/owl-linux/owl-linux.mk:$(eval $(kernel-module)) package/pkg-kernel-module.mk:#   $(eval $(kernel-module)) package/pkg-kernel-module.mk:#   $(eval $(kernel-module)) package/rtl8188eu/rtl8188eu.mk:$(eval $(kernel-module)) package/rtl8821au/rtl8821au.mk:$(eval $(kernel-module)) package/simicsfs/simicsfs.mk:$(eval $(kernel-module)) package/sysdig/sysdig.mk:$(eval $(kernel-module)) 

Yeah, I guess I could write a longish reply, but I would be just copying the Buildroot manual. So let's honor the braves developers that have written such clean documentation and such clean code (Buildroot core is really clean, and each package is extensively reviewed so they are usually very well written too).



回答2:

Fully automated out-of-tree QEMU example

https://github.com/cirosantilli/linux-kernel-module-cheat

Source tree:

  • buildroot/: Buildroot 2017.02 submodule
  • kernel_module/: external package with some modules
    • Config.in
    • external.mk
    • Makefile
    • hello.c: hello world module

kernel_module/Config.in

config BR2_PACKAGE_KERNEL_MODULE         bool "kernel_module"         depends on BR2_LINUX_KERNEL         help                 Linux Kernel Module Cheat. 

kernel_module/external.mk

KERNEL_MODULE_VERSION = 1.0 KERNEL_MODULE_SITE = $(BR2_EXTERNAL_KERNEL_MODULE_PATH) KERNEL_MODULE_SITE_METHOD = local $(eval $(kernel-module)) $(eval $(generic-package)) 

kernel_module/Makefile

obj-m += $(addsuffix .o, $(notdir $(basename $(wildcard $(BR2_EXTERNAL_KERNEL_MODULE_PATH)/*.c)))) ccflags-y := -DDEBUG -g -std=gnu99 -Wno-declaration-after-statement  .PHONY: all clean  all:     $(MAKE) -C '$(LINUX_DIR)' M='$(PWD)' modules  clean:     $(MAKE) -C '$(LINUX_DIR)' M='$(PWD)' clean 

kernel_module/hello.c

#include  #include   MODULE_LICENSE("GPL");  static int myinit(void) {     printk(KERN_INFO "hello init\n");     return 0; }  static void myexit(void) {     printk(KERN_INFO "hello exit\n"); }  module_init(myinit) module_exit(myexit) 

Usage:

cd buildroot make BR2_EXTERNAL="$(pwd)/../kernel_module" qemu_x86_64_defconfig echo 'BR2_PACKAGE_KERNEL_MODULE=y' >> .config make BR2_JLEVEL="$(($(nproc) - 2))" all qemu-system-x86_64 -M pc -kernel output/images/bzImage -drive file=output/images/rootfs.ext2,if=virtio,format=raw -append root=/dev/vda -net nic,model=virtio -net user 

QEMU opens up, then run:

root modprobe hello modprobe -r hello 

dmesg shows:

hello init hello exit 

The key line is $(eval $(kernel-module)) in external.mk, which sets everything up for us, and installs the modules where modprobe will find them (/lib/modules/*/extra/hello.ko), including modules.dep for inter-module dependencies: How to call exported kernel module functions from another module?

How to GDB step debug the kernel modules: How to debug Linux kernel modules with QEMU?

To autoload modules at startup, use BR2_ROOTFS_OVERLAY="../rootfs_overlay" and a rootfs_overlay/etc/init.d/S99modules file that does the modprobe.

In-tree example: https://github.com/cirosantilli/buildroot/tree/9580078b98f885ca94e4dfc896265a8a491f6ae1 It is less clean, but also works.

Tested on a Ubuntu 16.04 host.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!