Wednesday, September 29, 2010

my kernel does'nt boot: the magic of EARLY_PRINTK

I am subscribed to TI's e2e portal and this post peeked my interest. Since sometime in mainline kernel we've had issues with kernel not booting up due to some weird bugs. As a kernel developer, I have screwed up multiple times preventing kernel boot from happening. Typical build results in:
## Booting kernel from Legacy Image at c0700000 ...
Image Name: Linux-2.6.32-rc6
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1939152 Bytes = 1.8 MB
Load Address: c0008000
Entry Point: c0008000
Verifying Checksum ... OK
Loading Kernel Image ... OK

Starting kernel ...
And that's it - no useful messages for the kernel geeks to figure out where the boot sequence crashed, no real debug information at all!

So the first question: why the kernel silence?
The boot messages can only be printed once you have the serial port enabled. Now, serial port enablement itself could be pretty much later in the kernel boot sequence, if the system crashes(oops/data abort etc..) prior to that, there is no messages printed as kernel configuration assumes that you have no configured serial port prior to this..

Now the solution: EARLY_PRINTK
The reality is usually a bit different in development platforms - usually you have something like u-boot or some bootloader spewing out a few prints to serial port, + ARM kernel boot requirements state that you could optionally (and recommended) have atleast 1 serial port configured prior to giving control to kernel. *if* you have such a bootloader which configures a serial port prior to giving control to kernel, you can enable a configuration called EARLY_PRINTK in the kernel .config. Note: there are many platforms that use this. How do we use this? two steps:
a) Build a kernel with EARLY PRINTK
b) provide earlyprintk as bootargs to actually get a more detailed log:

Step a) building kernel with EARLY_PRINTK
build with your default configuration of your choice, and then enable CONFIG_DEBUG_LL and CONFIG_EARLY_PRINTK in your kernel hacking options:

Kernel low-level debugging functions (DEBUG_LL) [N/y/?] (NEW) y
Early printk (EARLY_PRINTK) [N/y/?] (NEW) y
Kernel low-level debugging via EmbeddedICE DCC channel (DEBUG_ICEDCC) [N/y/?] (NEW) n

and build your uImage, zImage etc..

Step b) add earlyprintk to your bootargs
it is as simple as that - just add the word earlyprintk to the bootargs
example on u-boot.:
setenv bootargs console=ttyS0,115200n8 root=/dev/mmcblk0p2 rootdelay=2 init=/bin/ash

setenv bootargs console=ttyS0,115200n8 root=/dev/mmcblk0p2 rootdelay=2 init=/bin/ash earlyprintk

and we are done, bootup and see detailed logs now...

Sidenote: if your serial port itself does'nt work and you have JTAG, you may want to explore the ICE support for earlyprintk as well.. good luck..

No comments: