Saturday 20 July 2013

initrd problem = Kernel panic - not syncing: No init found. Try passing init= option to kernel.

About Initrd
An initrd file, often zipped as initrd.gz is a file containing an "Initial Ram Disk" that Linux loads when it boots. The initrd can contain a very small set of programs needed to just work the computer, like checking files or formatting drives, or it can contain much more functionality, such as display managers and window managers and even GUI programs.

If you have ever tried to make an initrd yourself, you might have come across this problem...

THE PROBLEM
1) The kernel boots
2) It finds the initrd file
3) Then this error here...
Kernel panic - not syncing: No init found. Try passing init= option to kernel.

And if you are like me, your init file is probably in the root directory as /init and it is probably a script linked to /bin/sh.

So I tried to copy over busybox and then make all the links, and I also copied all the needed libraries for busybox, which is just libc. Not matter what I tried I get "Kernel panic - not syncing: No init found. Try passing init= option to kernel." from the Linux kernel. This went on for like 8 hours of trying every single combination of things I could think of.

What does "Kernel panic - not syncing: No init found. Try passing init= option to kernel." mean?
A) It most normally means that the kernel can see your "init" script, but when it tries to load it in /bin/sh the sh program is throwing an exception, so the kernel error message can be misleading.
B) It can also mean that the initrd.gz file is corrupt(unlikely), or that the /init file is not there either, also unlikely. The error is most commonly generated from option A, so see solution 2 below for the proper fix to this annoying and misleading error message.

Solution 1 - Use Static Linking
I unzipped the initrd file from Puppy Linux 5.61 using cpio and gzip and I noted that the busybox inside the initrd.gz file is not the same as the busybox found once Puppy is booted. So I tried using this busybox inside the initrd instead and then it boots fine. The reason it works is because it is statically linked, it does not depend on any .so library files, but the real busybox when Puppy is running is linked to libc.so. But this solution is really bad because now you have two copies of busybox in your distribution, one in the initrd.gz file and another somewhere else that gets loaded at the switch_root! I mean two copies of busybox is just not acceptable!

Solution 2 - Put the ld.so libraries!
So I was hunting around on the internet and went through five hundred forums where every guy was making all kind of guesses as to what the problem is but to no avail! So finally I simply copy the ld.so(in Puppy is like ld.22.so and ld-linux.so.2, you need both the files and they are in /lib and are statically linked) files from /lib in Puppy 5.61 into the initrd, and it worked! In other words the kernel error message was caused because when it was trying to execute the /bin/sh program, the program tried to load libc.so, but in order to load libc.so it must also load ld.so first, which then actually loads libc.so on behalf of the program.

Notes
ldd is a program which tells you what libraries a program uses, but you need to be aware that any program which uses libraries also uses ld.so! Keep that in mind when making your initrd.gz file and you can forget about the init not found error message and get on with putting all your files from one distribution into your custom distribution.






1 comment:

  1. Thanks a lot ! This got me out of some serious head scratching when playing with system imager (the busy box initrd was missing some basic libs) ..

    ReplyDelete