Linux: Compiling a kernel device driver in standalone fashion - linux

I'm compiling linux for an ARM board. I need to make some customized changes into an existing driver code present in the kernel repository and reload the driver.
I was expecting to find a ".ko" file in the driver directory after doing the make, but no such file exists. Apparently uImage/device tree image compilation doesn't work that way.
Do I need to write my own Makefile for standalone device driver compilation?
It may be a silly question, but sorry I'm pretty new to kernel/device drivers.
EDIT:
I followed the process outlined here: http://odroid.com/dokuwiki/doku.php?id=en:c1_building_kernel
After git checkout and installing the cross-compiler(arm-linux-gnueabihf-gcc 4.9.2), I issue the basic make comands
$ make odroidc_defconfig
$ make -j4
$ make -j4 modules
$ make uImage
All the steps are successful. The last few lines of log look like
KSYM .tmp_kallsyms1.o
KSYM .tmp_kallsyms2.o
LD vmlinux
SORTEX vmlinux
SYSMAP System.map
OBJCOPY arch/arm/boot/ccImage
Kernel: arch/arm/boot/ccImage is ready
Image arch/arm/boot/ccImage.lzo is ready
UIMAGE arch/arm/boot/uImage
Image Name: Linux-3.10.72
Created: Sat Mar 28 22:44:45 2015
Image Type: ARM Linux Kernel Image (lzo compressed)
Data Size: 5459649 Bytes = 5331.69 kB = 5.21 MB
Load Address: 00208000
Entry Point: 00208000
Image arch/arm/boot/uImage is ready
EDIT 2: Path to the driver code
https://github.com/hardkernel/linux/tree/odroidc-3.10.y/drivers/amlogic/efuse

Examining your Makefile
#
# Makefile for eFuse.
#
obj-$(CONFIG_EFUSE) += efuse_bch_8.o efuse_version.o efuse_hw.o efuse.o
We learn that the code can be built as either a loadable module, or permanently linked into the kernel itself.
Examining odroidc_defconfig from branch odroidc-3.10.y-android mentioned in your instructions we find
#
# EFUSE Support
#
CONFIG_EFUSE=y
With the "y" indicating that the code is to be linked into the driver. Had it instead said "m" it would be built as a module.
It's possible you could change that in the kernel config, but it might also cause problems if there's nothing setup to load the module before it is needed.
Likely simply installing the newly built kernel with the code already linked inside (ie, forgetting about the module idea) will work.

Not sure if you are still looking for the answers to this question.
But looking at the Kconfig file in your code, show that -
config EFUSE
bool "EFUSE Driver"
And since all your driver files are compiled with this config, the above config description allows the CONFIG_EFUSE to be 'n' or 'y'. So you can only build static modules (build-in) with this.
All you need to do is change the above description to:
config EFUSE
**tristate** "EFUSE Driver"
and also change the other configs in Kconfig to tristate.
This will allow your driver to be compiled as module once you select the driver as 'M' in your kernel config. Then you should be able to see the ".ko" file corresponding to the driver.
Also do make sure to use EXPORT_SYMBOL(foo) when building the driver as module so that any dependencies are taken care of when loading module symbols.

Related

Linux Kernel : Building Out-of-tree module for kernel , but no linux-headers in apt-cache search

I am working on linux kernel development, and was trying to make my own modules for testing purposes. However, for the latest kernel source codes, the linux-headers don't exist. It only exists for 4.9.0-7 .
I googled and found 1 method where we make the module against the kernel source tree that we want (eg. 4.18)
make -C /home/prasad/linux-4.18/ M=$(PWD)
which does generate the .ko for my module. However, when I load up my kernel and insmod it , it says
insmod: ERROR: could not insert module test.ko: Unknown symbol in module
So how exactly do I generate a .ko file from my host machine that can be inserted for the 4.18 kernel ?
PS: My doubt is not a duplicate as I cannot "install" the 4.18 kernel in my vm, Im trying to avoid doing that. My question is more specific to generating an insertable .ko module, and not finding any other way to insert it in 4.18.
You cant use a module built for 4.18 in a 4.9 kernel.
If the headers for the kernel version you are building for are not available via apt/yum/etc, you will need to download the source manually from: https://www.kernel.org/
In the makefile for your module, you will specify the path to the kernel source code that you have downloaded and extracted.
That should allow you to build the module for the desired kernel version.

