How to compile a module from downloaded Linux source? - c

I would ultimately like to modify and compile the existing Linux USB storage driver and test it. For the first step, I wanted to compile the module as is.
I downloaded the latest Linux kernel (version 3.12) and extracted it to ~/linux-3.12.
I found the driver I wanted to compile: drivers/usb/storage, but when I ran make, I got the following error:
make: *** No targets. Stop.
I found many guides online, but none of them worked for the USB storage driver. All I want is to compile this one module and get the .ko so I can test it out.
NOTE: I'm running Ubuntu 13.04 64-bit, and uname -r outputs 3.8.0-30-generic - I'm not sure if that's the problem, but I managed to compile the whole Kernel before. I don't want to do that now because it takes an eon.

If you wanted to build the drivers/usb/storage module you would do this:
make M=drivers/usb/storage
from the root directory of the kernel tree. Before doing so, you will need to make sure that your configuration is the same as the config of the running kernel.

You can't simply take the source code for one kernel and use it to build modules for another one. The module needs to be built from the same source and with the same configuration as the kernel itself.
Basically, you need to find the source code for the Ubuntu kernel you're running. In Ubuntu, as in Debian, that can be done with 'apt-get source '. The package name is probably something like 'linux-image-3.8-2-amd64'.
Once you have the source code you need to find the configuration of your running kernel. Fortunately Ubuntu keeps that in /boot/config-3.8-....
Copy that config to your kernel source tree as .config and run 'make oldconfig'. Now you should be able to build the module (assuming it's not already built into your kernel!).

Related

Rebuild linux kernel module for another architecture

Suppose I have x86-64 machine with some version of Linux kernel. And I have directory with kernel sources of another version. The kernel was built for arm arch and loaded to the appropriate device.
Now I need to rebuild just one kernel module in this big directory.
I read this post and tried something like
make path/to/the/module/itself.ko
, but it build module for amd64.
When I try
make M=path/to/the/module/
it gives a bunch of arch-related C-errors.
Could someone explain how can easy use this ARM-ready environment to rebuild some kernel module?
You could try:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- M=path/to/the/module/
Also read:
Cross compiling a kernel module
gcc-arm-linux-gnueabi command not found

Disagrees about version of symbol symbol_name after insmod

I am new in kernel programming.
For implementing my project work, I have downloaded the latest stable kernel (v4.3) from kernel.org.
Just for checking I have copied a few files from the kernel directories into my project directory. Made changes to it and inserted a few more code to it.
Then I compiled on SLES11 Linux kernel using
make -C /lib/modules/$(uname -r)/build M=$PWD modules
I have used the below makefile
obj-m := my_module.o
my_module-objs := module_main.0 other_module1.o other_module2.o other_module3.o
It compiled successfully.
But when I tried to insert into the kernel using
insmod my_sample.ko
It showed the following
disagrees about version of symbol symbol_name
You need to build your kernel module against the same version kernel you are going to run. Thus if you have kernel 4.3 sources that you have downloaded you need to compile that version of the kernel and boot with that running before trying to load your kernel.
You have two solutions then:
Download the kernel sources for the kernel you are currently running (you can install those with zypper install kernel-source on SLES or an equivalent command on other distributions.)
Compile and install the 4.3 kernel in to your operating system. If you need help with this then ask a separate question (and it probably belongs on superuser not here). Note that if kernel and glibc are tightly coupled, and it is possible that you can't run a new kernel if you have a very old C library.
The problem here is that your Kernel module is using the exported symbols of other kernel modules which in this case appears to be the linux InfiniBand RDMA stack's exported methods or symbols.
To solve the symbol version problems, copy the Module.symvers file from the
/usr/src/ofa-kernel
directory and paste it to your current working directory. Then you make your modules again. Now the insmod should work perfectly fine.
NOTE: The Module.symvers file contains information of all the kernel
module exported symbol. So by copying it to your working directory,
you are helping kbuild to know more about the used exported symbols.
And if you don't find Module.symvers or it is empty, then create one using create_Module.symvers.sh
make -C /lib/modules/$(uname -r)/build M=$PWD modules,
"$(uname -r)" shows that you are compiling against the kernel version you are running now so you should be able to insmod the module in the current kernel if you haven't changed the headers.
From your text,
"Just for checking I have copied a few files from the kernel directories into my project directory. Made changes to it and inserted a few more code to it."
If you have made modifications to the kernel source then you may need to recompile the new kernel and boot with the new updated kernel. Then you should be able to compile your kernel module with the modified headers.
Looks like you built agAinst right kernel.something to do with how your kernel is compiled. (See Config_conversions). Try --force

How to build and deploy a Linux driver?

I am using ubuntu, but the question is for linux in general.
I installed a module/driver by compiling my linux kernel and install the new compiled kernel. It works fine.
In order to make this driver work in another machine without installing the new kernel, I copy the .ko file to the new machine under /lib/modules/<version>/... and then run sudo depmod -a. Then run sudo modprobe <drivername>. The module can be loaded without a problem. but the device is not working well with this .ko module.
The two machines are not identical to hardwares, BUT they are identical to kernel version and ubuntu release version. Normally, copying .ko file should work for the same linux release and the same kernel.
More information about the driver. it's a hid pen tablet driver. All patch files:
one .c file in drivers/hid/
add one line in drivers/hid/Makefile
add a few lines to drivers/hid/usbhid/Kconfig
add a few lines to drivers/hid/hid-ids.h
add a few lines to drivers/hid/usbhid/hid-quirks.c's hid_blacklist struct before { 0, 0 }
That's all.
I even tried to copy the entire drivers/hid/ directory includig all the .ko files from the first machine to the second one. but no luck. The pen tablet can be recognized in the second machine, I am able to do mouse left click event with the pen, but the pen can not move the cursor.
Hopefully, I provided enough details. My goal is to only install the module to identical linux release (kernel) without reinstalling the kernel. I am not sure how to achieve that or if it's possible.
Thanks a lot.
PS:
The dmesg output in 1st machine which works: http://paste.ubuntu.com/6419301/
The dmesg output in 2nd machine: http://paste.ubuntu.com/6419302/
In 1st machine, before plugging in the tablet, lsmod doesn't show the module. after plugging in, the module can be loaded automatically. I can see lsmod shows the module.
In 2nd mahcine, the module can not be loaded automatically by plugging in the device. I have to do sudo modprobe <module> manually.
Since I will have to install the module to many machines in my company, it's easier to install the module without reinstalling the kernel. I tried to install the kernel .deb packages which built in the 1st machine to the 2nd machine, it works fine in 2nd machine. but I don't feel good to reinstall the kernel to many machines. Thanks.
It seems the kernel you built isn't a 1:1 match. Also, generally there's no need to compile a new kernel.
The simplest way to deal with an out-of-tree driver deployment is to use DKMS.
What you need to provide is just a dkms.conf file specifying the package name, version, and driver names and destinations (within /lib/modules/{kernel}).
In the following examples, things within braces need to be replaced with the real thing, e.g. if version is 1.0.0, then {version} with 1.0.0, obviously.
Example dkms.conf:
PACKAGE_NAME="{mydriver}"
PACKAGE_VERSION="{version}"
BUILT_MODULE_NAME[0]="{mydriver}"
BUILT_MODULE_LOCATION[0]="/{mycompany?}"
AUTOINSTALL="yes"
Then you just need to install the sources to /usr/src/{mydriver}-{version}, and run dkms:
dkms add -m {mydriver} -v {version}
dkms build -m {mydriver} -v {version}
dkms install -m {mydriver} -v {version}
You should take a look at what other people have done in this area, there's a great deal of automation you can apply to testing and release processes. Bluecherry's solo6x10 out-of-tree version provides some useful make targets (disclosure: I'm the one who wrote that).
Also, you definitely want to build and distribute packages, you can use solo6x10/debian as a template, and you can read about repositories in the Debian wiki.
You can add the module to /etc/modules so it's loaded at boot time.

Can we only recompile a kernel module in kernel source tree?

Let's say we install a kernel 2.6.32.el6, then we download the 2.6.32.el6.src.rpm, can we just install the source and modify some module, and use make -C 2.6.32.el6.src.source.directry -M$PWD in the module directory to compile the module, then we copy into /lib/modules/2.6.32.el6/kernel/moduledirectory and the new module would work?
I try to modify kvm modules and compile it, but when I recompile the module and copy it into the directory, machine said when booting:
kvm: no symbol version for module_layout
kvm_intel: no symbol version for module_layout
Anyone knows what is wrong?
Probably linux kernel 2.6.32.el6 has been compiled with modversions but your module was compiled without it. Check if you have CONFIG_MODVERSIONS selected or deselected in your kernel config file. Compare it with /proc/.config file which is the kernel confguration file - of course if you have it.
In other words - probably your linux kernel requires that modules supports versioning, but your module doesn't provide it.

How would one compile a program for the Coldfire toolchain?

I'm trying to compile a simple hello world application to be run on uCLinux (2.4) which is running on a board with a Freescale Coldfire (MCF5280C) processor...and I'm not quite sure what to do here.
I know I need to compile with the correct version/tools from Freescale to target this hardware, so I downloaded and installed the Coldfire tool chain and verified that one I have is for my target:
mike#linux-4puc:/usr/local/m68k-elf/bin> ./gcc -v
Reading specs from /usr/local/lib/gcc-lib/m68k-elf/2.95.3/specs
gcc version 2.95.3 20010315 (release)(ColdFire patches - 20010318 from http://fiddes.net/coldfire/)(uClinux XIP and shared lib patches from http://www.snapgear.com/)
I tried a simple gcc "file" type command:
mike#linux-4puc:/home/mike> /usr/local/m68k-elf/bin/gcc test.c
/usr/local/m68k-elf/bin/ld.real: cannot open crt0.o: No such file or directory
collect2: ld returned 1 exit status
Which does not work at all.. so it's clearly more complex that than. The output almost looks like it wants me to build the tool chain before I use it?? Anyone ever done this before? Not sure what I need to do or if I just need some flags.
You might also try seeing if you have a command called m68k-elf-gcc or something along those lines. This is a common naming for cross-compilers.
As for your problem, it sounds like there is something wrong with your compiler setup. crt0.o is the object file that contains C-runtime setup code. The linker (what is actually giving the error) should know where this file is if setup properly.
When you installed you should have run make install as the last step without having modified anything since the make step. The configuration step will setup certain variables and such based on the path where it's supposed to be installed.
Where did you get a FreeScale toolchain? I took a look at their site and it seemed only third parties supplied C++ cross-compilers. In the toolchain I get from NetBurner (for use with their hardware) the crt0.o file exists under the gcc-m68k\m68k-elf\lib directory.

Resources