Search code examples
linuxlinux-kernelembeddedboot

Kernel Panic with ramfs on embedded device: No filesystem could mount root


I'm working on an embedded ARM device running Linux (kernel 3.10), with NAND memory for storage. I'm trying to build a minimal linux which will reside on its own partition and carry out updates of the main firmware.

The kernel uses a very minimal root fs which is stored in a ramfs. However, I can't get it to boot. I get the following error:

[    0.794113] List of all partitions:
[    0.797600] 1f00             128 mtdblock0  (driver?)
[    0.802669] 1f01            1280 mtdblock1  (driver?)
[    0.807697] 1f02            1280 mtdblock2  (driver?)
[    0.812735] 1f03            8192 mtdblock3  (driver?)
[    0.817761] 1f04            8192 mtdblock4  (driver?)
[    0.822794] 1f05            8192 mtdblock5  (driver?)
[    0.827820] 1f06           82944 mtdblock6  (driver?)
[    0.832850] 1f07           82944 mtdblock7  (driver?)
[    0.837876] 1f08           12288 mtdblock8  (driver?)
[    0.842906] 1f09           49152 mtdblock9  (driver?)
[    0.847928] No filesystem could mount root, tried:  squashfs
[    0.853569] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)
[    0.861806] CPU: 0 PID: 1 Comm: swapper Not tainted 3.10.73 #11
[    0.867732] [<800133ec>] (unwind_backtrace+0x0/0x12c) from [<80011a50>] (show_stack+0x10/0x14)
(...etc)

The root fs is built by the build process, using the following (simplified for clarity):

# [Copy some things to $(ROOTFS_OUT_DIR)/mini_rootfs]
cd $(ROOTFS_OUT_DIR)/mini_rootfs && find . | cpio --quiet -o -H newc > $(ROOTFS_OUT_DIR)/backup.cpio
gzip -f -9 $(ROOTFS_OUT_DIR)/backup.cpio

This creates $(ROOTFS_OUT_DIR)/backup.cpio.gz

The kernel is then built like this:

@$(MAKE) -C $(LINUX_SRC_DIR) O=$(LINUX_OUT_DIR) \
             CONFIG_INITRAMFS_SOURCE="$(ROOTFS_OUT_DIR)/backup.cpio.gz" \
             CONFIG_INITRAMFS_ROOT_UID=0 CONFIG_INITRAMFS_ROOT_GID=0

I think this means it uses the same config as the main firmware (built elsewhere), but supplies the minimal ramfs image using CONFIG_INITRAMFS_SOURCE.

From Kernel.Org, the ramfs is always built anyway, and CONFIG_INITRAMFS_SOURCE is all that is needed to specify a pre-made root fs to use. There are no build errors to indicate that there is a problem creating the ramfs, and the size of the resulting kernel looks about right. backup.cpio.gz is about 3.6 MB; the final zImage is 6.1 MB; the image is written to a partition which is 8 MB in size.

To use this image, I set some flags used by the (custom) boot loader which tell it to boot from the minimal partition, and also set a different command line for the kernel. Here is the command line used to boot:

console=ttyS0 rootfs=ramfs root=/dev/ram rw rdinit=/linuxrc mem=220M

Note that the nimimal root fs contains "/linuxrc", which is actually a link to /bin/busybox:

lrwxrwxrwx  1 root root   11 Nov  5  2015 linuxrc -> bin/busybox

Why doesn't this boot? Why is it trying "squashfs" filesystem, and is this wrong?


Solution

  • SOLVED! It turned out that a file name used by the (custom) build system had changed as part of an update, and so it was not putting the correct kernel image into the firmware package. I was actually trying to boot the wrong kernel with the "rootfs=ramfs" parameter, one which didn't have a ramfs.

    So, for future reference, this error occurs if you specify "rootfs=ramfs" but your kernel wasn't built with any rootfs built in (CONFIG_INITRAMFS_SOURCE=... NOT specified)