How to extract the config from a kernel image file when CONFIG_IKCONFIG is set as a module (=m)?

How do I extract the kernel configuration from a kernel image file?
The kernel image file type is:
/boot/kernel7.img: Linux kernel ARM boot executable zImage (little-endian)
The kernel has been compiled with CONFIG_IKCONFIG enabled. However,
scripts/extract-ikconfig /boot/kernel7.img
returns
extract-ikconfig: Cannot find kernel config.
Note: I am trying the get the config without booting the kernel.
If the kernel has been compiled with CONFIG_IKCONFIG=m (note the m), the configuration in stored in a module (configs.ko) and not in the kernel itself. That's the reason why running extract-ikconfig on the kernel image fails.
In this case, we can extract the config from the configuration module:
/usr/src/$(uname -r)/scripts/extract-ikconfig \
/lib/modules/$(uname -r)/kernel/kernel/configs.ko

How to debug Linux kernel modules with QEMU?

I am working on academic project that modifies some Kernel Networking code as well as include a new Kernel module.
I am using QEMU to load modified kernel and test.
However, i find that a complete OS is required in some .img to debug.
Is it possible without it ?
Or, which is the distro that can be used with Kernel 2.6 for system. The distro need not have any features, except ability to run programs, including networking support.
The easiest way in my opinion is to use buildroot
http://buildroot.uclibc.org/
clone it, configure it to use your custom kernel (default userspace is fine for a start, you might want to change it later).
it will build your kernel and root filesystem. the entire process takes about half an hour, twenty minutes of which is compiling the monster
my run line looks something:
qemu-system-i386
-hda rootfs.ext2
-kernel bzImage
-m 512M
-append "root=/dev/sda console=ttyS0"
-localtime
-serial stdio
and some more options regarding a tap device
Minimal fully automated QEMU + GDB + Buildroot example
QEMU + GDB on non-module Linux kernel is covered in detail at: How to debug the Linux kernel with GDB and QEMU? and building the kernel modules inside QEMU at: How to add Linux driver as a Buildroot package Get those working first.
Next, I have also fully automated GDB module debugging at: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/1c29163c3919d4168d5d34852d804fd3eeb3ba67#kernel-module-debugging
These are the main steps you have to take:
Compile the kernel module with debug symbols:
ccflags-y += -g -DDEBUG
as mentioned at: kernel module no debugging symbols found
Stop GDB with Ctrl + C and run:
lx-symbols path/to/parent/of/modules/
This amazing command, which is defined in a GDB Python script inside the Linux kernel source tree, automatically loads symbols for loaded modules present under the given directory recursively whenever GDB stops.
The best way to make that command available is to use:
gdb -ex add-auto-load-safe-path /full/path/to/linux/kernel
as explained at: GDB: lx-symbols undefined command
insmod the kernel module.
This must be done before setting breakpoints, because we don't know where the kernel will insert the module in memory beforehand.
lx-symbols automatically takes care of finding the module location (in host filesystem and guest memory!) for us.
Break GDB again with Ctrl + C, set breakpoints, and enjoy.
If were feeling hardcore, you could also drop lx-symbols entirely, and find the module location after insmod with:
cat /proc/modules
and then add the .ko manually with:
add-symbol-file path/to/mymodule.ko 0xfffffffa00000000

Patching and compiling Ext4 as a kernel module

