Manually compiled kernel fails to boot: stuck in initramfs prompt - linux

I am trying to compile a custom kernel for my old laptop (it's a Dell Inspiron 1525, with a Core 2 Duo processor, 2GB of memory and a HDD -- not SSD). In this computer I have 3 partitions, 2 small ones (10GB each) with the roots of distros that I use, and a large one for files. I'm using MX Linux (if that is relevant) and compiling the kernel in the large partition, which is mounted at /mnt/files. The first thing I did was to clone the v4.19 tag from Linus' repo at kernel.org, then I copied the configuration from the kernel that is currently running (from /boot/config-4.19.0-9-686-pae), run make menuconfig, just changed the string that goes after the version name to -copy, saved and exited. Then I compiled. This kernel, with the configuration just copied from the one that currently runs, works well. It is not custom, however, as it just uses the exact same configurations.
Then I started a new one, again by copying the current .config and using make menuconfig to disable a lot of things that I thought were not relevant for me. The compilation with make ARCH=i386 -j3 and then make INSTALL_MOD_STRIP=1 modules_install went well, apparently, but when I type make INSTALL_MOD_STRIP=1 install I get this:
$ sudo make INSTALL_MOD_STRIP=1 install
sh ./arch/x86/boot/install.sh 4.19.0-custom arch/x86/boot/bzImage \
System.map "/boot"
run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 4.19.0-custom /boot/vmlinuz-4.19.0-custom
run-parts: executing /etc/kernel/postinst.d/dkms 4.19.0-custom /boot/vmlinuz-4.19.0-custom
Warning: Unable to find an initial ram disk that I know how to handle.
Will not try to make an initrd.
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 4.19.0-custom /boot/vmlinuz-4.19.0-custom
update-initramfs: Generating /boot/initrd.img-4.19.0-custom
cryptsetup: WARNING: The initramfs image may not contain cryptsetup binaries
nor crypto modules. If that's on purpose, you may want to uninstall the
'cryptsetup-initramfs' package in order to disable the cryptsetup initramfs
integration and avoid this warning.
I: The initramfs will attempt to resume from /dev/sda1
I: (UUID=a1472f28-bb65-4a3a-a964-59b72d46b645)
I: Set the RESUME variable to override this.
run-parts: executing /etc/kernel/postinst.d/pm-utils 4.19.0-custom /boot/vmlinuz-4.19.0-custom
run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 4.19.0-custom /boot/vmlinuz-4.19.0-custom
run-parts: executing /etc/kernel/postinst.d/zz-update-grub 4.19.0-custom /boot/vmlinuz-4.19.0-custom
Generating grub configuration file ...
Found theme: /boot/grub/themes/linen/theme.txt
Found linux image: /boot/vmlinuz-4.19.0-custom
Found initrd image: /boot/initrd.img-4.19.0-custom
Found linux image: /boot/vmlinuz-4.19.0-9-686-pae
Found initrd image: /boot/initrd.img-4.19.0-9-686-pae
Found linux image: /boot/vmlinuz-4.19.0-copy
Found initrd image: /boot/initrd.img-4.19.0-copy
Found memtest86+ image: /boot/memtest86+.bin
Found antiX 19.2 (19.2) on /dev/sda2
done
The first kernel (-copy) also gave these warnings, however (and it is working). This new kernel (-custom) starts booting but then gets stuck in a busybox (initramfs) prompt. I can issue some commands there, and I can see that there is a file system with some basic programs (I suppose from busybox). But it doesn't finish the boot process.
When I execute the exit command in this (initramfs) prompt I get something along these lines:
Gave up waiting for root file system device. Common problems:
- Boot args (cat /proc/cmdline)
- Check rootdelay= (did the system wait long enough?)
- Missing modules (cat /proc/modules; ls /dev)
ALERT! UUID=efdafcea-bdab-4c13-b2a7-caa77e4330ca does not exist. Dropping to a shell!
I tried to type the suggestions from the message above, but I don't know what to make out of them. If I type cat proc/cmdline in this same initramfs environment, I get something like:
BOOT_IMAGE=/boot/vmlinuz-4.19.0-custom root=UUID=efdafcea-bdab-4c13-b2a7-caa77e4330ca ro video=SVIDEO-1:d quiet splash
If I type cat proc/modules I get this output and if I type ls dev I get this. (Sorry for the bad image quality).
I am quite sure something that I removed during the configuration in menuconfig is what caused the problem, and if I understand anything from these messages I would guess that the kernel is not being able to mount the root filesystem, perhaps it is not finding the partition to mount?
My question here is, given this situation, is there any obvious candidates to be the problem among the settings in .config? This is my .config file.

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.

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

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

Resources