Patching and compiling Ext4 as a kernel module - linux

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

Related

Linux Kernel makefile process explained

In LinuxSrc/Documentation/admin-guide/README.rst under the section for building the kernel exists these 4 steps, can someone explain what each one does?
Is it similiar to a ./configure, ./make, ./install?
To configure and build the kernel, use:
1.) cd /usr/src/linux-4.X
2.) make O=/home/name/build/kernel menuconfig
3.) make O=/home/name/build/kernel
4.) sudo make O=/home/name/build/kernel modules_install install
1) simple cd - no explanation needed
2) Running make menuconfig starts an ncurses-based text mode kernel configuration tool.
3) make O=/home/name/build/kernel configures and builds the kernel.
4.1) modules_install: This will copy the compiled modules into /lib/modules/-.
4.2) install: This command will copy following files into /boot directory (and might do more depending on the distribution):
Config-, System.map-, Vmlinuz-*
vmlinuz - Is a compressed Linux kernel
system.map - Is a lookup table between symbol names and their addresses in memory for a particular build of a kernel
config - The kernel configuration created by the make menuconfig

Linux: Compiling a kernel device driver in standalone fashion

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.

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

Compiling a kernel - no bzImage/vmlinuz produced

I'm trying to compile a kernel (altered version of 2.6.32.9, found here https://github.com/rabeeh/linux-2.6.32.9). I am doing the compilation on a emulated ARM system (qemu) (yes, I should probably cross-compile, but that's a different topic) running Ubuntu Core (https://wiki.ubuntu.com/Core) and the kernel (vmlinuz) from Ubuntu 11.04 (downloaded from http://ports.ubuntu.com/ubuntu-ports/dists/natty/main/installer-armel/current/images/versatile/netboot/vmlinuz).
After running make bzImage, I look in the arch/arm/boot folder, and find only a file called zImage. I tried using this zImage instead of the vmlinuz I downloaded from ubuntu.com in qemu, but that doesn't work, just shows a black screen. I guess zImage is not the same as bzImage, which is what I think vmlinuz (judging from different articles on the internet) is.
So, a few questions:
Why doesn't make bzImage produce a bzImage/vmlinuz?
Can I convert a vmlinux to a vmlinuz using for example mkimage (there are lots of guides on the opposite...)?
Thanks
The bzImage filename and make target was originally x86-specific (big zImage). Many of the bootloaders on architectures that are not equal to baremetal-x86 (SPARC, PPC, IA64, etc. and also Xen on *) directly take vmlinux (or one of its compressed forms, for example vmlinux.gz, aka zImage). I guess some maintainers just added bzImage as a make target name because they wanted to have the x86 madness on their arch as well.
I get the result you describe by asking qemu to emulate a different cpu than arm926ej-s. But booting versatilepb with the default cpu works. I've cross-compiled my kernel, and I compiled all the drivers into it (so I don't use initrd).
Just download 100MB arm-eabi toolchain from http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/ (it's free but they want your email, like the x86 Intel compiler). It has an installer, just say "next" until it's done, like on Windows. Then add the bin directory to your path:
export PATH=~/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/:$PATH
Then go back to your kernel source dir and do
make ARCH=arm CROSS_COMPILE=arm-none-eabi- menuconfig
make ARCH=arm CROSS_COMPILE=arm-none-eabi- zImage modules
You can do
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi- INSTALL_MOD_PATH=path_to_arm_root modules_install
if you can reach your ARM filesystem from the host. If you're using NFS root it's trivial, but if you're using a disk image you need to either:
use a raw disk image and kpartx (depends on your host kernel having dm-multipath) or
qemu-nbd which supports qcow (and depends on host kernel having network block device support)
To boot in qemu with disk you need the right drivers (SYM53C8XX SCSI). The versatile defconfig doesn't select those.

What does this make command do?

make -C $(KERNEL_DIR) SUBDIRS=pwd` modules
Can someone elaborate this?
The -C means "change to this directory before starting make." The SUBDIRS is a variable used by the Linux kernel make system. SUBDIRS=`pwd` means that the kernel makefiles should look in the current directory, because pwd means "print working directory." And modules means to make modules.
It probably uses the kernel make system to build an out-of-tree module. Out-of-tree means a kernel module that is not shipped with the kernel.
In fact, I seem to recall seeing this command used as part of the Nvidia binary module installer.

Resources