14.5. When It Doesn't Boot

One of the most frequently asked questions on the various mailing lists that serve embedded Linux goes something like this:

I am trying to boot Linux on my board, and I get stuck after this message prints to my console:

'Uncompressing Kernel Image. . . OK.'

Thus starts the long and sometimes frustrating learning curve of embedded Linux! Many things that can go wrong could lead to this common failure. With some knowledge and a JTAG debugger, there are ways to determine what went awry.

14.5.1. Early Serial Debug Output

The first tool you might have available is CONFIG_SERIAL_TEXT_DEBUG. This Linux kernel-configuration option adds support for debug messages very early in the boot process. At the present time, this feature is limited to the PowerPC architecture, but nothing prevents you from duplicating the functionality in other architectures. Listing 14-22 provides an example of this feature in use on a PowerPC target using the U-Boot bootloader.

Listing 14-22. Early Serial Text Debug

## Booting image at 00200000 ...

   Image Name:   Linux-2.6.14

   Created:      2005-12-19  22:24:03 UTC

   Image Type:   PowerPC Linux Kernel Image (gzip compressed)

   Data Size:    607149 Bytes = 592.9 kB

   Load Address: 00000000

   Entry Point:  00000000

   Verifying Checksum ... OK

   Uncompressing Kernel Image ... OK

id mach(): done      <== Start of messages enabled by

MMU:enter            <== CONFIG_SERIAL_TEXT_DEBUG

MMU:hw init

MMU:mapin

MMU:setio

MMU:exit

setup_arch: enter

setup_arch: bootmem

arch: exit

arch: real exit

Using this feature, you can often tell where your board is getting stuck during the boot process. Of course, you can add your own early debug messages in other places in the kernel. Here is an example of its usage found in .../arch/ppc/mm/init.c :

/* Map in all of RAM starting at KERNELBASE */

if (ppc_md.progress)

 ppc_md.progress('MMU:mapin', 0x301);

mapin_ram();

The AMCC Yosemite platform is an excellent example of this infrastructure. Consult the following files in the Linux source tree[99] for details of how this debugging system is implemented:

File Function Purpose
gen550_dbg.c gen550_init Serial port setup, called by yosemite.c platform-initialization file
gen550_dbg.c gen550_progress Low-level serial output routine
ibm44x_common.c ibm44x_platform_init Binds platform-specific progress routine to generic ppc machine-dependent infrastructure

14.5.2. Dumping the printk Log Buffer

When we discussed printk debugging in Section 14.3.6, we pointed out some of the limitations of this method. printk itself is a very robust implementation. One of its shortcomings is that you can't see any printk messages until later in the boot sequence when the console device has been initialized. Very often, when your board hangs on boot, quite a few messages are stuck in the printk buffer. If you know where to find them, you can often pinpoint the exact problem that is causing the boot to hang. Indeed, many times you will discover that the kernel has encountered an error that led to a call to panic(). The output from panic() has likely been dumped into the printk buffer, and you can often pinpoint the exact line of offending code.

This is best accomplished with a JTAG debugger, but it is still possible to use a bootloader and its memory dump capability to display the contents of the printk buffer after a reset. Some corruption of memory contents might occur as a result of the reset, but log buffer text is usually very readable.

The actual buffer where printk stores its message text is declared in the printk source file .../kernel/printk.c.

static char __log_buf[__LOG_BUF_LEN];

We can easily determine the linked location of this buffer from the Linux kernel map file System.map.

$ grep __log_buf System.map

c022e5a4 b __log_buf

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату