Install a modified kernel header for access to kernel programs - linux

I am a newbie to kernel programming and I want to modify a header file in arch/x86/include/asm/tlbflush.h so that my kernel module can use one of the functions exported by this header file.
I have the source code for 3.2.59 kernel and made changes to tlbflush.h. I included the header file tlbflush.h. When i compile the module i get a warning saying the function that I am using is not found and as a result I am not able to insmod my kernel module.
I went through the following
how to export a modified kernel header
and tried the following steps to install the modified kernel header:
make
sudo make modules_install
sudo make headers_install INSTALL_HDR_PATH=/usr/include
sudo make install
sudo update-initramfs -c -k 3.2.59
The link mentioned talks about installing kernel headers to /usr/include for access to user space processes
I want to mention that I have so many headers installed due to the upgrades done on my ubuntu machine. Also all of them have extensions like 3.2.0-59, 3.2.0-xx
I considered 3.2.0-59 to be same as 3.2.59 though I am not sure. Please correct me in case this is wrong. Thanks !
Edit:
I am sorry, I got confused with the headers in /usr/src/... folder versus the headers in the source code of kernel that is being modified. I made a change in the headers of the kernel source that i downloaded and after that there is no warning now.
But the question still remains that why are the kernel headers in /usr/src/ used?
I am sorry for the waste of time, if you spent on this.

But the question still remains that why are the kernel headers in /usr/src/ used?
Actually, nobody forces that. If you're using standard Makefile for building your module, it is a place that states it.
Mine contains the following line:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
If you examine what /lib/modules/$(shell uname -r)/build really is, you will find that this is a symlink to folder where kernel source is located.
~ $ ls -l /lib/modules/$(uname -r)/build
lrwxrwxrwx 1 root root 32 Jun 9 04:46 /lib/modules/3.12.21-gentoo-r1/build -> /usr/src/linux-3.12.21-gentoo-r1
For ubuntu, linux-headers contains only minimum kernel part necessary to build your own module (not only headers).

Related

How to include linux driver source files in a kernel module written in C?

I am currently writing a linux kernel module that needs to include a file from the linux driver source code. The particular file I am trying to include is: https://elixir.bootlin.com/linux/latest/source/drivers/nvme/host/nvme.h
But the /lib/modules/$(shell uname -r)/build directory does not contain the drivers folder. I tried doing sudo apt-get install linux-headers-$(shell uname -r) but that also does not include the driver header files. My Makefile looks like this:
obj-m += hello_world.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
I then tried to get a full kernel checkout of the kernel version closest to my kernel version (I couldn't find the exact source code for my kernel version.) I pointed my Makefile to use that version but then when I try to insert the kernel module, it throws Invalid module format error and dmesg shows no symbol version for module layout. My source directory does contain the Module.symvers file but it still throws this error. I believe this error could be resolved if I somehow use my current linux source.
So, what's the best way to get the driver header files and use them in a kernel module. Any help would be appreciated.
I see you are using apt. In such case you can get the correct source for your kernel simply enabling source repositories (see here or here to know how) and then getting the source code of the package:
$ sudo apt-get update
$ sudo apt-get source linux-image-$(uname -r)
After this, you will have the following files in the current directory:
linux-XXX/
linux_XXX.tar.xz
linux_XXX.dsc
linux_XXX.orig.tar.xz
The first one is a folder containing the correct source code for your installed kernel. You'll then be able to #include the header you need for your module.

Intel Galileo adding kernel header files to the cross compile toolchain

im on BSP v1.1
yocto is 1.6
I'm trying to set up the cross compile toolchain to compile character driver code
but the output i get is
[mark#localhost ~]$ ${CC} first.c -o first
first.c:1:24: fatal error: linux/init.h: No such file or directory
.#include
^ compilation terminated.
I think the issue is that
the header is not in the toolchain
/opt/iot-devkit/1.6.1/sysroots/i586-poky-linux/usr/include/linux/~
there is no at this location
I think something has to be added as IMAGE_INSTALL or IMAGE_FEATURE but i dont know what
am I on the right track ?
does anyone know what i have to add ?
or am i completely off tracks altogether?
Well, first and foremost, you can never build a kernel module by just running ${CC} on it. You should always use a Makefile, which redirects most of its work to the kernel source Makefil.
Create a Makefile for you module, consisting of something similar to:
obj-m += hello-1.o
all:
make -C $(KERNEL_SRC M=$(PWD) modules
clean:
make -C $(KERNEL_SRC) M=$(PWD) clean
Example taken from The Linux Kernel Module Programming Guide (Note that the actual commands needs to have a tab character for indentation).
Then you'll have to define KERNEL_SRC to be /opt/iot-devkit/1.6.1/sysroots/i586-poky-linux/usr/src/kernel/, either in the Makefile, or from your make call. (Using a variable like KERNEL_SRC will ensure that your module recipe automatically picks the right location when building using bitbake).
To manually build your kernel module:
Source the environment-* file for your SDK.
Go to you modules directory.
KERNEL_SRC=/opt/iot-devkit/1.6.1/sysroots/i586-poky-linux/usr/src/kernel LDFLAGS="" make
However, this will fail, as fixdep can't be found. We'll fix this manually.
cd /opt/iot-devkit/1.6.1/sysroots/i586-poky-linux/usr/src/kernel
make silentoldconfig scripts
Go back to your modules directory.
KERNEL_SRC=/opt/iot-devkit/1.6.1/sysroots/i586-poky-linux/usr/src/kernel LDFLAGS="" make
This should now produce hello.ko which you should be able to insmod on the Galileo board.

building /lib/modules/$(uname -r)/build while compiling a kernel

I am cross-compiling 3.4.0 kernel for an embedded device. Then I would like to install compat-wireless drivers which require /lib/modules/3.4/build directory and sub-files. Could anyone explain how can I build that directory so that when I do INSTALL_MOD_PATH=newmodules make modules_install it would load /lib/modules/$(uname -r)/build directory as well? I would appreciate for a clear explanation.
I am using debian distro. I know I can install the kernel headers by apt-get install linux-headers-$(uname -r), but I doubt it would be a good idea since the kernel sources might not be identical.
Typically /lib/modules/$(uname -r)/build is a soft-link to the directory where performed the build. So the way to do this is to simply do a
make modules_install INSTALL_MOD_PATH=/some/root/
in the build directory of the kernel where /some/root is where you want your cross compile pieces to end up. This will create a link to your kernel build path in /some/root/lib/modules/$(uname -r) ... verify that.
Now when you build the compat_wireless drivers specify the kernel build directory in the Makefile as /some/root using the KLIB_BUILD variable (read the Makefile)
make modules KLIB_BUILD=/some/root/lib/modules/$(uname -r)/build
this should do the trick for you.
EDIT A
In answer to your comment below:
Keep "newmodules" outside the kernel directory it's a bad idea to put it in the kernel directory. so mkdir newmodules somewhere like /home/foo or /tmp or something. This is one of the reasons your build link is screwed up
ALSO .../build is a soft link /to/kernel/build/location it will only copy over as a soft-link. You also need to copy over the actual kernel source / kernel build directory to your microSD, using the same relative location. For example,
Let's say your kernel source is in:
/usr/src/linux-3.5.0/
Your kernel build directory is:
/usr/src/linux-3.5.0-build/
Your newmodules (after following 1.) is in:
/tmp/newmodules/
So under /tmp/newmodules/ you see the modules installed in a tree like:
lib/modules/$(uname -r)/
when you do an ls -al in this directory, you'll see that build is a soft link to:
build -> /usr/src/linux-3.5.0-build/
Now let's say your microSD is mounted under /mnt/microSD
then you need to do the following
mkdir -p /mnt/microSD/usr/src
cp -a /usr/src/linux-3.5.0 /usr/src/linux-3.5.0-build /mnt/microSD/usr/src
cp -a /tmp/newmodules/lib /mnt/microSD/lib
Now you have all the content you need to bring over to your embedded environment. I take it you are doing the compat_wireless build on your target system rather than cross compiling it?
NOTE
If your kernel build is the same as the kernel source then just copy over the kernel source and ignore the linux-3.5.0-build in copy instructions above
This is old, but some people will need this information.
I have spent many hours to figure out where build folder comes from, and why it is just a link when I compile my own kernel. Finally figured it out;
Linux kernel usually just links the build and source folders to the source folder.
But!
Arch linux (probably some other distros too); has a manual script for deleting those links, and adding (filtered) files to build folder.
https://git.archlinux.org/svntogit/packages.git/tree/trunk/PKGBUILD?h=packages/linux
I've extracted that script to work standalone (in a kernel source tree) here: https://gist.github.com/furkanmustafa/9e73feb64b0b18942047fd7b7e2fd53e

Driver/module cross compilation

I am trying to cross compile a driver for an arm based board. In the make file the search path for include files is that of the host machine's kernel i.e it points to the linux headers that come with ubuntu.
I also have the kernel source tree of target board present on the host system(i7/ubuntu).
My Question is that which include path is needed for cross compilation (native system's linux headers path or the path to the kernel source tree of board ?
Does same thing applies to all modules including drivers?
Here is a Makefile for an out of tree driver. The architecture, toolchain and kernel dir specified :
ifneq ($(KERNELRELEASE),)
# We were called by kbuild
obj-m += fpgacam.o
else # We were called from command line
KDIR := path/to/your/target/kernel
PWD := $(shell pwd)
CROSS=arm-none-linux-gnueabi-
default:
#echo ' Building Cam drivers for 2.6 kernel.'
#echo ' PLEASE IGNORE THE "Overriding SUBDIRS" WARNING'
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) ARCH=arm CROSS_COMPILE=$(CROSS) modules
install:
./do_install.sh *.ko
endif # End kbuild check
######################### Version independent targets ##########################
clean:
rm -f -r *.o *.ko .*cmd .tmp* core *.i
When make is called from the module directory, the command line path is taken, and make is redirected to the kernel directory build system using make -C. The kernel build system then the different variable passed to it to go back into the module directory with everything setup (include path, toolchain etc ..) to compile a module. This second time through the Makefile, the kbuild path is taken, and the module is built as if it was in-tree.
Compiling with your build-system's headers is spectacularly bad news, and may subtle binary incompatibilities that manifest themselves as seemingly bizarre crashes on the target.
As you've already discovered, the kernel is already hardened against this and will refuse to load modules built against the wrong headers. You'll need to build using the same source tree as the existing kernel - including any patches. You might as well at this point rebuild the entire kernel.
The kernel tree is self-contained, so simply cross-compiling it in place will work. If you're adding a driver it's probably easiest to compile it in-tree.
If you want to build any user-space components, you have two solutions:
Pass the --sysroot=<dir> option to gcc, where <dir> is the system root of your target system
Build gcc and binutils to use as their default sysroot
The latter approach is the one that Angstrom uses, and it save a lot of butt-hurt.
You might want to try using crosstool-ng
It takes care of the majority of the work. You only need to bother about the configuration settings you want to enable for kernel compilation.
Here another reference: link

How to recompile just a single kernel module?

Usually kernel source are stored in /usr/src/linux-2.6.x/.
To avoid to recompile the entire kernel if I modify a module's source, how can I recompile just that module?
Switch to the root directory of your source tree and run the following command:
$ make modules SUBDIRS=drivers/the_module_directory
And to install the compiled module:
$ make modules_install SUBDIRS=drivers/the_module_directory
Note: As lunakid mentions, the latter command might not build the module first, so be careful.
since kernel versions 3.x.x and 4.x.x the procedure gets more complicated (but there is a hope, so keep reading):
make distclean if you haven't just cloned a new source but used to build other modules before
create new folder somewhere for the module source (example: extra)
and copy only source files (from the kernel source or somewhere else) related to the module needed to be build into this new folder
copy /boot/config-`uname -r` file (example: /boot/config-4.8.0-46-generic) into kernel source folder file .config and run make oldconfig. if the module belongs to the kernel source, verify if it has been enabled by calling make menuconfig, by searching for the module and applying letter 'M' if necessary
kernel source root Makefile has to be altered with exact version components matching the current running one (you may verify with make kernelversion if it matches exactly the uname -rone)
there is been a strong suggestion to build scripts also before with
make scripts
make prepare and make modules_prepare has to be executed prior to the actual module build
Module.symvers has to be copied from the target system headers folder corresponding running kernel version /usr/src/linux-headers-`uname -r`/Module.symvers (example: /usr/src/linux-headers-3.13.0-117-generic/Module.symvers) into the newly created module source files folder prepared for the module compilation (the one extra in example).
create new Makefile inside module source compilation folder having following line: obj-y += <module_source_file_name>.o or if the source code is complicated, use the guidance from here
only then it's the right time to build module with make -C <kernel source path> M=the_module_directory (example: make -C . M=extra/)
Use command modprobe --dump-modversion <module_name>.ko to verify CRC match between module exporting API and corresponding values in Module.symvers. in case of failure use command modinfo <module_name>.ko instead
verify if kernel.release file content match exactly the one from headers of the current running version. if you'll discover + appended at the end, it means you've been compiling git clonned source and your experimental modifications caused build system to compromise the localversion string by adding + at the end.
if only + has been discovered at the tail of kernel.release stored value and it's a mismatch with the exact name of the target running kernel,
the solution would be following:
commit all your changes, force release tag to shift above your modifications with the git tag -a <tag version> -f command. then rebuild your modules from step 8
You can pass the path to the module name or module directory to make as parameter.
make path/to/the/module/itself.ko
make path/to/the/module/directory/
In case you have edited just code in drivers/net/ethernet/intel/e1000/e1000_main.c file
Build the module.
make scripts prepare modules_prepare
make -C . M=drivers/net/ethernet/intel/e1000
Install the module.
cp drivers/net/ethernet/intel/e1000/e1000.ko /lib/modules/5.1.15/kernel/drivers/net/ethernet/intel/e1000/e1000.ko
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install
https://askubuntu.com/questions/515407/how-recipe-to-build-only-one-kernel-module

Resources