I'm currently patching Ext4 for academic purposes (only linux/fs/ext4/*, like file.c, ioctl.c, ext4.h) . I'm working on the QEMU virtual machine, and to speed up the whole process I've selected Ext4 to compile as a kernel module. The problem occurs when it comes to test new changes, as, even though I run make modules ARCH=x86 && make modules_install ARCH=x86 and reboot the machine (/ is Ext4), they are not visible unless I recompile the whole kernel. It's a little bit weird as I have a variety of signs that the Ext4 has been compiled as a module:
It is configured as that:
$ grep EXT4 .config
CONFIG_EXT4_FS=m
It does compile as a module:
$ make modules ARCH=x86
(...)
CC [M] fs/ext4/ioctl.o
LD [M] fs/ext4/ext4.o
Building modules, stage 2.
MODPOST 3 modules
LD [M] fs/ext4/ext4.ko
After $ make modules_install ARCH=x86 the files in /lib/modules/3.13.3/kernel/fs/ have proper time stamp.
Finally:
$ lsmod
Module Size Used by
ext4 340817 1
(...)
For some reason I have to do $ make all ARCH=x86 in order to see my changes appear in the runtime. What have I missed? Thanks!
Most boot processes use an "initial ramdisk" (initrd) which contains all kernel modules which the kernel needs to load to be able to do anything - after all, to read files from an Ext4 file system, the kernel needs a driver for this file system and if the driver is on said file system, well, ...
So the solution is to pack all those files into an archive (the initial ramdisk) and save the hard disk blocks as a list of numbers in the boot loader. It can then use a primitive IDE/SATA driver to load the blocks directly, extract the drivers and load them.
Check the documentation of your linux distro to find out how to update initrd. On my Ubuntu Linux, it's mkinitramfs.
Related:
Linux initial RAM disk (initrd) overview

Recompile Linux kernel (with Xen) config flags not being used

I am trying to compile the linux kernel (3.0.0-13) with the Xen dom0 config flags which are not exposed via menuconfig. (Yes, I know that ubuntu provides a 'virtual' flavoured kernel that supports Xen paravirtualization, but that kernel does not seem to boot on my hardware. So, I am trying to compile the 'generic' flavoured ubuntu kernel with the extra Xen config flags since I know that the 'generic' flavour runs on my hardware). Every time that I try to compile my config flags are ignored based on the .config file that is generated and packaged with my kernel binary.
I have tried the following the following:
Downloaded the kernel source using apt-get source linux-image
I have then followed all of the steps from this guide: How to compile a new Ubuntu 11.10 (Oneiric) kernel and performed the following extra steps:
put my own config flags in the config.flavour.xxx file then compiled the linux-image package
Paused the 'debian/rules editconfigs' command immediately after the it runs 'menuconfig' and replaced the build/.config file with my custom .config file then compiled the linux-image package
I have also used the following howto How To Compile A Kernel - The Ubuntu Way and run the following commands on kernel source code that I already had:
edit the .config file to have my config flags
run 'make oldconfig'
run 'make-kpkg clean && fakeroot make-kpkg --initrd --append-to-version=-custom kernel_image kernel_headers'
After every time I have compiled the kernel I have installed the newly compiled linux-image package and have discovered that my config flags are not in the /boot/config-xxx file as I expect.
What am I doing wrong to cause my config flags to be ignored?
What can I do to make sure that my kernel config flags are used when compiling?
Is there some other option than recompiling the kernel to get a Xen dom0 kernel that work for my hardware?
For question 3: Is there another way to get a xen dom0 kernel for my hardware?
Yes.
Although all of the xen documentation says that all stock kernel support xen dom0, what they mean is that the source for all stock kernels now support xen dom0 but that support is turned off in their precompiled binaries.
On debian there is the following package which is a prebuilt linux kernel with the xen dom0 support turned on. Package: linux-image-xen-686
For anyone else who is really looking to compile their own xen dom0 kernel the following site has a good guide: Compiling a Xen Dom0 Kernel for Ubuntu Jaunty
What am I doing wrong to cause my config flags to be ignored?
The root of the issue lies in the first portion of your problem; the Xen dom0 config flags are not exposed via menuconfig
Simply setting them in the .config doesn't mean they'll be activated. You have to consider the dependencies for the config options.
From the linux 3.0 tag at github: https://github.com/torvalds/linux/blob/02f8c6aee8df3cdc935e9bdd4f2d020306035dbe/arch/x86/xen/Kconfig
config XEN_DOM0
def_bool y
depends on XEN && PCI_XEN && SWIOTLB_XEN
depends on X86_LOCAL_APIC && X86_IO_APIC && ACPI && PCI
Are all these depends flags met?
What can I do to make sure that my kernel config flags are used when compiling?
In the beginning stages of the kernel compile process, the .config file is re-written if there are any discrepancies. A good test to make sure your edits will persist is checking if they still exist in your .config file after doing a make menuconfig and saving changes. If after that your flags are still there, you can be sure that your flags are being used.
Is there some other option than recompiling the kernel to get a Xen dom0 kernel that work for my hardware?
Not unless another distribution ships with XEN_DOM0 enabled.

Resources